Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart

* master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart:
  [AGPGART] drivers/char/agp/sgi-agp.c: check kmalloc() return value
  [AGPGART] Fix PCI-posting flush typo.
  [AGPGART] fix detection of aperture size versus GTT size on G965
  [AGPGART] Remove unnecessary flushes when inserting and removing pages.
  [AGPGART] K8M890 support for amd-k8.
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 8b3317f..1d59e2a 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -225,6 +225,10 @@
 #define I810_GMS_DISABLE	0x00000000
 #define I810_PGETBL_CTL		0x2020
 #define I810_PGETBL_ENABLED	0x00000001
+#define I965_PGETBL_SIZE_MASK	0x0000000e
+#define I965_PGETBL_SIZE_512KB	(0 << 1)
+#define I965_PGETBL_SIZE_256KB	(1 << 1)
+#define I965_PGETBL_SIZE_128KB	(2 << 1)
 #define I810_DRAM_CTL		0x3000
 #define I810_DRAM_ROW_0		0x00000001
 #define I810_DRAM_ROW_0_SDRAM	0x00000001
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 2f2c4ef..9793004 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -650,6 +650,15 @@
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
+	/* VIA K8M890 / K8N890 */
+	{
+	.class          = (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask     = ~0,
+	.vendor         = PCI_VENDOR_ID_VIA,
+	.device         = PCI_DEVICE_ID_VIA_K8M890CE,
+	.subvendor      = PCI_ANY_ID,
+	.subdevice      = PCI_ANY_ID,
+	},
 	/* VIA K8T890 */
 	{
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 883a36a..3491d6f 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -965,6 +965,9 @@
 	if (!bridge)
 		return -EINVAL;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	temp = bridge->current_size;
 
 	switch (bridge->driver->size_type) {
@@ -1016,8 +1019,8 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
-		readl(bridge->gatt_table+j);	/* PCI Posting. */
 	}
+	readl(bridge->gatt_table+j-1);	/* PCI Posting. */
 
 	bridge->driver->tlb_flush(mem);
 	return 0;
@@ -1034,6 +1037,9 @@
 	if (!bridge)
 		return -EINVAL;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	if (type != 0 || mem->type != 0) {
 		/* The generic routines know nothing of memory types */
 		return -EINVAL;
@@ -1042,10 +1048,9 @@
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		writel(bridge->scratch_page, bridge->gatt_table+i);
-		readl(bridge->gatt_table+i);	/* PCI Posting. */
 	}
+	readl(bridge->gatt_table+i-1);	/* PCI Posting. */
 
-	global_cache_flush();
 	bridge->driver->tlb_flush(mem);
 	return 0;
 }
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 555b3a8..ab0a9c0 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -207,6 +207,9 @@
 	int i, j, num_entries;
 	void *temp;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
@@ -221,12 +224,16 @@
 	if (type != 0 || mem->type != 0) {
 		if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
 			/* special insert */
-			global_cache_flush();
+			if (!mem->is_flushed) {
+				global_cache_flush();
+				mem->is_flushed = TRUE;
+			}
+
 			for (i = pg_start; i < (pg_start + mem->page_count); i++) {
 				writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
-				readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
 			}
-			global_cache_flush();
+			readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));	/* PCI Posting. */
+
 			agp_bridge->driver->tlb_flush(mem);
 			return 0;
 		}
@@ -236,14 +243,17 @@
 	}
 
 insert:
-	global_cache_flush();
+	if (!mem->is_flushed) {
+		global_cache_flush();
+		mem->is_flushed = TRUE;
+	}
+
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
 			mem->memory[i], mem->type),
 			intel_i810_private.registers+I810_PTE_BASE+(j*4));
-		readl(intel_i810_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */
 	}
-	global_cache_flush();
+	readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));	/* PCI Posting. */
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -254,12 +264,14 @@
 {
 	int i;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
-		readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
 	}
+	readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
 
