bk://linux-dj.bkbits.net/agpgart
davej@redhat.com|ChangeSet|20040527132839|65108 davej

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/28 16:57:21-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/05/28 16:57:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/28 13:14:32-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/05/28 13:14:29-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/27 14:28:39+01:00 davej@redhat.com 
#   [AGPGART] SIS AGP updates
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   
#   From: "Heilmann, Oliver" <Oliver.Heilmann@drkw.com>
#                                                                                            
#   * renamed sis_648_enable to sis_delayed_enable and removed chipset
#     references
#                                                                                            
#   * All chipsets that require the sis delay-hack are listed in
#     sis_broken_chipsets (and no other place).
#                                                                                            
#   * There are two new module options to force agp3-spec compliant
#     initialisation and/or the delay hack.  As I only have a 648FX chipset to
#     test on, I figured this might be useful to experiment with on other
#     chipsets (i.e.746[FX]).
#                                                                                            
#   Basically, if you have an  SiS chipset and your machine freezes when you
#   start X, try the -agp_sis_force_delay=1 option. If this fixes your
#   problem add your PCI ID to sis_broken_chipsets in sis-agp.c
#   Note to 746[FX] people: I'm still not sure what the differences between
#   the two 746 versions and the 648 series are. If this patch does not work
#   for you try playing with the agp_sis_agp_spec module option. Any
#   feedback is greatly appreciated.
# 
# drivers/char/agp/sis-agp.c
#   2004/05/27 14:28:32+01:00 davej@redhat.com +36 -24
#   [AGPGART] SIS AGP updates
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   
#   From: "Heilmann, Oliver" <Oliver.Heilmann@drkw.com>
#                                                                                            
#   * renamed sis_648_enable to sis_delayed_enable and removed chipset
#     references
#                                                                                            
#   * All chipsets that require the sis delay-hack are listed in
#     sis_broken_chipsets (and no other place).
#                                                                                            
#   * There are two new module options to force agp3-spec compliant
#     initialisation and/or the delay hack.  As I only have a 648FX chipset to
#     test on, I figured this might be useful to experiment with on other
#     chipsets (i.e.746[FX]).
#                                                                                            
#   Basically, if you have an  SiS chipset and your machine freezes when you
#   start X, try the -agp_sis_force_delay=1 option. If this fixes your
#   problem add your PCI ID to sis_broken_chipsets in sis-agp.c
#   Note to 746[FX] people: I'm still not sure what the differences between
#   the two 746 versions and the 648 series are. If this patch does not work
#   for you try playing with the agp_sis_agp_spec module option. Any
#   feedback is greatly appreciated.
# 
# ChangeSet
#   2004/05/24 11:19:17-07:00 akpm@bix.(none) 
#   Merge bk://linux-dj.bkbits.net/agpgart
#   into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/05/24 11:19:14-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/23 13:02:45+01:00 davej@redhat.com 
#   [AGPGART] Fix a potential leak in intel driver.
#   It's not leaking anything currently, as agp_alloc_bridge() doesn't do any
#   actual allocations right now, but if/when things get changed to support
#   multiple bridges, these error paths need to free up the allocation.
#    
# 
# drivers/char/agp/intel-agp.c
#   2004/05/23 13:02:38+01:00 davej@redhat.com +6 -3
#   [AGPGART] Fix a potential leak in intel driver.
#   It's not leaking anything currently, as agp_alloc_bridge() doesn't do any
#   actual allocations right now, but if/when things get changed to support
#   multiple bridges, these error paths need to free up the allocation.
#    
# 
# ChangeSet
#   2004/05/23 12:38:50+01:00 davej@redhat.com 
#   [AGPGART] Add ID for Intel E7501 chipset.
# 
# include/linux/pci_ids.h
#   2004/05/23 12:38:43+01:00 davej@redhat.com +1 -0
#   [AGPGART] Add ID for Intel E7501 chipset.
# 
# drivers/char/agp/intel-agp.c
#   2004/05/23 12:38:43+01:00 davej@redhat.com +2 -1
#   [AGPGART] Add ID for Intel E7501 chipset.
# 
# ChangeSet
#   2004/05/19 15:47:31+01:00 davej@redhat.com 
#   [AGPGART] Remove lots of trailing whitespace from amd64 gart driver.
#   No code changes.
# 
# drivers/char/agp/amd64-agp.c
#   2004/05/19 15:47:25+01:00 davej@redhat.com +67 -69
#   [AGPGART] Remove lots of trailing whitespace from amd64 gart driver.
#   No code changes.
# 
# ChangeSet
#   2004/05/19 15:43:11+01:00 davej@redhat.com 
#   [AGPGART] Add missing SIS755 ID to AMD64 AGP driver
#   From: Andi Kleen
# 
# drivers/char/agp/amd64-agp.c
#   2004/05/19 15:43:05+01:00 davej@redhat.com +9 -0
#   [AGPGART] Add missing SIS755 ID to AMD64 AGP driver
#   From: Andi Kleen
# 
# ChangeSet
#   2004/05/19 15:41:33+01:00 davej@redhat.com 
#   [AGPGART] Make the Nvidia AGP driver only announce PCI IDs it actually supports.
#   From: Andi Kleen
# 
# drivers/char/agp/nvidia-agp.c
#   2004/05/19 15:41:26+01:00 davej@redhat.com +9 -1
#   [AGPGART] Make the Nvidia AGP driver only announce PCI IDs it actually supports.
#   From: Andi Kleen
# 
# ChangeSet
#   2004/05/19 15:40:43+01:00 davej@redhat.com 
#   [AGPGART] Make the VIA AGP driver only announce PCI IDs it actually supports.
#   Avoids dups with the AMD64 driver.
#   From: Andi Kleen
# 
# drivers/char/agp/via-agp.c
#   2004/05/19 15:40:36+01:00 davej@redhat.com +37 -21
#   [AGPGART] Make the VIA AGP driver only announce PCI IDs it actually supports.
#   Avoids dups with the AMD64 driver.
#   From: Andi Kleen
# 
# ChangeSet
#   2004/05/19 15:39:09+01:00 davej@redhat.com 
#   [AGPGART] kill trailing whitespace & indentation fixes.
# 
# drivers/char/agp/amd-k7-agp.c
#   2004/05/19 15:39:03+01:00 davej@redhat.com +9 -9
#   [AGPGART] kill trailing whitespace & indentation fixes.
# 
# ChangeSet
#   2004/05/19 15:36:10+01:00 davej@redhat.com 
#   [AGPGART] Make the driver only announce the PCI IDs it actually supports.
#   This avoids dups with the amd64 driver.
#   From: Andi Kleen
# 
# drivers/char/agp/amd-k7-agp.c
#   2004/05/19 15:36:03+01:00 davej@redhat.com +24 -15
#   [AGPGART] Make the driver only announce the PCI IDs it actually supports.
#   This avoids dups with the amd64 driver.
#   From: Andi Kleen
# 
# ChangeSet
#   2004/05/17 16:29:24+01:00 davej@redhat.com 
#   [AGPGART] Don't abort if Intel-agp can't find AGP capability.
#   Some bridges don't have this set it seems.
#   Detective work, and fixing by Andi Kleen.
# 
# drivers/char/agp/intel-agp.c
#   2004/05/17 16:29:18+01:00 davej@redhat.com +0 -2
#   [AGPGART] Don't abort if Intel-agp can't find AGP capability.
#   Some bridges don't have this set it seems.
#   Detective work, and fixing by Andi Kleen.
# 
# ChangeSet
#   2004/05/12 11:50:18+01:00 davej@redhat.com 
#   [AGPGART] Various Intel/EM64T AGP fixes.
#   
#   From Andi Kleen.
#   
#   - Add full PCI IDs to the module table for intel-agp and intel-mch-agp.
#   Don't use PCI_ANY_ID for device, since the drivers cannot handle unknown
#   devices anyways.
#   This fixes the problems with them loading both when compiled in and
#   also helps external tools that use the module PCI table to find the
#   correct driver.
#   - Remove wrong hack in intel-mch-agp that checked for long mode.
#   EM64T capability has nothing to do with the MCH version.
#   To avoid double probing the fix above is better.
#   - Handle the case of no AGP capability (unlikely, but better to handle it)
# 
# drivers/char/agp/intel-mch-agp.c
#   2004/05/12 11:50:12+01:00 davej@redhat.com +11 -4
#   [AGPGART] Various Intel/EM64T AGP fixes.
#   
#   From Andi Kleen.
#   
#   - Add full PCI IDs to the module table for intel-agp and intel-mch-agp.
#   Don't use PCI_ANY_ID for device, since the drivers cannot handle unknown
#   devices anyways.
#   This fixes the problems with them loading both when compiled in and
#   also helps external tools that use the module PCI table to find the
#   correct driver.
#   - Remove wrong hack in intel-mch-agp that checked for long mode.
#   EM64T capability has nothing to do with the MCH version.
#   To avoid double probing the fix above is better.
#   - Handle the case of no AGP capability (unlikely, but better to handle it)
# 
# drivers/char/agp/intel-agp.c
#   2004/05/12 11:50:12+01:00 davej@redhat.com +32 -8
#   [AGPGART] Various Intel/EM64T AGP fixes.
#   
#   From Andi Kleen.
#   
#   - Add full PCI IDs to the module table for intel-agp and intel-mch-agp.
#   Don't use PCI_ANY_ID for device, since the drivers cannot handle unknown
#   devices anyways.
#   This fixes the problems with them loading both when compiled in and
#   also helps external tools that use the module PCI table to find the
#   correct driver.
#   - Remove wrong hack in intel-mch-agp that checked for long mode.
#   EM64T capability has nothing to do with the MCH version.
#   To avoid double probing the fix above is better.
#   - Handle the case of no AGP capability (unlikely, but better to handle it)
# 
# ChangeSet
#   2004/04/16 20:16:10+01:00 davej@redhat.com 
#   [AGPGART] If ati_create_gatt_pages() fails, don't propagate an address we've freed.
# 
# drivers/char/agp/ati-agp.c
#   2004/04/16 20:16:04+01:00 davej@redhat.com +1 -0
#   [AGPGART] If ati_create_gatt_pages() fails, don't propagate an address we've freed.
# 
diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
--- a/drivers/char/agp/amd-k7-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/amd-k7-agp.c	2004-05-31 16:01:10 -07:00
@@ -20,6 +20,8 @@
 #define AMD_TLBFLUSH	0x0c	/* In mmio region (32-bit register) */
 #define AMD_CACHEENTRY	0x10	/* In mmio region (32-bit register) */
 
