0001
0002
0003
0004
0005
0006
0007 #include <linux/jiffies.h>
0008
0009 #include <drm/drm_file.h>
0010
0011 #include "i915_drv.h"
0012 #include "i915_file_private.h"
0013 #include "i915_gem_context.h"
0014 #include "i915_gem_ioctls.h"
0015 #include "i915_gem_object.h"
0016
0017
0018
0019
0020
0021
0022
0023 #define DRM_I915_THROTTLE_JIFFIES msecs_to_jiffies(20)
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 int
0037 i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
0038 struct drm_file *file)
0039 {
0040 const unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES;
0041 struct drm_i915_file_private *file_priv = file->driver_priv;
0042 struct drm_i915_private *i915 = to_i915(dev);
0043 struct i915_gem_context *ctx;
0044 unsigned long idx;
0045 long ret;
0046
0047
0048 ret = intel_gt_terminally_wedged(to_gt(i915));
0049 if (ret)
0050 return ret;
0051
0052 rcu_read_lock();
0053 xa_for_each(&file_priv->context_xa, idx, ctx) {
0054 struct i915_gem_engines_iter it;
0055 struct intel_context *ce;
0056
0057 if (!kref_get_unless_zero(&ctx->ref))
0058 continue;
0059 rcu_read_unlock();
0060
0061 for_each_gem_engine(ce,
0062 i915_gem_context_lock_engines(ctx),
0063 it) {
0064 struct i915_request *rq, *target = NULL;
0065
0066 if (!ce->timeline)
0067 continue;
0068
0069 mutex_lock(&ce->timeline->mutex);
0070 list_for_each_entry_reverse(rq,
0071 &ce->timeline->requests,
0072 link) {
0073 if (i915_request_completed(rq))
0074 break;
0075
0076 if (time_after(rq->emitted_jiffies,
0077 recent_enough))
0078 continue;
0079
0080 target = i915_request_get(rq);
0081 break;
0082 }
0083 mutex_unlock(&ce->timeline->mutex);
0084 if (!target)
0085 continue;
0086
0087 ret = i915_request_wait(target,
0088 I915_WAIT_INTERRUPTIBLE,
0089 MAX_SCHEDULE_TIMEOUT);
0090 i915_request_put(target);
0091 if (ret < 0)
0092 break;
0093 }
0094 i915_gem_context_unlock_engines(ctx);
0095 i915_gem_context_put(ctx);
0096
0097 rcu_read_lock();
0098 }
0099 rcu_read_unlock();
0100
0101 return ret < 0 ? ret : 0;
0102 }