Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 /dev/null                                   |   62 ----
 25-akpm/Documentation/kernel-parameters.txt |    4 
 25-akpm/arch/i386/kernel/quirks.c           |    4 
 25-akpm/arch/i386/pci/acpi.c                |   30 +-
 25-akpm/arch/i386/pci/common.c              |    4 
 25-akpm/arch/i386/pci/fixup.c               |  129 +++++++++
 25-akpm/arch/i386/pci/irq.c                 |   16 -
 25-akpm/arch/ia64/pci/pci.c                 |   33 +-
 25-akpm/drivers/atm/idt77252.c              |    4 
 25-akpm/drivers/char/cyclades.c             |    2 
 25-akpm/drivers/isdn/tpam/tpam_main.c       |    4 
 25-akpm/drivers/misc/ibmasm/module.c        |    6 
 25-akpm/drivers/net/tulip/de4x5.c           |    4 
 25-akpm/drivers/pci/Makefile                |    8 
 25-akpm/drivers/pci/hotplug/acpiphp_glue.c  |    4 
 25-akpm/drivers/pci/hotplug/pciehp.h        |   21 +
 25-akpm/drivers/pci/hotplug/pciehp_core.c   |   18 -
 25-akpm/drivers/pci/hotplug/pciehp_ctrl.c   |  387 +++++++++++++++++-----------
 25-akpm/drivers/pci/hotplug/pciehp_hpc.c    |   36 +-
 25-akpm/drivers/pci/hotplug/pciehp_pci.c    |    8 
 25-akpm/drivers/pci/hotplug/pciehprm_acpi.c |   43 ++-
 25-akpm/drivers/pci/hotplug/shpchp_ctrl.c   |   34 ++
 25-akpm/drivers/pci/hotplug/shpchp_hpc.c    |    1 
 25-akpm/drivers/pci/pci-acpi.c              |  209 +++++++++++++++
 25-akpm/drivers/pci/pci-driver.c            |   15 -
 25-akpm/drivers/pci/pci-sysfs.c             |  120 ++++++++
 25-akpm/drivers/pci/pci.c                   |   12 
 25-akpm/drivers/pci/pci.h                   |    6 
 25-akpm/drivers/pci/probe.c                 |    5 
 25-akpm/drivers/pci/quirks.c                |   18 -
 25-akpm/drivers/pci/remove.c                |    2 
 25-akpm/drivers/pci/rom.c                   |  225 ++++++++++++++++
 25-akpm/drivers/pci/setup-res.c             |    2 
 25-akpm/include/asm-generic/vmlinux.lds.h   |    3 
 25-akpm/include/linux/ioport.h              |    5 
 25-akpm/include/linux/pci-acpi.h            |   61 ++++
 25-akpm/include/linux/pci.h                 |   42 +--
 25-akpm/include/linux/pci_ids.h             |    8 
 arch/i386/kernel/acpi/boot.c                |    0 
 39 files changed, 1286 insertions(+), 309 deletions(-)

diff -puN arch/i386/kernel/acpi/boot.c~bk-pci arch/i386/kernel/acpi/boot.c
diff -puN arch/i386/kernel/quirks.c~bk-pci arch/i386/kernel/quirks.c
--- 25/arch/i386/kernel/quirks.c~bk-pci	2004-11-09 01:18:58.767259992 -0800
+++ 25-akpm/arch/i386/kernel/quirks.c	2004-11-09 01:18:59.829098568 -0800
@@ -6,7 +6,7 @@
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
 
-void __init quirk_intel_irqbalance(struct pci_dev *dev)
+void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
 {
 	u8 config, rev;
 	u32 word;
@@ -45,5 +45,5 @@ void __init quirk_intel_irqbalance(struc
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_SMCH,	quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7520_MCH,	quirk_intel_irqbalance);
 #endif
diff -puN arch/i386/pci/acpi.c~bk-pci arch/i386/pci/acpi.c
--- 25/arch/i386/pci/acpi.c~bk-pci	2004-11-09 01:18:58.769259688 -0800
+++ 25-akpm/arch/i386/pci/acpi.c	2004-11-09 01:18:59.829098568 -0800
@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan
 	return pcibios_scan_root(busnum);
 }
 
+extern int pci_routeirq;
 static int __init pci_acpi_init(void)
 {
 	struct pci_dev *dev = NULL;
@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void)
 	pcibios_scanned++;
 	pcibios_enable_irq = acpi_pci_irq_enable;
 
-	/*
-	 * PCI IRQ routing is set up by pci_enable_device(), but we
-	 * also do it here in case there are still broken drivers that
-	 * don't use pci_enable_device().
-	 */
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
-		acpi_pci_irq_enable(dev);
-
+	if (pci_routeirq) {
+		/*
+		 * PCI IRQ routing is set up by pci_enable_device(), but we
+		 * also do it here in case there are still broken drivers that
+		 * don't use pci_enable_device().
+		 */
+		printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
+		printk(KERN_INFO "** was specified.  If this was required to make a driver work,\n");
+		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
+		printk(KERN_INFO "** so I can fix the driver.\n");
+		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+			acpi_pci_irq_enable(dev);
+	} else {
+		printk(KERN_INFO "** PCI interrupts are no longer routed automatically.  If this\n");
+		printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
+		printk(KERN_INFO "** driver failed to call pci_enable_device().  As a temporary\n");
+		printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
+		printk(KERN_INFO "** behavior.  If this argument makes the device work again,\n");
+		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
+		printk(KERN_INFO "** so I can fix the driver.\n");
+	}
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_ioapic)
 		print_IO_APIC();
diff -L arch/i386/pci/changelog -puN arch/i386/pci/changelog~bk-pci /dev/null
--- 25/arch/i386/pci/changelog
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,62 +0,0 @@
-/*
- * CHANGELOG :
- * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
- *	Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
- *
- * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
- *     Potter, potter@cao-vlsi.ibp.fr
- *
- * Jan 10, 1995 : Modified to store the information about configured pci
- *      devices into a list, which can be accessed via /proc/pci by
- *      Curtis Varner, cvarner@cs.ucr.edu
- *
- * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
- *	Alpha version. Intel & UMC chipset support only.
- *
- * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
- *	moved to drivers/pci/pci.c.
- *
- * Dec 7, 1996  : Added support for direct configuration access of boards
- *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
- *
- * Feb 3, 1997  : Set internal functions to static, save/restore flags
- *	avoid dead locks reading broken PCI BIOS, werner@suse.de 
- *
- * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
- *	(mj@atrey.karlin.mff.cuni.cz)
- *
- * May 7,  1997 : Added some missing cli()'s. [mj]
- * 
- * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
- *      (paubert@iram.es)
- *
- * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
- *	and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- *
- * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
- *
- * May 1,  1998 : Support for peer host bridges. [mj]
- *
- * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
- *	can be accessed from interrupts even on SMP systems. [mj]
- *
- * August  1998 : Better support for peer host bridges and more paranoid
- *	checks for direct hardware access. Ugh, this file starts to look as
- *	a large gallery of common hardware bug workarounds (watch the comments)
- *	-- the PCI specs themselves are sane, but most implementors should be
- *	hit hard with \hammer scaled \magstep5. [mj]
- *
- * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
- *
- * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
- *
- * August  1999 : New resource management and configuration access stuff. [mj]
- *
- * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
- *		  Based on ideas by Chris Frantz and David Hinds. [mj]
- *
- * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
- *		  for a lot of patience during testing. [mj]
- *
- * Oct  8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
- */
\ No newline at end of file
diff -puN arch/i386/pci/common.c~bk-pci arch/i386/pci/common.c
--- 25/arch/i386/pci/common.c~bk-pci	2004-11-09 01:18:58.772259232 -0800
+++ 25-akpm/arch/i386/pci/common.c	2004-11-09 01:18:59.831098264 -0800
@@ -23,6 +23,7 @@ extern  void pcibios_sort(void);
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
 				PCI_PROBE_MMCONF;
 
+int pci_routeirq;
 int pcibios_last_bus = -1;
 struct pci_bus *pci_root_bus = NULL;
 struct pci_raw_ops *raw_pci_ops;
@@ -227,6 +228,9 @@ char * __devinit  pcibios_setup(char *st
 	} else if (!strcmp(str, "assign-busses")) {
 		pci_probe |= PCI_ASSIGN_ALL_BUSSES;
 		return NULL;
+	} else if (!strcmp(str, "routeirq")) {
+		pci_routeirq = 1;
+		return NULL;
 	}
 	return str;
 }