+static struct pci_device_id agp_amdk7_pci_table[];
+
 struct amd_page_map {
 	unsigned long *real;
 	unsigned long *remapped;
@@ -41,7 +43,7 @@
 
 	SetPageReserved(virt_to_page(page_map->real));
 	global_cache_flush();
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
+	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
 		ClearPageReserved(virt_to_page(page_map->real));
@@ -90,7 +92,7 @@
 	int retval = 0;
 	int i;
 
-	tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), 
+	tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *),
 			 GFP_KERNEL);
 	if (tables == NULL)
 		return -ENOMEM;
@@ -124,7 +126,7 @@
 #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
 #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
 	GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
-#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) 
+#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
 #define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
 	GET_PAGE_DIR_IDX(addr)]->remapped)
 
@@ -174,7 +176,7 @@
 static int amd_free_gatt_table(void)
 {
 	struct amd_page_map page_dir;
-   
+
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
 	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
 
@@ -224,9 +226,9 @@
 
 	/* Write the Sync register */
 	pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL, 0x80);
-   
-   	/* Set indexing mode */
-   	pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00);
+
+	/* Set indexing mode */
+	pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00);
 
 	/* Write the enable register */
 	enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE);
@@ -394,7 +396,6 @@
 static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
-	struct agp_device_ids *devs = amd_agp_device_ids;
 	struct agp_bridge_data *bridge;
 	u8 cap_ptr;
 	int j;
