[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