diff -puN arch/i386/pci/fixup.c~bk-pci arch/i386/pci/fixup.c
--- 25/arch/i386/pci/fixup.c~bk-pci	2004-11-09 01:18:58.773259080 -0800
+++ 25-akpm/arch/i386/pci/fixup.c	2004-11-09 01:18:59.832098112 -0800
@@ -255,3 +255,132 @@ static void __init pci_fixup_nforce2(str
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
 
+/* Max PCI Express root ports */
+#define MAX_PCIEROOT	6
+static int quirk_aspm_offset[MAX_PCIEROOT << 3];
+
+#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
+
+static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+}
+
+/*
+ * Replace the original pci bus ops for write with a new one that will filter
+ * the request to insure ASPM cannot be enabled.
+ */
+static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	u8 offset;
+
+	offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
+
+	if ((offset) && (where == offset))
+		value = value & 0xfffffffc;
+	
+	return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+}
+
+struct pci_ops quirk_pcie_aspm_ops = {
+	.read = quirk_pcie_aspm_read,
+	.write = quirk_pcie_aspm_write,
+};
+
+/*
+ * Prevents PCI Express ASPM (Active State Power Management) being enabled.
+ *
+ * Save the register offset, where the ASPM control bits are located,
+ * for each PCI Express device that is in the device list of
+ * the root port in an array for fast indexing. Replace the bus ops
+ * with the modified one.
+ */
+void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
+{
+	int cap_base, i;
+	struct pci_bus  *pbus;
+	struct pci_dev *dev;
+
+	if ((pbus = pdev->subordinate) == NULL)
+		return;
+
+	/*
+	 * Check if the DID of pdev matches one of the six root ports. This
+	 * check is needed in the case this function is called directly by the
+	 * hot-plug driver.
+	 */
+	if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) ||
+	    (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1))
+		return;
+
+	if (list_empty(&pbus->devices)) {
+		/*
+		 * If no device is attached to the root port at power-up or
+		 * after hot-remove, the pbus->devices is empty and this code
+		 * will set the offsets to zero and the bus ops to parent's bus
+		 * ops, which is unmodified.
+	 	 */
+		for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
+			quirk_aspm_offset[i] = 0;
+
+		pbus->ops = pbus->parent->ops;
+	} else {
+		/*
+		 * If devices are attached to the root port at power-up or
+		 * after hot-add, the code loops through the device list of
+		 * each root port to save the register offsets and replace the
+		 * bus ops.
+		 */
+		list_for_each_entry(dev, &pbus->devices, bus_list) {
+			/* There are 0 to 8 devices attached to this bus */
+			cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
+			quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10;
+		}
+		pbus->ops = &quirk_pcie_aspm_ops;
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA,	pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PA1,	pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PB,	pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PB1,	pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC,	pcie_rootport_aspm_quirk );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC1,	pcie_rootport_aspm_quirk );
+
+/*
+ * Fixup to mark boot BIOS video selected by BIOS before it changes
+ *
+ * From information provided by "Jon Smirl" <jonsmirl@yahoo.com>
+ *
+ * The standard boot ROM sequence for an x86 machine uses the BIOS
+ * to select an initial video card for boot display. This boot video 
+ * card will have it's BIOS copied to C0000 in system RAM. 
+ * IORESOURCE_ROM_SHADOW is used to associate the boot video
+ * card with this copy. On laptops this copy has to be used since
+ * the main ROM may be compressed or combined with another image.
+ * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
+ * is marked here since the boot video device will be the only enabled
+ * video device at this point.
+ *
+ */static void __devinit pci_fixup_video(struct pci_dev *pdev)
+{
+	struct pci_dev *bridge;
+	struct pci_bus *bus;
+	u16 l;
+
+	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+		return;
+
+	/* Is VGA routed to us? */
+	bus = pdev->bus;
+	while (bus) {
+		bridge = bus->self;
+		if (bridge) {
+			pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
+			if (!(l & PCI_BRIDGE_CTL_VGA))
+				return;
+		}
+		bus = bus->parent;
+	}
+	pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
diff -puN arch/i386/pci/irq.c~bk-pci arch/i386/pci/irq.c
--- 25/arch/i386/pci/irq.c~bk-pci	2004-11-09 01:18:58.775258776 -0800
+++ 25-akpm/arch/i386/pci/irq.c	2004-11-09 01:19:00.611979552 -0800
@@ -460,21 +460,17 @@ static int pirq_bios_set(struct pci_dev 
 
 #endif
 
-
 static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
 {
-	struct pci_dev *dev1, *dev2;
+	static struct pci_device_id pirq_440gx[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
+		{ },
+	};
 
 	/* 440GX has a proprietary PIRQ router -- don't use it */
-	dev1 = pci_get_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82443GX_0, NULL);
-	dev2 = pci_get_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82443GX_2, NULL);
-	if ((dev1 != NULL) || (dev2 != NULL)) {
-		pci_dev_put(dev1);
-		pci_dev_put(dev2);
+	if (pci_dev_present(pirq_440gx))
 		return 0;
-	}
 
 	switch(device)
 	{
diff -puN arch/ia64/pci/pci.c~bk-pci arch/ia64/pci/pci.c
--- 25/arch/ia64/pci/pci.c~bk-pci	2004-11-09 01:18:58.776258624 -0800
+++ 25-akpm/arch/ia64/pci/pci.c	2004-11-09 01:19:00.613979248 -0800
@@ -46,6 +46,8 @@
 #define DBG(x...)
 #endif
 
+static int pci_routeirq;
+
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acp
 
 	acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
 #endif
-	/*
-	 * PCI IRQ routing is set up by pci_enable_device(), but we
-	 * also do it here in case there are still broken drivers that
-	 * don't use pci_enable_device().
-	 */
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
-		acpi_pci_irq_enable(dev);
+
+	if (pci_routeirq) {
+		/*
+		 * PCI IRQ routing is set up by pci_enable_device(), but we
+		 * also do it here in case there are still broken drivers that
+		 * don't use pci_enable_device().
+		 */
+		printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
+		printk(KERN_INFO "** was specified.  If this was required to make a driver work,\n");
+		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
+		printk(KERN_INFO "** so I can fix the driver.\n");
+		while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+			acpi_pci_irq_enable(dev);
+	} else {
+		printk(KERN_INFO "** PCI interrupts are no longer routed automatically.  If this\n");
+		printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
+		printk(KERN_INFO "** driver failed to call pci_enable_device().  As a temporary\n");
+		printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
+		printk(KERN_INFO "** behavior.  If this argument makes the device work again,\n");
+		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
+		printk(KERN_INFO "** so I can fix the driver.\n");
+	}
 
 	return 0;
 }
@@ -475,6 +492,8 @@ pcibios_align_resource (void *data, stru
 char * __init
 pcibios_setup (char *str)
 {
+	if (!strcmp(str, "routeirq"))
+		pci_routeirq = 1;
 	return NULL;
 }
 
diff -puN Documentation/kernel-parameters.txt~bk-pci Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~bk-pci	2004-11-09 01:18:58.778258320 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt	2004-11-09 01:18:58.831250264 -0800
@@ -940,6 +940,10 @@ running once the system is up.
 					enabled.
 		noacpi			[IA-32] Do not use ACPI for IRQ routing
 					or for PCI scanning.
+		routeirq		Do IRQ routing for all PCI devices.
+					This is normally done in pci_enable_device(),
+					so this option is a temporary workaround
+					for broken drivers that don't call it.
 
 		firmware		[ARM] Do not re-enumerate the bus but
 					instead just use the configuration
diff -puN drivers/atm/idt77252.c~bk-pci drivers/atm/idt77252.c
--- 25/drivers/atm/idt77252.c~bk-pci	2004-11-09 01:18:58.780258016 -0800
+++ 25-akpm/drivers/atm/idt77252.c	2004-11-09 01:19:00.615978944 -0800
@@ -3685,9 +3685,9 @@ idt77252_init_one(struct pci_dev *pcidev
 	int i, err;
 
 
-	if (pci_enable_device(pcidev)) {
+	if ((err = pci_enable_device(pcidev))) {
 		printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
-		return -ENODEV;
+		return err;
 	}
 
 	if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
diff -puN drivers/char/cyclades.c~bk-pci drivers/char/cyclades.c
--- 25/drivers/char/cyclades.c~bk-pci	2004-11-09 01:18:58.782257712 -0800
+++ 25-akpm/drivers/char/cyclades.c	2004-11-09 01:19:00.620978184 -0800
@@ -4725,7 +4725,7 @@ cy_detect_pci(void)
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
                 while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-                        if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES,
+                        if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
                                         device_id, pdev)) == NULL) {
                                 dev_index++;    /* try next device id */
                         } else {
diff -puN drivers/isdn/tpam/tpam_main.c~bk-pci drivers/isdn/tpam/tpam_main.c
--- 25/drivers/isdn/tpam/tpam_main.c~bk-pci	2004-11-09 01:18:58.783257560 -0800
+++ 25-akpm/drivers/isdn/tpam/tpam_main.c	2004-11-09 01:19:00.620978184 -0800
@@ -88,10 +88,10 @@ static int __devinit tpam_probe(struct p
 	tpam_card *card, *c;
 	int i, err;
 
-	if (pci_enable_device(dev)) {
+	if ((err = pci_enable_device(dev))) {
 		printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
 			pci_name(dev));
-		return -ENODEV;
+		return err;
 	}
 
 	/* allocate memory for the board structure */
diff -puN drivers/misc/ibmasm/module.c~bk-pci drivers/misc/ibmasm/module.c
--- 25/drivers/misc/ibmasm/module.c~bk-pci	2004-11-09 01:18:58.785257256 -0800
+++ 25-akpm/drivers/misc/ibmasm/module.c	2004-11-09 01:19:00.621978032 -0800
@@ -59,13 +59,13 @@
 
 static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	int result = -ENOMEM;
+	int err, result = -ENOMEM;
 	struct service_processor *sp;
 
-	if (pci_enable_device(pdev)) {
+	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_ERR "%s: can't enable PCI device at %s\n",
 			DRIVER_NAME, pci_name(pdev));
-		return -ENODEV;
+		return err;
 	}
 
 	sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
diff -puN drivers/net/tulip/de4x5.c~bk-pci drivers/net/tulip/de4x5.c
--- 25/drivers/net/tulip/de4x5.c~bk-pci	2004-11-09 01:18:58.787256952 -0800
+++ 25-akpm/drivers/net/tulip/de4x5.c	2004-11-09 01:19:00.625977424 -0800
@@ -2242,8 +2242,8 @@ static int __devinit de4x5_pci_probe (st
 		return -ENODEV;
 
 	/* Ok, the device seems to be for us. */
-	if (pci_enable_device (pdev))
-		return -ENODEV;
+	if ((error = pci_enable_device (pdev)))
+		return error;
 
 	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
 		error = -ENOMEM;
diff -puN drivers/pci/hotplug/acpiphp_glue.c~bk-pci drivers/pci/hotplug/acpiphp_glue.c
--- 25/drivers/pci/hotplug/acpiphp_glue.c~bk-pci	2004-11-09 01:18:58.788256800 -0800
+++ 25-akpm/drivers/pci/hotplug/acpiphp_glue.c	2004-11-09 01:19:00.627977120 -0800
@@ -389,7 +389,7 @@ static void add_host_bridge(acpi_handle 
 
 	bridge->pci_bus = pci_find_bus(seg, bus);
 
-	bridge->res_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&bridge->res_lock);
 
 	/* to be overridden when we decode _CRS	*/
 	bridge->sub = bridge->bus;
@@ -457,7 +457,7 @@ static void add_p2p_bridge(acpi_handle *
 		return;
 	}
 
-	bridge->res_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&bridge->res_lock);
 
 	bridge->bus = bridge->pci_bus->number;
 	bridge->sub = bridge->pci_bus->subordinate;
diff -puN drivers/pci/hotplug/pciehp_core.c~bk-pci drivers/pci/hotplug/pciehp_core.c
--- 25/drivers/pci/hotplug/pciehp_core.c~bk-pci	2004-11-09 01:18:58.790256496 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehp_core.c	2004-11-09 01:19:00.629976816 -0800
@@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct c
 	int num_ctlr_slots;		/* Not needed; PCI Express has 1 slot per port*/
 	int first_device_num;		/* Not needed */
 	int physical_slot_num;
-	int updown;			/* Not needed */
+	u8 ctrlcap;			
 	int rc;
-	int flags;			/* Not needed */
 
-	rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags);
+	rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap);
 	if (rc) {
 		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
 		return (-1);
@@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct c
 	ctrl->num_slots = num_ctlr_slots;	/* PCI Express has 1 slot per port */
 	ctrl->slot_device_offset = first_device_num;
 	ctrl->first_slot = physical_slot_num;
-	ctrl->slot_num_inc = updown; 	/* Not needed */		/* either -1 or 1 */
+	ctrl->ctrlcap = ctrlcap; 	
 
-	dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n",
-		__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, 
+	dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n",
+		__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap, 
 		ctrl->bus, ctrl->device);
 
 	return (0);