@@ -403,19 +404,10 @@
 	if (!cap_ptr)
 		return -ENODEV;
 
-	for (j = 0; devs[j].chipset_name; j++) {
-		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected AMD %s chipset\n",
-					devs[j].chipset_name);
-			goto found;
-		}
-	}
-
-	printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)\n",
-		    pdev->device);
-	return -ENODEV;
+	j = ent - agp_amdk7_pci_table;
+	printk(KERN_INFO PFX "Detected AMD %s chipset\n",
+	       amd_agp_device_ids[j].chipset_name);
 
-found:
 	bridge = agp_alloc_bridge();
 	if (!bridge)
 		return -ENOMEM;
@@ -442,12 +434,29 @@
 	agp_put_bridge(bridge);
 }
 
+/* must be the same order as name table above */
 static struct pci_device_id agp_amdk7_pci_table[] = {
 	{
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
 	.class_mask	= ~0,
 	.vendor		= PCI_VENDOR_ID_AMD,
-	.device		= PCI_ANY_ID,
+	.device		= PCI_DEVICE_ID_AMD_FE_GATE_7006,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_AMD,
+	.device		= PCI_DEVICE_ID_AMD_FE_GATE_700E,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_AMD,
+	.device		= PCI_DEVICE_ID_AMD_FE_GATE_700C,
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
--- a/drivers/char/agp/amd64-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/amd64-agp.c	2004-05-31 16:01:10 -07:00
@@ -1,7 +1,7 @@
-/* 
+/*
  * Copyright 2001-2003 SuSE Labs.
  * Distributed under the GNU public license, v2.
- * 
+ *
  * This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge.
  * It also includes support for the AMD 8151 AGP bridge,
  * although it doesn't actually do much, as all the real
@@ -194,7 +194,7 @@
 
 	/* keep CPU's coherent. */
 	flush_amd64_tlb (hammer);
-	
+
 	return aper_base;
 }
 
@@ -261,53 +261,53 @@
 
 /* Some basic sanity checks for the aperture. */
 static int __devinit aperture_valid(u64 aper, u32 size)
-{ 
+{
 	u32 pfn, c;
-	if (aper == 0) { 
+	if (aper == 0) {
 		printk(KERN_ERR PFX "No aperture\n");
-		return 0; 
+		return 0;
 	}
 	if (size < 32*1024*1024) {
 		printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
 		return 0;
 	}
-	if (aper + size > 0xffffffff) { 
-		printk(KERN_ERR PFX "Aperture out of bounds\n"); 
+	if (aper + size > 0xffffffff) {
+		printk(KERN_ERR PFX "Aperture out of bounds\n");
 		return 0;
-	} 
+	}
 	pfn = aper >> PAGE_SHIFT;
-	for (c = 0; c < size/PAGE_SIZE; c++) { 
+	for (c = 0; c < size/PAGE_SIZE; c++) {
 		if (!pfn_valid(pfn + c))
 			break;
-		if (!PageReserved(pfn_to_page(pfn + c))) { 
+		if (!PageReserved(pfn_to_page(pfn + c))) {
 			printk(KERN_ERR PFX "Aperture pointing to RAM\n");
 			return 0;
 		}
 	}
 
 	/* Request the Aperture. This catches cases when someone else
-	   already put a mapping in there - happens with some very broken BIOS 
+	   already put a mapping in there - happens with some very broken BIOS
 
-	   Maybe better to use pci_assign_resource/pci_enable_device instead trusting
-	   the bridges? */
+	   Maybe better to use pci_assign_resource/pci_enable_device instead
+	   trusting the bridges? */
 	if (!aperture_resource &&
 	    !(aperture_resource = request_mem_region(aper, size, "aperture"))) {
-		printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n"); 
+		printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n");
 		return 0;
 	}
 	return 1;
-} 
+}
 
-/* 
+/*
  * W*s centric BIOS sometimes only set up the aperture in the AGP
- * bridge, not the northbridge. On AMD64 this is handled early 
+ * bridge, not the northbridge. On AMD64 this is handled early
  * in aperture.c, but when GART_IOMMU is not enabled or we run
- * on a 32bit kernel this needs to be redone. 
+ * on a 32bit kernel this needs to be redone.
  * Unfortunately it is impossible to fix the aperture here because it's too late
  * to allocate that much memory. But at least error out cleanly instead of
  * crashing.
- */ 
-static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, 
+ */
+static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
 								 u16 cap)
 {
 	u32 aper_low, aper_hi;
@@ -316,38 +316,38 @@
 	u32 nb_order, nb_base;
 	u16 apsize;
 
-	pci_read_config_dword(nb, 0x90, &nb_order); 
+	pci_read_config_dword(nb, 0x90, &nb_order);
 	nb_order = (nb_order >> 1) & 7;
-	pci_read_config_dword(nb, 0x94, &nb_base); 
-	nb_aper = nb_base << 25;	
-	if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) { 
+	pci_read_config_dword(nb, 0x94, &nb_base);
+	nb_aper = nb_base << 25;
+	if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
 		return 0;
 	}
 
 	/* Northbridge seems to contain crap. Try the AGP bridge. */
 
-	pci_read_config_word(agp, cap+0x14, &apsize); 
-	if (apsize == 0xffff) 
-		return -1; 
+	pci_read_config_word(agp, cap+0x14, &apsize);
+	if (apsize == 0xffff)
+		return -1;
 
 	apsize &= 0xfff;
 	/* Some BIOS use weird encodings not in the AGPv3 table. */
-	if (apsize & 0xff) 
-		apsize |= 0xf00; 
-	order = 7 - hweight16(apsize); 
+	if (apsize & 0xff)
+		apsize |= 0xf00;
+	order = 7 - hweight16(apsize);
 
 	pci_read_config_dword(agp, 0x10, &aper_low);
 	pci_read_config_dword(agp, 0x14, &aper_hi);
-	aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); 
+	aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
 	printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order);
 	if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order))
