mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-27 06:30:56 +07:00
drm/nouveau/bios: fetch the vbios from PROM using only aligned 32-bit accesses
Other kind of accesses are unreliable on Kepler cards. As advised by NVIDIA, let's only use 32-bit accesses to fetch the vbios from PROM. This fixes vbios fetching on my nve7 which failed in certain specific conditions. I suggest we Cc stable, for all kernels they still maintain after the big rewrite. Suggested-by: Christian Zander <czander@nvidia.com> Signed-off-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
0e994d6456
commit
18acc6d84e
@ -157,6 +157,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
|
||||
pcireg = 0x001850;
|
||||
access = nv_mask(bios, pcireg, 0x00000001, 0x00000000);
|
||||
|
||||
/* WARNING: PROM accesses should always be 32-bits aligned. Other
|
||||
* accesses work on most chipset but do not on Kepler chipsets
|
||||
*/
|
||||
|
||||
/* bail if no rom signature, with a workaround for a PROM reading
|
||||
* issue on some chipsets. the first read after a period of
|
||||
* inactivity returns the wrong result, so retry the first header
|
||||
@ -164,31 +168,32 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
|
||||
*/
|
||||
i = 16;
|
||||
do {
|
||||
if (nv_rd08(bios, 0x300000) == 0x55)
|
||||
if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55)
|
||||
break;
|
||||
} while (i--);
|
||||
|
||||
if (!i || nv_rd08(bios, 0x300001) != 0xaa)
|
||||
goto out;
|
||||
|
||||
/* additional check (see note below) - read PCI record header */
|
||||
pcir = nv_rd08(bios, 0x300018) |
|
||||
nv_rd08(bios, 0x300019) << 8;
|
||||
if (nv_rd08(bios, 0x300000 + pcir) != 'P' ||
|
||||
nv_rd08(bios, 0x300001 + pcir) != 'C' ||
|
||||
nv_rd08(bios, 0x300002 + pcir) != 'I' ||
|
||||
nv_rd08(bios, 0x300003 + pcir) != 'R')
|
||||
if (!i)
|
||||
goto out;
|
||||
|
||||
/* read entire bios image to system memory */
|
||||
bios->size = nv_rd08(bios, 0x300002) * 512;
|
||||
bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512;
|
||||
if (!bios->size)
|
||||
goto out;
|
||||
|
||||
bios->data = kmalloc(bios->size, GFP_KERNEL);
|
||||
if (bios->data) {
|
||||
for (i = 0; i < bios->size; i++)
|
||||
nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i));
|
||||
for (i = 0; i < bios->size; i+=4)
|
||||
nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i));
|
||||
}
|
||||
|
||||
/* check the PCI record header */
|
||||
pcir = nv_ro16(bios, 0x0018);
|
||||
if (bios->data[pcir + 0] != 'P' ||
|
||||
bios->data[pcir + 1] != 'C' ||
|
||||
bios->data[pcir + 2] != 'I' ||
|
||||
bios->data[pcir + 3] != 'R') {
|
||||
bios->size = 0;
|
||||
kfree(bios->data);
|
||||
}
|
||||
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user