diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/subdev/bios/base.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index 70ca7d5a1aa1..dd111947eb86 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -63,7 +63,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios) struct pci_dev *pdev = nv_device(bios)->pdev; struct device_node *dn; const u32 *data; - int size, i; + int size; dn = pci_device_to_OF_node(pdev); if (!dn) { @@ -210,11 +210,19 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) return; bios->data = kmalloc(bios->size, GFP_KERNEL); - for (i = 0; bios->data && i < bios->size; i += cnt) { - cnt = min((bios->size - i), (u32)4096); - ret = nouveau_acpi_get_bios_chunk(bios->data, i, cnt); - if (ret != cnt) - break; + if (bios->data) { + /* disobey the acpi spec - much faster on at least w530 ... */ + ret = nouveau_acpi_get_bios_chunk(bios->data, 0, bios->size); + if (ret != bios->size || + nvbios_checksum(bios->data, bios->size)) { + /* ... that didn't work, ok, i'll be good now */ + for (i = 0; i < bios->size; i += cnt) { + cnt = min((bios->size - i), (u32)4096); + ret = nouveau_acpi_get_bios_chunk(bios->data, i, cnt); + if (ret != cnt) + break; + } + } } } @@ -358,42 +366,42 @@ nouveau_bios_shadow(struct nouveau_bios *bios) } static u8 -nouveau_bios_rd08(struct nouveau_object *object, u32 addr) +nouveau_bios_rd08(struct nouveau_object *object, u64 addr) { struct nouveau_bios *bios = (void *)object; return bios->data[addr]; } static u16 -nouveau_bios_rd16(struct nouveau_object *object, u32 addr) +nouveau_bios_rd16(struct nouveau_object *object, u64 addr) { struct nouveau_bios *bios = (void *)object; return get_unaligned_le16(&bios->data[addr]); } static u32 -nouveau_bios_rd32(struct nouveau_object *object, u32 addr) +nouveau_bios_rd32(struct nouveau_object *object, u64 addr) { struct nouveau_bios *bios = (void *)object; return get_unaligned_le32(&bios->data[addr]); } static void -nouveau_bios_wr08(struct nouveau_object *object, u32 addr, u8 data) +nouveau_bios_wr08(struct nouveau_object *object, u64 addr, u8 data) { struct nouveau_bios *bios = (void *)object; bios->data[addr] = data; } static void -nouveau_bios_wr16(struct nouveau_object *object, u32 addr, u16 data) +nouveau_bios_wr16(struct nouveau_object *object, u64 addr, u16 data) { struct nouveau_bios *bios = (void *)object; put_unaligned_le16(data, &bios->data[addr]); } static void -nouveau_bios_wr32(struct nouveau_object *object, u32 addr, u32 data) +nouveau_bios_wr32(struct nouveau_object *object, u64 addr, u32 data) { struct nouveau_bios *bios = (void *)object; put_unaligned_le32(data, &bios->data[addr]); |