-		return -1; 
-	
-	pci_write_config_dword(nb, 0x90, order << 1); 
-	pci_write_config_dword(nb, 0x94, aper >> 25); 
+		return -1;
+
+	pci_write_config_dword(nb, 0x90, order << 1);
+	pci_write_config_dword(nb, 0x94, aper >> 25);
 
 	return 0;
-} 
+}
 
 static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
 {
@@ -355,19 +355,19 @@
 	int i = 0;
 
 	/* cache pci_devs of northbridges. */
-	while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) 
+	while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
 			!= NULL) {
-		if (i == MAX_HAMMER_GARTS) { 
+		if (i == MAX_HAMMER_GARTS) {
 			printk(KERN_ERR PFX "Too many northbridges for AGP\n");
 			return -1;
 		}
-		if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { 
+		if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
 			printk(KERN_ERR PFX "No usable aperture found.\n");
-#ifdef __x86_64__ 
+#ifdef __x86_64__
 			/* should port this to i386 */
 			printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n");
-#endif 
-			return -1;  
+#endif
+			return -1;
 		}
 		hammers[i++] = loop_dev;
 	}
@@ -377,8 +377,7 @@
 
 /* Handle AMD 8151 quirks */
 static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
-
-{		
+{
 	char *revstring;
 	u8 rev_id;
 
@@ -417,12 +416,12 @@
 
 /* Handle shadow device of the Nvidia NForce3 */
 /* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */
-static int __devinit nforce3_agp_init(struct pci_dev *pdev) 
-{ 
+static int __devinit nforce3_agp_init(struct pci_dev *pdev)
+{
 	u32 tmp, apbase, apbar, aplimit;
-	struct pci_dev *dev1; 
+	struct pci_dev *dev1;
 	int i;
-	unsigned size = amd64_fetch_size(); 
+	unsigned size = amd64_fetch_size();
 
 	printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n");
 
@@ -432,17 +431,17 @@
 			"nForce3 chipset, but could not find "
 			"the secondary device.\n");
 		return -ENODEV;
-	}	
+	}
 
-	for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) 
+	for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++)
 		if (nforce3_sizes[i].size == size)
