1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2014-2016 Intel Corporation 5 */ 6 7 #include <linux/jiffies.h> 8 9 #include <drm/drm_file.h> 10 11 #include "i915_drv.h" 12 #include "i915_gem_ioctls.h" 13 #include "i915_gem_object.h" 14 15 /* 16 * 20ms is a fairly arbitrary limit (greater than the average frame time) 17 * chosen to prevent the CPU getting more than a frame ahead of the GPU 18 * (when using lax throttling for the frontbuffer). We also use it to 19 * offer free GPU waitboosts for severely congested workloads. 20 */ 21 #define DRM_I915_THROTTLE_JIFFIES msecs_to_jiffies(20) 22 23 /* 24 * Throttle our rendering by waiting until the ring has completed our requests 25 * emitted over 20 msec ago. 26 * 27 * Note that if we were to use the current jiffies each time around the loop, 28 * we wouldn't escape the function with any frames outstanding if the time to 29 * render a frame was over 20ms. 30 * 31 * This should get us reasonable parallelism between CPU and GPU but also 32 * relatively low latency when blocking on a particular request to finish. 33 */ 34 int 35 i915_gem_throttle_ioctl(struct drm_device *dev, void *data, 36 struct drm_file *file) 37 { 38 struct drm_i915_file_private *file_priv = file->driver_priv; 39 unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; 40 struct i915_request *request, *target = NULL; 41 long ret; 42 43 /* ABI: return -EIO if already wedged */ 44 ret = intel_gt_terminally_wedged(&to_i915(dev)->gt); 45 if (ret) 46 return ret; 47 48 spin_lock(&file_priv->mm.lock); 49 list_for_each_entry(request, &file_priv->mm.request_list, client_link) { 50 if (time_after_eq(request->emitted_jiffies, recent_enough)) 51 break; 52 53 if (target && xchg(&target->file_priv, NULL)) 54 list_del(&target->client_link); 55 56 target = request; 57 } 58 if (target) 59 i915_request_get(target); 60 spin_unlock(&file_priv->mm.lock); 61 62 if (!target) 63 return 0; 64 65 ret = i915_request_wait(target, 66 I915_WAIT_INTERRUPTIBLE, 67 MAX_SCHEDULE_TIMEOUT); 68 i915_request_put(target); 69 70 return ret < 0 ? ret : 0; 71 } 72