diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-08-10 15:36:23 +0300 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-08-10 15:36:23 +0300 |
commit | fdbdfefbabefcdf3f57560163b43fdc4cf95eb2f (patch) | |
tree | 1d0c420d4eaff48cf2486f10dded8d551241ee94 /drivers/gpu/drm/nouveau/nvkm/subdev/bios | |
parent | 6731b0d611a1274f9e785fa0189ac2aeeabd0591 (diff) | |
parent | a0cba2179ea4c1820fce2ee046b6ed90ecc56196 (diff) | |
download | linux-fdbdfefbabefcdf3f57560163b43fdc4cf95eb2f.tar.xz |
Merge branch 'linus' into timers/urgent, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/bios')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 6 |
6 files changed, 88 insertions, 32 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c index e15b9627b07e..f3c30b2a788e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c @@ -26,6 +26,49 @@ #include <subdev/bios.h> #include <subdev/bios/bmp.h> #include <subdev/bios/bit.h> +#include <subdev/bios/image.h> + +static bool +nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) +{ + u32 p = *addr; + + if (*addr > bios->image0_size && bios->imaged_addr) { + *addr -= bios->image0_size; + *addr += bios->imaged_addr; + } + + if (unlikely(*addr + size >= bios->size)) { + nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr); + return false; + } + + return true; +} + +u8 +nvbios_rd08(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 1))) + return bios->data[addr]; + return 0x00; +} + +u16 +nvbios_rd16(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 2))) + return get_unaligned_le16(&bios->data[addr]); + return 0x0000; +} + +u32 +nvbios_rd32(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 4))) + return get_unaligned_le32(&bios->data[addr]); + return 0x00000000; +} u8 nvbios_checksum(const u8 *data, int size) @@ -100,8 +143,9 @@ int nvkm_bios_new(struct nvkm_device *device, int index, struct nvkm_bios **pbios) { struct nvkm_bios *bios; + struct nvbios_image image; struct bit_entry bit_i; - int ret; + int ret, idx = 0; if (!(bios = *pbios = kzalloc(sizeof(*bios), GFP_KERNEL))) return -ENOMEM; @@ -111,6 +155,19 @@ nvkm_bios_new(struct nvkm_device *device, int index, struct nvkm_bios **pbios) if (ret) return ret; + /* Some tables have weird pointers that need adjustment before + * they're dereferenced. I'm not entirely sure why... + */ + if (nvbios_image(bios, idx++, &image)) { + bios->image0_size = image.size; + while (nvbios_image(bios, idx++, &image)) { + if (image.type == 0xe0) { + bios->imaged_addr = image.base; + break; + } + } + } + /* detect type of vbios we're dealing with */ bios->bmp_offset = nvbios_findstr(bios->data, bios->size, "\xff\x7f""NV\0", 5); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c index 05332476354a..d89e78c4e689 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c @@ -40,6 +40,7 @@ nvbios_dp_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) case 0x30: case 0x40: case 0x41: + case 0x42: *hdr = nvbios_rd08(bios, data + 0x01); *len = nvbios_rd08(bios, data + 0x02); *cnt = nvbios_rd08(bios, data + 0x03); @@ -70,6 +71,7 @@ nvbios_dpout_entry(struct nvkm_bios *bios, u8 idx, break; case 0x40: case 0x41: + case 0x42: *hdr = nvbios_rd08(bios, data + 0x04); *cnt = 0; *len = 0; @@ -109,6 +111,7 @@ nvbios_dpout_parse(struct nvkm_bios *bios, u8 idx, break; case 0x40: case 0x41: + case 0x42: info->flags = nvbios_rd08(bios, data + 0x04); info->script[0] = nvbios_rd16(bios, data + 0x05); info->script[1] = nvbios_rd16(bios, data + 0x07); @@ -180,6 +183,11 @@ nvbios_dpcfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx, info->pe = nvbios_rd08(bios, data + 0x02); info->tx_pu = nvbios_rd08(bios, data + 0x03); break; + case 0x42: + info->dc = nvbios_rd08(bios, data + 0x00); + info->pe = nvbios_rd08(bios, data + 0x01); + info->tx_pu = nvbios_rd08(bios, data + 0x02); + break; default: data = 0x0000; break; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c index 74b14cf09308..1dbff7aeafec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c @@ -68,11 +68,16 @@ nvbios_imagen(struct nvkm_bios *bios, struct nvbios_image *image) bool nvbios_image(struct nvkm_bios *bios, int idx, struct nvbios_image *image) { + u32 imaged_addr = bios->imaged_addr; memset(image, 0x00, sizeof(*image)); + bios->imaged_addr = 0; do { image->base += image->size; - if (image->last || !nvbios_imagen(bios, image)) + if (image->last || !nvbios_imagen(bios, image)) { + bios->imaged_addr = imaged_addr; return false; + } } while(idx--); + bios->imaged_addr = imaged_addr; return true; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c index 91a7dc56e406..2ca23a9157ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c @@ -77,15 +77,17 @@ g84_pll_mapping[] = { {} }; -static u16 +static u32 pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { struct bit_entry bit_C; - u16 data = 0x0000; + u32 data = 0x0000; if (!bit_entry(bios, 'C', &bit_C)) { if (bit_C.version == 1 && bit_C.length >= 10) data = nvbios_rd16(bios, bit_C.offset + 8); + if (bit_C.version == 2 && bit_C.length >= 4) + data = nvbios_rd32(bios, bit_C.offset + 0); if (data) { *ver = nvbios_rd08(bios, data + 0); *hdr = nvbios_rd08(bios, data + 1); @@ -137,12 +139,12 @@ pll_map(struct nvkm_bios *bios) } } -static u16 +static u32 pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) { struct pll_mapping *map; u8 hdr, cnt; - u16 data; + u32 data; data = pll_limits_table(bios, ver, &hdr, &cnt, len); if (data && *ver >= 0x30) { @@ -160,7 +162,7 @@ pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) map = pll_map(bios); while (map && map->reg) { if (map->reg == reg && *ver >= 0x20) { - u16 addr = (data += hdr); + u32 addr = (data += hdr); *type = map->type; while (cnt--) { if (nvbios_rd32(bios, data) == map->reg) @@ -179,12 +181,12 @@ pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) return 0x0000; } -static u16 +static u32 pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) { struct pll_mapping *map; u8 hdr, cnt; - u16 data; + u32 data; data = pll_limits_table(bios, ver, &hdr, &cnt, len); if (data && *ver >= 0x30) { @@ -202,7 +204,7 @@ pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) map = pll_map(bios); while (map && map->reg) { if (map->type == type && *ver >= 0x20) { - u16 addr = (data += hdr); + u32 addr = (data += hdr); *reg = map->reg; while (cnt--) { if (nvbios_rd32(bios, data) == map->reg) @@ -228,7 +230,7 @@ nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) struct nvkm_device *device = subdev->device; u8 ver, len; u32 reg = type; - u16 data; + u32 data; if (type > PLL_MAX) { reg = type; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c index c268e5afe852..b4a308f3cf7b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c @@ -26,21 +26,6 @@ #include <subdev/bios/image.h> #include <subdev/bios/pmu.h> -static u32 -weirdo_pointer(struct nvkm_bios *bios, u32 data) -{ - struct nvbios_image image; - int idx = 0; - if (nvbios_image(bios, idx++, &image)) { - data -= image.size; - while (nvbios_image(bios, idx++, &image)) { - if (image.type == 0xe0) - return image.base + data; - } - } - return 0; -} - u32 nvbios_pmuTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { @@ -50,7 +35,7 @@ nvbios_pmuTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'p', &bit_p)) { if (bit_p.version == 2 && bit_p.length >= 4) data = nvbios_rd32(bios, bit_p.offset + 0x00); - if ((data = weirdo_pointer(bios, data))) { + if (data) { *ver = nvbios_rd08(bios, data + 0x00); /* maybe? */ *hdr = nvbios_rd08(bios, data + 0x01); *len = nvbios_rd08(bios, data + 0x02); @@ -97,8 +82,7 @@ nvbios_pmuRm(struct nvkm_bios *bios, u8 type, struct nvbios_pmuR *info) u32 data; memset(info, 0x00, sizeof(*info)); while ((data = nvbios_pmuEp(bios, idx++, &ver, &hdr, &pmuE))) { - if ( pmuE.type == type && - (data = weirdo_pointer(bios, pmuE.data))) { + if (pmuE.type == type && (data = pmuE.data)) { info->init_addr_pmu = nvbios_rd32(bios, data + 0x08); info->args_addr_pmu = nvbios_rd32(bios, data + 0x0c); info->boot_addr = data + 0x30; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index d0ae7454764e..b57c370c725d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -30,11 +30,11 @@ nvbios_rammapTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) { struct bit_entry bit_P; - u16 rammap = 0x0000; + u32 rammap = 0x0000; if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) - rammap = nvbios_rd16(bios, bit_P.offset + 4); + rammap = nvbios_rd32(bios, bit_P.offset + 4); if (rammap) { *ver = nvbios_rd08(bios, rammap + 0); @@ -61,7 +61,7 @@ nvbios_rammapEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { u8 snr, ssz; - u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz); + u32 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz); if (rammap && idx < *cnt) { rammap = rammap + *hdr + (idx * (*len + (snr * ssz))); *hdr = *len; |