-			break; 
+			break;
 
 	if (i == ARRAY_SIZE(nforce3_sizes)) {
-		printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); 
-		return -ENODEV; 
+		printk(KERN_INFO PFX "No NForce3 size found for %d\n", size);
+		return -ENODEV;
 	}
-	
+
 	pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp);
 	tmp &= ~(0xf);
 	tmp |= nforce3_sizes[i].size_value;
@@ -491,8 +490,7 @@
 	    pdev->device == PCI_DEVICE_ID_AMD_8151_0) {
 		amd8151_init(pdev, bridge);
 	} else {
-		printk(KERN_INFO PFX "Detected AGP bridge %x\n",
-			pdev->devfn);
+		printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn);
 	}
 
 	bridge->driver = &amd_8151_driver;
@@ -507,10 +505,10 @@
 		return -ENODEV;
 	}
 
-	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { 
+	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
 		int ret = nforce3_agp_init(pdev);
-		if (ret) { 
-			agp_put_bridge(bridge); 
+		if (ret) {
+			agp_put_bridge(bridge);
 			return ret;
 		}
 	}
@@ -523,8 +521,8 @@
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-	release_mem_region(virt_to_phys(bridge->gatt_table_real), 
-			   amd64_aperture_sizes[bridge->aperture_size_idx].size); 
+	release_mem_region(virt_to_phys(bridge->gatt_table_real),
+			   amd64_aperture_sizes[bridge->aperture_size_idx].size);
 	agp_remove_bridge(bridge);
 	agp_put_bridge(bridge);
 }
@@ -581,6 +579,15 @@
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
+	/* SIS 755 */
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_SI,
+	.device		= PCI_DEVICE_ID_SI_755,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
 	{ }
 };
 
@@ -600,15 +607,15 @@
 	int err = 0;
 	if (agp_off)
 		return -EINVAL;
