[Nouveau] [PATCH] drm/nouveau/device: fix changing endianess code to work on older GPUs

Karol Herbst kherbst at redhat.com
Tue Oct 13 13:56:00 UTC 2020


On Tue, Oct 13, 2020 at 3:55 PM Ilia Mirkin <imirkin at alum.mit.edu> wrote:
>
> On Tue, Oct 13, 2020 at 8:01 AM Karol Herbst <kherbst at redhat.com> wrote:
> >
> > With this we try to detect if the endianess switch works and assume LE if
> > not. Suggested by Ben.
> >
> > Fixes: 51c05340e407 ("drm/nouveau/device: detect if changing endianness failed")
> > ---
> >  .../gpu/drm/nouveau/nvkm/engine/device/base.c | 39 ++++++++++++-------
> >  1 file changed, 26 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
> > index dcb70677d0acc..7851bec5f0e5f 100644
> > --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
> > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
> > @@ -2924,17 +2924,34 @@ nvkm_device_del(struct nvkm_device **pdevice)
> >         }
> >  }
> >
> > +/* returns true if the GPU is in the CPU native byte order */
> >  static inline bool
> >  nvkm_device_endianness(struct nvkm_device *device)
> >  {
> > -       u32 boot1 = nvkm_rd32(device, 0x000004) & 0x01000001;
> >  #ifdef __BIG_ENDIAN
> > -       if (!boot1)
> > -               return false;
> > +       const bool big_endian = true;
> >  #else
> > -       if (boot1)
> > -               return false;
> > +       const bool big_endian = false;
> >  #endif
> > +
> > +       /* Read NV_PMC_BOOT_1, and assume non-functional endian switch if it
> > +        * doesn't contain the expected values.
> > +        */
> > +       u32 pmc_boot_1 = nvkm_rd32(device, 0x000004);
> > +       if (pmc_boot_1 && pmc_boot_1 != 0x01000001)
>
> Are you sure there are no other bits in there, esp on newer GPUs?
>

Fairly. Checked on GP107 today, which is nearly the last gen to even
support it. I think it's gone with volta or turing.

> > +               return !big_endian; /* Assume GPU is LE in this case. */
> > +
> > +       /* 0 means LE and 0x01000001 means BE GPU. Condition is true when
> > +        * GPU/CPU endianness don't match.
> > +        */
> > +       if (big_endian == !pmc_boot_1) {
> > +               nvkm_wr32(device, 0x000004, 0x01000001);
> > +               nvkm_rd32(device, 0x000000);
> > +               if (nvkm_rd32(device, 0x000004) != (big_endian ? 0x01000001 : 0x00000000))
> > +                       return !big_endian; /* Assume GPU is LE on any unexpected read-back. */
> > +       }
> > +
> > +       /* CPU/GPU endianness should (hopefully) match. */
> >         return true;
> >  }
> >
> > @@ -2987,14 +3004,10 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
> >         if (detect) {
> >                 /* switch mmio to cpu's native endianness */
> >                 if (!nvkm_device_endianness(device)) {
> > -                       nvkm_wr32(device, 0x000004, 0x01000001);
> > -                       nvkm_rd32(device, 0x000000);
> > -                       if (!nvkm_device_endianness(device)) {
> > -                               nvdev_error(device,
> > -                                           "GPU not supported on big-endian\n");
> > -                               ret = -ENOSYS;
> > -                               goto done;
> > -                       }
> > +                       nvdev_error(device,
> > +                                   "Couldn't switch GPU to CPUs endianess\n");
> > +                       ret = -ENOSYS;
> > +                       goto done;
> >                 }
> >
> >                 boot0 = nvkm_rd32(device, 0x000000);
> > --
> > 2.26.2
> >
> > _______________________________________________
> > Nouveau mailing list
> > Nouveau at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/nouveau
> _______________________________________________
> Nouveau mailing list
> Nouveau at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/nouveau
>



More information about the Nouveau mailing list