Browse Source

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
Dave Airlie 12 years ago
parent
commit
ae168d973f

+ 5 - 0
drivers/gpu/drm/nouveau/core/core/gpuobj.c

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

+ 1 - 1
drivers/gpu/drm/nouveau/core/core/mm.c

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

+ 23 - 7
drivers/gpu/drm/nouveau/core/subdev/bios/base.c

@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
 	}
 
 	data = of_get_property(dn, "NVDA,BMP", &size);
-	if (data) {
+	if (data && size) {
 		bios->size = size;
 		bios->data = kmalloc(bios->size, GFP_KERNEL);
 		if (bios->data)
@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
 		goto out;
 
 	bios->size = nv_rd08(bios, 0x700002) * 512;
+	if (!bios->size)
+		goto out;
+
 	bios->data = kmalloc(bios->size, GFP_KERNEL);
 	if (bios->data) {
 		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 */
 	bios->size = nv_rd08(bios, 0x300002) * 512;
+	if (!bios->size)
+		goto out;
+
 	bios->data = kmalloc(bios->size, GFP_KERNEL);
 	if (bios->data) {
 		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;
 	int ret, cnt, i;
-	u8  data[3];
 
-	if (!nouveau_acpi_rom_supported(pdev))
+	if (!nouveau_acpi_rom_supported(pdev)) {
+		bios->data = NULL;
 		return;
+	}
 
 	bios->size = 0;
-	if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
-		bios->size = data[2] * 512;
+	bios->data = kmalloc(4096, GFP_KERNEL);
+	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);
 	for (i = 0; bios->data && i < bios->size; i += cnt) {
@@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 static int
 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");
 		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");
 		/* if a ro image is somewhat bad, it's probably all rubbish */
 		return writeable ? 2 : 1;

+ 4 - 6
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c

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

+ 1 - 0
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c

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

+ 2 - 1
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c

@@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nv04_vmmgr_priv *priv;
 	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,
 					   data, size, pobject);
 	}

+ 2 - 1
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c

@@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nv04_vmmgr_priv *priv;
 	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,
 					   data, size, pobject);
 	}

+ 9 - 5
drivers/gpu/drm/nouveau/nouveau_display.c

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