@@ -237,7 +236,9 @@ static int set_attention_status(struct h
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 	hotplug_slot->info->attention_status = status;
-	slot->hpc_ops->set_attention_status(slot, status);
+	
+	if (ATTN_LED(slot->ctrl->ctrlcap)) 
+		slot->hpc_ops->set_attention_status(slot, status);
 
 	return 0;
 }
@@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pd
 
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	dbg("%s: adpater value %x\n", __FUNCTION__, value);
-	if (!value) {
+	
+	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc) {
 			/* Done with exclusive hardware access */
diff -puN drivers/pci/hotplug/pciehp_ctrl.c~bk-pci drivers/pci/hotplug/pciehp_ctrl.c
--- 25/drivers/pci/hotplug/pciehp_ctrl.c~bk-pci	2004-11-09 01:18:58.792256192 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehp_ctrl.c	2004-11-09 01:19:00.633976208 -0800
@@ -38,6 +38,7 @@
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include "../pci.h"
 #include "pciehp.h"
 #include "pciehprm.h"
 
@@ -51,6 +52,7 @@ static struct semaphore event_semaphore;
 static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
 static int event_finished;
 static unsigned long pushbutton_pending;	/* = 0 */
+static unsigned long surprise_rm_pending;	/* = 0 */
 
 u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
@@ -1063,25 +1065,29 @@ static void set_slot_off(struct controll
 	/* Wait for exclusive access to hardware */
 	down(&ctrl->crit_sect);
 
-	/* turn off slot, turn on Amber LED, turn off Green LED */
-	if (pslot->hpc_ops->power_off_slot(pslot)) {   
-		err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-		up(&ctrl->crit_sect);
-		return;
+	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
+	if (POWER_CTRL(ctrl->ctrlcap)) {
+		if (pslot->hpc_ops->power_off_slot(pslot)) {   
+			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
+			up(&ctrl->crit_sect);
+			return;
+		}
+		wait_for_ctrl_irq (ctrl);
 	}
-	wait_for_ctrl_irq (ctrl);
 
-	pslot->hpc_ops->green_led_off(pslot);   
-	
-	wait_for_ctrl_irq (ctrl);
+	if (PWR_LED(ctrl->ctrlcap)) {
+		pslot->hpc_ops->green_led_off(pslot);   
+		wait_for_ctrl_irq (ctrl);
+	}
 
-	/* turn on Amber LED */
-	if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
-		err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-		up(&ctrl->crit_sect);
-		return;
+	if (ATTN_LED(ctrl->ctrlcap)) { 
+		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
+			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
+			up(&ctrl->crit_sect);
+			return;
+		}
+		wait_for_ctrl_irq (ctrl);
 	}
-	wait_for_ctrl_irq (ctrl);
 
 	/* Done with exclusive hardware access */
 	up(&ctrl->crit_sect);
@@ -1112,20 +1118,24 @@ static u32 board_added(struct pci_func *
 	/* Wait for exclusive access to hardware */
 	down(&ctrl->crit_sect);
 
-	/* Power on slot */
-	rc = p_slot->hpc_ops->power_on_slot(p_slot);
-	if (rc) {
-		up(&ctrl->crit_sect);
-		return -1;
-	}
+	if (POWER_CTRL(ctrl->ctrlcap)) {
+		/* Power on slot */
+		rc = p_slot->hpc_ops->power_on_slot(p_slot);
+		if (rc) {
+			up(&ctrl->crit_sect);
+			return -1;
+		}
 
-	/* Wait for the command to complete */
-	wait_for_ctrl_irq (ctrl);
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+	}
 	
-	p_slot->hpc_ops->green_led_blink(p_slot);
+	if (PWR_LED(ctrl->ctrlcap)) {
+		p_slot->hpc_ops->green_led_blink(p_slot);
 			
-	/* Wait for the command to complete */
-	wait_for_ctrl_irq (ctrl);
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+	}
 
 	/* Done with exclusive hardware access */
 	up(&ctrl->crit_sect);
@@ -1212,18 +1222,24 @@ static u32 board_added(struct pci_func *
 			}
 		} while (new_func);
 
-		/* Wait for exclusive access to hardware */
-		down(&ctrl->crit_sect);
-
-		p_slot->hpc_ops->green_led_on(p_slot);
-
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq (ctrl);
-
-
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
-
+ 		/* 
+ 		 * Some PCI Express root ports require fixup after hot-plug operation.
+ 		 */
+ 		if (pcie_mch_quirk)
+ 			pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
+ 
+  		if (PWR_LED(ctrl->ctrlcap)) {
+  			/* Wait for exclusive access to hardware */
+  			down(&ctrl->crit_sect);
+   
+  			p_slot->hpc_ops->green_led_on(p_slot);
+  
+  			/* Wait for the command to complete */
+  			wait_for_ctrl_irq (ctrl);
+  	
+  			/* Done with exclusive hardware access */
+  			up(&ctrl->crit_sect);
+  		}
 	} else {
 		set_slot_off(ctrl, p_slot);
 		return -1;
@@ -1289,21 +1305,25 @@ static u32 remove_board(struct pci_func 
 	/* Wait for exclusive access to hardware */
 	down(&ctrl->crit_sect);
 
-	/* power off slot */
-	rc = p_slot->hpc_ops->power_off_slot(p_slot);
-	if (rc) {
-		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-		up(&ctrl->crit_sect);
-		return rc;
+	if (POWER_CTRL(ctrl->ctrlcap)) {
+		/* power off slot */
+		rc = p_slot->hpc_ops->power_off_slot(p_slot);
+		if (rc) {
+			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+			up(&ctrl->crit_sect);
+			return rc;
+		}
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
 	}
-	/* Wait for the command to complete */
-	wait_for_ctrl_irq (ctrl);
 
-	/* turn off Green LED */
-	p_slot->hpc_ops->green_led_off(p_slot);
+	if (PWR_LED(ctrl->ctrlcap)) {
+		/* turn off Green LED */
+		p_slot->hpc_ops->green_led_off(p_slot);
 	
-	/* Wait for the command to complete */
-	wait_for_ctrl_irq (ctrl);
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+	}
 
 	/* Done with exclusive hardware access */
 	up(&ctrl->crit_sect);
@@ -1368,7 +1388,6 @@ static void pushbutton_helper_thread(uns
 	up(&event_semaphore);
 }
 
-
 /**
  * pciehp_pushbutton_thread
  *
@@ -1399,7 +1418,55 @@ static void pciehp_pushbutton_thread(uns
 		p_slot->state = POWERON_STATE;
 		dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
-		if (pciehp_enable_slot(p_slot)) {
+		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
+			/* Wait for exclusive access to hardware */
+			down(&p_slot->ctrl->crit_sect);
+
+			p_slot->hpc_ops->green_led_off(p_slot);
+
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&p_slot->ctrl->crit_sect);
+		}
+		p_slot->state = STATIC_STATE;
+	}
+
+	return;
+}
+
+/**
+ * pciehp_surprise_rm_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the surprise removal
+ * Handles all pending events and exits.
+ *
+ */
+static void pciehp_surprise_rm_thread(unsigned long slot)
+{
+	struct slot *p_slot = (struct slot *) slot;
+	u8 getstatus;
+	
+	surprise_rm_pending = 0;
+
+	if (!p_slot) {
+		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+		return;
+	}
+
+	p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (!getstatus) {
+		p_slot->state = POWEROFF_STATE;
+		dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		pciehp_disable_slot(p_slot);
+		p_slot->state = STATIC_STATE;
+	} else {
+		p_slot->state = POWERON_STATE;
+		dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 			/* Wait for exclusive access to hardware */
 			down(&p_slot->ctrl->crit_sect);
 
@@ -1418,6 +1485,7 @@ static void pciehp_pushbutton_thread(uns
 }
 
 
+
 /* this is the main worker thread */
 static int event_thread(void* data)
 {
@@ -1436,6 +1504,8 @@ static int event_thread(void* data)
 		/* Do stuff here */
 		if (pushbutton_pending)
 			pciehp_pushbutton_thread(pushbutton_pending);
+		else if (surprise_rm_pending)
+			pciehp_surprise_rm_thread(surprise_rm_pending);
 		else
 			for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
 				interrupt_event_handler(ctrl);
@@ -1528,16 +1598,18 @@ static void interrupt_event_handler(stru
 					case BLINKINGOFF_STATE:
 						/* Wait for exclusive access to hardware */
 						down(&ctrl->crit_sect);
-
-						p_slot->hpc_ops->green_led_on(p_slot);
-						/* Wait for the command to complete */
-						wait_for_ctrl_irq (ctrl);
-
-						p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-						/* Wait for the command to complete */
-						wait_for_ctrl_irq (ctrl);
-
+						
+						if (PWR_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->green_led_on(p_slot);
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
+						if (ATTN_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
 						/* Done with exclusive hardware access */
 						up(&ctrl->crit_sect);
 						break;
@@ -1545,14 +1617,16 @@ static void interrupt_event_handler(stru
 						/* Wait for exclusive access to hardware */
 						down(&ctrl->crit_sect);
 
-						p_slot->hpc_ops->green_led_off(p_slot);
-						/* Wait for the command to complete */
-						wait_for_ctrl_irq (ctrl);
-
-						p_slot->hpc_ops->set_attention_status(p_slot, 0);
-						/* Wait for the command to complete */
-						wait_for_ctrl_irq (ctrl);
-
+						if (PWR_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->green_led_off(p_slot);
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
+						if (ATTN_LED(ctrl->ctrlcap)){
+							p_slot->hpc_ops->set_attention_status(p_slot, 0);
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
 						/* Done with exclusive hardware access */
 						up(&ctrl->crit_sect);
 
@@ -1566,59 +1640,83 @@ static void interrupt_event_handler(stru
 				}
 				/* ***********Button Pressed (No action on 1st press...) */
 				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-					dbg("Button pressed\n");
-
-					p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-					if (getstatus) {
-						/* slot is on */
-						dbg("slot is on\n");
-						p_slot->state = BLINKINGOFF_STATE;
-						info(msg_button_off, p_slot->number);
-					} else {
-						/* slot is off */
-						dbg("slot is off\n");
-						p_slot->state = BLINKINGON_STATE;
-						info(msg_button_on, p_slot->number);
-					}
-
-					/* Wait for exclusive access to hardware */
-					down(&ctrl->crit_sect);
-
-					/* blink green LED and turn off amber */
-					p_slot->hpc_ops->green_led_blink(p_slot);
-					/* Wait for the command to complete */
-					wait_for_ctrl_irq (ctrl);
 					
-					p_slot->hpc_ops->set_attention_status(p_slot, 0);
+					if (ATTN_BUTTN(ctrl->ctrlcap)) {
+						dbg("Button pressed\n");
+						p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+						if (getstatus) {
+							/* slot is on */
+							dbg("slot is on\n");
+							p_slot->state = BLINKINGOFF_STATE;
+							info(msg_button_off, p_slot->number);
+						} else {
+							/* slot is off */
+							dbg("slot is off\n");
+							p_slot->state = BLINKINGON_STATE;
+							info(msg_button_on, p_slot->number);
+						}
 
-					/* Wait for the command to complete */
-					wait_for_ctrl_irq (ctrl);
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
 
-					/* Done with exclusive hardware access */
-					up(&ctrl->crit_sect);
+						/* blink green LED and turn off amber */
+						if (PWR_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->green_led_blink(p_slot);
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
+
+						if (ATTN_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+							/* Wait for the command to complete */
+							wait_for_ctrl_irq (ctrl);
+						}
+
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
 
-					init_timer(&p_slot->task_event);
-					p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
-					p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
-					p_slot->task_event.data = (unsigned long) p_slot;
+						init_timer(&p_slot->task_event);
+						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
+						p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
+						p_slot->task_event.data = (unsigned long) p_slot;
 
-					dbg("add_timer p_slot = %p\n", (void *) p_slot);
-					add_timer(&p_slot->task_event);
+						dbg("add_timer p_slot = %p\n", (void *) p_slot);
+						add_timer(&p_slot->task_event);
+					}
 				}
 				/***********POWER FAULT********************/
 				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-					dbg("power fault\n");
-					/* Wait for exclusive access to hardware */
-					down(&ctrl->crit_sect);
+					if (POWER_CTRL(ctrl->ctrlcap)) {
+						dbg("power fault\n");
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
 
-					p_slot->hpc_ops->set_attention_status(p_slot, 1);
-					wait_for_ctrl_irq (ctrl);
-						
-					p_slot->hpc_ops->green_led_off(p_slot);
-					wait_for_ctrl_irq (ctrl);
+						if (ATTN_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->set_attention_status(p_slot, 1);
+							wait_for_ctrl_irq (ctrl);
+						}
+
+						if (PWR_LED(ctrl->ctrlcap)) {
+							p_slot->hpc_ops->green_led_off(p_slot);
+							wait_for_ctrl_irq (ctrl);
+						}
 
-					/* Done with exclusive hardware access */
-					up(&ctrl->crit_sect);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
+					}
+				}
+				/***********SURPRISE REMOVAL********************/
+				else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || 
+					(ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
+					if (HP_SUPR_RM(ctrl->ctrlcap)) {
+						dbg("Surprise Removal\n");
+						if (p_slot) {
+							surprise_rm_pending = (unsigned long) p_slot;
+							up(&event_semaphore);
+							update_slot_info(p_slot);
+						}
+					}
 				} else {
 					/* refresh notification */
 					if (p_slot)
@@ -1648,25 +1746,29 @@ int pciehp_enable_slot(struct slot *p_sl
 
 	/* Check to see if (latch closed, card present, power off) */
 	down(&p_slot->ctrl->crit_sect);
+
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
 		return 1;
 	}
-	
-	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-	if (rc || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return 1;
+	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
+		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+		if (rc || getstatus) {
+			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+			up(&p_slot->ctrl->crit_sect);
+			return 1;
+		}
 	}
 	
-	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-	if (rc || getstatus) {
-		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return 1;
+	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {	
+		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+		if (rc || getstatus) {
+			info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+			up(&p_slot->ctrl->crit_sect);
+			return 1;
+		}
 	}
 	up(&p_slot->ctrl->crit_sect);
 
@@ -1735,26 +1837,33 @@ int pciehp_disable_slot(struct slot *p_s
 	/* Check to see if (latch closed, card present, power on) */
 	down(&p_slot->ctrl->crit_sect);
 
-	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
-	if (ret || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return 1;
+	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {	
+		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+		if (ret || !getstatus) {
+			info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+			up(&p_slot->ctrl->crit_sect);
+			return 1;
+		}
 	}
 
-	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-	if (ret || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return 1;
+	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
+		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+		if (ret || getstatus) {
+			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+			up(&p_slot->ctrl->crit_sect);
+			return 1;
+		}
 	}
 
-	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-	if (ret || !getstatus) {
-		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
-		up(&p_slot->ctrl->crit_sect);
-		return 1;
+	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {	
+		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+		if (ret || !getstatus) {
+			info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+			up(&p_slot->ctrl->crit_sect);
+			return 1;
+		}
 	}
+
 	up(&p_slot->ctrl->crit_sect);
 
 	func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
diff -puN drivers/pci/hotplug/pciehp.h~bk-pci drivers/pci/hotplug/pciehp.h
--- 25/drivers/pci/hotplug/pciehp.h~bk-pci	2004-11-09 01:18:58.793256040 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehp.h	2004-11-09 01:19:00.628976968 -0800
@@ -127,8 +127,7 @@ struct controller {
 	enum pci_bus_speed speed;
 	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
-	u8 push_flag;
-	u16 ctlrcap;
+	u8 ctrlcap;
 	u16 vendor_id;
 };
 
@@ -180,6 +179,21 @@ struct resource_lists {
 
 #define DISABLE_CARD			1
 
+/* Field definitions in Slot Capabilities Register */
+#define ATTN_BUTTN_PRSN	0x00000001
+#define	PWR_CTRL_PRSN	0x00000002
+#define MRL_SENS_PRSN	0x00000004
+#define ATTN_LED_PRSN	0x00000008
+#define PWR_LED_PRSN	0x00000010
+#define HP_SUPR_RM_SUP	0x00000020
+
+#define ATTN_BUTTN(cap)		(cap & ATTN_BUTTN_PRSN)
+#define POWER_CTRL(cap)		(cap & PWR_CTRL_PRSN)
+#define MRL_SENS(cap)		(cap & MRL_SENS_PRSN)
+#define ATTN_LED(cap)		(cap & ATTN_LED_PRSN)
+#define PWR_LED(cap)		(cap & PWR_LED_PRSN) 
+#define HP_SUPR_RM(cap)		(cap & HP_SUPR_RM_SUP)
+
 /*
  * error Messages
  */
@@ -312,8 +326,7 @@ int pcie_get_ctlr_slot_config(struct con
 		int *num_ctlr_slots,
 		int *first_device_num,
 		int *physical_slot_num,
-		int *updown,
-		int *flags);
+		u8 *ctrlcap);
 
 struct hpc_ops {
 	int	(*power_on_slot)	(struct slot *slot);
diff -puN drivers/pci/hotplug/pciehp_hpc.c~bk-pci drivers/pci/hotplug/pciehp_hpc.c
--- 25/drivers/pci/hotplug/pciehp_hpc.c~bk-pci	2004-11-09 01:18:58.795255736 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehp_hpc.c	2004-11-09 01:19:00.635975904 -0800
@@ -182,7 +182,7 @@ static int pcie_cap_base = 0;		/* Base o
 #define MRL_SENS_PRSN	0x00000004
 #define ATTN_LED_PRSN	0x00000008
 #define PWR_LED_PRSN	0x00000010
-#define HP_SUPR_RM	0x00000020
+#define HP_SUPR_RM_SUP	0x00000020
 #define HP_CAP		0x00000040
 #define SLOT_PWR_VALUE	0x000003F8
 #define SLOT_PWR_LIMIT	0x00000C00
@@ -237,8 +237,8 @@ struct php_ctlr_state_s {
 static spinlock_t hpc_event_lock;
 
 DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
-static struct php_ctlr_state_s *php_ctlr_list_head;	/* HPC state linked list */
-static int ctlr_seq_num;	/* Controller sequence # */
+static struct php_ctlr_state_s *php_ctlr_list_head = 0;	/* HPC state linked list */
+static int ctlr_seq_num = 0;	/* Controller sequence # */
 static spinlock_t list_lock;
 
 static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
@@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct con
 	int *num_ctlr_slots,	/* number of slots in this HPC; only 1 in PCIE  */	
 	int *first_device_num,	/* PCI dev num of the first slot in this PCIE	*/
 	int *physical_slot_num,	/* phy slot num of the first slot in this PCIE	*/
-	int *updown,		/* physical_slot_num increament: 1 or -1	*/
-	int *flags)
+	u8 *ctrlcap)
 {
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	u32 slot_cap;
@@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct con
 	}
 	
 	*physical_slot_num = slot_cap >> 19;
-
-	*updown = -1;
+	dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num);
+	
+	*ctrlcap = slot_cap & 0x0000007f;
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct cont
 		if (php_ctlr->irq) {
 			free_irq(php_ctlr->irq, ctrl);
 			php_ctlr->irq = 0;
+			if (!pcie_mch_quirk) 
+				pci_disable_msi(php_ctlr->pci_dev);
 		}
 	}
 	if (php_ctlr->pci_dev) 
@@ -1259,7 +1261,7 @@ int pcie_init(struct controller * ctrl,
 	static int first = 1;
 	u16 temp_word;
 	u16 cap_reg;
-	u16 intr_enable;
+	u16 intr_enable = 0;
 	u32 slot_cap;
 	int cap_base, saved_cap_base;
 	u16 slot_status, slot_ctrl;
@@ -1402,8 +1404,8 @@ int pcie_init(struct controller * ctrl,
 		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
 	} else {
 		/* Installs the interrupt handler */
-		dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk);
-		if (!pciehp_msi_quirk) {
+		dbg("%s: pcie_mch_quirk = %x\n", __FUNCTION__, pcie_mch_quirk);
+		if (!pcie_mch_quirk) {
 			rc = pci_enable_msi(pdev);
 			if (rc) {
 				info("Can't get msi for the hotplug controller\n");
@@ -1412,6 +1414,7 @@ int pcie_init(struct controller * ctrl,
 			} else 
 				php_ctlr->irq = pdev->irq;
 		}
+
 		rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
 		if (rc) {
@@ -1426,9 +1429,18 @@ int pcie_init(struct controller * ctrl,
 		goto abort_free_ctlr;
 	}
 	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+	dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
 
-	intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
-					PRSN_DETECT_ENABLE;
+	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+	if (ATTN_BUTTN(slot_cap))
+		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+	
+	if (POWER_CTRL(slot_cap))
+		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+	
+	if (MRL_SENS(slot_cap))
+		intr_enable = intr_enable | MRL_DETECT_ENABLE;
 
 	temp_word = (temp_word & ~intr_enable) | intr_enable; 
 
diff -puN drivers/pci/hotplug/pciehp_pci.c~bk-pci drivers/pci/hotplug/pciehp_pci.c
--- 25/drivers/pci/hotplug/pciehp_pci.c~bk-pci	2004-11-09 01:18:58.796255584 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehp_pci.c	2004-11-09 01:19:00.636975752 -0800
@@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci
 {
 	int rc = 0;
 	int j;
+	struct pci_bus *pbus;
 
 	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
 				func->device, func->function);
+	pbus = func->pci_dev->bus;
 
 	for (j=0; j<8 ; j++) {
 		struct pci_dev* temp = pci_find_slot(func->bus,
@@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci
 			pci_remove_bus_device(temp);
 		}
 	}
+	/* 
+	 * Some PCI Express root ports require fixup after hot-plug operation.
+	 */
+	if (pcie_mch_quirk) 
+		pci_fixup_device(pci_fixup_final, pbus->self);
+	
 	return rc;
 }
 
diff -puN drivers/pci/hotplug/pciehprm_acpi.c~bk-pci drivers/pci/hotplug/pciehprm_acpi.c
--- 25/drivers/pci/hotplug/pciehprm_acpi.c~bk-pci	2004-11-09 01:18:58.798255280 -0800
+++ 25-akpm/drivers/pci/hotplug/pciehprm_acpi.c	2004-11-09 01:19:00.638975448 -0800
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
+#include <linux/pci-acpi.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #ifdef	CONFIG_IA64
@@ -50,6 +51,14 @@
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME_OSHP	"OSHP"
 
+/* Status code for running acpi method to gain native control */
+#define NC_NOT_RUN	0
+#define OSC_NOT_EXIST	1
+#define OSC_RUN_FAILED	2
+#define OSHP_NOT_EXIST	3
+#define OSHP_RUN_FAILED	4
+#define NC_RUN_SUCCESS	5
+
 #define	PHP_RES_BUS		0xA0
 #define	PHP_RES_IO		0xA1
 #define	PHP_RES_MEM		0xA2
@@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle	
 }
 
 static void acpi_get__hpp ( struct acpi_bridge	*ab);
-static void acpi_run_oshp ( struct acpi_bridge	*ab);
+static int acpi_run_oshp ( struct acpi_bridge	*ab);
+static int osc_run_status = NC_NOT_RUN;
+static int oshp_run_status = NC_NOT_RUN;
 
 static int acpi_add_slot_to_php_slots(
 	struct acpi_bridge	*ab,
@@ -158,8 +169,9 @@ static int acpi_add_slot_to_php_slots(
 	ab->scanned += 1;
 	if (!ab->_hpp)
 		acpi_get__hpp(ab);
-
-	acpi_run_oshp(ab);
+	
+	if (osc_run_status == OSC_NOT_EXIST)
+		oshp_run_status = acpi_run_oshp(ab);
 
 	if (sun != samesun) {
 		info("acpi_pciehprm:   Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", 
@@ -238,7 +250,7 @@ free_and_return:
 	kfree(ret_buf.pointer);
 }
 
-static void acpi_run_oshp ( struct acpi_bridge	*ab)
+static int acpi_run_oshp ( struct acpi_bridge	*ab)
 {
 	acpi_status		status;
 	u8			*path_name = acpi_path_name(ab->handle);
@@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_
 	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
 	if (ACPI_FAILURE(status)) {
 		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
-	} else
+		oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
+	} else {
+		oshp_run_status = NC_RUN_SUCCESS;
 		dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
-	return;
+		dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status);
+	}
+	return oshp_run_status;
 }
 
 static acpi_status acpi_evaluate_crs(
@@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bri
 		kfree(ab);
 		return NULL;
 	}
+
+	status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); 
+	if (ACPI_FAILURE(status)) {
+		err("%s: status %x\n", __FUNCTION__, status);
+		osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED;
+	} else {
+		osc_run_status = NC_RUN_SUCCESS;
+	}	
+	dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status);
+	
 	build_a_bridge(ab, ab);
 
 	return ab;
@@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctl
 	if (rc)
 		return rc;
 
+	if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) {
+		err("Fails to gain control of native hot-plug\n");
+		rc = -ENODEV;
+	}
+
 	dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
 	return rc;
 }
diff -puN drivers/pci/hotplug/shpchp_ctrl.c~bk-pci drivers/pci/hotplug/shpchp_ctrl.c
--- 25/drivers/pci/hotplug/shpchp_ctrl.c~bk-pci	2004-11-09 01:18:58.799255128 -0800
+++ 25-akpm/drivers/pci/hotplug/shpchp_ctrl.c	2004-11-09 01:19:00.640975144 -0800
@@ -1157,6 +1157,40 @@ static u32 board_added(struct pci_func *
 		return -1;
 	}
 
+	
+	if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
+		if (slots_not_empty)
+			return WRONG_BUS_FREQUENCY;
+		
+		if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
+			err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+			up(&ctrl->crit_sect);
+			return WRONG_BUS_FREQUENCY;
+		}
+		wait_for_ctrl_irq (ctrl);
+		
+		if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
+			err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+				  __FUNCTION__);
+			err("%s: Error code (%d)\n", __FUNCTION__, rc);
+			up(&ctrl->crit_sect);
+			return WRONG_BUS_FREQUENCY;
+		}
+		/* turn on board, blink green LED, turn off Amber LED */
+		if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+			err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
+			up(&ctrl->crit_sect);
+			return rc;
+		}
+		wait_for_ctrl_irq (ctrl);
+
+		if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
+			err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
+			up(&ctrl->crit_sect);
+			return rc;  
+		}
+	}
+ 
 	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
 	/* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
 	/* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC,  0xa = PCI-X 133 Mhz 266, */
diff -puN drivers/pci/hotplug/shpchp_hpc.c~bk-pci drivers/pci/hotplug/shpchp_hpc.c
--- 25/drivers/pci/hotplug/shpchp_hpc.c~bk-pci	2004-11-09 01:18:58.801254824 -0800
+++ 25-akpm/drivers/pci/hotplug/shpchp_hpc.c	2004-11-09 01:19:00.642974840 -0800
@@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct cont
 		if (php_ctlr->irq) {
 			free_irq(php_ctlr->irq, ctrl);
 			php_ctlr->irq = 0;
+			pci_disable_msi(php_ctlr->pci_dev);
 		}
 	}
 	if (php_ctlr->pci_dev) {
diff -puN drivers/pci/Makefile~bk-pci drivers/pci/Makefile
--- 25/drivers/pci/Makefile~bk-pci	2004-11-09 01:18:58.802254672 -0800
+++ 25-akpm/drivers/pci/Makefile	2004-11-09 01:19:00.626977272 -0800
@@ -3,7 +3,8 @@
 #
 
 obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o \
-			names.o pci-driver.o search.o pci-sysfs.o
+			names.o pci-driver.o search.o pci-sysfs.o \
+			rom.o
 obj-$(CONFIG_PROC_FS) += proc.o
 
 ifndef CONFIG_SPARC64
@@ -28,6 +29,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
 obj-$(CONFIG_PCI_MSI) += msi.o
 
+#
+# ACPI Related PCI FW Functions
+#
+obj-$(CONFIG_ACPI)    += pci-acpi.o
+
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
 
diff -puN /dev/null drivers/pci/pci-acpi.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pci/pci-acpi.c	2004-11-09 01:19:00.643974688 -0800
@@ -0,0 +1,209 @@
+/*
+ * File:	pci-acpi.c
+ * Purpose:	Provide PCI supports in ACPI
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <acpi/acpi.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acresrc.h>
+#include <acpi/acpi_bus.h>
+
+#include <linux/pci-acpi.h>
+
+static u32 ctrlset_buf[3] = {0, 0, 0};
+static u32 global_ctrlsets = 0;
+u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
+
+static acpi_status  
+acpi_query_osc (
+	acpi_handle	handle,
+	u32		level,
+	void		*context,
+	void		**retval )
+{
+	acpi_status		status;
+	struct acpi_object_list	input;
+	union acpi_object 	in_params[4];
+	struct acpi_buffer	output;
+	union acpi_object 	out_obj;	
+	u32			osc_dw0;
+
+	/* Setting up output buffer */
+	output.length = sizeof(out_obj) + 3*sizeof(u32);  
+	output.pointer = &out_obj;
+	
+	/* Setting up input parameters */
+	input.count = 4;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= 16;
+	in_params[0].buffer.pointer	= OSC_UUID;
+	in_params[1].type 		= ACPI_TYPE_INTEGER;
+	in_params[1].integer.value 	= 1;
+	in_params[2].type 		= ACPI_TYPE_INTEGER;
+	in_params[2].integer.value	= 3;
+	in_params[3].type		= ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length 	= 12;
+	in_params[3].buffer.pointer 	= (u8 *)context;
+
+	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
+	if (ACPI_FAILURE (status)) {
+		printk(KERN_DEBUG  
+			"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+		return status;
+	}
+	if (out_obj.type != ACPI_TYPE_BUFFER) {
+		printk(KERN_DEBUG  
+			"Evaluate _OSC returns wrong type\n");
+		return AE_TYPE;
+	}
+	osc_dw0 = *((u32 *) out_obj.buffer.pointer);
+	if (osc_dw0) {
+		if (osc_dw0 & OSC_REQUEST_ERROR)
+			printk(KERN_DEBUG "_OSC request fails\n"); 
+		if (osc_dw0 & OSC_INVALID_UUID_ERROR)
+			printk(KERN_DEBUG "_OSC invalid UUID\n"); 
+		if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
+			printk(KERN_DEBUG "_OSC invalid revision\n"); 
+		if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
+			/* Update Global Control Set */
+			global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8));
+			return AE_OK;
+		}
+		return AE_ERROR;
+	}
+
+	/* Update Global Control Set */
+	global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8));
+	return AE_OK;
+}
+
+
+static acpi_status  
+acpi_run_osc (
+	acpi_handle	handle,
+	u32		level,
+	void		*context,
+	void		**retval )
+{
+	acpi_status		status;
+	struct acpi_object_list	input;
+	union acpi_object 	in_params[4];
+	struct acpi_buffer	output;
+	union acpi_object 	out_obj;	
+	u32			osc_dw0;
+
+	/* Setting up output buffer */
+	output.length = sizeof(out_obj) + 3*sizeof(u32);  
+	output.pointer = &out_obj;
+	
+	/* Setting up input parameters */
+	input.count = 4;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= 16;
+	in_params[0].buffer.pointer	= OSC_UUID;
+	in_params[1].type 		= ACPI_TYPE_INTEGER;
+	in_params[1].integer.value 	= 1;
+	in_params[2].type 		= ACPI_TYPE_INTEGER;
+	in_params[2].integer.value	= 3;
+	in_params[3].type		= ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length 	= 12;
+	in_params[3].buffer.pointer 	= (u8 *)context;
+
+	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
+	if (ACPI_FAILURE (status)) {
+		printk(KERN_DEBUG  
+			"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+		return status;
+	}
+	if (out_obj.type != ACPI_TYPE_BUFFER) {
+		printk(KERN_DEBUG  
+			"Evaluate _OSC returns wrong type\n");
+		return AE_TYPE;
+	}
+	osc_dw0 = *((u32 *) out_obj.buffer.pointer);
+	if (osc_dw0) {
+		if (osc_dw0 & OSC_REQUEST_ERROR)
+			printk(KERN_DEBUG "_OSC request fails\n"); 
+		if (osc_dw0 & OSC_INVALID_UUID_ERROR)
+			printk(KERN_DEBUG "_OSC invalid UUID\n"); 
+		if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
+			printk(KERN_DEBUG "_OSC invalid revision\n"); 
+		if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
+			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
+			return AE_SUPPORT;
+		}
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+/**
+ * pci_osc_support_set - register OS support to Firmware
+ * @flags: OS support bits
+ *
+ * Update OS support fields and doing a _OSC Query to obtain an update
+ * from Firmware on supported control bits.
+ **/
+acpi_status pci_osc_support_set(u32 flags)
+{
+	u32 temp;
+
+	if (!(flags & OSC_SUPPORT_MASKS)) {
+		return AE_TYPE;
+	}
+	ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
+
+	/* do _OSC query for all possible controls */
+	temp = ctrlset_buf[OSC_CONTROL_TYPE];
+	ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
+	ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
+	acpi_get_devices ( PCI_ROOT_HID_STRING,
+			acpi_query_osc,
+			ctrlset_buf,
+			NULL );
+	ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
+	ctrlset_buf[OSC_CONTROL_TYPE] = temp;
+	return AE_OK;
+}
+EXPORT_SYMBOL(pci_osc_support_set);
+
+/**
+ * pci_osc_control_set - commit requested control to Firmware
+ * @flags: driver's requested control bits
+ *
+ * Attempt to take control from Firmware on requested control bits.
+ **/
+acpi_status pci_osc_control_set(u32 flags)
+{
+	acpi_status	status;
+	u32		ctrlset;
+
+	ctrlset = (flags & OSC_CONTROL_MASKS);
+	if (!ctrlset) {
+		return AE_TYPE;
+	}
+	if (ctrlset_buf[OSC_SUPPORT_TYPE] && 
+	 	((global_ctrlsets & ctrlset) != ctrlset)) {
+		return AE_SUPPORT;
+	}
+	ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
+	status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+				acpi_run_osc,
+				ctrlset_buf,
+				NULL );
+	if (ACPI_FAILURE (status)) {
+		ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
+	}
+	
+	return status;
+}
+EXPORT_SYMBOL(pci_osc_control_set);
diff -puN drivers/pci/pci.c~bk-pci drivers/pci/pci.c
--- 25/drivers/pci/pci.c~bk-pci	2004-11-09 01:18:58.804254368 -0800
+++ 25-akpm/drivers/pci/pci.c	2004-11-09 01:19:00.646974232 -0800
@@ -375,6 +375,16 @@ pci_enable_device(struct pci_dev *dev)
 }
 
 /**
+ * pcibios_disable_device - disable arch specific PCI resources for device dev
+ * @dev: the PCI device to disable
+ *
+ * Disables architecture specific PCI resources for the device. This
+ * is the default implementation. Architecture implementations can
+ * override this.
+ */
+void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
+
+/**
  * pci_disable_device - Disable PCI device after use
  * @dev: PCI device to be disabled
  *
@@ -394,6 +404,8 @@ pci_disable_device(struct pci_dev *dev)
 		pci_command &= ~PCI_COMMAND_MASTER;
 		pci_write_config_word(dev, PCI_COMMAND, pci_command);
 	}
+
+	pcibios_disable_device(dev);
 }
 
 /**
diff -puN drivers/pci/pci-driver.c~bk-pci drivers/pci/pci-driver.c
--- 25/drivers/pci/pci-driver.c~bk-pci	2004-11-09 01:18:58.805254216 -0800
+++ 25-akpm/drivers/pci/pci-driver.c	2004-11-09 01:19:00.644974536 -0800
@@ -271,17 +271,14 @@ static int pci_device_remove(struct devi
 		pci_dev->driver = NULL;
 	}
 
-#ifdef CONFIG_DEBUG_KERNEL
 	/*
-	 * If the driver decides to stop using the device, it should
-	 * call pci_disable_device().
+	 * We would love to complain here if pci_dev->is_enabled is set, that
+	 * the driver should have called pci_disable_device(), but the
+	 * unfortunate fact is there are too many odd BIOS and bridge setups
+	 * that don't like drivers doing that all of the time.  
+	 * Oh well, we can dream of sane hardware when we sleep, no matter how
+	 * horrible the crap we have to deal with is when we are awake...
 	 */