-	global_cache_flush();
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -370,6 +382,11 @@
 	struct pci_dev *i830_dev;		/* device one */
 	volatile u8 __iomem *registers;
 	volatile u32 __iomem *gtt;		/* I915G */
+	/* gtt_entries is the number of gtt entries that are already mapped
+	 * to stolen memory.  Stolen memory is larger than the memory mapped
+	 * through gtt_entries, as it includes some reserved space for the BIOS
+	 * popup and for the GTT.
+	 */
 	int gtt_entries;
 } intel_i830_private;
 
@@ -380,14 +397,41 @@
 	u8 rdct;
 	int local = 0;
 	static const int ddt[4] = { 0, 16, 32, 64 };
-	int size;
+	int size; /* reserved space (in kb) at the top of stolen memory */
 
 	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
 
-	/* We obtain the size of the GTT, which is also stored (for some
-	 * reason) at the top of stolen memory. Then we add 4KB to that
-	 * for the video BIOS popup, which is also stored in there. */
-	size = agp_bridge->driver->fetch_size() + 4;
+	if (IS_I965) {
+		u32 pgetbl_ctl;
+
+		pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
+				      &pgetbl_ctl);
+		/* The 965 has a field telling us the size of the GTT,
+		 * which may be larger than what is necessary to map the
+		 * aperture.
+		 */
+		switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+		case I965_PGETBL_SIZE_128KB:
+			size = 128;
+			break;
+		case I965_PGETBL_SIZE_256KB:
+			size = 256;
+			break;
+		case I965_PGETBL_SIZE_512KB:
+			size = 512;
+			break;
+		default:
+			printk(KERN_INFO PFX "Unknown page table size, "
+			       "assuming 512KB\n");
+			size = 512;
+		}
+		size += 4; /* add in BIOS popup space */
+	} else {
+		/* On previous hardware, the GTT size was just what was
+		 * required to map the aperture.
+		 */
+		size = agp_bridge->driver->fetch_size() + 4;
+	}
 
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
 	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -576,6 +620,9 @@
 	int i,j,num_entries;
 	void *temp;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
@@ -598,16 +645,18 @@
 		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
 		return -EINVAL;
 
-	global_cache_flush();	/* FIXME: Necessary ?*/
+	if (!mem->is_flushed) {
+		global_cache_flush();
+		mem->is_flushed = TRUE;
+	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
 			mem->memory[i], mem->type),
 			intel_i830_private.registers+I810_PTE_BASE+(j*4));
-		readl(intel_i830_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */
 	}
+	readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
 
-	global_cache_flush();
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -617,7 +666,8 @@
 {
 	int i;
 
-	global_cache_flush();
+	if (mem->page_count == 0)
+		return 0;
 
 	if (pg_start < intel_i830_private.gtt_entries) {
 		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -626,10 +676,9 @@
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
-		readl(intel_i830_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
 	}
+	readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
 
-	global_cache_flush();
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -686,6 +735,9 @@
 	int i,j,num_entries;
 	void *temp;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
@@ -708,15 +760,17 @@
 		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
 		return -EINVAL;
 
-	global_cache_flush();
+	if (!mem->is_flushed) {
+		global_cache_flush();
+		mem->is_flushed = TRUE;
+	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
 			mem->memory[i], mem->type), intel_i830_private.gtt+j);
-		readl(intel_i830_private.gtt+j);	/* PCI Posting. */
 	}
+	readl(intel_i830_private.gtt+j-1);
 
