Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2021 Intel Corporation
0004  */
0005 
0006 /**
0007  * DOC: display pinning helpers
0008  */
0009 
0010 #include "gem/i915_gem_domain.h"
0011 #include "gem/i915_gem_object.h"
0012 
0013 #include "i915_drv.h"
0014 #include "intel_display_types.h"
0015 #include "intel_dpt.h"
0016 #include "intel_fb.h"
0017 #include "intel_fb_pin.h"
0018 
0019 static struct i915_vma *
0020 intel_pin_fb_obj_dpt(struct drm_framebuffer *fb,
0021              const struct i915_ggtt_view *view,
0022              bool uses_fence,
0023              unsigned long *out_flags,
0024              struct i915_address_space *vm)
0025 {
0026     struct drm_device *dev = fb->dev;
0027     struct drm_i915_private *dev_priv = to_i915(dev);
0028     struct drm_i915_gem_object *obj = intel_fb_obj(fb);
0029     struct i915_vma *vma;
0030     u32 alignment;
0031     int ret;
0032 
0033     if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
0034         return ERR_PTR(-EINVAL);
0035 
0036     alignment = 4096 * 512;
0037 
0038     atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
0039 
0040     ret = i915_gem_object_lock_interruptible(obj, NULL);
0041     if (!ret) {
0042         ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
0043         i915_gem_object_unlock(obj);
0044     }
0045     if (ret) {
0046         vma = ERR_PTR(ret);
0047         goto err;
0048     }
0049 
0050     vma = i915_vma_instance(obj, vm, view);
0051     if (IS_ERR(vma))
0052         goto err;
0053 
0054     if (i915_vma_misplaced(vma, 0, alignment, 0)) {
0055         ret = i915_vma_unbind_unlocked(vma);
0056         if (ret) {
0057             vma = ERR_PTR(ret);
0058             goto err;
0059         }
0060     }
0061 
0062     ret = i915_vma_pin(vma, 0, alignment, PIN_GLOBAL);
0063     if (ret) {
0064         vma = ERR_PTR(ret);
0065         goto err;
0066     }
0067 
0068     vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
0069 
0070     i915_gem_object_flush_if_display(obj);
0071 
0072     i915_vma_get(vma);
0073 err:
0074     atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
0075 
0076     return vma;
0077 }
0078 
0079 struct i915_vma *
0080 intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
0081                bool phys_cursor,
0082                const struct i915_ggtt_view *view,
0083                bool uses_fence,
0084                unsigned long *out_flags)
0085 {
0086     struct drm_device *dev = fb->dev;
0087     struct drm_i915_private *dev_priv = to_i915(dev);
0088     struct drm_i915_gem_object *obj = intel_fb_obj(fb);
0089     intel_wakeref_t wakeref;
0090     struct i915_gem_ww_ctx ww;
0091     struct i915_vma *vma;
0092     unsigned int pinctl;
0093     u32 alignment;
0094     int ret;
0095 
0096     if (drm_WARN_ON(dev, !i915_gem_object_is_framebuffer(obj)))
0097         return ERR_PTR(-EINVAL);
0098 
0099     if (phys_cursor)
0100         alignment = intel_cursor_alignment(dev_priv);
0101     else
0102         alignment = intel_surf_alignment(fb, 0);
0103     if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment)))
0104         return ERR_PTR(-EINVAL);
0105 
0106     /* Note that the w/a also requires 64 PTE of padding following the
0107      * bo. We currently fill all unused PTE with the shadow page and so
0108      * we should always have valid PTE following the scanout preventing
0109      * the VT-d warning.
0110      */
0111     if (intel_scanout_needs_vtd_wa(dev_priv) && alignment < 256 * 1024)
0112         alignment = 256 * 1024;
0113 
0114     /*
0115      * Global gtt pte registers are special registers which actually forward
0116      * writes to a chunk of system memory. Which means that there is no risk
0117      * that the register values disappear as soon as we call
0118      * intel_runtime_pm_put(), so it is correct to wrap only the
0119      * pin/unpin/fence and not more.
0120      */
0121     wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
0122 
0123     atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
0124 
0125     /*
0126      * Valleyview is definitely limited to scanning out the first
0127      * 512MiB. Lets presume this behaviour was inherited from the
0128      * g4x display engine and that all earlier gen are similarly
0129      * limited. Testing suggests that it is a little more
0130      * complicated than this. For example, Cherryview appears quite
0131      * happy to scanout from anywhere within its global aperture.
0132      */
0133     pinctl = 0;
0134     if (HAS_GMCH(dev_priv))
0135         pinctl |= PIN_MAPPABLE;
0136 
0137     i915_gem_ww_ctx_init(&ww, true);
0138 retry:
0139     ret = i915_gem_object_lock(obj, &ww);
0140     if (!ret && phys_cursor)
0141         ret = i915_gem_object_attach_phys(obj, alignment);
0142     else if (!ret && HAS_LMEM(dev_priv))
0143         ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0);
0144     /* TODO: Do we need to sync when migration becomes async? */
0145     if (!ret)
0146         ret = i915_gem_object_pin_pages(obj);
0147     if (ret)
0148         goto err;
0149 
0150     vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment,
0151                            view, pinctl);
0152     if (IS_ERR(vma)) {
0153         ret = PTR_ERR(vma);
0154         goto err_unpin;
0155     }
0156 
0157     if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {
0158         /*
0159          * Install a fence for tiled scan-out. Pre-i965 always needs a
0160          * fence, whereas 965+ only requires a fence if using
0161          * framebuffer compression.  For simplicity, we always, when
0162          * possible, install a fence as the cost is not that onerous.
0163          *
0164          * If we fail to fence the tiled scanout, then either the
0165          * modeset will reject the change (which is highly unlikely as
0166          * the affected systems, all but one, do not have unmappable
0167          * space) or we will not be able to enable full powersaving
0168          * techniques (also likely not to apply due to various limits
0169          * FBC and the like impose on the size of the buffer, which
0170          * presumably we violated anyway with this unmappable buffer).
0171          * Anyway, it is presumably better to stumble onwards with
0172          * something and try to run the system in a "less than optimal"
0173          * mode that matches the user configuration.
0174          */
0175         ret = i915_vma_pin_fence(vma);
0176         if (ret != 0 && DISPLAY_VER(dev_priv) < 4) {
0177             i915_vma_unpin(vma);
0178             goto err_unpin;
0179         }
0180         ret = 0;
0181 
0182         if (vma->fence)
0183             *out_flags |= PLANE_HAS_FENCE;
0184     }
0185 
0186     i915_vma_get(vma);
0187 
0188 err_unpin:
0189     i915_gem_object_unpin_pages(obj);
0190 err:
0191     if (ret == -EDEADLK) {
0192         ret = i915_gem_ww_ctx_backoff(&ww);
0193         if (!ret)
0194             goto retry;
0195     }
0196     i915_gem_ww_ctx_fini(&ww);
0197     if (ret)
0198         vma = ERR_PTR(ret);
0199 
0200     atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
0201     intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
0202     return vma;
0203 }
0204 
0205 void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags)
0206 {
0207     if (flags & PLANE_HAS_FENCE)
0208         i915_vma_unpin_fence(vma);
0209     i915_vma_unpin(vma);
0210     i915_vma_put(vma);
0211 }
0212 
0213 int intel_plane_pin_fb(struct intel_plane_state *plane_state)
0214 {
0215     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0216     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0217     struct drm_framebuffer *fb = plane_state->hw.fb;
0218     struct i915_vma *vma;
0219     bool phys_cursor =
0220         plane->id == PLANE_CURSOR &&
0221         INTEL_INFO(dev_priv)->display.cursor_needs_physical;
0222 
0223     if (!intel_fb_uses_dpt(fb)) {
0224         vma = intel_pin_and_fence_fb_obj(fb, phys_cursor,
0225                          &plane_state->view.gtt,
0226                          intel_plane_uses_fence(plane_state),
0227                          &plane_state->flags);
0228         if (IS_ERR(vma))
0229             return PTR_ERR(vma);
0230 
0231         plane_state->ggtt_vma = vma;
0232     } else {
0233         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
0234 
0235         vma = intel_dpt_pin(intel_fb->dpt_vm);
0236         if (IS_ERR(vma))
0237             return PTR_ERR(vma);
0238 
0239         plane_state->ggtt_vma = vma;
0240 
0241         vma = intel_pin_fb_obj_dpt(fb, &plane_state->view.gtt, false,
0242                        &plane_state->flags, intel_fb->dpt_vm);
0243         if (IS_ERR(vma)) {
0244             intel_dpt_unpin(intel_fb->dpt_vm);
0245             plane_state->ggtt_vma = NULL;
0246             return PTR_ERR(vma);
0247         }
0248 
0249         plane_state->dpt_vma = vma;
0250 
0251         WARN_ON(plane_state->ggtt_vma == plane_state->dpt_vma);
0252     }
0253 
0254     return 0;
0255 }
0256 
0257 void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
0258 {
0259     struct drm_framebuffer *fb = old_plane_state->hw.fb;
0260     struct i915_vma *vma;
0261 
0262     if (!intel_fb_uses_dpt(fb)) {
0263         vma = fetch_and_zero(&old_plane_state->ggtt_vma);
0264         if (vma)
0265             intel_unpin_fb_vma(vma, old_plane_state->flags);
0266     } else {
0267         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
0268 
0269         vma = fetch_and_zero(&old_plane_state->dpt_vma);
0270         if (vma)
0271             intel_unpin_fb_vma(vma, old_plane_state->flags);
0272 
0273         vma = fetch_and_zero(&old_plane_state->ggtt_vma);
0274         if (vma)
0275             intel_dpt_unpin(intel_fb->dpt_vm);
0276     }
0277 }