Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6/**
7 * DOC: display pinning helpers
8 */
9
10#include "gem/i915_gem_domain.h"
11#include "gem/i915_gem_object.h"
12
13#include "i915_drv.h"
14#include "intel_atomic_plane.h"
15#include "intel_display_rpm.h"
16#include "intel_display_types.h"
17#include "intel_dpt.h"
18#include "intel_fb.h"
19#include "intel_fb_pin.h"
20
21static struct i915_vma *
22intel_fb_pin_to_dpt(const struct drm_framebuffer *fb,
23 const struct i915_gtt_view *view,
24 unsigned int alignment,
25 unsigned long *out_flags,
26 struct i915_address_space *vm)
27{
28 struct drm_device *dev = fb->dev;
29 struct intel_display *display = to_intel_display(dev);
30 struct drm_i915_private *dev_priv = to_i915(dev);
31 struct drm_gem_object *_obj = intel_fb_bo(fb);
32 struct drm_i915_gem_object *obj = to_intel_bo(_obj);
33 struct i915_gem_ww_ctx ww;
34 struct i915_vma *vma;
35 int ret;
36
37 /*
38 * We are not syncing against the binding (and potential migrations)
39 * below, so this vm must never be async.
40 */
41 if (drm_WARN_ON(&dev_priv->drm, vm->bind_async_flags))
42 return ERR_PTR(-EINVAL);
43
44 if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
45 return ERR_PTR(-EINVAL);
46
47 atomic_inc(&display->restore.pending_fb_pin);
48
49 for_i915_gem_ww(&ww, ret, true) {
50 ret = i915_gem_object_lock(obj, &ww);
51 if (ret)
52 continue;
53
54 if (HAS_LMEM(dev_priv)) {
55 unsigned int flags = obj->flags;
56
57 /*
58 * For this type of buffer we need to able to read from the CPU
59 * the clear color value found in the buffer, hence we need to
60 * ensure it is always in the mappable part of lmem, if this is
61 * a small-bar device.
62 */
63 if (intel_fb_rc_ccs_cc_plane(fb) >= 0)
64 flags &= ~I915_BO_ALLOC_GPU_ONLY;
65 ret = __i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0,
66 flags);
67 if (ret)
68 continue;
69 }
70
71 ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
72 if (ret)
73 continue;
74
75 vma = i915_vma_instance(obj, vm, view);
76 if (IS_ERR(vma)) {
77 ret = PTR_ERR(vma);
78 continue;
79 }
80
81 if (i915_vma_misplaced(vma, 0, alignment, 0)) {
82 ret = i915_vma_unbind(vma);
83 if (ret)
84 continue;
85 }
86
87 ret = i915_vma_pin_ww(vma, &ww, 0, alignment, PIN_GLOBAL);
88 if (ret)
89 continue;
90 }
91 if (ret) {
92 vma = ERR_PTR(ret);
93 goto err;
94 }
95
96 vma->display_alignment = max(vma->display_alignment, alignment);
97
98 i915_gem_object_flush_if_display(obj);
99
100 i915_vma_get(vma);
101err:
102 atomic_dec(&display->restore.pending_fb_pin);
103
104 return vma;
105}
106
107struct i915_vma *
108intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
109 const struct i915_gtt_view *view,
110 unsigned int alignment,
111 unsigned int phys_alignment,
112 unsigned int vtd_guard,
113 bool uses_fence,
114 unsigned long *out_flags)
115{
116 struct drm_device *dev = fb->dev;
117 struct intel_display *display = to_intel_display(dev);
118 struct drm_i915_private *dev_priv = to_i915(dev);
119 struct drm_gem_object *_obj = intel_fb_bo(fb);
120 struct drm_i915_gem_object *obj = to_intel_bo(_obj);
121 struct ref_tracker *wakeref;
122 struct i915_gem_ww_ctx ww;
123 struct i915_vma *vma;
124 unsigned int pinctl;
125 int ret;
126
127 if (drm_WARN_ON(dev, !i915_gem_object_is_framebuffer(obj)))
128 return ERR_PTR(-EINVAL);
129
130 if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment)))
131 return ERR_PTR(-EINVAL);
132
133 /*
134 * Global gtt pte registers are special registers which actually forward
135 * writes to a chunk of system memory. Which means that there is no risk
136 * that the register values disappear as soon as we call
137 * intel_runtime_pm_put(), so it is correct to wrap only the
138 * pin/unpin/fence and not more.
139 */
140 wakeref = intel_display_rpm_get(display);
141
142 atomic_inc(&display->restore.pending_fb_pin);
143
144 /*
145 * Valleyview is definitely limited to scanning out the first
146 * 512MiB. Lets presume this behaviour was inherited from the
147 * g4x display engine and that all earlier gen are similarly
148 * limited. Testing suggests that it is a little more
149 * complicated than this. For example, Cherryview appears quite
150 * happy to scanout from anywhere within its global aperture.
151 */
152 pinctl = 0;
153 if (HAS_GMCH(dev_priv))
154 pinctl |= PIN_MAPPABLE;
155
156 i915_gem_ww_ctx_init(&ww, true);
157retry:
158 ret = i915_gem_object_lock(obj, &ww);
159 if (!ret && phys_alignment)
160 ret = i915_gem_object_attach_phys(obj, phys_alignment);
161 else if (!ret && HAS_LMEM(dev_priv))
162 ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0);
163 if (!ret)
164 ret = i915_gem_object_pin_pages(obj);
165 if (ret)
166 goto err;
167
168 vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment,
169 vtd_guard, view, pinctl);
170 if (IS_ERR(vma)) {
171 ret = PTR_ERR(vma);
172 goto err_unpin;
173 }
174
175 if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {
176 /*
177 * Install a fence for tiled scan-out. Pre-i965 always needs a
178 * fence, whereas 965+ only requires a fence if using
179 * framebuffer compression. For simplicity, we always, when
180 * possible, install a fence as the cost is not that onerous.
181 *
182 * If we fail to fence the tiled scanout, then either the
183 * modeset will reject the change (which is highly unlikely as
184 * the affected systems, all but one, do not have unmappable
185 * space) or we will not be able to enable full powersaving
186 * techniques (also likely not to apply due to various limits
187 * FBC and the like impose on the size of the buffer, which
188 * presumably we violated anyway with this unmappable buffer).
189 * Anyway, it is presumably better to stumble onwards with
190 * something and try to run the system in a "less than optimal"
191 * mode that matches the user configuration.
192 */
193 ret = i915_vma_pin_fence(vma);
194 if (ret != 0 && DISPLAY_VER(dev_priv) < 4) {
195 i915_vma_unpin(vma);
196 goto err_unpin;
197 }
198 ret = 0;
199
200 if (vma->fence)
201 *out_flags |= PLANE_HAS_FENCE;
202 }
203
204 i915_vma_get(vma);
205
206err_unpin:
207 i915_gem_object_unpin_pages(obj);
208err:
209 if (ret == -EDEADLK) {
210 ret = i915_gem_ww_ctx_backoff(&ww);
211 if (!ret)
212 goto retry;
213 }
214 i915_gem_ww_ctx_fini(&ww);
215 if (ret)
216 vma = ERR_PTR(ret);
217
218 atomic_dec(&display->restore.pending_fb_pin);
219 intel_display_rpm_put(display, wakeref);
220 return vma;
221}
222
223void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags)
224{
225 if (flags & PLANE_HAS_FENCE)
226 i915_vma_unpin_fence(vma);
227 i915_vma_unpin(vma);
228 i915_vma_put(vma);
229}
230
231static unsigned int
232intel_plane_fb_min_alignment(const struct intel_plane_state *plane_state)
233{
234 const struct intel_framebuffer *fb = to_intel_framebuffer(plane_state->hw.fb);
235
236 return fb->min_alignment;
237}
238
239static unsigned int
240intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state)
241{
242 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
243 const struct drm_framebuffer *fb = plane_state->hw.fb;
244
245 if (!intel_plane_needs_physical(plane))
246 return 0;
247
248 return plane->min_alignment(plane, fb, 0);
249}
250
251static unsigned int
252intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state)
253{
254 return intel_fb_view_vtd_guard(plane_state->hw.fb,
255 &plane_state->view,
256 plane_state->hw.rotation);
257}
258
259int intel_plane_pin_fb(struct intel_plane_state *plane_state,
260 const struct intel_plane_state *old_plane_state)
261{
262 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
263 const struct intel_framebuffer *fb =
264 to_intel_framebuffer(plane_state->hw.fb);
265 struct i915_vma *vma;
266
267 if (!intel_fb_uses_dpt(&fb->base)) {
268 vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt,
269 intel_plane_fb_min_alignment(plane_state),
270 intel_plane_fb_min_phys_alignment(plane_state),
271 intel_plane_fb_vtd_guard(plane_state),
272 intel_plane_uses_fence(plane_state),
273 &plane_state->flags);
274 if (IS_ERR(vma))
275 return PTR_ERR(vma);
276
277 plane_state->ggtt_vma = vma;
278
279 /*
280 * Pre-populate the dma address before we enter the vblank
281 * evade critical section as i915_gem_object_get_dma_address()
282 * will trigger might_sleep() even if it won't actually sleep,
283 * which is the case when the fb has already been pinned.
284 */
285 if (intel_plane_needs_physical(plane)) {
286 struct drm_i915_gem_object *obj = to_intel_bo(intel_fb_bo(&fb->base));
287
288 plane_state->phys_dma_addr = i915_gem_object_get_dma_address(obj, 0);
289 }
290 } else {
291 unsigned int alignment = intel_plane_fb_min_alignment(plane_state);
292
293 vma = intel_dpt_pin_to_ggtt(fb->dpt_vm, alignment / 512);
294 if (IS_ERR(vma))
295 return PTR_ERR(vma);
296
297 plane_state->ggtt_vma = vma;
298
299 vma = intel_fb_pin_to_dpt(&fb->base, &plane_state->view.gtt,
300 alignment, &plane_state->flags,
301 fb->dpt_vm);
302 if (IS_ERR(vma)) {
303 intel_dpt_unpin_from_ggtt(fb->dpt_vm);
304 plane_state->ggtt_vma = NULL;
305 return PTR_ERR(vma);
306 }
307
308 plane_state->dpt_vma = vma;
309
310 WARN_ON(plane_state->ggtt_vma == plane_state->dpt_vma);
311 }
312
313 return 0;
314}
315
316void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
317{
318 const struct intel_framebuffer *fb =
319 to_intel_framebuffer(old_plane_state->hw.fb);
320 struct i915_vma *vma;
321
322 if (!intel_fb_uses_dpt(&fb->base)) {
323 vma = fetch_and_zero(&old_plane_state->ggtt_vma);
324 if (vma)
325 intel_fb_unpin_vma(vma, old_plane_state->flags);
326 } else {
327 vma = fetch_and_zero(&old_plane_state->dpt_vma);
328 if (vma)
329 intel_fb_unpin_vma(vma, old_plane_state->flags);
330
331 vma = fetch_and_zero(&old_plane_state->ggtt_vma);
332 if (vma)
333 intel_dpt_unpin_from_ggtt(fb->dpt_vm);
334 }
335}