-	global_cache_flush();
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -726,7 +780,8 @@
 {
 	int i;
 
-	global_cache_flush();
+	if (mem->page_count == 0)
+		return 0;
 
 	if (pg_start < intel_i830_private.gtt_entries) {
 		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -735,30 +790,34 @@
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
-		readl(intel_i830_private.gtt+i);
 	}
+	readl(intel_i830_private.gtt+i-1);
 
-	global_cache_flush();
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
 
-static int intel_i915_fetch_size(void)
+/* Return the aperture size by just checking the resource length.  The effect
+ * described in the spec of the MSAC registers is just changing of the
+ * resource size.
+ */
+static int intel_i9xx_fetch_size(void)
 {
-	struct aper_size_info_fixed *values;
-	u32 temp, offset;
+	int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
+	int aper_size; /* size in megabytes */
+	int i;
 
-#define I915_256MB_ADDRESS_MASK (1<<27)
+	aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
 
-	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+	for (i = 0; i < num_sizes; i++) {
+		if (aper_size == intel_i830_sizes[i].size) {
+			agp_bridge->current_size = intel_i830_sizes + i;
+			agp_bridge->previous_size = agp_bridge->current_size;
+			return aper_size;
+		}
+	}
 
-	pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
-	if (temp & I915_256MB_ADDRESS_MASK)
-		offset = 0;	/* 128MB aperture */
-	else
-		offset = 2;	/* 256MB aperture */
-	agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
-	return values[offset].size;
+	return 0;
 }
 
 /* The intel i915 automatically initializes the agp aperture during POST.
@@ -821,40 +880,9 @@
 	return addr | bridge->driver->masks[type].mask;
 }
 
-static int intel_i965_fetch_size(void)
-{
-       struct aper_size_info_fixed *values;
-       u32 offset = 0;
-       u8 temp;
-
-#define I965_512MB_ADDRESS_MASK (3<<1)
-
-       values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
-       pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
-       temp &= I965_512MB_ADDRESS_MASK;
-       switch (temp) {
-       case 0x00:
-               offset = 0; /* 128MB */
-               break;
-       case 0x06:
-               offset = 3; /* 512MB */
-               break;
-       default:
-       case 0x02:
-               offset = 2; /* 256MB */
-               break;
-       }
-
-       agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
-
-	/* The i965 GTT is always sized as if it had a 512kB aperture size */
-	return 512;
-}
-
 /* The intel i965 automatically initializes the agp aperture during POST.
-+ * Use the memory already set aside for in the GTT.
-+ */
+ * Use the memory already set aside for in the GTT.
+ */
 static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
 {
        int page_order;
@@ -1574,7 +1602,7 @@
 	.num_aperture_sizes	= 4,
 	.needs_scratch_page	= TRUE,
 	.configure		= intel_i915_configure,
-	.fetch_size		= intel_i915_fetch_size,
+	.fetch_size		= intel_i9xx_fetch_size,
 	.cleanup		= intel_i915_cleanup,
 	.tlb_flush		= intel_i810_tlbflush,
 	.mask_memory		= intel_i810_mask_memory,
@@ -1598,7 +1626,7 @@
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = TRUE,
        .configure              = intel_i915_configure,
-       .fetch_size             = intel_i965_fetch_size,
+       .fetch_size             = intel_i9xx_fetch_size,
        .cleanup                = intel_i915_cleanup,
        .tlb_flush              = intel_i810_tlbflush,
        .mask_memory            = intel_i965_mask_memory,
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index d73be4c..902648d 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -281,10 +281,11 @@
 	else
 		return 0;
 
-	sgi_tioca_agp_bridges =
-	    (struct agp_bridge_data **)kmalloc(tioca_gart_found *
-					       sizeof(struct agp_bridge_data *),
-					       GFP_KERNEL);
+	sgi_tioca_agp_bridges = kmalloc(tioca_gart_found *
+					sizeof(struct agp_bridge_data *),
+					GFP_KERNEL);
+	if (!sgi_tioca_agp_bridges)
+		return -ENOMEM;
 
 	j = 0;
 	list_for_each_entry(info, &tioca_list, ca_list) {
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 778e701..f7a416c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1277,6 +1277,7 @@
 #define PCI_DEVICE_ID_VIA_3296_0	0x0296
 #define PCI_DEVICE_ID_VIA_8363_0	0x0305
 #define PCI_DEVICE_ID_VIA_P4M800CE	0x0314
+#define PCI_DEVICE_ID_VIA_K8M890CE	0x0336
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
 #define PCI_DEVICE_ID_VIA_82C561	0x0561