Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * SPDX-License-Identifier: MIT
0003  *
0004  * Copyright © 2014-2016 Intel Corporation
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      * The uABI guarantees an active writer is also amongst the read
0027      * engines. This would be true if we accessed the activity tracking
0028      * under the lock, but as we perform the lookup of the object and
0029      * its activity locklessly we can not guarantee that the last_write
0030      * being active implies that we have set the same engine flag from
0031      * last_read - hence we always set both read and write busy for
0032      * last_write.
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      * We have to check the current hw status of the fence as the uABI
0047      * guarantees forward progress. We could rely on the idle worker
0048      * to eventually flush us, but to minimise latency just ask the
0049      * hardware.
0050      *
0051      * Note we only report on the status of native fences and we currently
0052      * have two native fences:
0053      *
0054      * 1. A composite fence (dma_fence_array) constructed of i915 requests
0055      * created during a parallel submission. In this case we deconstruct the
0056      * composite fence into individual i915 requests and check the status of
0057      * each request.
0058      *
0059      * 2. A single i915 request.
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             /* Not an i915 fence, can't be busy per above */
0070             if (!dma_fence_is_i915(current_fence) ||
0071                 !test_bit(I915_FENCE_FLAG_COMPOSITE,
0072                       &current_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         /* All requests in array complete, not busy */
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         /* Beware type-expansion follies! */
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      * A discrepancy here is that we do not report the status of
0130      * non-i915 fences, i.e. even though we may report the object as idle,
0131      * a call to set-domain may still stall waiting for foreign rendering.
0132      * This also means that wait-ioctl may report an object as busy,
0133      * where busy-ioctl considers it idle.
0134      *
0135      * We trade the ability to warn of foreign fences to report on which
0136      * i915 engines are active for the object.
0137      *
0138      * Alternatively, we can trade that extra information on read/write
0139      * activity with
0140      *  args->busy =
0141      *      !dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ);
0142      * to report the overall busyness. This is what the wait-ioctl does.
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             /* Translate the write fences to the READ *and* WRITE engine */
0153             args->busy |= busy_check_writer(fence);
0154         else
0155             /* Translate read fences to READ set of engines */
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 }