-	if (pci_module_init(&agp_amd64_pci_driver) > 0) { 
+	if (pci_module_init(&agp_amd64_pci_driver) > 0) {
 		struct pci_dev *dev;
-		if (!agp_try_unsupported && !agp_try_unsupported_boot) { 
+		if (!agp_try_unsupported && !agp_try_unsupported_boot) {
 			printk(KERN_INFO PFX "No supported AGP bridge found.\n");
-#ifdef MODULE			
+#ifdef MODULE
 			printk(KERN_INFO PFX "You can try agp_try_unsupported=1\n");
 #else
 			printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n");
-#endif			
+#endif
 			return -ENODEV;
 		}
 
@@ -622,12 +629,12 @@
 		while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) {
 			if (!pci_find_capability(dev, PCI_CAP_ID_AGP))
 				continue;
-			/* Only one bridge supported right now */	
+			/* Only one bridge supported right now */
 			if (agp_amd64_probe(dev, NULL) == 0) {
 				err = 0;
 				break;
-			}	
-		}		
+			}
+		}
 	}
 	return err;
 }
diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
--- a/drivers/char/agp/ati-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/ati-agp.c	2004-05-31 16:01:10 -07:00
@@ -131,6 +131,7 @@
 				i--;
 			}
 			kfree (tables);
+			tables = NULL;
 			retval = -ENOMEM;
 			break;
 		}
diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
--- a/drivers/char/agp/intel-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/intel-agp.c	2004-05-31 16:01:10 -07:00
@@ -1233,7 +1233,7 @@
 				name);
 		return 0;
 	}
-	
+
 	intel_i810_private.i810_dev = i810_dev;
 	return 1;
 }
@@ -1384,6 +1384,7 @@
 	default:
 		printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
 			    pdev->device);
+		agp_put_bridge(bridge);
 		return -ENODEV;
 	};
 
@@ -1406,7 +1407,8 @@
 	if (!r->start && r->end) {
 		if(pci_assign_resource(pdev, 0)) {
 			printk(KERN_ERR PFX "could not assign resource 0\n");
-			return (-ENODEV);
+			agp_put_bridge(bridge);
+			return -ENODEV;
 		}
 	}
 
@@ -1417,7 +1419,8 @@
 	*/
 	if (pci_enable_device(pdev)) {
 		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
-		return (-ENODEV);
+		agp_put_bridge(bridge);
+		return -ENODEV;
 	}
 
 	/* Fill in the mode register */
@@ -1462,14 +1465,37 @@
 }
 
 static struct pci_device_id agp_intel_pci_table[] = {
-	{
-	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-	.class_mask	= ~0,
-	.vendor		= PCI_VENDOR_ID_INTEL,
-	.device		= PCI_ANY_ID,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-	},
+#define ID(x)						\
+	{ 						\
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),	\
+	.class_mask	= ~0,				\
+	.vendor		= PCI_VENDOR_ID_INTEL,		\
+	.device		= x,				\
+	.subvendor	= PCI_ANY_ID,			\
+	.subdevice	= PCI_ANY_ID,			\
+	}
+	ID(PCI_DEVICE_ID_INTEL_82443LX_0),
+	ID(PCI_DEVICE_ID_INTEL_82443BX_0),
+	ID(PCI_DEVICE_ID_INTEL_82443GX_0),
+	ID(PCI_DEVICE_ID_INTEL_82810_MC1),
+	ID(PCI_DEVICE_ID_INTEL_82810_MC3),
+	ID(PCI_DEVICE_ID_INTEL_82810E_MC),
+	ID(PCI_DEVICE_ID_INTEL_82815_MC),
+	ID(PCI_DEVICE_ID_INTEL_82820_HB),
+	ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
+	ID(PCI_DEVICE_ID_INTEL_82830_HB),
+	ID(PCI_DEVICE_ID_INTEL_82840_HB),
+	ID(PCI_DEVICE_ID_INTEL_82845_HB),
+	ID(PCI_DEVICE_ID_INTEL_82845G_HB),
+	ID(PCI_DEVICE_ID_INTEL_82850_HB),
+	ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
+	ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
+	ID(PCI_DEVICE_ID_INTEL_82860_HB),
+	ID(PCI_DEVICE_ID_INTEL_82865_HB),
+	ID(PCI_DEVICE_ID_INTEL_82875_HB),
+	ID(PCI_DEVICE_ID_INTEL_7505_0),
+	ID(PCI_DEVICE_ID_INTEL_7501_0),
+	ID(PCI_DEVICE_ID_INTEL_7205_0),
 	{ }
 };
 
