Commit dcd292c1 authored by Karol Herbst's avatar Karol Herbst Committed by Ben Skeggs

drm/nouveau/device: fix changing endianess code to work on older GPUs

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

Fixes: 51c05340 ("drm/nouveau/device: detect if changing endianness failed")
Signed-off-by: default avatarKarol Herbst <kherbst@redhat.com>
Cc: <stable@vger.kernel.org> # v5.8+
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 92568145
...@@ -2924,17 +2924,34 @@ nvkm_device_del(struct nvkm_device **pdevice) ...@@ -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 static inline bool
nvkm_device_endianness(struct nvkm_device *device) nvkm_device_endianness(struct nvkm_device *device)
{ {
u32 boot1 = nvkm_rd32(device, 0x000004) & 0x01000001;
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
if (!boot1) const bool big_endian = true;
return false;
#else #else
if (boot1) const bool big_endian = false;
return false;
#endif #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; return true;
} }
...@@ -2987,14 +3004,10 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ...@@ -2987,14 +3004,10 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
if (detect) { if (detect) {
/* switch mmio to cpu's native endianness */ /* switch mmio to cpu's native endianness */
if (!nvkm_device_endianness(device)) { if (!nvkm_device_endianness(device)) {
nvkm_wr32(device, 0x000004, 0x01000001); nvdev_error(device,
nvkm_rd32(device, 0x000000); "Couldn't switch GPU to CPUs endianess\n");
if (!nvkm_device_endianness(device)) { ret = -ENOSYS;
nvdev_error(device, goto done;
"GPU not supported on big-endian\n");
ret = -ENOSYS;
goto done;
}
} }
boot0 = nvkm_rd32(device, 0x000000); boot0 = nvkm_rd32(device, 0x000000);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment