0001
0002
0003
0004
0005
0006
0007 #include <linux/dma-fence-array.h>
0008
0009 #include "gt/intel_engine.h"
0010
0011 #include "i915_gem_ioctls.h"
0012 #include "i915_gem_object.h"
0013
0014 static __always_inline u32 __busy_read_flag(u16 id)
0015 {
0016 if (id == (u16)I915_ENGINE_CLASS_INVALID)
0017 return 0xffff0000u;
0018
0019 GEM_BUG_ON(id >= 16);
0020 return 0x10000u << id;
0021 }
0022
0023 static __always_inline u32 __busy_write_id(u16 id)
0024 {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 if (id == (u16)I915_ENGINE_CLASS_INVALID)
0035 return 0xffffffffu;
0036
0037 return (id + 1) | __busy_read_flag(id);
0038 }
0039
0040 static __always_inline unsigned int
0041 __busy_set_if_active(struct dma_fence *fence, u32 (*flag)(u16 id))
0042 {
0043 const struct i915_request *rq;
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 if (dma_fence_is_array(fence)) {
0062 struct dma_fence_array *array = to_dma_fence_array(fence);
0063 struct dma_fence **child = array->fences;
0064 unsigned int nchild = array->num_fences;
0065
0066 do {
0067 struct dma_fence *current_fence = *child++;
0068
0069
0070 if (!dma_fence_is_i915(current_fence) ||
0071 !test_bit(I915_FENCE_FLAG_COMPOSITE,
0072 ¤t_fence->flags)) {
0073 return 0;
0074 }
0075
0076 rq = to_request(current_fence);
0077 if (!i915_request_completed(rq))
0078 return flag(rq->engine->uabi_class);
0079 } while (--nchild);
0080
0081
0082 return 0;
0083 } else {
0084 if (!dma_fence_is_i915(fence))
0085 return 0;
0086
0087 rq = to_request(fence);
0088 if (i915_request_completed(rq))
0089 return 0;
0090
0091
0092 BUILD_BUG_ON(!typecheck(u16, rq->engine->uabi_class));
0093 return flag(rq->engine->uabi_class);
0094 }
0095 }
0096
0097 static __always_inline unsigned int
0098 busy_check_reader(struct dma_fence *fence)
0099 {
0100 return __busy_set_if_active(fence, __busy_read_flag);
0101 }
0102
0103 static __always_inline unsigned int
0104 busy_check_writer(struct dma_fence *fence)
0105 {
0106 if (!fence)
0107 return 0;
0108
0109 return __busy_set_if_active(fence, __busy_write_id);
0110 }
0111
0112 int
0113 i915_gem_busy_ioctl(struct drm_device *dev, void *data,
0114 struct drm_file *file)
0115 {
0116 struct drm_i915_gem_busy *args = data;
0117 struct drm_i915_gem_object *obj;
0118 struct dma_resv_iter cursor;
0119 struct dma_fence *fence;
0120 int err;
0121
0122 err = -ENOENT;
0123 rcu_read_lock();
0124 obj = i915_gem_object_lookup_rcu(file, args->handle);
0125 if (!obj)
0126 goto out;
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 args->busy = 0;
0146 dma_resv_iter_begin(&cursor, obj->base.resv, DMA_RESV_USAGE_READ);
0147 dma_resv_for_each_fence_unlocked(&cursor, fence) {
0148 if (dma_resv_iter_is_restarted(&cursor))
0149 args->busy = 0;
0150
0151 if (dma_resv_iter_usage(&cursor) <= DMA_RESV_USAGE_WRITE)
0152
0153 args->busy |= busy_check_writer(fence);
0154 else
0155
0156 args->busy |= busy_check_reader(fence);
0157 }
0158 dma_resv_iter_end(&cursor);
0159
0160 err = 0;
0161 out:
0162 rcu_read_unlock();
0163 return err;
0164 }