diff -Nru a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
--- a/drivers/char/agp/intel-mch-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/intel-mch-agp.c	2004-05-31 16:01:10 -07:00
@@ -491,10 +491,9 @@
 	char *name = "(unknown)";
 	u8 cap_ptr = 0;
 
-	if (!boot_cpu_has(X86_FEATURE_LM))
-		return -ENODEV;
-
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr) 
+		return -ENODEV;
 
 	bridge = agp_alloc_bridge();
 	if (!bridge)
@@ -590,7 +589,15 @@
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
 	.class_mask	= ~0,
 	.vendor		= PCI_VENDOR_ID_INTEL,
-	.device		= PCI_ANY_ID,
+	.device		= PCI_DEVICE_ID_INTEL_82865_HB,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_INTEL,
+	.device		= PCI_DEVICE_ID_INTEL_82875_HB,
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
--- a/drivers/char/agp/nvidia-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/nvidia-agp.c	2004-05-31 16:01:10 -07:00
@@ -380,7 +380,15 @@
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
 	.class_mask	= ~0,
 	.vendor		= PCI_VENDOR_ID_NVIDIA,
-	.device		= PCI_ANY_ID,
+	.device		= PCI_DEVICE_ID_NVIDIA_NFORCE,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_NVIDIA,
+	.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2,
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/sis-agp.c	2004-05-31 16:01:10 -07:00
@@ -13,6 +13,8 @@
 #define SIS_TLBCNTRL	0x97
 #define SIS_TLBFLUSH	0x98
 
+static int __devinitdata agp_sis_force_delay = 0;
+static int __devinitdata agp_sis_agp_spec = -1;
 
 static int sis_fetch_size(void)
 {
@@ -67,7 +69,7 @@
 			      (previous_size->size_value & ~(0x03)));
 }
 
-static void sis_648_enable(u32 mode)
+static void sis_delayed_enable(u32 mode)
 {
 	struct pci_dev *device = NULL;
 	u32 command;
@@ -94,13 +96,12 @@
 		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
 
 		/*
-		 * Weird: on 648(fx) and 746(fx) chipsets any rate change in the target
+		 * Weird: on some sis chipsets any rate change in the target
 		 * command register triggers a 5ms screwup during which the master
 		 * cannot be configured		 
 		 */
-		if (device->device == PCI_DEVICE_ID_SI_648 ||
-		    device->device == PCI_DEVICE_ID_SI_746) {
-			printk(KERN_INFO PFX "SiS chipset with AGP problems detected. Giving bridge time to recover.\n");
+		if (device->device == agp_bridge->dev->device) {
+			printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout (1+(HZ*10)/1000);
 		}
@@ -223,28 +224,35 @@
 };
 
 
+// chipsets that require the 'delay hack'
+static int sis_broken_chipsets[] __devinitdata = {
+	PCI_DEVICE_ID_SI_648,
+	PCI_DEVICE_ID_SI_746,
+	0 // terminator
+};
+
 static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
 {
-	if (bridge->dev->device == PCI_DEVICE_ID_SI_648) { 
-		sis_driver.agp_enable=sis_648_enable;
-		if (agp_bridge->major_version == 3) {
-			sis_driver.aperture_sizes = agp3_generic_sizes;
-			sis_driver.size_type = U16_APER_SIZE;
-			sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
-			sis_driver.configure = agp3_generic_configure;
-			sis_driver.fetch_size = agp3_generic_fetch_size;
-			sis_driver.cleanup = agp3_generic_cleanup;
-			sis_driver.tlb_flush = agp3_generic_tlbflush;
-		}
-	}
+	int i;
 
-	if (bridge->dev->device == PCI_DEVICE_ID_SI_746) {
-		/*
-		 * We don't know enough about the 746 to enable it properly.
-		 * Though we do know that it needs the 'delay' hack to settle
-		 * after changing modes.
-		 */
-		sis_driver.agp_enable=sis_648_enable;
+	for(i=0; sis_broken_chipsets[i]!=0; ++i)
+		if(bridge->dev->device==sis_broken_chipsets[i])
+			break;
+
+	if(sis_broken_chipsets[i] || agp_sis_force_delay)
+		sis_driver.agp_enable=sis_delayed_enable;
+
+	// sis chipsets that indicate less than agp3.5
+	// are not actually fully agp3 compliant
+	if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5
+	     && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) {
+		sis_driver.aperture_sizes = agp3_generic_sizes;
+		sis_driver.size_type = U16_APER_SIZE;
+		sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
+		sis_driver.configure = agp3_generic_configure;
+		sis_driver.fetch_size = agp3_generic_fetch_size;
+		sis_driver.cleanup = agp3_generic_cleanup;
+		sis_driver.tlb_flush = agp3_generic_tlbflush;
 	}
 }
 
@@ -335,4 +343,8 @@
 module_init(agp_sis_init);
 module_exit(agp_sis_cleanup);
 
+MODULE_PARM(agp_sis_force_delay,"i");
+MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack");
+MODULE_PARM(agp_sis_agp_spec,"i");
+MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect");
 MODULE_LICENSE("GPL and additional rights");
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	2004-05-31 16:01:10 -07:00
+++ b/drivers/char/agp/via-agp.c	2004-05-31 16:01:10 -07:00
@@ -9,6 +9,8 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+static struct pci_device_id agp_via_pci_table[];
+
 #define VIA_GARTCTRL	0x80
 #define VIA_APSIZE	0x84
 #define VIA_ATTBASE	0x88
@@ -378,20 +380,9 @@
 	if (!cap_ptr)
 		return -ENODEV;
 
-	/* probe for known chipsets */
-	for (j = 0; devs[j].chipset_name; j++) {
-		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected VIA %s chipset\n",
-					devs[j].chipset_name);
-			goto found;
-		}
-	}
-
-	printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)\n",
-		    pdev->device);
-	return -ENODEV;
+	j = ent - agp_via_pci_table;
+	printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
 
