[Nouveau] [PATCH] drm/nouveau/device: fix changing endianess code to work on older GPUs
Ilia Mirkin
imirkin at alum.mit.edu
Tue Oct 13 13:54:51 UTC 2020
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?
> + 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
More information about the Nouveau
mailing list