Merge branch 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2.6 into drm-fixes

Fixes from Ben, off note:
ACPI ROM regression fix,
some IGP and AGP regressions fixes from rework fallout.

* 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2.6:
  drm/nouveau/clock: fix missing pll type/addr when matching default entry
  drm/nouveau/fb: fix reporting of memory type on GF8+ IGPs
  drm/nv41/vm: don't init hw pciegart on boards with agp bridge
  drm/nouveau/bios: fetch full 4KiB block to determine ACPI ROM image size
  drm/nouveau: validate vbios size
  drm/nouveau: warn when trying to free mm which is still in use
  drm/nouveau: fix nouveau_mm/nouveau_mm_node leak
  drm/nouveau/bios: improve error handling when reading the vbios from ACPI
  drm/nouveau: handle same-fb page flips
This commit is contained in:
Dave Airlie 2012-10-22 17:50:07 +10:00
Родитель 64acba6a7a 5e5a195ecc
Коммит ae168d973f
8 изменённых файлов: 47 добавлений и 21 удалений

Просмотреть файл

@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)
nv_wo32(gpuobj, i, 0x00000000); nv_wo32(gpuobj, i, 0x00000000);
} }
if (gpuobj->node) {
nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap,
&gpuobj->node);
}
if (gpuobj->heap.block_size) if (gpuobj->heap.block_size)
nouveau_mm_fini(&gpuobj->heap); nouveau_mm_fini(&gpuobj->heap);

Просмотреть файл

@ -236,7 +236,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)
int nodes = 0; int nodes = 0;
list_for_each_entry(node, &mm->nodes, nl_entry) { list_for_each_entry(node, &mm->nodes, nl_entry) {
if (nodes++ == mm->heap_nodes) if (WARN_ON(nodes++ == mm->heap_nodes))
return -EBUSY; return -EBUSY;
} }

Просмотреть файл

@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
} }
data = of_get_property(dn, "NVDA,BMP", &size); data = of_get_property(dn, "NVDA,BMP", &size);
if (data) { if (data && size) {
bios->size = size; bios->size = size;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) if (bios->data)
@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
goto out; goto out;
bios->size = nv_rd08(bios, 0x700002) * 512; bios->size = nv_rd08(bios, 0x700002) * 512;
if (!bios->size)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) { if (bios->data) {
for (i = 0; i < bios->size; i++) for (i = 0; i < bios->size; i++)
@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
/* read entire bios image to system memory */ /* read entire bios image to system memory */
bios->size = nv_rd08(bios, 0x300002) * 512; bios->size = nv_rd08(bios, 0x300002) * 512;
if (!bios->size)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) { if (bios->data) {
for (i = 0; i < bios->size; i++) for (i = 0; i < bios->size; i++)
@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
{ {
struct pci_dev *pdev = nv_device(bios)->pdev; struct pci_dev *pdev = nv_device(bios)->pdev;
int ret, cnt, i; int ret, cnt, i;
u8 data[3];
if (!nouveau_acpi_rom_supported(pdev)) if (!nouveau_acpi_rom_supported(pdev)) {
bios->data = NULL;
return; return;
}
bios->size = 0; bios->size = 0;
if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) bios->data = kmalloc(4096, GFP_KERNEL);
bios->size = data[2] * 512; if (bios->data) {
if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
bios->size = bios->data[2] * 512;
kfree(bios->data);
}
if (!bios->size)
return;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
for (i = 0; bios->data && i < bios->size; i += cnt) { for (i = 0; bios->data && i < bios->size; i += cnt) {
@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
static int static int
nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
{ {
if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
bios->data[1] != 0xAA) {
nv_info(bios, "... signature not found\n"); nv_info(bios, "... signature not found\n");
return 0; return 0;
} }
if (nvbios_checksum(bios->data, bios->data[2] * 512)) { if (nvbios_checksum(bios->data,
min_t(u32, bios->data[2] * 512, bios->size))) {
nv_info(bios, "... checksum invalid\n"); nv_info(bios, "... checksum invalid\n");
/* if a ro image is somewhat bad, it's probably all rubbish */ /* if a ro image is somewhat bad, it's probably all rubbish */
return writeable ? 2 : 1; return writeable ? 2 : 1;

Просмотреть файл

@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
while (map->reg) { while (map->reg) {
if (map->reg == reg && *ver >= 0x20) { if (map->reg == reg && *ver >= 0x20) {
u16 addr = (data += hdr); u16 addr = (data += hdr);
*type = map->type;
while (cnt--) { while (cnt--) {
if (nv_ro32(bios, data) == map->reg) { if (nv_ro32(bios, data) == map->reg)
*type = map->type;
return data; return data;
}
data += *len; data += *len;
} }
return addr; return addr;
@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
while (map->reg) { while (map->reg) {
if (map->type == type && *ver >= 0x20) { if (map->type == type && *ver >= 0x20) {
u16 addr = (data += hdr); u16 addr = (data += hdr);
*reg = map->reg;
while (cnt--) { while (cnt--) {
if (nv_ro32(bios, data) == map->reg) { if (nv_ro32(bios, data) == map->reg)
*reg = map->reg;
return data; return data;
}
data += *len; data += *len;
} }
return addr; return addr;

Просмотреть файл

@ -237,6 +237,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret; return ret;
priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
break; break;
default: default:
ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,

Просмотреть файл

@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_vmmgr_priv *priv; struct nv04_vmmgr_priv *priv;
int ret; int ret;
if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
data, size, pobject); data, size, pobject);
} }

Просмотреть файл

@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_vmmgr_priv *priv; struct nv04_vmmgr_priv *priv;
int ret; int ret;
if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
data, size, pobject); data, size, pobject);
} }

Просмотреть файл

@ -530,9 +530,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
if (ret) if (ret)
goto fail; goto fail;
ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); if (likely(old_bo != new_bo)) {
if (ret) ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
goto fail_unreserve; if (ret)
goto fail_unreserve;
}
return 0; return 0;
@ -551,8 +553,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
nouveau_bo_fence(new_bo, fence); nouveau_bo_fence(new_bo, fence);
ttm_bo_unreserve(&new_bo->bo); ttm_bo_unreserve(&new_bo->bo);
nouveau_bo_fence(old_bo, fence); if (likely(old_bo != new_bo)) {
ttm_bo_unreserve(&old_bo->bo); nouveau_bo_fence(old_bo, fence);
ttm_bo_unreserve(&old_bo->bo);
}
nouveau_bo_unpin(old_bo); nouveau_bo_unpin(old_bo);
} }