-found:
 	bridge = agp_alloc_bridge();
 	if (!bridge)
 		return -ENOMEM;
@@ -432,15 +423,40 @@
 	agp_put_bridge(bridge);
 }
 
+/* must be the same order as name table above */
 static struct pci_device_id agp_via_pci_table[] = {
-	{
-	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-	.class_mask	= ~0,
-	.vendor		= PCI_VENDOR_ID_VIA,
-	.device		= PCI_ANY_ID,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-	},
+#define ID(x) \
+	{						\
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),	\
+	.class_mask	= ~0,				\
+	.vendor		= PCI_VENDOR_ID_VIA,		\
+	.device		= x,				\
+	.subvendor	= PCI_ANY_ID,			\
+	.subdevice	= PCI_ANY_ID,			\
+	}
+	ID(PCI_DEVICE_ID_VIA_82C598_0),
+	ID(PCI_DEVICE_ID_VIA_8501_0),
+	ID(PCI_DEVICE_ID_VIA_8601_0),
+	ID(PCI_DEVICE_ID_VIA_82C691_0),
+	ID(PCI_DEVICE_ID_VIA_8371_0),
+	ID(PCI_DEVICE_ID_VIA_8633_0),
+	ID(PCI_DEVICE_ID_VIA_XN266),
+	ID(PCI_DEVICE_ID_VIA_8361),
+	ID(PCI_DEVICE_ID_VIA_8363_0),
+	ID(PCI_DEVICE_ID_VIA_8753_0),
+	ID(PCI_DEVICE_ID_VIA_8367_0),
+	ID(PCI_DEVICE_ID_VIA_8653_0),
+	ID(PCI_DEVICE_ID_VIA_XM266),
+	ID(PCI_DEVICE_ID_VIA_862X_0),
+	ID(PCI_DEVICE_ID_VIA_8377_0),
+	ID(PCI_DEVICE_ID_VIA_8605_0),
+	ID(PCI_DEVICE_ID_VIA_8703_51_0),
+	ID(PCI_DEVICE_ID_VIA_8754C_0),
+	ID(PCI_DEVICE_ID_VIA_8763_0),
+	ID(PCI_DEVICE_ID_VIA_8378_0),
+	ID(PCI_DEVICE_ID_VIA_PT880),
+	ID(PCI_DEVICE_ID_VIA_8783_0),
+	ID(PCI_DEVICE_ID_VIA_PX8X0_0),	
 	{ }
 };
 
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	2004-05-31 16:01:10 -07:00
+++ b/include/linux/pci_ids.h	2004-05-31 16:01:10 -07:00
@@ -2005,6 +2005,7 @@
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
 #define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
+#define PCI_DEVICE_ID_INTEL_7501_0	0x254c
 #define PCI_DEVICE_ID_INTEL_7505_0	0x2550  
 #define PCI_DEVICE_ID_INTEL_7505_1	0x2552  
 #define PCI_DEVICE_ID_INTEL_7205_0	0x255d