-	if (pci_dev->is_enabled) {
-		dev_warn(&pci_dev->dev, "Device was removed without properly "
-			 "calling pci_disable_device(). This may need fixing.\n");
-		/* WARN_ON(1); */
-	}
-#endif /* CONFIG_DEBUG_KERNEL */
 
 	pci_dev_put(pci_dev);
 	return 0;
diff -puN drivers/pci/pci.h~bk-pci drivers/pci/pci.h
--- 25/drivers/pci/pci.h~bk-pci	2004-11-09 01:18:58.807253912 -0800
+++ 25-akpm/drivers/pci/pci.h	2004-11-09 01:19:00.646974232 -0800
@@ -2,7 +2,9 @@
 
 extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
 			 char *buffer, int buffer_size);
-extern void pci_create_sysfs_dev_files(struct pci_dev *pdev);
+extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
+extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+extern void pci_cleanup_rom(struct pci_dev *dev);
 extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 				  unsigned long size, unsigned long align,
 				  unsigned long min, unsigned int type_mask,
@@ -61,7 +63,7 @@ extern int pci_visit_dev(struct pci_visi
 /* Lock for read/write access to pci device and bus lists */
 extern spinlock_t pci_bus_lock;
 
-extern int pciehp_msi_quirk;
+extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
 
 /**
diff -puN drivers/pci/pci-sysfs.c~bk-pci drivers/pci/pci-sysfs.c
--- 25/drivers/pci/pci-sysfs.c~bk-pci	2004-11-09 01:18:58.808253760 -0800
+++ 25-akpm/drivers/pci/pci-sysfs.c	2004-11-09 01:19:00.645974384 -0800
@@ -5,6 +5,8 @@
  * (C) Copyright 2002-2004 IBM Corp.
  * (C) Copyright 2003 Matthew Wilcox
  * (C) Copyright 2003 Hewlett-Packard
+ * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
+ * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
  *
  * File attributes for PCI devices
  *
@@ -20,6 +22,8 @@
 
 #include "pci.h"
 
+static int sysfs_initialized;	/* = 0 */
+
 /* show configuration fields */
 #define pci_config_attr(field, format_string)				\
 static ssize_t								\
@@ -164,6 +168,65 @@ pci_write_config(struct kobject *kobj, c
 	return count;
 }
 
+/**
+ * pci_write_rom - used to enable access to the PCI ROM display
+ * @kobj: kernel object handle
+ * @buf: user input
+ * @off: file offset
+ * @count: number of byte in input
+ *
+ * writing anything except 0 enables it
+ */
+static ssize_t
+pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
+
+	if ((off ==  0) && (*buf == '0') && (count == 2))
+		pdev->rom_attr_enabled = 0;
+	else
+		pdev->rom_attr_enabled = 1;
+
+	return count;
+}
+
+/**
+ * pci_read_rom - read a PCI ROM
+ * @kobj: kernel object handle
+ * @buf: where to put the data we read from the ROM
+ * @off: file offset
+ * @count: number of bytes to read
+ *
+ * Put @count bytes starting at @off into @buf from the ROM in the PCI
+ * device corresponding to @kobj.
+ */
+static ssize_t
+pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
+	void __iomem *rom;
+	size_t size;
+
+	if (!pdev->rom_attr_enabled)
+		return -EINVAL;
+	
+	rom = pci_map_rom(pdev, &size);	/* size starts out as PCI window size */
+	if (!rom)
+		return 0;
+		
+	if (off >= size)
+		count = 0;
+	else {
+		if (off + count > size)
+			count = size - off;
+		
+		memcpy_fromio(buf, rom + off, count);
+	}
+	pci_unmap_rom(pdev, rom);
+		
+	return count;
+}
+
 static struct bin_attribute pci_config_attr = {
 	.attr =	{
 		.name = "config",
@@ -186,13 +249,68 @@ static struct bin_attribute pcie_config_
 	.write = pci_write_config,
 };
 
-void pci_create_sysfs_dev_files (struct pci_dev *pdev)
+int pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
+	if (!sysfs_initialized)
+		return -EACCES;
+
 	if (pdev->cfg_size < 4096)
 		sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
 		sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 
+	/* If the device has a ROM, try to expose it in sysfs. */
+	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
+		struct bin_attribute *rom_attr;
+		
+		rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC);
+		if (rom_attr) {
+			pdev->rom_attr = rom_attr;
+			rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+			rom_attr->attr.name = "rom";
+			rom_attr->attr.mode = S_IRUSR;
+			rom_attr->attr.owner = THIS_MODULE;
+			rom_attr->read = pci_read_rom;
+			rom_attr->write = pci_write_rom;
+			sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+		}
+	}
 	/* add platform-specific attributes */
 	pcibios_add_platform_entries(pdev);
