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(crtc: wait->crtc); |
37 | |
38 | list_del(entry: &wait->wait.entry); |
39 | kfree(objp: 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(size: sizeof(*wait), GFP_KERNEL); |
58 | if (!wait) { |
59 | drm_crtc_vblank_put(crtc); |
60 | return; |
61 | } |
62 | |
63 | wait->request = to_request(fence: 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(wq_head: drm_crtc_vblank_waitqueue(crtc), wq_entry: &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(rps: &to_gt(i915)->rps, interactive); |
80 | state->rps_interactive = interactive; |
81 | } |
82 | |