Branch data Line data Source code
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 : 0 : i915_gem_throttle_ioctl(struct drm_device *dev, void *data, 36 : : struct drm_file *file) 37 : : { 38 : 0 : struct drm_i915_file_private *file_priv = file->driver_priv; 39 : 0 : unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; 40 : 0 : struct i915_request *request, *target = NULL; 41 : 0 : long ret; 42 : : 43 : : /* ABI: return -EIO if already wedged */ 44 : 0 : ret = intel_gt_terminally_wedged(&to_i915(dev)->gt); 45 [ # # ]: 0 : if (ret) 46 : : return ret; 47 : : 48 : 0 : spin_lock(&file_priv->mm.lock); 49 [ # # ]: 0 : list_for_each_entry(request, &file_priv->mm.request_list, client_link) { 50 [ # # ]: 0 : if (time_after_eq(request->emitted_jiffies, recent_enough)) 51 : : break; 52 : : 53 [ # # # # ]: 0 : if (target && xchg(&target->file_priv, NULL)) 54 : 0 : list_del(&target->client_link); 55 : : 56 : 0 : target = request; 57 : : } 58 [ # # ]: 0 : if (target) 59 [ # # ]: 0 : i915_request_get(target); 60 : 0 : spin_unlock(&file_priv->mm.lock); 61 : : 62 [ # # ]: 0 : if (!target) 63 : : return 0; 64 : : 65 : 0 : ret = i915_request_wait(target, 66 : : I915_WAIT_INTERRUPTIBLE, 67 : : MAX_SCHEDULE_TIMEOUT); 68 : 0 : i915_request_put(target); 69 : : 70 : 0 : return ret < 0 ? ret : 0; 71 : : }