+	
+	return 0;
+}
+
+/**
+ * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
+ * @pdev: device whose entries we should free
+ *
+ * Cleanup when @pdev is removed from sysfs.
+ */
+void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+	if (pdev->cfg_size < 4096)
+		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+	else
+		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+
+	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
+		if (pdev->rom_attr) {
+			sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+			kfree(pdev->rom_attr);
+		}
+	}
 }
+
+static int __init pci_sysfs_init(void)
+{
+	struct pci_dev *pdev = NULL;
+	
+	sysfs_initialized = 1;
+	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
+		pci_create_sysfs_dev_files(pdev);
+
+	return 0;
+}
+
+__initcall(pci_sysfs_init);
diff -puN drivers/pci/probe.c~bk-pci drivers/pci/probe.c
--- 25/drivers/pci/probe.c~bk-pci	2004-11-09 01:18:58.810253456 -0800
+++ 25-akpm/drivers/pci/probe.c	2004-11-09 01:19:00.647974080 -0800
@@ -170,7 +170,7 @@ static void pci_read_bases(struct pci_de
 		if (sz && sz != 0xffffffff) {
 			sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK);
 			if (sz) {
-				res->flags = (l & PCI_ROM_ADDRESS_ENABLE) |
+				res->flags = (l & IORESOURCE_ROM_ENABLE) |
 				  IORESOURCE_MEM | IORESOURCE_PREFETCH |
 				  IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
 				res->start = l & PCI_ROM_ADDRESS_MASK;
@@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_d
 	/* "Unknown power state" */
 	dev->current_state = 4;
 
+	/* Early fixups, before probing the BARs */
+	pci_fixup_device(pci_fixup_early, dev);
+
 	switch (dev->hdr_type) {		    /* header type */
 	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
 		if (class == PCI_CLASS_BRIDGE_PCI)
diff -puN drivers/pci/quirks.c~bk-pci drivers/pci/quirks.c
--- 25/drivers/pci/quirks.c~bk-pci	2004-11-09 01:18:58.812253152 -0800
+++ 25-akpm/drivers/pci/quirks.c	2004-11-09 01:19:00.648973928 -0800
@@ -1136,7 +1136,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
 #endif
 
 #ifdef CONFIG_SCSI_SATA
-static void __init quirk_intel_ide_combined(struct pci_dev *pdev)
+static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
 {
 	u8 prog, comb, tmp;
 	int ich = 0;
@@ -1210,14 +1210,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
 #endif /* CONFIG_SCSI_SATA */
 
 
-int pciehp_msi_quirk;
+int pcie_mch_quirk;
 
-static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
+static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
 {
-	pciehp_msi_quirk = 1;
+	pcie_mch_quirk = 1;
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi );
-
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7520_MCH,	quirk_pcie_mch );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_pcie_mch );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_pcie_mch );
 
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
 {
@@ -1266,4 +1267,7 @@ void pci_fixup_device(enum pci_fixup_pas
 	pci_do_fixups(dev, start, end);
 }
 
-EXPORT_SYMBOL(pciehp_msi_quirk);
+EXPORT_SYMBOL(pcie_mch_quirk);
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pci_fixup_device);
+#endif
diff -puN drivers/pci/remove.c~bk-pci drivers/pci/remove.c
--- 25/drivers/pci/remove.c~bk-pci	2004-11-09 01:18:58.813253000 -0800
+++ 25-akpm/drivers/pci/remove.c	2004-11-09 01:19:00.649973776 -0800
@@ -16,6 +16,7 @@ static void pci_free_resources(struct pc
 
  	msi_remove_pci_irq_vectors(dev);
 
+	pci_cleanup_rom(dev);
 	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 		struct resource *res = dev->resource + i;
 		if (res->parent)
@@ -26,6 +27,7 @@ static void pci_free_resources(struct pc
 static void pci_destroy_dev(struct pci_dev *dev)
 {
 	pci_proc_detach_device(dev);
+	pci_remove_sysfs_dev_files(dev);
 	device_unregister(&dev->dev);
 
 	/* Remove the device from the device lists, and prevent any further
diff -puN /dev/null drivers/pci/rom.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pci/rom.c	2004-11-09 01:19:00.650973624 -0800
@@ -0,0 +1,225 @@
+/*
+ * drivers/pci/rom.c
+ *
+ * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
+ * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
+ *
+ * PCI ROM access routines
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "pci.h"
+
+/**
+ * pci_enable_rom - enable ROM decoding for a PCI device
+ * @dev: PCI device to enable
+ *
+ * Enable ROM decoding on @dev.  This involves simply turning on the last
+ * bit of the PCI ROM BAR.  Note that some cards may share address decoders
+ * between the ROM and other resources, so enabling it may disable access
+ * to MMIO registers or other card memory.
+ */
+static void
+pci_enable_rom(struct pci_dev *pdev)
+{
+	u32 rom_addr;
+	
+	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
+	rom_addr |= PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
+}
+
+/**
+ * pci_disable_rom - disable ROM decoding for a PCI device
+ * @dev: PCI device to disable
+ *
+ * Disable ROM decoding on a PCI device by turning off the last bit in the
+ * ROM BAR.
+ */
+static void
+pci_disable_rom(struct pci_dev *pdev)
+{
+	u32 rom_addr;
+	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
+	rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
+}
+
+/**
+ * pci_map_rom - map a PCI ROM to kernel space
+ * @dev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ * @return: kernel virtual pointer to image of ROM
+ *
+ * Map a PCI ROM into kernel space. If ROM is boot video ROM,
+ * the shadow BIOS copy will be returned instead of the 
+ * actual ROM.
+ */
+void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
+{
+	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+	loff_t start;
+	void __iomem *rom;
+	void __iomem *image;
+	int last_image;
+	
+	if (res->flags & IORESOURCE_ROM_SHADOW) {	/* IORESOURCE_ROM_SHADOW only set on x86 */
+		start = (loff_t)0xC0000; 	/* primary video rom always starts here */
+		*size = 0x20000;		/* cover C000:0 through E000:0 */
+	} else {
+		if (res->flags & IORESOURCE_ROM_COPY) {
+			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+			return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE);
+		} else {
+			/* assign the ROM an address if it doesn't have one */
+			if (res->parent == NULL)
+				pci_assign_resource(pdev, PCI_ROM_RESOURCE);
+	
+			start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
+			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+			if (*size == 0)
+				return NULL;
+			
+			/* Enable ROM space decodes */
+			pci_enable_rom(pdev);
+		}
+	}
+	
+	rom = ioremap(start, *size);
+	if (!rom) {
+		/* restore enable if ioremap fails */
+		if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY)))
+			pci_disable_rom(pdev);
+		return NULL;
+	}		
+
+	/* Try to find the true size of the ROM since sometimes the PCI window */
+	/* size is much larger than the actual size of the ROM. */
+	/* True size is important if the ROM is going to be copied. */
+	image = rom;
+	do {
+		void __iomem *pds;
+		/* Standard PCI ROMs start out with these bytes 55 AA */
+		if (readb(image) != 0x55)
+			break;
+		if (readb(image + 1) != 0xAA)
+			break;
+		/* get the PCI data structure and check its signature */
+		pds = image + readw(image + 24);
+		if (readb(pds) != 'P')
+			break;
+		if (readb(pds + 1) != 'C')
+			break;
+		if (readb(pds + 2) != 'I')
+			break;
+		if (readb(pds + 3) != 'R')
+			break;
+		last_image = readb(pds + 21) & 0x80;
+		/* this length is reliable */
+		image += readw(pds + 16) * 512;
+	} while (!last_image);
+
+	*size = image - rom;
+
+	return rom;
+}
+
+/**
+ * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
+ * @dev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ * @return: kernel virtual pointer to image of ROM
+ *
+ * Map a PCI ROM into kernel space. If ROM is boot video ROM,
+ * the shadow BIOS copy will be returned instead of the 
+ * actual ROM.
+ */
+void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
+{
+	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+	void __iomem *rom;
+	
+	rom = pci_map_rom(pdev, size);
+	if (!rom)
+		return NULL;
+		
+	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW))
+		return rom;
+		
+	res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
+	if (!res->start) 
+		return rom;
+
+	res->end = res->start + *size; 
+	memcpy_fromio((void*)res->start, rom, *size);
+	pci_unmap_rom(pdev, rom);
+	res->flags |= IORESOURCE_ROM_COPY;
+	
+	return (void __iomem *)res->start;
+}
+
+/**
+ * pci_unmap_rom - unmap the ROM from kernel space
+ * @dev: pointer to pci device struct
+ * @rom: virtual address of the previous mapping
+ *
+ * Remove a mapping of a previously mapped ROM
+ */
+void 
+pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
+{
+	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+
+	if (res->flags & IORESOURCE_ROM_COPY)
+		return;
+		
+	iounmap(rom);
+		
+	/* Disable again before continuing, leave enabled if pci=rom */
+	if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
+		pci_disable_rom(pdev);
+}
+
+/**
+ * pci_remove_rom - disable the ROM and remove its sysfs attribute
+ * @dev: pointer to pci device struct
+ *
+ */
+void 
+pci_remove_rom(struct pci_dev *pdev) 
+{
+	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+	
+	if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+	if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY)))
+		pci_disable_rom(pdev);
+}
+
+/**
+ * pci_cleanup_rom - internal routine for freeing the ROM copy created 
+ * by pci_map_rom_copy called from remove.c
+ * @dev: pointer to pci device struct
+ *
+ */
+void 
+pci_cleanup_rom(struct pci_dev *pdev) 
+{
+	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+	if (res->flags & IORESOURCE_ROM_COPY) {
+		kfree((void*)res->start);
+		res->flags &= ~IORESOURCE_ROM_COPY;
+		res->start = 0;
+		res->end = 0;
+	}
+}
+
+EXPORT_SYMBOL(pci_map_rom);
+EXPORT_SYMBOL(pci_map_rom_copy);
+EXPORT_SYMBOL(pci_unmap_rom);
+EXPORT_SYMBOL(pci_remove_rom);
diff -puN drivers/pci/setup-res.c~bk-pci drivers/pci/setup-res.c
--- 25/drivers/pci/setup-res.c~bk-pci	2004-11-09 01:18:58.815252696 -0800
+++ 25-akpm/drivers/pci/setup-res.c	2004-11-09 01:19:00.651973472 -0800
@@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev,
 	if (resno < 6) {
 		reg = PCI_BASE_ADDRESS_0 + 4 * resno;
 	} else if (resno == PCI_ROM_RESOURCE) {
-		new |= res->flags & PCI_ROM_ADDRESS_ENABLE;
+		new |= res->flags & IORESOURCE_ROM_ENABLE;
 		reg = dev->rom_base_reg;
 	} else {
 		/* Hmm, non-standard resource. */
diff -puN include/asm-generic/vmlinux.lds.h~bk-pci include/asm-generic/vmlinux.lds.h
--- 25/include/asm-generic/vmlinux.lds.h~bk-pci	2004-11-09 01:18:58.816252544 -0800
+++ 25-akpm/include/asm-generic/vmlinux.lds.h	2004-11-09 01:19:00.651973472 -0800
@@ -18,6 +18,9 @@
 									\
 	/* PCI quirks */						\
 	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start_pci_fixups_early) = .;		\
