1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <drm/drm_crtc.h> 7 #include <drm/drm_vblank.h> 8 9 #include "gt/intel_rps.h" 10 #include "i915_drv.h" 11 #include "intel_display_rps.h" 12 #include "intel_display_types.h" 13 14 struct wait_rps_boost { 15 struct wait_queue_entry wait; 16 17 struct drm_crtc *crtc; 18 struct i915_request *request; 19 }; 20 21 static int do_rps_boost(struct wait_queue_entry *_wait, 22 unsigned mode, int sync, void *key) 23 { 24 struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); 25 struct i915_request *rq = wait->request; 26 27 /* 28 * If we missed the vblank, but the request is already running it 29 * is reasonable to assume that it will complete before the next 30 * vblank without our intervention, so leave RPS alone. 31 */ 32 if (!i915_request_started(rq)) 33 intel_rps_boost(rq); 34 i915_request_put(rq); 35 36 drm_crtc_vblank_put(wait->crtc); 37 38 list_del(&wait->wait.entry); 39 kfree(wait); 40 return 1; 41 } 42 43 void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, 44 struct dma_fence *fence) 45 { 46 struct wait_rps_boost *wait; 47 48 if (!dma_fence_is_i915(fence)) 49 return; 50 51 if (DISPLAY_VER(to_i915(crtc->dev)) < 6) 52 return; 53 54 if (drm_crtc_vblank_get(crtc)) 55 return; 56 57 wait = kmalloc(sizeof(*wait), GFP_KERNEL); 58 if (!wait) { 59 drm_crtc_vblank_put(crtc); 60 return; 61 } 62 63 wait->request = to_request(dma_fence_get(fence)); 64 wait->crtc = crtc; 65 66 wait->wait.func = do_rps_boost; 67 wait->wait.flags = 0; 68 69 add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait); 70 } 71 72 void intel_display_rps_mark_interactive(struct drm_i915_private *i915, 73 struct intel_atomic_state *state, 74 bool interactive) 75 { 76 if (state->rps_interactive == interactive) 77 return; 78 79 intel_rps_mark_interactive(&to_gt(i915)->rps, interactive); 80 state->rps_interactive = interactive; 81 } 82