]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
drm/nouveau/disp: modify OR allocation policy to account for HDA requirements
authorBen Skeggs <bskeggs@redhat.com>
Wed, 3 Jun 2020 01:43:23 +0000 (11:43 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 4 Jun 2020 04:23:21 +0000 (14:23 +1000)
Since GM200, SORs are no longer tied to a specific connector, and we
allocate them instead, with the assumption that all SORs are equally
capable.

However, there's a 1<->1 mapping between SOR and HDA pin widget, and
it turns out that it's possible for some widgets to be disabled...

In order to avoid picking a SOR without a valid pin widget, some new
rules need to be added.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c

index b56224558a05b9f1612a972508a7fbcb8f43356a..dcf08249374a35dd1af04185bc3245a2ba18f0c3 100644 (file)
@@ -121,14 +121,14 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type,
         * on HW, if any, in order to prevent unnecessary switching.
         */
        list_for_each_entry(ior, &outp->disp->ior, head) {
-               if (!ior->identity &&
+               if (!ior->identity && !!ior->func->hda.hpd == hda &&
                    !ior->asy.outp && ior->arm.outp == outp)
                        return nvkm_outp_acquire_ior(outp, user, ior);
        }
 
        /* Failing that, a completely unused OR is the next best thing. */
        list_for_each_entry(ior, &outp->disp->ior, head) {
-               if (!ior->identity &&
+               if (!ior->identity && !!ior->func->hda.hpd == hda &&
                    !ior->asy.outp && ior->type == type && !ior->arm.outp &&
                    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
                        return nvkm_outp_acquire_ior(outp, user, ior);
@@ -138,7 +138,7 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type,
         * but will be released during the next modeset.
         */
        list_for_each_entry(ior, &outp->disp->ior, head) {
-               if (!ior->identity &&
+               if (!ior->identity && !!ior->func->hda.hpd == hda &&
                    !ior->asy.outp && ior->type == type &&
                    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
                        return nvkm_outp_acquire_ior(outp, user, ior);
@@ -173,7 +173,25 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda)
                return nvkm_outp_acquire_ior(outp, user, ior);
        }
 
-       return nvkm_outp_acquire_hda(outp, type, user, true);
+       /* If we don't need HDA, first try to acquire an OR that doesn't
+        * support it to leave free the ones that do.
+        */
+       if (!hda) {
+               if (!nvkm_outp_acquire_hda(outp, type, user, false))
+                       return 0;
+
+               /* Use a HDA-supporting SOR anyway. */
+               return nvkm_outp_acquire_hda(outp, type, user, true);
+       }
+
+       /* We want HDA, try to acquire an OR that supports it. */
+       if (!nvkm_outp_acquire_hda(outp, type, user, true))
+               return 0;
+
+       /* There weren't any free ORs that support HDA, grab one that
+        * doesn't and at least allow display to work still.
+        */
+       return nvkm_outp_acquire_hda(outp, type, user, false);
 }
 
 void