+		*(.pci_fixup_early)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_early) = .;		\
 		VMLINUX_SYMBOL(__start_pci_fixups_header) = .;		\
 		*(.pci_fixup_header)					\
 		VMLINUX_SYMBOL(__end_pci_fixups_header) = .;		\
diff -puN include/linux/ioport.h~bk-pci include/linux/ioport.h
--- 25/include/linux/ioport.h~bk-pci	2004-11-09 01:18:58.817252392 -0800
+++ 25-akpm/include/linux/ioport.h	2004-11-09 01:19:00.652973320 -0800
@@ -82,6 +82,11 @@ struct resource_list {
 #define IORESOURCE_MEM_SHADOWABLE	(1<<5)	/* dup: IORESOURCE_SHADOWABLE */
 #define IORESOURCE_MEM_EXPANSIONROM	(1<<6)
 
+/* PCI ROM control bits (IORESOURCE_BITS) */
+#define IORESOURCE_ROM_ENABLE		(1<<0)	/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
+#define IORESOURCE_ROM_SHADOW		(1<<1)	/* ROM is copy at C000:0 */
+#define IORESOURCE_ROM_COPY		(1<<2)	/* ROM is alloc'd copy, resource field overlaid */
+
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
diff -puN /dev/null include/linux/pci-acpi.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/linux/pci-acpi.h	2004-11-09 01:19:00.652973320 -0800
@@ -0,0 +1,61 @@
+/*
+ * File		pci-acpi.h
+ *
+ * Copyright (C) 2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+ */
+
+#ifndef _PCI_ACPI_H_
+#define _PCI_ACPI_H_
+
+#define OSC_QUERY_TYPE			0
+#define OSC_SUPPORT_TYPE 		1
+#define OSC_CONTROL_TYPE		2
+#define OSC_SUPPORT_MASKS		0x1f
+
+/*
+ * _OSC DW0 Definition 
+ */
+#define OSC_QUERY_ENABLE		1
+#define OSC_REQUEST_ERROR		2
+#define OSC_INVALID_UUID_ERROR		4
+#define OSC_INVALID_REVISION_ERROR	8
+#define OSC_CAPABILITIES_MASK_ERROR	16
+
+/*
+ * _OSC DW1 Definition (OS Support Fields)
+ */
+#define OSC_EXT_PCI_CONFIG_SUPPORT		1
+#define OSC_ACTIVE_STATE_PWR_SUPPORT 		2
+#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT	4
+#define OSC_PCI_SEGMENT_GROUPS_SUPPORT		8
+#define OSC_MSI_SUPPORT				16
+
+/*
+ * _OSC DW1 Definition (OS Control Fields)
+ */
+#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL	1
+#define OSC_SHPC_NATIVE_HP_CONTROL 		2
+#define OSC_PCI_EXPRESS_PME_CONTROL		4
+#define OSC_PCI_EXPRESS_AER_CONTROL		8
+#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL	16
+
+#define OSC_CONTROL_MASKS 	(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | 	\
+				OSC_SHPC_NATIVE_HP_CONTROL | 		\
+				OSC_PCI_EXPRESS_PME_CONTROL |		\
+				OSC_PCI_EXPRESS_AER_CONTROL |		\
+				OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
+
+#ifdef CONFIG_ACPI
+extern acpi_status pci_osc_control_set(u32 flags);
+extern acpi_status pci_osc_support_set(u32 flags);
+#else
+#if !defined(acpi_status)
+typedef u32 		acpi_status;
+#define AE_ERROR      	(acpi_status) (0x0001)
+#endif    
+static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;}
+static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} 
+#endif
+
+#endif	/* _PCI_ACPI_H_ */
diff -puN include/linux/pci.h~bk-pci include/linux/pci.h
--- 25/include/linux/pci.h~bk-pci	2004-11-09 01:18:58.819252088 -0800
+++ 25-akpm/include/linux/pci.h	2004-11-09 01:19:00.654973016 -0800
@@ -537,6 +537,8 @@ struct pci_dev {
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	
 	u32		saved_config_space[16]; /* config space saved at suspend time */
+	struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
+	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
 #ifdef CONFIG_PCI_NAMES
 #define PCI_NAME_SIZE	96
 #define PCI_NAME_HALF	__stringify(43)	/* less than half to handle slop */
@@ -785,6 +787,12 @@ int pci_dac_set_dma_mask(struct pci_dev 
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_assign_resource(struct pci_dev *dev, int i);
 
+/* ROM control related routines */
+void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size);
+void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
+void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
+void pci_remove_rom(struct pci_dev *pdev);
+
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
 int pci_restore_state(struct pci_dev *dev);
@@ -989,31 +997,33 @@ static inline char *pci_name(struct pci_
  */
 
 struct pci_fixup {
-	u16 vendor, device;			/* You can use PCI_ANY_ID here of course */
+	u16 vendor, device;	/* You can use PCI_ANY_ID here of course */
 	void (*hook)(struct pci_dev *dev);
 };
 
 enum pci_fixup_pass {
-	pci_fixup_header,	/* Called immediately after reading configuration header */
+	pci_fixup_early,	/* Before probing BARs */
+	pci_fixup_header,	/* After reading configuration header */
 	pci_fixup_final,	/* Final phase of device fixups */
 	pci_fixup_enable,	/* pci_enable_device() time */
 };
 
 /* Anonymous variables would be nice... */
-#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)					\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_header"))) = {				\
-		vendor, device, hook };
-
-#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)				\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_final"))) = {				\
-		vendor, device, hook };
-
-#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)				\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_enable"))) = {				\
-		vendor, device, hook };
+#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook)	\
+	static struct pci_fixup __pci_fixup_##name __attribute_used__	\
+	__attribute__((__section__(#section))) = { vendor, device, hook };
+#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\
+			vendor##device##hook, vendor, device, hook)
 
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
diff -puN include/linux/pci_ids.h~bk-pci include/linux/pci_ids.h
--- 25/include/linux/pci_ids.h~bk-pci	2004-11-09 01:18:58.821251784 -0800
+++ 25-akpm/include/linux/pci_ids.h	2004-11-09 01:19:00.667971040 -0800
@@ -2209,8 +2209,14 @@
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
 #define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
 #define PCI_DEVICE_ID_INTEL_82855GM_IG	0x3582
-#define PCI_DEVICE_ID_INTEL_SMCH	0x3590
+#define PCI_DEVICE_ID_INTEL_E7520_MCH	0x3590
 #define PCI_DEVICE_ID_INTEL_E7320_MCH	0x3592
+#define PCI_DEVICE_ID_INTEL_MCH_PA	0x3595
+#define PCI_DEVICE_ID_INTEL_MCH_PA1	0x3596
+#define PCI_DEVICE_ID_INTEL_MCH_PB	0x3597
+#define PCI_DEVICE_ID_INTEL_MCH_PB1	0x3598
+#define PCI_DEVICE_ID_INTEL_MCH_PC	0x3599
+#define PCI_DEVICE_ID_INTEL_MCH_PC1	0x359a
 #define PCI_DEVICE_ID_INTEL_E7525_MCH	0x359e
 #define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
_
