Skip to content

Commit

Permalink
drm/nouveau/device: fix changing endianess code to work on older GPUs
Browse files Browse the repository at this point in the history
commit dcd292c upstream.

With this we try to detect if the endianess switch works and assume LE if
not. Suggested by Ben.

Fixes: 51c0534 ("drm/nouveau/device: detect if changing endianness failed")
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Cc: <stable@vger.kernel.org> # v5.8+
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
karolherbst authored and gregkh committed Nov 10, 2020
1 parent 8d6ef44 commit 656ebbd
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
Expand Up @@ -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)
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;
}

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 656ebbd

Please sign in to comment.