Browse Source

Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (74 commits)
  PCI: make msi_free_irqs() to use msix_mask_irq() instead of open coded write
  PCI: Fix the NIU MSI-X problem in a better way
  PCI ASPM: remove get_root_port_link
  PCI ASPM: cleanup pcie_aspm_sanity_check
  PCI ASPM: remove has_switch field
  PCI ASPM: cleanup calc_Lx_latency
  PCI ASPM: cleanup pcie_aspm_get_cap_device
  PCI ASPM: cleanup clkpm checks
  PCI ASPM: cleanup __pcie_aspm_check_state_one
  PCI ASPM: cleanup initialization
  PCI ASPM: cleanup change input argument of aspm functions
  PCI ASPM: cleanup misc in struct pcie_link_state
  PCI ASPM: cleanup clkpm state in struct pcie_link_state
  PCI ASPM: cleanup latency field in struct pcie_link_state
  PCI ASPM: cleanup aspm state field in struct pcie_link_state
  PCI ASPM: fix typo in struct pcie_link_state
  PCI: drivers/pci/slot.c should depend on CONFIG_SYSFS
  PCI: remove redundant __msi_set_enable()
  PCI PM: consistently use type bool for wake enable variable
  x86/ACPI: Correct maximum allowed _CRS returned resources and warn if exceeded
  ...
Linus Torvalds 16 years ago
parent
commit
59ef7a83f1
55 changed files with 3038 additions and 2201 deletions
  1. 7 0
      Documentation/ABI/testing/sysfs-bus-pci
  2. 25 0
      Documentation/PCI/pcieaer-howto.txt
  3. 10 1
      Documentation/kernel-parameters.txt
  4. 24 14
      arch/powerpc/platforms/pseries/eeh_driver.c
  5. 1 0
      arch/x86/include/asm/pci.h
  6. 1 1
      arch/x86/include/asm/pci_x86.h
  7. 28 7
      arch/x86/pci/acpi.c
  8. 1 1
      arch/x86/pci/amd_bus.c
  9. 2 2
      arch/x86/pci/common.c
  10. 1 0
      drivers/acpi/Kconfig
  11. 2 1
      drivers/pci/Makefile
  12. 19 0
      drivers/pci/access.c
  13. 15 3
      drivers/pci/bus.c
  14. 2 2
      drivers/pci/hotplug/Kconfig
  15. 0 1
      drivers/pci/hotplug/acpiphp_core.c
  16. 0 1
      drivers/pci/hotplug/cpci_hotplug_core.c
  17. 95 72
      drivers/pci/hotplug/cpqphp.h
  18. 560 608
      drivers/pci/hotplug/cpqphp_core.c
  19. 191 180
      drivers/pci/hotplug/cpqphp_ctrl.c
  20. 51 46
      drivers/pci/hotplug/cpqphp_nvram.c
  21. 297 302
      drivers/pci/hotplug/cpqphp_pci.c
  22. 1 1
      drivers/pci/hotplug/ibmphp_core.c
  23. 84 71
      drivers/pci/hotplug/pci_hotplug_core.c
  24. 0 3
      drivers/pci/hotplug/pciehp.h
  25. 1 111
      drivers/pci/hotplug/pciehp_core.c
  26. 0 31
      drivers/pci/hotplug/pciehp_hpc.c
  27. 0 1
      drivers/pci/hotplug/pcihp_skeleton.c
  28. 0 1
      drivers/pci/hotplug/rpaphp_core.c
  29. 0 1
      drivers/pci/hotplug/sgi_hotplug.c
  30. 0 1
      drivers/pci/hotplug/shpchp_core.c
  31. 4 2
      drivers/pci/iov.c
  32. 51 49
      drivers/pci/msi.c
  33. 4 10
      drivers/pci/msi.h
  34. 158 88
      drivers/pci/pci.c
  35. 15 0
      drivers/pci/pcie/aer/Kconfig
  36. 18 0
      drivers/pci/pcie/aer/Kconfig.debug
  37. 3 0
      drivers/pci/pcie/aer/Makefile
  38. 473 0
      drivers/pci/pcie/aer/aer_inject.c
  39. 2 1
      drivers/pci/pcie/aer/aerdrv.c
  40. 6 0
      drivers/pci/pcie/aer/aerdrv.h
  41. 191 87
      drivers/pci/pcie/aer/aerdrv_core.c
  42. 131 0
      drivers/pci/pcie/aer/ecrc.c
  43. 371 416
      drivers/pci/pcie/aspm.c
  44. 8 3
      drivers/pci/probe.c
  45. 24 0
      drivers/pci/quirks.c
  46. 0 2
      drivers/pci/remove.c
  47. 1 31
      drivers/pci/search.c
  48. 42 11
      drivers/pci/setup-bus.c
  49. 36 13
      drivers/pci/setup-res.c
  50. 39 0
      drivers/pci/slot.c
  51. 2 0
      include/linux/ioport.h
  52. 2 2
      include/linux/pci-acpi.h
  53. 24 11
      include/linux/pci.h
  54. 13 10
      include/linux/pci_hotplug.h
  55. 2 2
      include/linux/pci_regs.h

+ 7 - 0
Documentation/ABI/testing/sysfs-bus-pci

@@ -122,3 +122,10 @@ Description:
 		This symbolic link appears when a device is a Virtual Function.
 		The symbolic link points to the PCI device sysfs entry of the
 		Physical Function this device associates with.
+
+What:		/sys/bus/pci/slots/.../module
+Date:		June 2009
+Contact:	linux-pci@vger.kernel.org
+Description:
+		This symbolic link points to the PCI hotplug controller driver
+		module that manages the hotplug slot.

+ 25 - 0
Documentation/PCI/pcieaer-howto.txt

@@ -61,6 +61,10 @@ be initiated although firmwares have no _OSC support. To enable the
 walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
 when booting kernel. Note that forceload=n by default.
 
+nosourceid, another parameter of type bool, can be used when broken
+hardware (mostly chipsets) has root ports that cannot obtain the reporting
+source ID. nosourceid=n by default.
+
 2.3 AER error output
 When a PCI-E AER error is captured, an error message will be outputed to
 console. If it's a correctable error, it is outputed as a warning.
@@ -246,3 +250,24 @@ with the PCI Express AER Root driver?
 A: It could call the helper functions to enable AER in devices and
 cleanup uncorrectable status register. Pls. refer to section 3.3.
 
+
+4. Software error injection
+
+Debugging PCIE AER error recovery code is quite difficult because it
+is hard to trigger real hardware errors. Software based error
+injection can be used to fake various kinds of PCIE errors.
+
+First you should enable PCIE AER software error injection in kernel
+configuration, that is, following item should be in your .config.
+
+CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
+
+After reboot with new kernel or insert the module, a device file named
+/dev/aer_inject should be created.
+
+Then, you need a user space tool named aer-inject, which can be gotten
+from:
+    http://www.kernel.org/pub/linux/utils/pci/aer-inject/
+
+More information about aer-inject can be found in the document comes
+with its source code.

+ 10 - 1
Documentation/kernel-parameters.txt

@@ -1776,6 +1776,9 @@ and is between 256 and 4096 characters. It is defined in the file
 				root domains (aka PCI segments, in ACPI-speak).
 		nommconf	[X86] Disable use of MMCONFIG for PCI
 				Configuration
+		check_enable_amd_mmconf [X86] check for and enable
+				properly configured MMIO access to PCI
+				config space on AMD family 10h CPU
 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
 				enabled, this kernel boot option can be used to
 				disable the use of MSI interrupts system-wide.
@@ -1828,7 +1831,7 @@ and is between 256 and 4096 characters. It is defined in the file
 				IRQ routing is enabled.
 		noacpi		[X86] Do not use ACPI for IRQ routing
 				or for PCI scanning.
-		use_crs		[X86] Use _CRS for PCI resource
+		nocrs		[X86] Don't use _CRS for PCI resource
 				allocation.
 		routeirq	Do IRQ routing for all PCI devices.
 				This is normally done in pci_enable_device(),
@@ -1865,6 +1868,12 @@ and is between 256 and 4096 characters. It is defined in the file
 				PAGE_SIZE is used as alignment.
 				PCI-PCI bridge can be specified, if resource
 				windows need to be expanded.
+		ecrc=		Enable/disable PCIe ECRC (transaction layer
+				end-to-end CRC checking).
+				bios: Use BIOS/firmware settings. This is the
+				the default.
+				off: Turn ECRC off
+				on: Turn ECRC on.
 
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.

+ 24 - 14
arch/powerpc/platforms/pseries/eeh_driver.c

@@ -122,7 +122,7 @@ static void eeh_enable_irq(struct pci_dev *dev)
  * passed back in "userdata".
  */
 
-static void eeh_report_error(struct pci_dev *dev, void *userdata)
+static int eeh_report_error(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
@@ -130,19 +130,21 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
 	dev->error_state = pci_channel_io_frozen;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->error_detected)
-		return;
+		return 0;
 
 	rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
 
 	/* A driver that needs a reset trumps all others */
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+
+	return 0;
 }
 
 /**
@@ -153,7 +155,7 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
  * Cumulative response passed back in "userdata".
  */
 
-static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
+static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
@@ -161,26 +163,28 @@ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
 	if (!driver ||
 	    !driver->err_handler ||
 	    !driver->err_handler->mmio_enabled)
-		return;
+		return 0;
 
 	rc = driver->err_handler->mmio_enabled (dev);
 
 	/* A driver that needs a reset trumps all others */
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+
+	return 0;
 }
 
 /**
  * eeh_report_reset - tell device that slot has been reset
  */
 
-static void eeh_report_reset(struct pci_dev *dev, void *userdata)
+static int eeh_report_reset(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
 
 	if (!driver)
-		return;
+		return 0;
 
 	dev->error_state = pci_channel_io_normal;
 
@@ -188,35 +192,39 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->slot_reset)
-		return;
+		return 0;
 
 	rc = driver->err_handler->slot_reset(dev);
 	if ((*res == PCI_ERS_RESULT_NONE) ||
 	    (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
 	if (*res == PCI_ERS_RESULT_DISCONNECT &&
 	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
+
+	return 0;
 }
 
 /**
  * eeh_report_resume - tell device to resume normal operations
  */
 
-static void eeh_report_resume(struct pci_dev *dev, void *userdata)
+static int eeh_report_resume(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
 
 	dev->error_state = pci_channel_io_normal;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_enable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->resume)
-		return;
+		return 0;
 
 	driver->err_handler->resume(dev);
+
+	return 0;
 }
 
 /**
@@ -226,22 +234,24 @@ static void eeh_report_resume(struct pci_dev *dev, void *userdata)
  * dead, and that no further recovery attempts will be made on it.
  */
 
-static void eeh_report_failure(struct pci_dev *dev, void *userdata)
+static int eeh_report_failure(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
 
 	dev->error_state = pci_channel_io_perm_failure;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->error_detected)
-		return;
+		return 0;
 
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
+
+	return 0;
 }
 
 /* ------------------------------------------------------- */

+ 1 - 0
arch/x86/include/asm/pci.h

@@ -130,6 +130,7 @@ extern void pci_iommu_alloc(void);
 
 /* generic pci stuff */
 #include <asm-generic/pci.h>
+#define PCIBIOS_MAX_MEM_32 0xffffffff
 
 #ifdef CONFIG_NUMA
 /* Returns the node based on pci bus */

+ 1 - 1
arch/x86/include/asm/pci_x86.h

@@ -25,7 +25,7 @@
 #define PCI_BIOS_IRQ_SCAN	0x2000
 #define PCI_ASSIGN_ALL_BUSSES	0x4000
 #define PCI_CAN_SKIP_ISA_ALIGN	0x8000
-#define PCI_USE__CRS		0x10000
+#define PCI_NO_ROOT_CRS		0x10000
 #define PCI_CHECK_ENABLE_AMD_MMCONF	0x20000
 #define PCI_HAS_IO_ECS		0x40000
 #define PCI_NOASSIGN_ROMS	0x80000

+ 28 - 7
arch/x86/pci/acpi.c

@@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data)
 	struct acpi_resource_address64 addr;
 	acpi_status status;
 
-	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
-		return AE_OK;
-
 	status = resource_to_addr(acpi_res, &addr);
 	if (ACPI_SUCCESS(status))
 		info->res_num++;
 	return AE_OK;
 }
 
+static int
+bus_has_transparent_bridge(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 class = dev->class >> 8;
+
+		if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
+			return true;
+	}
+	return false;
+}
+
 static acpi_status
 setup_resource(struct acpi_resource *acpi_res, void *data)
 {
@@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	acpi_status status;
 	unsigned long flags;
 	struct resource *root;
-
-	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
-		return AE_OK;
+	int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
 
 	status = resource_to_addr(acpi_res, &addr);
 	if (!ACPI_SUCCESS(status))
@@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	res->end = res->start + addr.address_length - 1;
 	res->child = NULL;
 
+	if (bus_has_transparent_bridge(info->bus))
+		max_root_bus_resources -= 3;
+	if (info->res_num >= max_root_bus_resources) {
+		printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
+			"from %s for %s due to _CRS returning more than "
+			"%d resource descriptors\n", (unsigned long) res->start,
+			(unsigned long) res->end, root->name, info->name,
+			max_root_bus_resources);
+		info->res_num++;
+		return AE_OK;
+	}
+
 	if (insert_resource(root, res)) {
 		printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
 			"from %s for %s\n", (unsigned long) res->start,
@@ -217,7 +238,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 #endif
 	}
 
-	if (bus && (pci_probe & PCI_USE__CRS))
+	if (bus && !(pci_probe & PCI_NO_ROOT_CRS))
 		get_current_resources(device, busnum, domain, bus);
 	return bus;
 }

+ 1 - 1
arch/x86/pci/amd_bus.c

@@ -101,7 +101,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
 	struct pci_root_info *info;
 
 	/* don't go for it if _CRS is used */
-	if (pci_probe & PCI_USE__CRS)
+	if (!(pci_probe & PCI_NO_ROOT_CRS))
 		return;
 
 	/* if only one root bus, don't need to anything */

+ 2 - 2
arch/x86/pci/common.c

@@ -515,8 +515,8 @@ char * __devinit  pcibios_setup(char *str)
 	} else if (!strcmp(str, "assign-busses")) {
 		pci_probe |= PCI_ASSIGN_ALL_BUSSES;
 		return NULL;
-	} else if (!strcmp(str, "use_crs")) {
-		pci_probe |= PCI_USE__CRS;
+	} else if (!strcmp(str, "nocrs")) {
+		pci_probe |= PCI_NO_ROOT_CRS;
 		return NULL;
 	} else if (!strcmp(str, "earlydump")) {
 		pci_early_dump_regs = 1;

+ 1 - 0
drivers/acpi/Kconfig

@@ -266,6 +266,7 @@ config ACPI_DEBUG_FUNC_TRACE
 
 config ACPI_PCI_SLOT
 	tristate "PCI slot detection driver"
+	depends on SYSFS
 	default n
 	help
 	  This driver creates entries in /sys/bus/pci/slots/ for all PCI

+ 2 - 1
drivers/pci/Makefile

@@ -2,10 +2,11 @@
 # Makefile for the PCI bus specific drivers.
 #
 
-obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
+obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o \
 			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
 			irq.o
 obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_SYSFS) += slot.o
 
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/

+ 19 - 0
drivers/pci/access.c

@@ -66,6 +66,25 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
 EXPORT_SYMBOL(pci_bus_write_config_word);
 EXPORT_SYMBOL(pci_bus_write_config_dword);
 
+/**
+ * pci_bus_set_ops - Set raw operations of pci bus
+ * @bus:	pci bus struct
+ * @ops:	new raw operations
+ *
+ * Return previous raw operations
+ */
+struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
+{
+	struct pci_ops *old_ops;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_lock, flags);
+	old_ops = bus->ops;
+	bus->ops = ops;
+	spin_unlock_irqrestore(&pci_lock, flags);
+	return old_ops;
+}
+EXPORT_SYMBOL(pci_bus_set_ops);
 
 /**
  * pci_read_vpd - Read one entry from Vital Product Data

+ 15 - 3
drivers/pci/bus.c

@@ -41,9 +41,14 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 		void *alignf_data)
 {
 	int i, ret = -ENOMEM;
+	resource_size_t max = -1;
 
 	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
+	/* don't allocate too high if the pref mem doesn't support 64bit*/
+	if (!(res->flags & IORESOURCE_MEM_64))
+		max = PCIBIOS_MAX_MEM_32;
+
 	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
 		struct resource *r = bus->resource[i];
 		if (!r)
@@ -62,7 +67,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 		/* Ok, try it out.. */
 		ret = allocate_resource(r, res, size,
 					r->start ? : min,
-					-1, align,
+					max, align,
 					alignf, alignf_data);
 		if (ret == 0)
 			break;
@@ -201,13 +206,18 @@ void pci_enable_bridges(struct pci_bus *bus)
  *  Walk the given bus, including any bridged devices
  *  on buses under this bus.  Call the provided callback
  *  on each device found.
+ *
+ *  We check the return of @cb each time. If it returns anything
+ *  other than 0, we break out.
+ *
  */
-void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
 		  void *userdata)
 {
 	struct pci_dev *dev;
 	struct pci_bus *bus;
 	struct list_head *next;
+	int retval;
 
 	bus = top;
 	down_read(&pci_bus_sem);
@@ -231,8 +241,10 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 
 		/* Run device routines with the device locked */
 		down(&dev->dev.sem);
-		cb(dev, userdata);
+		retval = cb(dev, userdata);
 		up(&dev->dev.sem);
+		if (retval)
+			break;
 	}
 	up_read(&pci_bus_sem);
 }

+ 2 - 2
drivers/pci/hotplug/Kconfig

@@ -4,7 +4,7 @@
 
 menuconfig HOTPLUG_PCI
 	tristate "Support for PCI Hotplug"
-	depends on PCI && HOTPLUG
+	depends on PCI && HOTPLUG && SYSFS
 	---help---
 	  Say Y here if you have a motherboard with a PCI Hotplug controller.
 	  This allows you to add and remove PCI cards while the machine is
@@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE
 
 config HOTPLUG_PCI_COMPAQ
 	tristate "Compaq PCI Hotplug driver"
-	depends on X86 && PCI_BIOS && PCI_LEGACY
+	depends on X86 && PCI_BIOS
 	help
 	  Say Y here if you have a motherboard with a Compaq PCI Hotplug
 	  controller.

+ 0 - 1
drivers/pci/hotplug/acpiphp_core.c

@@ -77,7 +77,6 @@ static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
 
 static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
-	.owner			= THIS_MODULE,
 	.enable_slot		= enable_slot,
 	.disable_slot		= disable_slot,
 	.set_attention_status	= set_attention_status,

+ 0 - 1
drivers/pci/hotplug/cpci_hotplug_core.c

@@ -72,7 +72,6 @@ static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
 static int get_latch_status(struct hotplug_slot *slot, u8 * value);
 
 static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
-	.owner = THIS_MODULE,
 	.enable_slot = enable_slot,
 	.disable_slot = disable_slot,
 	.set_attention_status = set_attention_status,

+ 95 - 72
drivers/pci/hotplug/cpqphp.h

@@ -150,25 +150,25 @@ struct ctrl_reg {			/* offset */
 
 /* offsets to the controller registers based on the above structure layout */
 enum ctrl_offsets {
-	SLOT_RST = 		offsetof(struct ctrl_reg, slot_RST),
+	SLOT_RST =		offsetof(struct ctrl_reg, slot_RST),
 	SLOT_ENABLE =		offsetof(struct ctrl_reg, slot_enable),
 	MISC =			offsetof(struct ctrl_reg, misc),
 	LED_CONTROL =		offsetof(struct ctrl_reg, led_control),
 	INT_INPUT_CLEAR =	offsetof(struct ctrl_reg, int_input_clear),
-	INT_MASK = 		offsetof(struct ctrl_reg, int_mask),
-	CTRL_RESERVED0 = 	offsetof(struct ctrl_reg, reserved0),
+	INT_MASK =		offsetof(struct ctrl_reg, int_mask),
+	CTRL_RESERVED0 =	offsetof(struct ctrl_reg, reserved0),
 	CTRL_RESERVED1 =	offsetof(struct ctrl_reg, reserved1),
 	CTRL_RESERVED2 =	offsetof(struct ctrl_reg, reserved1),
-	GEN_OUTPUT_AB = 	offsetof(struct ctrl_reg, gen_output_AB),
-	NON_INT_INPUT = 	offsetof(struct ctrl_reg, non_int_input),
+	GEN_OUTPUT_AB =		offsetof(struct ctrl_reg, gen_output_AB),
+	NON_INT_INPUT =		offsetof(struct ctrl_reg, non_int_input),
 	CTRL_RESERVED3 =	offsetof(struct ctrl_reg, reserved3),
 	CTRL_RESERVED4 =	offsetof(struct ctrl_reg, reserved4),
 	CTRL_RESERVED5 =	offsetof(struct ctrl_reg, reserved5),
 	CTRL_RESERVED6 =	offsetof(struct ctrl_reg, reserved6),
 	CTRL_RESERVED7 =	offsetof(struct ctrl_reg, reserved7),
 	CTRL_RESERVED8 =	offsetof(struct ctrl_reg, reserved8),
-	SLOT_MASK = 		offsetof(struct ctrl_reg, slot_mask),
-	CTRL_RESERVED9 = 	offsetof(struct ctrl_reg, reserved9),
+	SLOT_MASK =		offsetof(struct ctrl_reg, slot_mask),
+	CTRL_RESERVED9 =	offsetof(struct ctrl_reg, reserved9),
 	CTRL_RESERVED10 =	offsetof(struct ctrl_reg, reserved10),
 	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
 	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
@@ -190,7 +190,9 @@ struct hrt {
 	u32 reserved2;
 } __attribute__ ((packed));
 
-/* offsets to the hotplug resource table registers based on the above structure layout */
+/* offsets to the hotplug resource table registers based on the above
+ * structure layout
+ */
 enum hrt_offsets {
 	SIG0 =			offsetof(struct hrt, sig0),
 	SIG1 =			offsetof(struct hrt, sig1),
@@ -217,18 +219,20 @@ struct slot_rt {
 	u16 pre_mem_length;
 } __attribute__ ((packed));
 
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
+/* offsets to the hotplug slot resource table registers based on the above
+ * structure layout
+ */
 enum slot_rt_offsets {
 	DEV_FUNC =		offsetof(struct slot_rt, dev_func),
-	PRIMARY_BUS = 		offsetof(struct slot_rt, primary_bus),
-	SECONDARY_BUS = 	offsetof(struct slot_rt, secondary_bus),
-	MAX_BUS = 		offsetof(struct slot_rt, max_bus),
-	IO_BASE = 		offsetof(struct slot_rt, io_base),
-	IO_LENGTH = 		offsetof(struct slot_rt, io_length),
-	MEM_BASE = 		offsetof(struct slot_rt, mem_base),
-	MEM_LENGTH = 		offsetof(struct slot_rt, mem_length),
-	PRE_MEM_BASE = 		offsetof(struct slot_rt, pre_mem_base),
-	PRE_MEM_LENGTH = 	offsetof(struct slot_rt, pre_mem_length),
+	PRIMARY_BUS =		offsetof(struct slot_rt, primary_bus),
+	SECONDARY_BUS =		offsetof(struct slot_rt, secondary_bus),
+	MAX_BUS =		offsetof(struct slot_rt, max_bus),
+	IO_BASE =		offsetof(struct slot_rt, io_base),
+	IO_LENGTH =		offsetof(struct slot_rt, io_length),
+	MEM_BASE =		offsetof(struct slot_rt, mem_base),
+	MEM_LENGTH =		offsetof(struct slot_rt, mem_length),
+	PRE_MEM_BASE =		offsetof(struct slot_rt, pre_mem_base),
+	PRE_MEM_LENGTH =	offsetof(struct slot_rt, pre_mem_length),
 };
 
 struct pci_func {
@@ -286,8 +290,8 @@ struct event_info {
 struct controller {
 	struct controller *next;
 	u32 ctrl_int_comp;
-	struct mutex crit_sect;		/* critical section mutex */
-	void __iomem *hpc_reg;		/* cookie for our pci controller location */
+	struct mutex crit_sect;	/* critical section mutex */
+	void __iomem *hpc_reg;	/* cookie for our pci controller location */
 	struct pci_resource *mem_head;
 	struct pci_resource *p_mem_head;
 	struct pci_resource *io_head;
@@ -299,7 +303,7 @@ struct controller {
 	u8 next_event;
 	u8 interrupt;
 	u8 cfgspc_irq;
-	u8 bus;				/* bus number for the pci hotplug controller */
+	u8 bus;			/* bus number for the pci hotplug controller */
 	u8 rev;
 	u8 slot_device_offset;
 	u8 first_slot;
@@ -401,46 +405,57 @@ struct resource_lists {
 
 
 /* debugfs functions for the hotplug controller info */
-extern void cpqhp_initialize_debugfs		(void);
-extern void cpqhp_shutdown_debugfs		(void);
-extern void cpqhp_create_debugfs_files		(struct controller *ctrl);
-extern void cpqhp_remove_debugfs_files		(struct controller *ctrl);
+extern void cpqhp_initialize_debugfs(void);
+extern void cpqhp_shutdown_debugfs(void);
+extern void cpqhp_create_debugfs_files(struct controller *ctrl);
+extern void cpqhp_remove_debugfs_files(struct controller *ctrl);
 
 /* controller functions */
-extern void	cpqhp_pushbutton_thread		(unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr		(int IRQ, void *data);
-extern int	cpqhp_find_available_resources	(struct controller *ctrl, void __iomem *rom_start);
-extern int	cpqhp_event_start_thread	(void);
-extern void	cpqhp_event_stop_thread		(void);
-extern struct pci_func *cpqhp_slot_create	(unsigned char busnumber);
-extern struct pci_func *cpqhp_slot_find		(unsigned char bus, unsigned char device, unsigned char index);
-extern int	cpqhp_process_SI		(struct controller *ctrl, struct pci_func *func);
-extern int	cpqhp_process_SS		(struct controller *ctrl, struct pci_func *func);
-extern int	cpqhp_hardware_test		(struct controller *ctrl, int test_num);
+extern void cpqhp_pushbutton_thread(unsigned long event_pointer);
+extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
+extern int cpqhp_find_available_resources(struct controller *ctrl,
+					  void __iomem *rom_start);
+extern int cpqhp_event_start_thread(void);
+extern void cpqhp_event_stop_thread(void);
+extern struct pci_func *cpqhp_slot_create(unsigned char busnumber);
+extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
+					unsigned char index);
+extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_hardware_test(struct controller *ctrl, int test_num);
 
 /* resource functions */
 extern int	cpqhp_resource_sort_and_combine	(struct pci_resource **head);
 
 /* pci functions */
-extern int	cpqhp_set_irq			(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-extern int	cpqhp_get_bus_dev		(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
-extern int	cpqhp_save_config		(struct controller *ctrl, int busnumber, int is_hot_plug);
-extern int	cpqhp_save_base_addr_length	(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_save_used_resources	(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_configure_board		(struct controller *ctrl, struct pci_func * func);
-extern int	cpqhp_save_slot_config		(struct controller *ctrl, struct pci_func * new_slot);
-extern int	cpqhp_valid_replace		(struct controller *ctrl, struct pci_func * func);
-extern void	cpqhp_destroy_board_resources	(struct pci_func * func);
-extern int	cpqhp_return_board_resources	(struct pci_func * func, struct resource_lists * resources);
-extern void	cpqhp_destroy_resource_list	(struct resource_lists * resources);
-extern int	cpqhp_configure_device		(struct controller* ctrl, struct pci_func* func);
-extern int	cpqhp_unconfigure_device	(struct pci_func* func);
+extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
+			     u8 slot);
+extern int cpqhp_save_config(struct controller *ctrl, int busnumber,
+			     int is_hot_plug);
+extern int cpqhp_save_base_addr_length(struct controller *ctrl,
+				       struct pci_func *func);
+extern int cpqhp_save_used_resources(struct controller *ctrl,
+				     struct pci_func *func);
+extern int cpqhp_configure_board(struct controller *ctrl,
+				 struct pci_func *func);
+extern int cpqhp_save_slot_config(struct controller *ctrl,
+				  struct pci_func *new_slot);
+extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
+extern void cpqhp_destroy_board_resources(struct pci_func *func);
+extern int cpqhp_return_board_resources	(struct pci_func *func,
+					 struct resource_lists *resources);
+extern void cpqhp_destroy_resource_list(struct resource_lists *resources);
+extern int cpqhp_configure_device(struct controller *ctrl,
+				  struct pci_func *func);
+extern int cpqhp_unconfigure_device(struct pci_func *func);
 
 /* Global variables */
 extern int cpqhp_debug;
 extern int cpqhp_legacy_mode;
 extern struct controller *cpqhp_ctrl_list;
 extern struct pci_func *cpqhp_slot_list[256];
+extern struct irq_routing_table *cpqhp_routing_table;
 
 /* these can be gotten rid of, but for debugging they are purty */
 extern u8 cpqhp_nic_irq;
@@ -449,7 +464,7 @@ extern u8 cpqhp_disk_irq;
 
 /* inline functions */
 
-static inline char *slot_name(struct slot *slot)
+static inline const char *slot_name(struct slot *slot)
 {
 	return hotplug_slot_name(slot->hotplug_slot);
 }
@@ -458,9 +473,9 @@ static inline char *slot_name(struct slot *slot)
  * return_resource
  *
  * Puts node back in the resource list pointed to by head
- *
  */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
+static inline void return_resource(struct pci_resource **head,
+				   struct pci_resource *node)
 {
 	if (!node || !head)
 		return;
@@ -471,7 +486,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
 static inline void set_SOGO(struct controller *ctrl)
 {
 	u16 misc;
-	
+
 	misc = readw(ctrl->hpc_reg + MISC);
 	misc = (misc | 0x0001) & 0xFFFB;
 	writew(misc, ctrl->hpc_reg + MISC);
@@ -481,7 +496,7 @@ static inline void set_SOGO(struct controller *ctrl)
 static inline void amber_LED_on(struct controller *ctrl, u8 slot)
 {
 	u32 led_control;
-	
+
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control |= (0x01010000L << slot);
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -491,7 +506,7 @@ static inline void amber_LED_on(struct controller *ctrl, u8 slot)
 static inline void amber_LED_off(struct controller *ctrl, u8 slot)
 {
 	u32 led_control;
-	
+
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control &= ~(0x01010000L << slot);
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -504,7 +519,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
 
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control &= (0x01010000L << slot);
-	
+
 	return led_control ? 1 : 0;
 }
 
@@ -512,7 +527,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
 static inline void green_LED_on(struct controller *ctrl, u8 slot)
 {
 	u32 led_control;
-	
+
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control |= 0x0101L << slot;
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -521,7 +536,7 @@ static inline void green_LED_on(struct controller *ctrl, u8 slot)
 static inline void green_LED_off(struct controller *ctrl, u8 slot)
 {
 	u32 led_control;
-	
+
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control &= ~(0x0101L << slot);
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -531,7 +546,7 @@ static inline void green_LED_off(struct controller *ctrl, u8 slot)
 static inline void green_LED_blink(struct controller *ctrl, u8 slot)
 {
 	u32 led_control;
-	
+
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
 	led_control &= ~(0x0101L << slot);
 	led_control |= (0x0001L << slot);
@@ -575,22 +590,21 @@ static inline u8 read_slot_enable(struct controller *ctrl)
 }
 
 
-/*
+/**
  * get_controller_speed - find the current frequency/mode of controller.
  *
  * @ctrl: controller to get frequency/mode for.
  *
  * Returns controller speed.
- *
  */
 static inline u8 get_controller_speed(struct controller *ctrl)
 {
 	u8 curr_freq;
- 	u16 misc;
- 	
+	u16 misc;
+
 	if (ctrl->pcix_support) {
 		curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
-		if ((curr_freq & 0xB0) == 0xB0) 
+		if ((curr_freq & 0xB0) == 0xB0)
 			return PCI_SPEED_133MHz_PCIX;
 		if ((curr_freq & 0xA0) == 0xA0)
 			return PCI_SPEED_100MHz_PCIX;
@@ -602,19 +616,18 @@ static inline u8 get_controller_speed(struct controller *ctrl)
 		return PCI_SPEED_33MHz;
 	}
 
- 	misc = readw(ctrl->hpc_reg + MISC);
- 	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+	misc = readw(ctrl->hpc_reg + MISC);
+	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
 }
- 
 
-/*
+
+/**
  * get_adapter_speed - find the max supported frequency/mode of adapter.
  *
  * @ctrl: hotplug controller.
  * @hp_slot: hotplug slot where adapter is installed.
  *
  * Returns adapter speed.
- *
  */
 static inline u8 get_adapter_speed(struct controller *ctrl, u8 hp_slot)
 {
@@ -672,7 +685,8 @@ static inline int get_slot_enabled(struct controller *ctrl, struct slot *slot)
 }
 
 
-static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slot)
+static inline int cpq_get_latch_status(struct controller *ctrl,
+				       struct slot *slot)
 {
 	u32 status;
 	u8 hp_slot;
@@ -687,7 +701,8 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo
 }
 
 
-static inline int get_presence_status(struct controller *ctrl, struct slot *slot)
+static inline int get_presence_status(struct controller *ctrl,
+				      struct slot *slot)
 {
 	int presence_save = 0;
 	u8 hp_slot;
@@ -696,7 +711,8 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot
 	hp_slot = slot->device - ctrl->slot_device_offset;
 
 	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-	presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
+	presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15))
+				>> hp_slot) & 0x02;
 
 	return presence_save;
 }
@@ -718,5 +734,12 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
 	return retval;
 }
 
-#endif
+#include <asm/pci_x86.h>
+static inline int cpqhp_routing_table_length(void)
+{
+	BUG_ON(cpqhp_routing_table == NULL);
+	return ((cpqhp_routing_table->size - sizeof(struct irq_routing_table)) /
+		sizeof(struct irq_info));
+}
 
+#endif

+ 560 - 608
drivers/pci/hotplug/cpqphp_core.c

@@ -25,8 +25,7 @@
  * Send feedback to <greg@kroah.com>
  *
  * Jan 12, 2003 -	Added 66/100/133MHz PCI-X support,
- * 			Torben Mathiasen <torben.mathiasen@hp.com>
- *
+ *			Torben Mathiasen <torben.mathiasen@hp.com>
  */
 
 #include <linux/module.h>
@@ -45,7 +44,6 @@
 
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include <asm/pci_x86.h>
 
 
 /* Global variables */
@@ -53,6 +51,7 @@ int cpqhp_debug;
 int cpqhp_legacy_mode;
 struct controller *cpqhp_ctrl_list;	/* = NULL */
 struct pci_func *cpqhp_slot_list[256];
+struct irq_routing_table *cpqhp_routing_table;
 
 /* local variables */
 static void __iomem *smbios_table;
@@ -78,33 +77,6 @@ MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 #define CPQHPC_MODULE_MINOR 208
 
-static int one_time_init	(void);
-static int set_attention_status	(struct hotplug_slot *slot, u8 value);
-static int process_SI		(struct hotplug_slot *slot);
-static int process_SS		(struct hotplug_slot *slot);
-static int hardware_test	(struct hotplug_slot *slot, u32 value);
-static int get_power_status	(struct hotplug_slot *slot, u8 *value);
-static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
-static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
-static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
-static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
-
-static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
-	.owner =		THIS_MODULE,
-	.set_attention_status =	set_attention_status,
-	.enable_slot =		process_SI,
-	.disable_slot =		process_SS,
-	.hardware_test =	hardware_test,
-	.get_power_status =	get_power_status,
-	.get_attention_status =	get_attention_status,
-	.get_latch_status =	get_latch_status,
-	.get_adapter_status =	get_adapter_status,
-  	.get_max_bus_speed =	get_max_bus_speed,
-  	.get_cur_bus_speed =	get_cur_bus_speed,
-};
-
-
 static inline int is_slot64bit(struct slot *slot)
 {
 	return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0;
@@ -144,7 +116,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
 			break;
 		}
 	}
-	
+
 	if (!status)
 		fp = NULL;
 
@@ -171,7 +143,7 @@ static int init_SERR(struct controller * ctrl)
 	tempdword = ctrl->first_slot;
 
 	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-	// Loop through slots
+	/* Loop through slots */
 	while (number_of_slots) {
 		physical_slot = tempdword;
 		writeb(0, ctrl->hpc_reg + SLOT_SERR);
@@ -182,41 +154,42 @@ static int init_SERR(struct controller * ctrl)
 	return 0;
 }
 
-
-/* nice debugging output */
-static int pci_print_IRQ_route (void)
+static int init_cpqhp_routing_table(void)
 {
-	struct irq_routing_table *routing_table;
 	int len;
-	int loop;
-
-	u8 tbus, tdevice, tslot;
 
-	routing_table = pcibios_get_irq_routing_table();
-	if (routing_table == NULL) {
-		err("No BIOS Routing Table??? Not good\n");
+	cpqhp_routing_table = pcibios_get_irq_routing_table();
+	if (cpqhp_routing_table == NULL)
 		return -ENOMEM;
-	}
 
-	len = (routing_table->size - sizeof(struct irq_routing_table)) /
-			sizeof(struct irq_info);
-	// Make sure I got at least one entry
+	len = cpqhp_routing_table_length();
 	if (len == 0) {
-		kfree(routing_table);
+		kfree(cpqhp_routing_table);
+		cpqhp_routing_table = NULL;
 		return -1;
 	}
 
-	dbg("bus dev func slot\n");
+	return 0;
+}
 
+/* nice debugging output */
+static void pci_print_IRQ_route(void)
+{
+	int len;
+	int loop;
+	u8 tbus, tdevice, tslot;
+
+	len = cpqhp_routing_table_length();
+
+	dbg("bus dev func slot\n");
 	for (loop = 0; loop < len; ++loop) {
-		tbus = routing_table->slots[loop].bus;
-		tdevice = routing_table->slots[loop].devfn;
-		tslot = routing_table->slots[loop].slot;
+		tbus = cpqhp_routing_table->slots[loop].bus;
+		tdevice = cpqhp_routing_table->slots[loop].devfn;
+		tslot = cpqhp_routing_table->slots[loop].slot;
 		dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
 
 	}
-	kfree(routing_table);
-	return 0;
+	return;
 }
 
 
@@ -242,9 +215,9 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
 	void __iomem *p_max;
 
 	if (!smbios_table || !curr)
-		return(NULL);
+		return NULL;
 
-	// set p_max to the end of the table
+	/* set p_max to the end of the table */
 	p_max = smbios_start + readw(smbios_table + ST_LENGTH);
 
 	p_temp = curr;
@@ -253,20 +226,19 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
 	while ((p_temp < p_max) && !bail) {
 		/* Look for the double NULL terminator
 		 * The first condition is the previous byte
-		 * and the second is the curr */
-		if (!previous_byte && !(readb(p_temp))) {
+		 * and the second is the curr
+		 */
+		if (!previous_byte && !(readb(p_temp)))
 			bail = 1;
-		}
 
 		previous_byte = readb(p_temp);
 		p_temp++;
 	}
 
-	if (p_temp < p_max) {
+	if (p_temp < p_max)
 		return p_temp;
-	} else {
+	else
 		return NULL;
-	}
 }
 
 
@@ -292,21 +264,18 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
 	if (!smbios_table)
 		return NULL;
 
-	if (!previous) {		  
+	if (!previous)
 		previous = smbios_start;
-	} else {
+	else
 		previous = get_subsequent_smbios_entry(smbios_start,
 					smbios_table, previous);
-	}
 
-	while (previous) {
-	       	if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
+	while (previous)
+		if (readb(previous + SMBIOS_GENERIC_TYPE) != type)
 			previous = get_subsequent_smbios_entry(smbios_start,
 						smbios_table, previous);
-		} else {
+		else
 			break;
-		}
-	}
 
 	return previous;
 }
@@ -322,144 +291,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 	kfree(slot);
 }
 
-#define SLOT_NAME_SIZE 10
-
-static int ctrl_slot_setup(struct controller *ctrl,
-			void __iomem *smbios_start,
-			void __iomem *smbios_table)
-{
-	struct slot *slot;
-	struct hotplug_slot *hotplug_slot;
-	struct hotplug_slot_info *hotplug_slot_info;
-	u8 number_of_slots;
-	u8 slot_device;
-	u8 slot_number;
-	u8 ctrl_slot;
-	u32 tempdword;
-	char name[SLOT_NAME_SIZE];
-	void __iomem *slot_entry= NULL;
-	int result = -ENOMEM;
-
-	dbg("%s\n", __func__);
-
-	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
-	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
-	slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
-	slot_number = ctrl->first_slot;
-
-	while (number_of_slots) {
-		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-		if (!slot)
-			goto error;
-
-		slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
-						GFP_KERNEL);
-		if (!slot->hotplug_slot)
-			goto error_slot;
-		hotplug_slot = slot->hotplug_slot;
-
-		hotplug_slot->info =
-				kzalloc(sizeof(*(hotplug_slot->info)),
-							GFP_KERNEL);
-		if (!hotplug_slot->info)
-			goto error_hpslot;
-		hotplug_slot_info = hotplug_slot->info;
-
-		slot->ctrl = ctrl;
-		slot->bus = ctrl->bus;
-		slot->device = slot_device;
-		slot->number = slot_number;
-		dbg("slot->number = %u\n", slot->number);
-
-		slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
-					slot_entry);
-
-		while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
-				slot->number)) {
-			slot_entry = get_SMBIOS_entry(smbios_start,
-						smbios_table, 9, slot_entry);
-		}
-
-		slot->p_sm_slot = slot_entry;
-
-		init_timer(&slot->task_event);
-		slot->task_event.expires = jiffies + 5 * HZ;
-		slot->task_event.function = cpqhp_pushbutton_thread;
-
-		//FIXME: these capabilities aren't used but if they are
-		//       they need to be correctly implemented
-		slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
-		slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
-
-		if (is_slot64bit(slot))
-			slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
-		if (is_slot66mhz(slot))
-			slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
-		if (ctrl->speed == PCI_SPEED_66MHz)
-			slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
-
-		ctrl_slot =
-			slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
-
-		// Check presence
-		slot->capabilities |=
-			((((~tempdword) >> 23) |
-			 ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
-		// Check the switch state
-		slot->capabilities |=
-			((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
-		// Check the slot enable
-		slot->capabilities |=
-			((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
-
-		/* register this slot with the hotplug pci core */
-		hotplug_slot->release = &release_slot;
-		hotplug_slot->private = slot;
-		snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
-		hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
-
-		hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
-		hotplug_slot_info->attention_status =
-			cpq_get_attention_status(ctrl, slot);
-		hotplug_slot_info->latch_status =
-			cpq_get_latch_status(ctrl, slot);
-		hotplug_slot_info->adapter_status =
-			get_presence_status(ctrl, slot);
-		
-		dbg("registering bus %d, dev %d, number %d, "
-				"ctrl->slot_device_offset %d, slot %d\n",
-				slot->bus, slot->device,
-				slot->number, ctrl->slot_device_offset,
-				slot_number);
-		result = pci_hp_register(hotplug_slot,
-					 ctrl->pci_dev->bus,
-					 slot->device,
-					 name);
-		if (result) {
-			err("pci_hp_register failed with error %d\n", result);
-			goto error_info;
-		}
-		
-		slot->next = ctrl->slot;
-		ctrl->slot = slot;
-
-		number_of_slots--;
-		slot_device++;
-		slot_number++;
-	}
-
-	return 0;
-error_info:
-	kfree(hotplug_slot_info);
-error_hpslot:
-	kfree(hotplug_slot);
-error_slot:
-	kfree(slot);
-error:
-	return result;
-}
-
 static int ctrl_slot_cleanup (struct controller * ctrl)
 {
 	struct slot *old_slot, *next_slot;
@@ -476,36 +307,32 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
 
 	cpqhp_remove_debugfs_files(ctrl);
 
-	//Free IRQ associated with hot plug device
+	/* Free IRQ associated with hot plug device */
 	free_irq(ctrl->interrupt, ctrl);
-	//Unmap the memory
+	/* Unmap the memory */
 	iounmap(ctrl->hpc_reg);
-	//Finally reclaim PCI mem
+	/* Finally reclaim PCI mem */
 	release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
 			   pci_resource_len(ctrl->pci_dev, 0));
 
-	return(0);
+	return 0;
 }
 
 
-//============================================================================
-// function:	get_slot_mapping
-//
-// Description: Attempts to determine a logical slot mapping for a PCI
-//		device.  Won't work for more than one PCI-PCI bridge
-//		in a slot.
-//
-// Input:	u8 bus_num - bus number of PCI device
-//		u8 dev_num - device number of PCI device
-//		u8 *slot - Pointer to u8 where slot number will
-//			be returned
-//
-// Output:	SUCCESS or FAILURE
-//=============================================================================
+/**
+ * get_slot_mapping - determine logical slot mapping for PCI device
+ *
+ * Won't work for more than one PCI-PCI bridge in a slot.
+ *
+ * @bus_num - bus number of PCI device
+ * @dev_num - device number of PCI device
+ * @slot - Pointer to u8 where slot number will	be returned
+ *
+ * Output:	SUCCESS or FAILURE
+ */
 static int
 get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
 {
-	struct irq_routing_table *PCIIRQRoutingInfoLength;
 	u32 work;
 	long len;
 	long loop;
@@ -516,36 +343,25 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
 
 	bridgeSlot = 0xFF;
 
-	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
-	if (!PCIIRQRoutingInfoLength)
-		return -1;
-
-	len = (PCIIRQRoutingInfoLength->size -
-	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		kfree(PCIIRQRoutingInfoLength);
-		return -1;
-	}
-
+	len = cpqhp_routing_table_length();
 	for (loop = 0; loop < len; ++loop) {
-		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
-		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
-		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+		tbus = cpqhp_routing_table->slots[loop].bus;
+		tdevice = cpqhp_routing_table->slots[loop].devfn >> 3;
+		tslot = cpqhp_routing_table->slots[loop].slot;
 
 		if ((tbus == bus_num) && (tdevice == dev_num)) {
 			*slot = tslot;
-			kfree(PCIIRQRoutingInfoLength);
 			return 0;
 		} else {
 			/* Did not get a match on the target PCI device. Check
-			 * if the current IRQ table entry is a PCI-to-PCI bridge
-			 * device.  If so, and it's secondary bus matches the
-			 * bus number for the target device, I need to save the
-			 * bridge's slot number.  If I can not find an entry for
-			 * the target device, I will have to assume it's on the
-			 * other side of the bridge, and assign it the bridge's
-			 * slot. */
+			 * if the current IRQ table entry is a PCI-to-PCI
+			 * bridge device.  If so, and it's secondary bus
+			 * matches the bus number for the target device, I need
+			 * to save the bridge's slot number.  If I can not find
+			 * an entry for the target device, I will have to
+			 * assume it's on the other side of the bridge, and
+			 * assign it the bridge's slot.
+			 */
 			bus->number = tbus;
 			pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0),
 						PCI_CLASS_REVISION, &work);
@@ -555,25 +371,23 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
 							PCI_DEVFN(tdevice, 0),
 							PCI_PRIMARY_BUS, &work);
 				// See if bridge's secondary bus matches target bus.
-				if (((work >> 8) & 0x000000FF) == (long) bus_num) {
+				if (((work >> 8) & 0x000000FF) == (long) bus_num)
 					bridgeSlot = tslot;
-				}
 			}
 		}
 
 	}
 
-	// If we got here, we didn't find an entry in the IRQ mapping table 
-	// for the target PCI device.  If we did determine that the target 
-	// device is on the other side of a PCI-to-PCI bridge, return the 
-	// slot number for the bridge.
+	/* If we got here, we didn't find an entry in the IRQ mapping table for
+	 * the target PCI device.  If we did determine that the target device
+	 * is on the other side of a PCI-to-PCI bridge, return the slot number
+	 * for the bridge.
+	 */
 	if (bridgeSlot != 0xFF) {
 		*slot = bridgeSlot;
-		kfree(PCIIRQRoutingInfoLength);
 		return 0;
 	}
-	kfree(PCIIRQRoutingInfoLength);
-	// Couldn't find an entry in the routing table for this PCI device
+	/* Couldn't find an entry in the routing table for this PCI device */
 	return -1;
 }
 
@@ -591,32 +405,32 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
 	u8 hp_slot;
 
 	if (func == NULL)
-		return(1);
+		return 1;
 
 	hp_slot = func->device - ctrl->slot_device_offset;
 
-	// Wait for exclusive access to hardware
+	/* Wait for exclusive access to hardware */
 	mutex_lock(&ctrl->crit_sect);
 
-	if (status == 1) {
+	if (status == 1)
 		amber_LED_on (ctrl, hp_slot);
-	} else if (status == 0) {
+	else if (status == 0)
 		amber_LED_off (ctrl, hp_slot);
-	} else {
-		// Done with exclusive hardware access
+	else {
+		/* Done with exclusive hardware access */
 		mutex_unlock(&ctrl->crit_sect);
-		return(1);
+		return 1;
 	}
 
 	set_SOGO(ctrl);
 
-	// Wait for SOBS to be unset
+	/* Wait for SOBS to be unset */
 	wait_for_ctrl_irq (ctrl);
 
-	// Done with exclusive hardware access
+	/* Done with exclusive hardware access */
 	mutex_unlock(&ctrl->crit_sect);
 
-	return(0);
+	return 0;
 }
 
 
@@ -719,7 +533,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
 
 	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
-	return cpqhp_hardware_test(ctrl, value);	
+	return cpqhp_hardware_test(ctrl, value);
 }
 
 
@@ -738,7 +552,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
 	struct slot *slot = hotplug_slot->private;
 	struct controller *ctrl = slot->ctrl;
-	
+
 	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
 	*value = cpq_get_attention_status(ctrl, slot);
@@ -793,256 +607,474 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
 	return 0;
 }
 
-static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
+	.set_attention_status =	set_attention_status,
+	.enable_slot =		process_SI,
+	.disable_slot =		process_SS,
+	.hardware_test =	hardware_test,
+	.get_power_status =	get_power_status,
+	.get_attention_status =	get_attention_status,
+	.get_latch_status =	get_latch_status,
+	.get_adapter_status =	get_adapter_status,
+	.get_max_bus_speed =	get_max_bus_speed,
+	.get_cur_bus_speed =	get_cur_bus_speed,
+};
+
+#define SLOT_NAME_SIZE 10
+
+static int ctrl_slot_setup(struct controller *ctrl,
+			void __iomem *smbios_start,
+			void __iomem *smbios_table)
 {
-	u8 num_of_slots = 0;
-	u8 hp_slot = 0;
-	u8 device;
-	u8 bus_cap;
-	u16 temp_word;
-	u16 vendor_id;
-	u16 subsystem_vid;
-	u16 subsystem_deviceid;
-	u32 rc;
-	struct controller *ctrl;
-	struct pci_func *func;
-	int err;
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *hotplug_slot_info;
+	u8 number_of_slots;
+	u8 slot_device;
+	u8 slot_number;
+	u8 ctrl_slot;
+	u32 tempdword;
+	char name[SLOT_NAME_SIZE];
+	void __iomem *slot_entry= NULL;
+	int result = -ENOMEM;
 
-	err = pci_enable_device(pdev);
-	if (err) {
-		printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
-			pci_name(pdev), err);
-		return err;
-	}
+	dbg("%s\n", __func__);
 
-	// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
-	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-	if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
-		err(msg_HPC_non_compaq_or_intel);
-		rc = -ENODEV;
-		goto err_disable_device;
-	}
-	dbg("Vendor ID: %x\n", vendor_id);
+	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
 
-	dbg("revision: %d\n", pdev->revision);
-	if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
-		err(msg_HPC_rev_error);
-		rc = -ENODEV;
-		goto err_disable_device;
-	}
+	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+	slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+	slot_number = ctrl->first_slot;
 
-	/* Check for the proper subsytem ID's
-	 * Intel uses a different SSID programming model than Compaq.  
-	 * For Intel, each SSID bit identifies a PHP capability.
-	 * Also Intel HPC's may have RID=0.
-	 */
-	if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
-		// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
-		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
-		if (rc) {
-			err("%s : pci_read_config_word failed\n", __func__);
-			goto err_disable_device;
-		}
-		dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
-		if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
-			err(msg_HPC_non_compaq_or_intel);
-			rc = -ENODEV;
-			goto err_disable_device;
-		}
+	while (number_of_slots) {
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+		if (!slot)
+			goto error;
+
+		slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
+						GFP_KERNEL);
+		if (!slot->hotplug_slot)
+			goto error_slot;
+		hotplug_slot = slot->hotplug_slot;
 
-		ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
-		if (!ctrl) {
-			err("%s : out of memory\n", __func__);
-			rc = -ENOMEM;
-			goto err_disable_device;
+		hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)),
+							GFP_KERNEL);
+		if (!hotplug_slot->info)
+			goto error_hpslot;
+		hotplug_slot_info = hotplug_slot->info;
+
+		slot->ctrl = ctrl;
+		slot->bus = ctrl->bus;
+		slot->device = slot_device;
+		slot->number = slot_number;
+		dbg("slot->number = %u\n", slot->number);
+
+		slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
+					slot_entry);
+
+		while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
+				slot->number)) {
+			slot_entry = get_SMBIOS_entry(smbios_start,
+						smbios_table, 9, slot_entry);
 		}
 
-		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
-		if (rc) {
-			err("%s : pci_read_config_word failed\n", __func__);
-			goto err_free_ctrl;
+		slot->p_sm_slot = slot_entry;
+
+		init_timer(&slot->task_event);
+		slot->task_event.expires = jiffies + 5 * HZ;
+		slot->task_event.function = cpqhp_pushbutton_thread;
+
+		/*FIXME: these capabilities aren't used but if they are
+		 *	 they need to be correctly implemented
+		 */
+		slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+		slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+
+		if (is_slot64bit(slot))
+			slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+		if (is_slot66mhz(slot))
+			slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+		if (ctrl->speed == PCI_SPEED_66MHz)
+			slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+
+		ctrl_slot =
+			slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+
+		/* Check presence */
+		slot->capabilities |=
+			((((~tempdword) >> 23) |
+			 ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+		/* Check the switch state */
+		slot->capabilities |=
+			((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+		/* Check the slot enable */
+		slot->capabilities |=
+			((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+
+		/* register this slot with the hotplug pci core */
+		hotplug_slot->release = &release_slot;
+		hotplug_slot->private = slot;
+		snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
+		hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+
+		hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
+		hotplug_slot_info->attention_status =
+			cpq_get_attention_status(ctrl, slot);
+		hotplug_slot_info->latch_status =
+			cpq_get_latch_status(ctrl, slot);
+		hotplug_slot_info->adapter_status =
+			get_presence_status(ctrl, slot);
+
+		dbg("registering bus %d, dev %d, number %d, "
+				"ctrl->slot_device_offset %d, slot %d\n",
+				slot->bus, slot->device,
+				slot->number, ctrl->slot_device_offset,
+				slot_number);
+		result = pci_hp_register(hotplug_slot,
+					 ctrl->pci_dev->bus,
+					 slot->device,
+					 name);
+		if (result) {
+			err("pci_hp_register failed with error %d\n", result);
+			goto error_info;
 		}
 
-		info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
-
-		/* Set Vendor ID, so it can be accessed later from other functions */
-		ctrl->vendor_id = vendor_id;
-
-		switch (subsystem_vid) {
-			case PCI_VENDOR_ID_COMPAQ:
-				if (pdev->revision >= 0x13) { /* CIOBX */
-					ctrl->push_flag = 1;
-					ctrl->slot_switch_type = 1;
-					ctrl->push_button = 1;
-					ctrl->pci_config_space = 1;
-					ctrl->defeature_PHP = 1;
-					ctrl->pcix_support = 1;
-					ctrl->pcix_speed_capability = 1;
-					pci_read_config_byte(pdev, 0x41, &bus_cap);
-					if (bus_cap & 0x80) {
-						dbg("bus max supports 133MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 0x40) {
-						dbg("bus max supports 100MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 20) {
-						dbg("bus max supports 66MHz PCI-X\n");
-						ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
-						break;
-					}
-					if (bus_cap & 10) {
-						dbg("bus max supports 66MHz PCI\n");
-						ctrl->speed_capability = PCI_SPEED_66MHz;
-						break;
-					}
-
-					break;
-				}
-
-				switch (subsystem_deviceid) {
-					case PCI_SUB_HPC_ID:
-						/* Original 6500/7000 implementation */
-						ctrl->slot_switch_type = 1;
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 0;
-						ctrl->pci_config_space = 1;
-						ctrl->defeature_PHP = 1;
-						ctrl->pcix_support = 0;
-						ctrl->pcix_speed_capability = 0;
-						break;
-					case PCI_SUB_HPC_ID2:
-						/* First Pushbutton implementation */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 1;
-						ctrl->pci_config_space = 1;
-						ctrl->defeature_PHP = 1;
-						ctrl->pcix_support = 0;
-						ctrl->pcix_speed_capability = 0;
-						break;
-					case PCI_SUB_HPC_ID_INTC:
-						/* Third party (6500/7000) */
-						ctrl->slot_switch_type = 1;
-						ctrl->speed_capability = PCI_SPEED_33MHz;
-						ctrl->push_button = 0;
-						ctrl->pci_config_space = 1;
-						ctrl->defeature_PHP = 1;
-						ctrl->pcix_support = 0;
-						ctrl->pcix_speed_capability = 0;
-						break;
-					case PCI_SUB_HPC_ID3:
-						/* First 66 Mhz implementation */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;
-						ctrl->speed_capability = PCI_SPEED_66MHz;
-						ctrl->push_button = 1;
-						ctrl->pci_config_space = 1;
-						ctrl->defeature_PHP = 1;
-						ctrl->pcix_support = 0;
-						ctrl->pcix_speed_capability = 0;
-						break;
-					case PCI_SUB_HPC_ID4:
-						/* First PCI-X implementation, 100MHz */
-						ctrl->push_flag = 1;
-						ctrl->slot_switch_type = 1;
-						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
-						ctrl->push_button = 1;
-						ctrl->pci_config_space = 1;
-						ctrl->defeature_PHP = 1;
-						ctrl->pcix_support = 1;
-						ctrl->pcix_speed_capability = 0;	
-						break;
-					default:
-						err(msg_HPC_not_supported);
-						rc = -ENODEV;
-						goto err_free_ctrl;
-				}
-				break;
+		slot->next = ctrl->slot;
+		ctrl->slot = slot;
+
+		number_of_slots--;
+		slot_device++;
+		slot_number++;
+	}
+
+	return 0;
+error_info:
+	kfree(hotplug_slot_info);
+error_hpslot:
+	kfree(hotplug_slot);
+error_slot:
+	kfree(slot);
+error:
+	return result;
+}
+
+static int one_time_init(void)
+{
+	int loop;
+	int retval = 0;
+
+	if (initialized)
+		return 0;
+
+	power_mode = 0;
+
+	retval = init_cpqhp_routing_table();
+	if (retval)
+		goto error;
+
+	if (cpqhp_debug)
+		pci_print_IRQ_route();
+
+	dbg("Initialize + Start the notification mechanism \n");
+
+	retval = cpqhp_event_start_thread();
+	if (retval)
+		goto error;
+
+	dbg("Initialize slot lists\n");
+	for (loop = 0; loop < 256; loop++)
+		cpqhp_slot_list[loop] = NULL;
+
+	/* FIXME: We also need to hook the NMI handler eventually.
+	 * this also needs to be worked with Christoph
+	 * register_NMI_handler();
+	 */
+	/* Map rom address */
+	cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+	if (!cpqhp_rom_start) {
+		err ("Could not ioremap memory region for ROM\n");
+		retval = -EIO;
+		goto error;
+	}
+
+	/* Now, map the int15 entry point if we are on compaq specific
+	 * hardware
+	 */
+	compaq_nvram_init(cpqhp_rom_start);
+
+	/* Map smbios table entry point structure */
+	smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
+					cpqhp_rom_start + ROM_PHY_LEN);
+	if (!smbios_table) {
+		err ("Could not find the SMBIOS pointer in memory\n");
+		retval = -EIO;
+		goto error_rom_start;
+	}
+
+	smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
+					readw(smbios_table + ST_LENGTH));
+	if (!smbios_start) {
+		err ("Could not ioremap memory region taken from SMBIOS values\n");
+		retval = -EIO;
+		goto error_smbios_start;
+	}
+
+	initialized = 1;
+
+	return retval;
+
+error_smbios_start:
+	iounmap(smbios_start);
+error_rom_start:
+	iounmap(cpqhp_rom_start);
+error:
+	return retval;
+}
+
+static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	u8 num_of_slots = 0;
+	u8 hp_slot = 0;
+	u8 device;
+	u8 bus_cap;
+	u16 temp_word;
+	u16 vendor_id;
+	u16 subsystem_vid;
+	u16 subsystem_deviceid;
+	u32 rc;
+	struct controller *ctrl;
+	struct pci_func *func;
+	int err;
 
-			case PCI_VENDOR_ID_INTEL:
-				/* Check for speed capability (0=33, 1=66) */
-				if (subsystem_deviceid & 0x0001) {
-					ctrl->speed_capability = PCI_SPEED_66MHz;
-				} else {
-					ctrl->speed_capability = PCI_SPEED_33MHz;
-				}
-
-				/* Check for push button */
-				if (subsystem_deviceid & 0x0002) {
-					/* no push button */
-					ctrl->push_button = 0;
-				} else {
-					/* push button supported */
-					ctrl->push_button = 1;
-				}
-
-				/* Check for slot switch type (0=mechanical, 1=not mechanical) */
-				if (subsystem_deviceid & 0x0004) {
-					/* no switch */
-					ctrl->slot_switch_type = 0;
-				} else {
-					/* switch */
-					ctrl->slot_switch_type = 1;
-				}
-
-				/* PHP Status (0=De-feature PHP, 1=Normal operation) */
-				if (subsystem_deviceid & 0x0008) {
-					ctrl->defeature_PHP = 1;	// PHP supported
-				} else {
-					ctrl->defeature_PHP = 0;	// PHP not supported
-				}
-
-				/* Alternate Base Address Register Interface (0=not supported, 1=supported) */
-				if (subsystem_deviceid & 0x0010) {
-					ctrl->alternate_base_address = 1;	// supported
-				} else {
-					ctrl->alternate_base_address = 0;	// not supported
-				}
-
-				/* PCI Config Space Index (0=not supported, 1=supported) */
-				if (subsystem_deviceid & 0x0020) {
-					ctrl->pci_config_space = 1;		// supported
-				} else {
-					ctrl->pci_config_space = 0;		// not supported
-				}
-
-				/* PCI-X support */
-				if (subsystem_deviceid & 0x0080) {
-					/* PCI-X capable */
-					ctrl->pcix_support = 1;
-					/* Frequency of operation in PCI-X mode */
-					if (subsystem_deviceid & 0x0040) {
-						/* 133MHz PCI-X if bit 7 is 1 */
-						ctrl->pcix_speed_capability = 1;
-					} else {
-						/* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
-						/* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
-						ctrl->pcix_speed_capability = 0;
-					}
-				} else {
-					/* Conventional PCI */
-					ctrl->pcix_support = 0;
-					ctrl->pcix_speed_capability = 0;
-				}
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+			pci_name(pdev), err);
+		return err;
+	}
+
+	/* Need to read VID early b/c it's used to differentiate CPQ and INTC
+	 * discovery
+	 */
+	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+	if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
+		err(msg_HPC_non_compaq_or_intel);
+		rc = -ENODEV;
+		goto err_disable_device;
+	}
+	dbg("Vendor ID: %x\n", vendor_id);
+
+	dbg("revision: %d\n", pdev->revision);
+	if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
+		err(msg_HPC_rev_error);
+		rc = -ENODEV;
+		goto err_disable_device;
+	}
+
+	/* Check for the proper subsytem ID's
+	 * Intel uses a different SSID programming model than Compaq.
+	 * For Intel, each SSID bit identifies a PHP capability.
+	 * Also Intel HPC's may have RID=0.
+	 */
+	if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) {
+		err(msg_HPC_not_supported);
+		return -ENODEV;
+	}
+
+	/* TODO: This code can be made to support non-Compaq or Intel
+	 * subsystem IDs
+	 */
+	rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+	if (rc) {
+		err("%s : pci_read_config_word failed\n", __func__);
+		goto err_disable_device;
+	}
+	dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+	if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+		err(msg_HPC_non_compaq_or_intel);
+		rc = -ENODEV;
+		goto err_disable_device;
+	}
+
+	ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
+	if (!ctrl) {
+		err("%s : out of memory\n", __func__);
+		rc = -ENOMEM;
+		goto err_disable_device;
+	}
+
+	rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+	if (rc) {
+		err("%s : pci_read_config_word failed\n", __func__);
+		goto err_free_ctrl;
+	}
+
+	info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
+
+	/* Set Vendor ID, so it can be accessed later from other
+	 * functions
+	 */
+	ctrl->vendor_id = vendor_id;
+
+	switch (subsystem_vid) {
+	case PCI_VENDOR_ID_COMPAQ:
+		if (pdev->revision >= 0x13) { /* CIOBX */
+			ctrl->push_flag = 1;
+			ctrl->slot_switch_type = 1;
+			ctrl->push_button = 1;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 1;
+			ctrl->pcix_speed_capability = 1;
+			pci_read_config_byte(pdev, 0x41, &bus_cap);
+			if (bus_cap & 0x80) {
+				dbg("bus max supports 133MHz PCI-X\n");
+				ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
+				break;
+			}
+			if (bus_cap & 0x40) {
+				dbg("bus max supports 100MHz PCI-X\n");
+				ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+				break;
+			}
+			if (bus_cap & 20) {
+				dbg("bus max supports 66MHz PCI-X\n");
+				ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
 				break;
+			}
+			if (bus_cap & 10) {
+				dbg("bus max supports 66MHz PCI\n");
+				ctrl->speed_capability = PCI_SPEED_66MHz;
+				break;
+			}
 
-			default:
-				err(msg_HPC_not_supported);
-				rc = -ENODEV;
-				goto err_free_ctrl;
+			break;
 		}
 
-	} else {
+		switch (subsystem_deviceid) {
+		case PCI_SUB_HPC_ID:
+			/* Original 6500/7000 implementation */
+			ctrl->slot_switch_type = 1;
+			ctrl->speed_capability = PCI_SPEED_33MHz;
+			ctrl->push_button = 0;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 0;
+			ctrl->pcix_speed_capability = 0;
+			break;
+		case PCI_SUB_HPC_ID2:
+			/* First Pushbutton implementation */
+			ctrl->push_flag = 1;
+			ctrl->slot_switch_type = 1;
+			ctrl->speed_capability = PCI_SPEED_33MHz;
+			ctrl->push_button = 1;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 0;
+			ctrl->pcix_speed_capability = 0;
+			break;
+		case PCI_SUB_HPC_ID_INTC:
+			/* Third party (6500/7000) */
+			ctrl->slot_switch_type = 1;
+			ctrl->speed_capability = PCI_SPEED_33MHz;
+			ctrl->push_button = 0;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 0;
+			ctrl->pcix_speed_capability = 0;
+			break;
+		case PCI_SUB_HPC_ID3:
+			/* First 66 Mhz implementation */
+			ctrl->push_flag = 1;
+			ctrl->slot_switch_type = 1;
+			ctrl->speed_capability = PCI_SPEED_66MHz;
+			ctrl->push_button = 1;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 0;
+			ctrl->pcix_speed_capability = 0;
+			break;
+		case PCI_SUB_HPC_ID4:
+			/* First PCI-X implementation, 100MHz */
+			ctrl->push_flag = 1;
+			ctrl->slot_switch_type = 1;
+			ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+			ctrl->push_button = 1;
+			ctrl->pci_config_space = 1;
+			ctrl->defeature_PHP = 1;
+			ctrl->pcix_support = 1;
+			ctrl->pcix_speed_capability = 0;
+			break;
+		default:
+			err(msg_HPC_not_supported);
+			rc = -ENODEV;
+			goto err_free_ctrl;
+		}
+		break;
+
+	case PCI_VENDOR_ID_INTEL:
+		/* Check for speed capability (0=33, 1=66) */
+		if (subsystem_deviceid & 0x0001)
+			ctrl->speed_capability = PCI_SPEED_66MHz;
+		else
+			ctrl->speed_capability = PCI_SPEED_33MHz;
+
+		/* Check for push button */
+		if (subsystem_deviceid & 0x0002)
+			ctrl->push_button = 0;
+		else
+			ctrl->push_button = 1;
+
+		/* Check for slot switch type (0=mechanical, 1=not mechanical) */
+		if (subsystem_deviceid & 0x0004)
+			ctrl->slot_switch_type = 0;
+		else
+			ctrl->slot_switch_type = 1;
+
+		/* PHP Status (0=De-feature PHP, 1=Normal operation) */
+		if (subsystem_deviceid & 0x0008)
+			ctrl->defeature_PHP = 1;	/* PHP supported */
+		else
+			ctrl->defeature_PHP = 0;	/* PHP not supported */
+
+		/* Alternate Base Address Register Interface
+		 * (0=not supported, 1=supported)
+		 */
+		if (subsystem_deviceid & 0x0010)
+			ctrl->alternate_base_address = 1;
+		else
+			ctrl->alternate_base_address = 0;
+
+		/* PCI Config Space Index (0=not supported, 1=supported) */
+		if (subsystem_deviceid & 0x0020)
+			ctrl->pci_config_space = 1;
+		else
+			ctrl->pci_config_space = 0;
+
+		/* PCI-X support */
+		if (subsystem_deviceid & 0x0080) {
+			ctrl->pcix_support = 1;
+			if (subsystem_deviceid & 0x0040)
+				/* 133MHz PCI-X if bit 7 is 1 */
+				ctrl->pcix_speed_capability = 1;
+			else
+				/* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
+				/* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
+				ctrl->pcix_speed_capability = 0;
+		} else {
+			/* Conventional PCI */
+			ctrl->pcix_support = 0;
+			ctrl->pcix_speed_capability = 0;
+		}
+		break;
+
+	default:
 		err(msg_HPC_not_supported);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err_free_ctrl;
 	}
 
-	// Tell the user that we found one.
+	/* Tell the user that we found one. */
 	info("Initializing the PCI hot plug controller residing on PCI bus %d\n",
 					pdev->bus->number);
 
@@ -1087,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (rc) {
 		goto err_free_bus;
 	}
-	
+
 	dbg("pdev = %p\n", pdev);
 	dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0));
 	dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0));
@@ -1109,7 +1141,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_free_mem_region;
 	}
 
-	// Check for 66Mhz operation
+	/* Check for 66Mhz operation */
 	ctrl->speed = get_controller_speed(ctrl);
 
 
@@ -1120,7 +1152,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 *
 	 ********************************************************/
 
-	// find the physical slot number of the first hot plug slot
+	/* find the physical slot number of the first hot plug slot */
 
 	/* Get slot won't work for devices behind bridges, but
 	 * in this case it will always be called for the "base"
@@ -1137,7 +1169,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_iounmap;
 	}
 
-	// Store PCI Config Space for all devices on this bus
+	/* Store PCI Config Space for all devices on this bus */
 	rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
 	if (rc) {
 		err("%s: unable to save PCI configuration data, error %d\n",
@@ -1148,7 +1180,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/*
 	 * Get IO, memory, and IRQ resources for new devices
 	 */
-	// The next line is required for cpqhp_find_available_resources
+	/* The next line is required for cpqhp_find_available_resources */
 	ctrl->interrupt = pdev->irq;
 	if (ctrl->interrupt < 0x10) {
 		cpqhp_legacy_mode = 1;
@@ -1182,7 +1214,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			__func__, rc);
 		goto err_iounmap;
 	}
-	
+
 	/* Mask all general input interrupts */
 	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
 
@@ -1196,12 +1228,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_iounmap;
 	}
 
-	/* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
+	/* Enable Shift Out interrupt and clear it, also enable SERR on power
+	 * fault
+	 */
 	temp_word = readw(ctrl->hpc_reg + MISC);
 	temp_word |= 0x4006;
 	writew(temp_word, ctrl->hpc_reg + MISC);
 
-	// Changed 05/05/97 to clear all interrupts at start
+	/* Changed 05/05/97 to clear all interrupts at start */
 	writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
 
 	ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
@@ -1216,13 +1250,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		cpqhp_ctrl_list = ctrl;
 	}
 
-	// turn off empty slots here unless command line option "ON" set
-	// Wait for exclusive access to hardware
+	/* turn off empty slots here unless command line option "ON" set
+	 * Wait for exclusive access to hardware
+	 */
 	mutex_lock(&ctrl->crit_sect);
 
 	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
 
-	// find first device number for the ctrl
+	/* find first device number for the ctrl */
 	device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
 
 	while (num_of_slots) {
@@ -1234,23 +1269,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		hp_slot = func->device - ctrl->slot_device_offset;
 		dbg("hp_slot: %d\n", hp_slot);
 
-		// We have to save the presence info for these slots
+		/* We have to save the presence info for these slots */
 		temp_word = ctrl->ctrl_int_comp >> 16;
 		func->presence_save = (temp_word >> hp_slot) & 0x01;
 		func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
 
-		if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+		if (ctrl->ctrl_int_comp & (0x1L << hp_slot))
 			func->switch_save = 0;
-		} else {
+		else
 			func->switch_save = 0x10;
-		}
 
-		if (!power_mode) {
+		if (!power_mode)
 			if (!func->is_a_board) {
 				green_LED_off(ctrl, hp_slot);
 				slot_disable(ctrl, hp_slot);
 			}
-		}
 
 		device++;
 		num_of_slots--;
@@ -1258,7 +1291,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if (!power_mode) {
 		set_SOGO(ctrl);
-		// Wait for SOBS to be unset
+		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq(ctrl);
 	}
 
@@ -1269,7 +1302,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_free_irq;
 	}
 
-	// Done with exclusive hardware access
+	/* Done with exclusive hardware access */
 	mutex_unlock(&ctrl->crit_sect);
 
 	cpqhp_create_debugfs_files(ctrl);
@@ -1291,77 +1324,6 @@ err_disable_device:
 	return rc;
 }
 
-
-static int one_time_init(void)
-{
-	int loop;
-	int retval = 0;
-
-	if (initialized)
-		return 0;
-
-	power_mode = 0;
-
-	retval = pci_print_IRQ_route();
-	if (retval)
-		goto error;
-
-	dbg("Initialize + Start the notification mechanism \n");
-
-	retval = cpqhp_event_start_thread();
-	if (retval)
-		goto error;
-
-	dbg("Initialize slot lists\n");
-	for (loop = 0; loop < 256; loop++) {
-		cpqhp_slot_list[loop] = NULL;
-	}
-
-	// FIXME: We also need to hook the NMI handler eventually.
-	// this also needs to be worked with Christoph
-	// register_NMI_handler();
-
-	// Map rom address
-	cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
-	if (!cpqhp_rom_start) {
-		err ("Could not ioremap memory region for ROM\n");
-		retval = -EIO;
-		goto error;
-	}
-	
-	/* Now, map the int15 entry point if we are on compaq specific hardware */
-	compaq_nvram_init(cpqhp_rom_start);
-	
-	/* Map smbios table entry point structure */
-	smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
-					cpqhp_rom_start + ROM_PHY_LEN);
-	if (!smbios_table) {
-		err ("Could not find the SMBIOS pointer in memory\n");
-		retval = -EIO;
-		goto error_rom_start;
-	}
-
-	smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
-					readw(smbios_table + ST_LENGTH));
-	if (!smbios_start) {
-		err ("Could not ioremap memory region taken from SMBIOS values\n");
-		retval = -EIO;
-		goto error_smbios_start;
-	}
-
-	initialized = 1;
-
-	return retval;
-
-error_smbios_start:
-	iounmap(smbios_start);
-error_rom_start:
-	iounmap(cpqhp_rom_start);
-error:
-	return retval;
-}
-
-
 static void __exit unload_cpqphpd(void)
 {
 	struct pci_func *next;
@@ -1381,10 +1343,10 @@ static void __exit unload_cpqphpd(void)
 		if (ctrl->hpc_reg) {
 			u16 misc;
 			rc = read_slot_enable (ctrl);
-			
+
 			writeb(0, ctrl->hpc_reg + SLOT_SERR);
 			writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
-			
+
 			misc = readw(ctrl->hpc_reg + MISC);
 			misc &= 0xFFFD;
 			writew(misc, ctrl->hpc_reg + MISC);
@@ -1464,38 +1426,34 @@ static void __exit unload_cpqphpd(void)
 		}
 	}
 
-	// Stop the notification mechanism
+	/* Stop the notification mechanism */
 	if (initialized)
 		cpqhp_event_stop_thread();
 
-	//unmap the rom address
+	/* unmap the rom address */
 	if (cpqhp_rom_start)
 		iounmap(cpqhp_rom_start);
 	if (smbios_start)
 		iounmap(smbios_start);
 }
 
-
-
 static struct pci_device_id hpcd_pci_tbl[] = {
 	{
 	/* handle any PCI Hotplug controller */
 	.class =        ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
 	.class_mask =   ~0,
-	
+
 	/* no matter who makes it */
 	.vendor =       PCI_ANY_ID,
 	.device =       PCI_ANY_ID,
 	.subvendor =    PCI_ANY_ID,
 	.subdevice =    PCI_ANY_ID,
-	
+
 	}, { /* end: all zeroes */ }
 };
 
 MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
 
-
-
 static struct pci_driver cpqhpc_driver = {
 	.name =		"compaq_pci_hotplug",
 	.id_table =	hpcd_pci_tbl,
@@ -1503,8 +1461,6 @@ static struct pci_driver cpqhpc_driver = {
 	/* remove:	cpqhpc_remove_one, */
 };
 
-
-
 static int __init cpqhpc_init(void)
 {
 	int result;
@@ -1518,7 +1474,6 @@ static int __init cpqhpc_init(void)
 	return result;
 }
 
-
 static void __exit cpqhpc_cleanup(void)
 {
 	dbg("unload_cpqphpd()\n");
@@ -1529,8 +1484,5 @@ static void __exit cpqhpc_cleanup(void)
 	cpqhp_shutdown_debugfs();
 }
 
-
 module_init(cpqhpc_init);
 module_exit(cpqhpc_cleanup);
-
-

+ 191 - 180
drivers/pci/hotplug/cpqphp_ctrl.c

@@ -81,14 +81,15 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
 
 	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
 		if (change & (0x1L << hp_slot)) {
-			/**********************************
+			/*
 			 * this one changed.
-			 **********************************/
+			 */
 			func = cpqhp_slot_find(ctrl->bus,
 				(hp_slot + ctrl->slot_device_offset), 0);
 
 			/* this is the structure that tells the worker thread
-			 *what to do */
+			 * what to do
+			 */
 			taskInfo = &(ctrl->event_queue[ctrl->next_event]);
 			ctrl->next_event = (ctrl->next_event + 1) % 10;
 			taskInfo->hp_slot = hp_slot;
@@ -100,17 +101,17 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
 			func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
 
 			if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
-				/**********************************
+				/*
 				 * Switch opened
-				 **********************************/
+				 */
 
 				func->switch_save = 0;
 
 				taskInfo->event_type = INT_SWITCH_OPEN;
 			} else {
-				/**********************************
+				/*
 				 * Switch closed
-				 **********************************/
+				 */
 
 				func->switch_save = 0x10;
 
@@ -131,9 +132,8 @@ static struct slot *cpqhp_find_slot(struct controller *ctrl, u8 device)
 {
 	struct slot *slot = ctrl->slot;
 
-	while (slot && (slot->device != device)) {
+	while (slot && (slot->device != device))
 		slot = slot->next;
-	}
 
 	return slot;
 }
@@ -152,17 +152,17 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
 	if (!change)
 		return 0;
 
-	/**********************************
+	/*
 	 * Presence Change
-	 **********************************/
+	 */
 	dbg("cpqsbd:  Presence/Notify input change.\n");
 	dbg("         Changed bits are 0x%4.4x\n", change );
 
 	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
 		if (change & (0x0101 << hp_slot)) {
-			/**********************************
+			/*
 			 * this one changed.
-			 **********************************/
+			 */
 			func = cpqhp_slot_find(ctrl->bus,
 				(hp_slot + ctrl->slot_device_offset), 0);
 
@@ -177,22 +177,23 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
 				return 0;
 
 			/* If the switch closed, must be a button
-			 * If not in button mode, nevermind */
+			 * If not in button mode, nevermind
+			 */
 			if (func->switch_save && (ctrl->push_button == 1)) {
 				temp_word = ctrl->ctrl_int_comp >> 16;
 				temp_byte = (temp_word >> hp_slot) & 0x01;
 				temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;
 
 				if (temp_byte != func->presence_save) {
-					/**************************************
+					/*
 					 * button Pressed (doesn't do anything)
-					 **************************************/
+					 */
 					dbg("hp_slot %d button pressed\n", hp_slot);
 					taskInfo->event_type = INT_BUTTON_PRESS;
 				} else {
-					/**********************************
+					/*
 					 * button Released - TAKE ACTION!!!!
-					 **********************************/
+					 */
 					dbg("hp_slot %d button released\n", hp_slot);
 					taskInfo->event_type = INT_BUTTON_RELEASE;
 
@@ -210,7 +211,8 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
 				}
 			} else {
 				/* Switch is open, assume a presence change
-				 * Save the presence state */
+				 * Save the presence state
+				 */
 				temp_word = ctrl->ctrl_int_comp >> 16;
 				func->presence_save = (temp_word >> hp_slot) & 0x01;
 				func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
@@ -241,17 +243,17 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
 	if (!change)
 		return 0;
 
-	/**********************************
+	/*
 	 * power fault
-	 **********************************/
+	 */
 
 	info("power fault interrupt\n");
 
 	for (hp_slot = 0; hp_slot < 6; hp_slot++) {
 		if (change & (0x01 << hp_slot)) {
-			/**********************************
+			/*
 			 * this one changed.
-			 **********************************/
+			 */
 			func = cpqhp_slot_find(ctrl->bus,
 				(hp_slot + ctrl->slot_device_offset), 0);
 
@@ -262,16 +264,16 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
 			rc++;
 
 			if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {
-				/**********************************
+				/*
 				 * power fault Cleared
-				 **********************************/
+				 */
 				func->status = 0x00;
 
 				taskInfo->event_type = INT_POWER_FAULT_CLEAR;
 			} else {
-				/**********************************
+				/*
 				 * power fault
-				 **********************************/
+				 */
 				taskInfo->event_type = INT_POWER_FAULT;
 
 				if (ctrl->rev < 4) {
@@ -432,13 +434,15 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h
 
 
 	/* If we got here, there the bridge requires some of the resource, but
-	 * we may be able to split some off of the front */
+	 * we may be able to split some off of the front
+	 */
 
 	node = *head;
 
 	if (node->length & (alignment -1)) {
 		/* this one isn't an aligned length, so we'll make a new entry
-		 * and split it up. */
+		 * and split it up.
+		 */
 		split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
 		if (!split_node)
@@ -544,10 +548,10 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
 	if (!(*head))
 		return NULL;
 
-	if ( cpqhp_resource_sort_and_combine(head) )
+	if (cpqhp_resource_sort_and_combine(head))
 		return NULL;
 
-	if ( sort_by_size(head) )
+	if (sort_by_size(head))
 		return NULL;
 
 	for (node = *head; node; node = node->next) {
@@ -556,7 +560,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
 
 		if (node->base & (size - 1)) {
 			/* this one isn't base aligned properly
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			temp_dword = (node->base | (size-1)) + 1;
 
 			/* Short circuit if adjusted size is too small */
@@ -581,7 +586,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
 		/* Don't need to check if too small since we already did */
 		if (node->length > size) {
 			/* this one is longer than we need
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
 			if (!split_node)
@@ -601,7 +607,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
 			continue;
 
 		/* If we got here, then it is the right size
-		 * Now take it out of the list and break */
+		 * Now take it out of the list and break
+		 */
 		if (*head == node) {
 			*head = node->next;
 		} else {
@@ -642,14 +649,16 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
 		return NULL;
 
 	for (max = *head; max; max = max->next) {
-		/* If not big enough we could probably just bail, 
-		 * instead we'll continue to the next. */
+		/* If not big enough we could probably just bail,
+		 * instead we'll continue to the next.
+		 */
 		if (max->length < size)
 			continue;
 
 		if (max->base & (size - 1)) {
 			/* this one isn't base aligned properly
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			temp_dword = (max->base | (size-1)) + 1;
 
 			/* Short circuit if adjusted size is too small */
@@ -672,7 +681,8 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
 
 		if ((max->base + max->length) & (size - 1)) {
 			/* this one isn't end aligned properly at the top
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
 			if (!split_node)
@@ -744,7 +754,8 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
 		if (node->base & (size - 1)) {
 			dbg("%s: not aligned\n", __func__);
 			/* this one isn't base aligned properly
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			temp_dword = (node->base | (size-1)) + 1;
 
 			/* Short circuit if adjusted size is too small */
@@ -769,7 +780,8 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
 		if (node->length > size) {
 			dbg("%s: too big\n", __func__);
 			/* this one is longer than we need
-			 * so we'll make a new entry and split it up */
+			 * so we'll make a new entry and split it up
+			 */
 			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
 			if (!split_node)
@@ -886,19 +898,19 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
 	u32 Diff;
 	u32 temp_dword;
 
-	
+
 	misc = readw(ctrl->hpc_reg + MISC);
-	/***************************************
+	/*
 	 * Check to see if it was our interrupt
-	 ***************************************/
+	 */
 	if (!(misc & 0x000C)) {
 		return IRQ_NONE;
 	}
 
 	if (misc & 0x0004) {
-		/**********************************
+		/*
 		 * Serial Output interrupt Pending
-		 **********************************/
+		 */
 
 		/* Clear the interrupt */
 		misc |= 0x0004;
@@ -961,11 +973,8 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)
 	struct pci_func *next;
 
 	new_slot = kzalloc(sizeof(*new_slot), GFP_KERNEL);
-	if (new_slot == NULL) {
-		/* I'm not dead yet!
-		 * You will be. */
+	if (new_slot == NULL)
 		return new_slot;
-	}
 
 	new_slot->next = NULL;
 	new_slot->configured = 1;
@@ -996,10 +1005,8 @@ static int slot_remove(struct pci_func * old_slot)
 		return 1;
 
 	next = cpqhp_slot_list[old_slot->bus];
-
-	if (next == NULL) {
+	if (next == NULL)
 		return 1;
-	}
 
 	if (next == old_slot) {
 		cpqhp_slot_list[old_slot->bus] = old_slot->next;
@@ -1008,9 +1015,8 @@ static int slot_remove(struct pci_func * old_slot)
 		return 0;
 	}
 
-	while ((next->next != old_slot) && (next->next != NULL)) {
+	while ((next->next != old_slot) && (next->next != NULL))
 		next = next->next;
-	}
 
 	if (next->next == old_slot) {
 		next->next = old_slot->next;
@@ -1040,9 +1046,8 @@ static int bridge_slot_remove(struct pci_func *bridge)
 	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
 		next = cpqhp_slot_list[tempBus];
 
-		while (!slot_remove(next)) {
+		while (!slot_remove(next))
 			next = cpqhp_slot_list[tempBus];
-		}
 	}
 
 	next = cpqhp_slot_list[bridge->bus];
@@ -1130,39 +1135,43 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
 	u16 reg16;
 	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
-	
+
 	if (ctrl->speed == adapter_speed)
 		return 0;
-	
+
 	/* We don't allow freq/mode changes if we find another adapter running
-	 * in another slot on this controller */
+	 * in another slot on this controller
+	 */
 	for(slot = ctrl->slot; slot; slot = slot->next) {
-		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
+		if (slot->device == (hp_slot + ctrl->slot_device_offset))
 			continue;
 		if (!slot->hotplug_slot || !slot->hotplug_slot->info)
 			continue;
-		if (slot->hotplug_slot->info->adapter_status == 0) 
+		if (slot->hotplug_slot->info->adapter_status == 0)
 			continue;
 		/* If another adapter is running on the same segment but at a
 		 * lower speed/mode, we allow the new adapter to function at
-		 * this rate if supported */
-		if (ctrl->speed < adapter_speed) 
+		 * this rate if supported
+		 */
+		if (ctrl->speed < adapter_speed)
 			return 0;
 
 		return 1;
 	}
-	
+
 	/* If the controller doesn't support freq/mode changes and the
-	 * controller is running at a higher mode, we bail */
+	 * controller is running at a higher mode, we bail
+	 */
 	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
 		return 1;
-	
+
 	/* But we allow the adapter to run at a lower rate if possible */
 	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
 		return 0;
 
 	/* We try to set the max speed supported by both the adapter and
-	 * controller */
+	 * controller
+	 */
 	if (ctrl->speed_capability < adapter_speed) {
 		if (ctrl->speed == ctrl->speed_capability)
 			return 0;
@@ -1171,22 +1180,22 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 
 	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
 	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
-	
-	set_SOGO(ctrl); 
+
+	set_SOGO(ctrl);
 	wait_for_ctrl_irq(ctrl);
-	
+
 	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
 		reg = 0xF5;
 	else
-		reg = 0xF4;	
+		reg = 0xF4;
 	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
-	
+
 	reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
 	reg16 &= ~0x000F;
 	switch(adapter_speed) {
-		case(PCI_SPEED_133MHz_PCIX): 
+		case(PCI_SPEED_133MHz_PCIX):
 			reg = 0x75;
-			reg16 |= 0xB; 
+			reg16 |= 0xB;
 			break;
 		case(PCI_SPEED_100MHz_PCIX):
 			reg = 0x74;
@@ -1203,48 +1212,48 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 		default: /* 33MHz PCI 2.2 */
 			reg = 0x71;
 			break;
-			
+
 	}
 	reg16 |= 0xB << 12;
 	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
-	
-	mdelay(5); 
-	
+
+	mdelay(5);
+
 	/* Reenable interrupts */
 	writel(0, ctrl->hpc_reg + INT_MASK);
 
-	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
-	
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+
 	/* Restart state machine */
 	reg = ~0xF;
 	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
 	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
-	
+
 	/* Only if mode change...*/
 	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
 		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
 			set_SOGO(ctrl);
-	
+
 	wait_for_ctrl_irq(ctrl);
 	mdelay(1100);
-	
+
 	/* Restore LED/Slot state */
 	writel(leds, ctrl->hpc_reg + LED_CONTROL);
 	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
-	
+
 	set_SOGO(ctrl);
 	wait_for_ctrl_irq(ctrl);
 
 	ctrl->speed = adapter_speed;
 	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-	info("Successfully changed frequency/mode for adapter in slot %d\n", 
+	info("Successfully changed frequency/mode for adapter in slot %d\n",
 			slot->number);
 	return 0;
 }
 
-/* the following routines constitute the bulk of the 
-   hotplug controller logic
+/* the following routines constitute the bulk of the
+ * hotplug controller logic
  */
 
 
@@ -1268,17 +1277,17 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 
 	hp_slot = func->device - ctrl->slot_device_offset;
 
-	if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) {
-		/**********************************
-		 * The switch is open.
-		 **********************************/
+	/*
+	 * The switch is open.
+	 */
+	if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot))
 		rc = INTERLOCK_OPEN;
-	} else if (is_slot_enabled (ctrl, hp_slot)) {
-		/**********************************
-		 * The board is already on
-		 **********************************/
+	/*
+	 * The board is already on
+	 */
+	else if (is_slot_enabled (ctrl, hp_slot))
 		rc = CARD_FUNCTIONING;
-	} else {
+	else {
 		mutex_lock(&ctrl->crit_sect);
 
 		/* turn on board without attaching to the bus */
@@ -1299,7 +1308,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 
 		/* Wait for SOBS to be unset */
 		wait_for_ctrl_irq (ctrl);
-		
+
 		adapter_speed = get_adapter_speed(ctrl, hp_slot);
 		if (ctrl->speed != adapter_speed)
 			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
@@ -1352,7 +1361,8 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 			 * Get slot won't work for devices behind
 			 * bridges, but in this case it will always be
 			 * called for the "base" bus/dev/func of an
-			 * adapter. */
+			 * adapter.
+			 */
 
 			mutex_lock(&ctrl->crit_sect);
 
@@ -1377,7 +1387,8 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 
 			 * Get slot won't work for devices behind bridges, but
 			 * in this case it will always be called for the "base"
-			 * bus/dev/func of an adapter. */
+			 * bus/dev/func of an adapter.
+			 */
 
 			mutex_lock(&ctrl->crit_sect);
 
@@ -1434,7 +1445,8 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	wait_for_ctrl_irq (ctrl);
 
 	/* Change bits in slot power register to force another shift out
-	 * NOTE: this is to work around the timer bug */
+	 * NOTE: this is to work around the timer bug
+	 */
 	temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
 	writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
 	writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
@@ -1443,12 +1455,12 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 
 	/* Wait for SOBS to be unset */
 	wait_for_ctrl_irq (ctrl);
-	
+
 	adapter_speed = get_adapter_speed(ctrl, hp_slot);
 	if (ctrl->speed != adapter_speed)
 		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 			rc = WRONG_BUS_FREQUENCY;
-	
+
 	/* turn off board without attaching to the bus */
 	disable_slot_power (ctrl, hp_slot);
 
@@ -1461,7 +1473,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 
 	if (rc)
 		return rc;
-	
+
 	p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	/* turn on board and blink green LED */
@@ -1521,7 +1533,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 	}
 
 	/* All F's is an empty slot or an invalid board */
-	if (temp_register != 0xFFFFFFFF) {	  /* Check for a board in the slot */
+	if (temp_register != 0xFFFFFFFF) {
 		res_lists.io_head = ctrl->io_head;
 		res_lists.mem_head = ctrl->mem_head;
 		res_lists.p_mem_head = ctrl->p_mem_head;
@@ -1570,9 +1582,8 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 		index = 0;
 		do {
 			new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);
-			if (new_slot && !new_slot->pci_dev) {
+			if (new_slot && !new_slot->pci_dev)
 				cpqhp_configure_device(ctrl, new_slot);
-			}
 		} while (new_slot);
 
 		mutex_lock(&ctrl->crit_sect);
@@ -1859,12 +1870,12 @@ static void interrupt_event_handler(struct controller *ctrl)
 						info(msg_button_on, p_slot->number);
 					}
 					mutex_lock(&ctrl->crit_sect);
-					
+
 					dbg("blink green LED and turn off amber\n");
-					
+
 					amber_LED_off (ctrl, hp_slot);
 					green_LED_blink (ctrl, hp_slot);
-					
+
 					set_SOGO(ctrl);
 
 					/* Wait for SOBS to be unset */
@@ -1958,7 +1969,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
 			if (cpqhp_process_SI(ctrl, func) != 0) {
 				amber_LED_on(ctrl, hp_slot);
 				green_LED_off(ctrl, hp_slot);
-				
+
 				set_SOGO(ctrl);
 
 				/* Wait for SOBS to be unset */
@@ -2079,7 +2090,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
 	struct pci_bus *pci_bus = ctrl->pci_bus;
 	int physical_slot=0;
 
-	device = func->device; 
+	device = func->device;
 	func = cpqhp_slot_find(ctrl->bus, device, index++);
 	p_slot = cpqhp_find_slot(ctrl, device);
 	if (p_slot) {
@@ -2113,9 +2124,8 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
 
 				/* If the VGA Enable bit is set, remove isn't
 				 * supported */
-				if (BCR & PCI_BRIDGE_CTL_VGA) {
+				if (BCR & PCI_BRIDGE_CTL_VGA)
 					rc = REMOVE_NOT_SUPPORTED;
-				}
 			}
 		}
 
@@ -2183,67 +2193,67 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
 	num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;
 
 	switch (test_num) {
-		case 1:
-			/* Do stuff here! */
-
-			/* Do that funky LED thing */
-			/* so we can restore them later */
-			save_LED = readl(ctrl->hpc_reg + LED_CONTROL);
-			work_LED = 0x01010101;
-			switch_leds(ctrl, num_of_slots, &work_LED, 0);
-			switch_leds(ctrl, num_of_slots, &work_LED, 1);
-			switch_leds(ctrl, num_of_slots, &work_LED, 0);
-			switch_leds(ctrl, num_of_slots, &work_LED, 1);
-
-			work_LED = 0x01010000;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			switch_leds(ctrl, num_of_slots, &work_LED, 0);
-			switch_leds(ctrl, num_of_slots, &work_LED, 1);
-			work_LED = 0x00000101;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			switch_leds(ctrl, num_of_slots, &work_LED, 0);
-			switch_leds(ctrl, num_of_slots, &work_LED, 1);
+	case 1:
+		/* Do stuff here! */
+
+		/* Do that funky LED thing */
+		/* so we can restore them later */
+		save_LED = readl(ctrl->hpc_reg + LED_CONTROL);
+		work_LED = 0x01010101;
+		switch_leds(ctrl, num_of_slots, &work_LED, 0);
+		switch_leds(ctrl, num_of_slots, &work_LED, 1);
+		switch_leds(ctrl, num_of_slots, &work_LED, 0);
+		switch_leds(ctrl, num_of_slots, &work_LED, 1);
+
+		work_LED = 0x01010000;
+		writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+		switch_leds(ctrl, num_of_slots, &work_LED, 0);
+		switch_leds(ctrl, num_of_slots, &work_LED, 1);
+		work_LED = 0x00000101;
+		writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+		switch_leds(ctrl, num_of_slots, &work_LED, 0);
+		switch_leds(ctrl, num_of_slots, &work_LED, 1);
+
+		work_LED = 0x01010000;
+		writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+		for (loop = 0; loop < num_of_slots; loop++) {
+			set_SOGO(ctrl);
 
-			work_LED = 0x01010000;
-			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			for (loop = 0; loop < num_of_slots; loop++) {
-				set_SOGO(ctrl);
+			/* Wait for SOGO interrupt */
+			wait_for_ctrl_irq (ctrl);
 
-				/* Wait for SOGO interrupt */
-				wait_for_ctrl_irq (ctrl);
+			/* Get ready for next iteration */
+			long_delay((3*HZ)/10);
+			work_LED = work_LED >> 16;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
 
-				/* Get ready for next iteration */
-				long_delay((3*HZ)/10);
-				work_LED = work_LED >> 16;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				
-				set_SOGO(ctrl);
+			set_SOGO(ctrl);
 
-				/* Wait for SOGO interrupt */
-				wait_for_ctrl_irq (ctrl);
+			/* Wait for SOGO interrupt */
+			wait_for_ctrl_irq (ctrl);
 
-				/* Get ready for next iteration */
-				long_delay((3*HZ)/10);
-				work_LED = work_LED << 16;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-				work_LED = work_LED << 1;
-				writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-			}
+			/* Get ready for next iteration */
+			long_delay((3*HZ)/10);
+			work_LED = work_LED << 16;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+			work_LED = work_LED << 1;
+			writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+		}
 
-			/* put it back the way it was */
-			writel(save_LED, ctrl->hpc_reg + LED_CONTROL);
+		/* put it back the way it was */
+		writel(save_LED, ctrl->hpc_reg + LED_CONTROL);
 
-			set_SOGO(ctrl);
+		set_SOGO(ctrl);
 
-			/* Wait for SOBS to be unset */
-			wait_for_ctrl_irq (ctrl);
-			break;
-		case 2:
-			/* Do other stuff here! */
-			break;
-		case 3:
-			/* and more... */
-			break;
+		/* Wait for SOBS to be unset */
+		wait_for_ctrl_irq (ctrl);
+		break;
+	case 2:
+		/* Do other stuff here! */
+		break;
+	case 3:
+		/* and more... */
+		break;
 	}
 	return 0;
 }
@@ -2312,9 +2322,9 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
 		while ((function < max_functions) && (!stop_it)) {
 			pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
 
-			if (ID == 0xFFFFFFFF) {	  /* There's nothing there. */
+			if (ID == 0xFFFFFFFF) {
 				function++;
-			} else {  /* There's something there */
+			} else {
 				/* Setup slot structure. */
 				new_slot = cpqhp_slot_create(func->bus);
 
@@ -2339,8 +2349,8 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
 
 
 /*
-  Configuration logic that involves the hotplug data structures and 
-  their bookkeeping
+ * Configuration logic that involves the hotplug data structures and
+ * their bookkeeping
  */
 
 
@@ -2393,7 +2403,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 	if (rc)
 		return rc;
 
-	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
 		/* set Primary bus */
 		dbg("set Primary bus = %d\n", func->bus);
 		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
@@ -2484,7 +2494,8 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 		temp_resources.irqs = &irqs;
 
 		/* Make copies of the nodes we are going to pass down so that
-		 * if there is a problem,we can just use these to free resources */
+		 * if there is a problem,we can just use these to free resources
+		 */
 		hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
 		hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
 		hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
@@ -2556,7 +2567,8 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 		temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
 		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
 
-		/* Adjust this to compensate for extra adjustment in first loop */
+		/* Adjust this to compensate for extra adjustment in first loop
+		 */
 		irqs.barber_pole--;
 
 		rc = 0;
@@ -2917,27 +2929,26 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 		}		/* End of base register loop */
 		if (cpqhp_legacy_mode) {
 			/* Figure out which interrupt pin this function uses */
-			rc = pci_bus_read_config_byte (pci_bus, devfn, 
+			rc = pci_bus_read_config_byte (pci_bus, devfn,
 				PCI_INTERRUPT_PIN, &temp_byte);
 
 			/* If this function needs an interrupt and we are behind
 			 * a bridge and the pin is tied to something that's
 			 * alread mapped, set this one the same */
-			if (temp_byte && resources->irqs && 
-			    (resources->irqs->valid_INT & 
+			if (temp_byte && resources->irqs &&
+			    (resources->irqs->valid_INT &
 			     (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
 				/* We have to share with something already set up */
-				IRQ = resources->irqs->interrupt[(temp_byte + 
+				IRQ = resources->irqs->interrupt[(temp_byte +
 					resources->irqs->barber_pole - 1) & 0x03];
 			} else {
 				/* Program IRQ based on card type */
 				rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
 
-				if (class_code == PCI_BASE_CLASS_STORAGE) {
+				if (class_code == PCI_BASE_CLASS_STORAGE)
 					IRQ = cpqhp_disk_irq;
-				} else {
+				else
 					IRQ = cpqhp_nic_irq;
-				}
 			}
 
 			/* IRQ Line */

+ 51 - 46
drivers/pci/hotplug/cpqphp_nvram.c

@@ -94,12 +94,13 @@ static u8 evbuffer[1024];
 
 static void __iomem *compaq_int15_entry_point;
 
-static spinlock_t int15_lock;		/* lock for ordering int15_bios_call() */
+/* lock for ordering int15_bios_call() */
+static spinlock_t int15_lock;
 
 
 /* This is a series of function that deals with
-   setting & getting the hotplug resource table in some environment variable.
-*/
+ * setting & getting the hotplug resource table in some environment variable.
+ */
 
 /*
  * We really shouldn't be doing this unless there is a _very_ good reason to!!!
@@ -113,7 +114,7 @@ static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
 
 	if ((*used + 1) > *avail)
 		return(1);
-	
+
 	*((u8*)*p_buffer) = value;
 	tByte = (u8**)p_buffer;
 	(*tByte)++;
@@ -170,10 +171,10 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
 	unsigned long flags;
 	int op = operation;
 	int ret_val;
-	
+
 	if (!compaq_int15_entry_point)
 		return -ENODEV;
-	
+
 	spin_lock_irqsave(&int15_lock, flags);
 	__asm__ (
 		"xorl   %%ebx,%%ebx\n" \
@@ -187,7 +188,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
 		"D" (buffer), "m" (compaq_int15_entry_point)
 		: "%ebx", "%edx");
 	spin_unlock_irqrestore(&int15_lock, flags);
-	
+
 	return((ret_val & 0xFF00) >> 8);
 }
 
@@ -210,14 +211,16 @@ static int load_HRT (void __iomem *rom_start)
 
 	available = 1024;
 
-	// Now load the EV
+	/* Now load the EV */
 	temp_dword = available;
 
 	rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
 
 	evbuffer_length = temp_dword;
 
-	// We're maintaining the resource lists so write FF to invalidate old info
+	/* We're maintaining the resource lists so write FF to invalidate old
+	 * info
+	 */
 	temp_dword = 1;
 
 	rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
@@ -263,13 +266,13 @@ static u32 store_HRT (void __iomem *rom_start)
 	p_EV_header = (struct ev_hrt_header *) pFill;
 
 	ctrl = cpqhp_ctrl_list;
-	
-	// The revision of this structure
+
+	/* The revision of this structure */
 	rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
 	if (rc)
 		return(rc);
 
-	// The number of controllers
+	/* The number of controllers */
 	rc = add_byte( &pFill, 1, &usedbytes, &available);
 	if (rc)
 		return(rc);
@@ -279,27 +282,27 @@ static u32 store_HRT (void __iomem *rom_start)
 
 		numCtrl++;
 
-		// The bus number
+		/* The bus number */
 		rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
 		if (rc)
 			return(rc);
 
-		// The device Number
+		/* The device Number */
 		rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
 		if (rc)
 			return(rc);
 
-		// The function Number
+		/* The function Number */
 		rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
 		if (rc)
 			return(rc);
 
-		// Skip the number of available entries
+		/* Skip the number of available entries */
 		rc = add_dword( &pFill, 0, &usedbytes, &available);
 		if (rc)
 			return(rc);
 
-		// Figure out memory Available
+		/* Figure out memory Available */
 
 		resNode = ctrl->mem_head;
 
@@ -308,12 +311,12 @@ static u32 store_HRT (void __iomem *rom_start)
 		while (resNode) {
 			loop ++;
 
-			// base
+			/* base */
 			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
 			if (rc)
 				return(rc);
 
-			// length
+			/* length */
 			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
 			if (rc)
 				return(rc);
@@ -321,10 +324,10 @@ static u32 store_HRT (void __iomem *rom_start)
 			resNode = resNode->next;
 		}
 
-		// Fill in the number of entries
+		/* Fill in the number of entries */
 		p_ev_ctrl->mem_avail = loop;
 
-		// Figure out prefetchable memory Available
+		/* Figure out prefetchable memory Available */
 
 		resNode = ctrl->p_mem_head;
 
@@ -333,12 +336,12 @@ static u32 store_HRT (void __iomem *rom_start)
 		while (resNode) {
 			loop ++;
 
-			// base
+			/* base */
 			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
 			if (rc)
 				return(rc);
 
-			// length
+			/* length */
 			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
 			if (rc)
 				return(rc);
@@ -346,10 +349,10 @@ static u32 store_HRT (void __iomem *rom_start)
 			resNode = resNode->next;
 		}
 
-		// Fill in the number of entries
+		/* Fill in the number of entries */
 		p_ev_ctrl->p_mem_avail = loop;
 
-		// Figure out IO Available
+		/* Figure out IO Available */
 
 		resNode = ctrl->io_head;
 
@@ -358,12 +361,12 @@ static u32 store_HRT (void __iomem *rom_start)
 		while (resNode) {
 			loop ++;
 
-			// base
+			/* base */
 			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
 			if (rc)
 				return(rc);
 
-			// length
+			/* length */
 			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
 			if (rc)
 				return(rc);
@@ -371,10 +374,10 @@ static u32 store_HRT (void __iomem *rom_start)
 			resNode = resNode->next;
 		}
 
-		// Fill in the number of entries
+		/* Fill in the number of entries */
 		p_ev_ctrl->io_avail = loop;
 
-		// Figure out bus Available
+		/* Figure out bus Available */
 
 		resNode = ctrl->bus_head;
 
@@ -383,12 +386,12 @@ static u32 store_HRT (void __iomem *rom_start)
 		while (resNode) {
 			loop ++;
 
-			// base
+			/* base */
 			rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
 			if (rc)
 				return(rc);
 
-			// length
+			/* length */
 			rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
 			if (rc)
 				return(rc);
@@ -396,15 +399,15 @@ static u32 store_HRT (void __iomem *rom_start)
 			resNode = resNode->next;
 		}
 
-		// Fill in the number of entries
+		/* Fill in the number of entries */
 		p_ev_ctrl->bus_avail = loop;
 
 		ctrl = ctrl->next;
 	}
-	
+
 	p_EV_header->num_of_ctrl = numCtrl;
 
-	// Now store the EV
+	/* Now store the EV */
 
 	temp_dword = usedbytes;
 
@@ -449,20 +452,21 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
 	struct ev_hrt_header *p_EV_header;
 
 	if (!evbuffer_init) {
-		// Read the resource list information in from NVRAM
+		/* Read the resource list information in from NVRAM */
 		if (load_HRT(rom_start))
 			memset (evbuffer, 0, 1024);
 
 		evbuffer_init = 1;
 	}
 
-	// If we saved information in NVRAM, use it now
+	/* If we saved information in NVRAM, use it now */
 	p_EV_header = (struct ev_hrt_header *) evbuffer;
 
-	// The following code is for systems where version 1.0 of this
-	// driver has been loaded, but doesn't support the hardware.
-	// In that case, the driver would incorrectly store something
-	// in NVRAM.
+	/* The following code is for systems where version 1.0 of this
+	 * driver has been loaded, but doesn't support the hardware.
+	 * In that case, the driver would incorrectly store something
+	 * in NVRAM.
+	 */
 	if ((p_EV_header->Version == 2) ||
 	    ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
 		p_byte = &(p_EV_header->next);
@@ -479,7 +483,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
 		function = p_ev_ctrl->function;
 
 		while ((bus != ctrl->bus) ||
-		       (device != PCI_SLOT(ctrl->pci_dev->devfn)) || 
+		       (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
 		       (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
 			nummem = p_ev_ctrl->mem_avail;
 			numpmem = p_ev_ctrl->p_mem_avail;
@@ -491,7 +495,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
 			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
 				return 2;
 
-			// Skip forward to the next entry
+			/* Skip forward to the next entry */
 			p_byte += (nummem + numpmem + numio + numbus) * 8;
 
 			if (p_byte > ((u8*)p_EV_header + evbuffer_length))
@@ -629,8 +633,9 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
 			ctrl->bus_head = bus_node;
 		}
 
-		// If all of the following fail, we don't have any resources for
-		// hot plug add
+		/* If all of the following fail, we don't have any resources for
+		 * hot plug add
+		 */
 		rc = 1;
 		rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
 		rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
@@ -640,14 +645,14 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
 		if (rc)
 			return(rc);
 	} else {
-		if ((evbuffer[0] != 0) && (!ctrl->push_flag)) 
+		if ((evbuffer[0] != 0) && (!ctrl->push_flag))
 			return 1;
 	}
 
 	return 0;
 }
 
-	
+
 int compaq_nvram_store (void __iomem *rom_start)
 {
 	int rc = 1;

+ 297 - 302
drivers/pci/hotplug/cpqphp_pci.c

@@ -37,7 +37,6 @@
 #include "../pci.h"
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include <asm/pci_x86.h>
 
 
 u8 cpqhp_nic_irq;
@@ -82,14 +81,14 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
 }
 
 
-int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
+int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 {
 	unsigned char bus;
 	struct pci_bus *child;
 	int num;
 
 	if (func->pci_dev == NULL)
-		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+		func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function));
 
 	/* No pci device, we need to create it then */
 	if (func->pci_dev == NULL) {
@@ -99,7 +98,7 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 		if (num)
 			pci_bus_add_devices(ctrl->pci_dev->bus);
 
-		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+		func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function));
 		if (func->pci_dev == NULL) {
 			dbg("ERROR: pci_dev still null\n");
 			return 0;
@@ -112,20 +111,24 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 		pci_do_scan_bus(child);
 	}
 
+	pci_dev_put(func->pci_dev);
+
 	return 0;
 }
 
 
-int cpqhp_unconfigure_device(struct pci_func* func) 
+int cpqhp_unconfigure_device(struct pci_func* func)
 {
 	int j;
-	
+
 	dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
 
 	for (j=0; j<8 ; j++) {
-		struct pci_dev* temp = pci_find_slot(func->bus, PCI_DEVFN(func->device, j));
-		if (temp)
+		struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j));
+		if (temp) {
+			pci_dev_put(temp);
 			pci_remove_bus_device(temp);
+		}
 	}
 	return 0;
 }
@@ -178,32 +181,22 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
 		if (!rc)
 			return !rc;
 
-		// set the Edge Level Control Register (ELCR)
+		/* set the Edge Level Control Register (ELCR) */
 		temp_word = inb(0x4d0);
 		temp_word |= inb(0x4d1) << 8;
 
 		temp_word |= 0x01 << irq_num;
 
-		// This should only be for x86 as it sets the Edge Level Control Register
-		outb((u8) (temp_word & 0xFF), 0x4d0);
-		outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-		rc = 0;
-	}
+		/* This should only be for x86 as it sets the Edge Level
+		 * Control Register
+		 */
+		outb((u8) (temp_word & 0xFF), 0x4d0); outb((u8) ((temp_word &
+		0xFF00) >> 8), 0x4d1); rc = 0; }
 
 	return rc;
 }
 
 
-/*
- * WTF??? This function isn't in the code, yet a function calls it, but the 
- * compiler optimizes it away?  strange.  Here as a placeholder to keep the 
- * compiler happy.
- */
-static int PCI_ScanBusNonBridge (u8 bus, u8 device)
-{
-	return 0;
-}
-
 static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num)
 {
 	u16 tdevice;
@@ -213,11 +206,11 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
 	ctrl->pci_bus->number = bus_num;
 
 	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
-		//Scan for access first
+		/* Scan for access first */
 		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
 			continue;
 		dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. Not a bridge ?
+		/* Yep we got one. Not a bridge ? */
 		if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
 			*dev_num = tdevice;
 			dbg("found it !\n");
@@ -225,16 +218,16 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
 		}
 	}
 	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
-		//Scan for access first
+		/* Scan for access first */
 		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
 			continue;
 		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
-		//Yep we got one. bridge ?
+		/* Yep we got one. bridge ? */
 		if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
 			pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
+			/* XXX: no recursion, wtf? */
 			dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
-			if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
-				return 0;
+			return 0;
 		}
 	}
 
@@ -244,39 +237,23 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
 
 static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
 {
-	struct irq_routing_table *PCIIRQRoutingInfoLength;
-	long len;
-	long loop;
+	int loop, len;
 	u32 work;
-
 	u8 tbus, tdevice, tslot;
 
-	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
-	if (!PCIIRQRoutingInfoLength)
-		return -1;
-
-	len = (PCIIRQRoutingInfoLength->size -
-	       sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
-	// Make sure I got at least one entry
-	if (len == 0) {
-		kfree(PCIIRQRoutingInfoLength );
-		return -1;
-	}
-
+	len = cpqhp_routing_table_length();
 	for (loop = 0; loop < len; ++loop) {
-		tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
-		tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;
-		tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+		tbus = cpqhp_routing_table->slots[loop].bus;
+		tdevice = cpqhp_routing_table->slots[loop].devfn;
+		tslot = cpqhp_routing_table->slots[loop].slot;
 
 		if (tslot == slot) {
 			*bus_num = tbus;
 			*dev_num = tdevice;
 			ctrl->pci_bus->number = tbus;
 			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
-			if (!nobridge || (work == 0xffffffff)) {
-				kfree(PCIIRQRoutingInfoLength );
+			if (!nobridge || (work == 0xffffffff))
 				return 0;
-			}
 
 			dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
 			pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
@@ -287,28 +264,26 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
 				dbg("Scan bus for Non Bridge: bus %d\n", tbus);
 				if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
 					*bus_num = tbus;
-					kfree(PCIIRQRoutingInfoLength );
 					return 0;
 				}
-			} else {
-				kfree(PCIIRQRoutingInfoLength );
+			} else
 				return 0;
-			}
-
 		}
 	}
-	kfree(PCIIRQRoutingInfoLength );
 	return -1;
 }
 
 
 int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
 {
-	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);	//plain (bridges allowed)
+	/* plain (bridges allowed) */
+	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);
 }
 
 
-/* More PCI configuration routines; this time centered around hotplug controller */
+/* More PCI configuration routines; this time centered around hotplug
+ * controller
+ */
 
 
 /*
@@ -339,12 +314,12 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
 	int stop_it;
 	int index;
 
-	//              Decide which slots are supported
+	/* Decide which slots are supported */
 
 	if (is_hot_plug) {
-		//*********************************
-		// is_hot_plug is the slot mask
-		//*********************************
+		/*
+		 * is_hot_plug is the slot mask
+		 */
 		FirstSupported = is_hot_plug >> 4;
 		LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
 	} else {
@@ -352,123 +327,127 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
 		LastSupported = 0x1F;
 	}
 
-	//     Save PCI configuration space for all devices in supported slots
+	/* Save PCI configuration space for all devices in supported slots */
 	ctrl->pci_bus->number = busnumber;
 	for (device = FirstSupported; device <= LastSupported; device++) {
 		ID = 0xFFFFFFFF;
-		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+		rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+
+		if (ID == 0xFFFFFFFF) {
+			if (is_hot_plug) {
+				/* Setup slot structure with entry for empty
+				 * slot
+				 */
+				new_slot = cpqhp_slot_create(busnumber);
+				if (new_slot == NULL)
+					return 1;
 
-		if (ID != 0xFFFFFFFF) {	  //  device in slot
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
-			if (rc)
-				return rc;
+				new_slot->bus = (u8) busnumber;
+				new_slot->device = (u8) device;
+				new_slot->function = 0;
+				new_slot->is_a_board = 0;
+				new_slot->presence_save = 0;
+				new_slot->switch_save = 0;
+			}
+			continue;
+		}
 
-			rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
-			if (rc)
-				return rc;
+		rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+		if (rc)
+			return rc;
 
-			// If multi-function device, set max_functions to 8
-			if (header_type & 0x80)
-				max_functions = 8;
-			else
-				max_functions = 1;
+		rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+		if (rc)
+			return rc;
 
-			function = 0;
+		/* If multi-function device, set max_functions to 8 */
+		if (header_type & 0x80)
+			max_functions = 8;
+		else
+			max_functions = 1;
 
-			do {
-				DevError = 0;
+		function = 0;
 
-				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   // P-P Bridge
-					//  Recurse the subordinate bus
-					//  get the subordinate bus number
-					rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
-					if (rc) {
+		do {
+			DevError = 0;
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+				/* Recurse the subordinate bus
+				 * get the subordinate bus number
+				 */
+				rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
+				if (rc) {
+					return rc;
+				} else {
+					sub_bus = (int) secondary_bus;
+
+					/* Save secondary bus cfg spc
+					 * with this recursive call.
+					 */
+					rc = cpqhp_save_config(ctrl, sub_bus, 0);
+					if (rc)
 						return rc;
-					} else {
-						sub_bus = (int) secondary_bus;
-
-						// Save secondary bus cfg spc
-						// with this recursive call.
-						rc = cpqhp_save_config(ctrl, sub_bus, 0);
-						if (rc)
-							return rc;
-						ctrl->pci_bus->number = busnumber;
-					}
+					ctrl->pci_bus->number = busnumber;
 				}
+			}
 
-				index = 0;
+			index = 0;
+			new_slot = cpqhp_slot_find(busnumber, device, index++);
+			while (new_slot &&
+			       (new_slot->function != (u8) function))
 				new_slot = cpqhp_slot_find(busnumber, device, index++);
-				while (new_slot && 
-				       (new_slot->function != (u8) function))
-					new_slot = cpqhp_slot_find(busnumber, device, index++);
 
-				if (!new_slot) {
-					// Setup slot structure.
-					new_slot = cpqhp_slot_create(busnumber);
-
-					if (new_slot == NULL)
-						return(1);
-				}
-
-				new_slot->bus = (u8) busnumber;
-				new_slot->device = (u8) device;
-				new_slot->function = (u8) function;
-				new_slot->is_a_board = 1;
-				new_slot->switch_save = 0x10;
-				// In case of unsupported board
-				new_slot->status = DevError;
-				new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
-
-				for (cloop = 0; cloop < 0x20; cloop++) {
-					rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
-					if (rc)
-						return rc;
-				}
+			if (!new_slot) {
+				/* Setup slot structure. */
+				new_slot = cpqhp_slot_create(busnumber);
+				if (new_slot == NULL)
+					return 1;
+			}
 
-				function++;
+			new_slot->bus = (u8) busnumber;
+			new_slot->device = (u8) device;
+			new_slot->function = (u8) function;
+			new_slot->is_a_board = 1;
+			new_slot->switch_save = 0x10;
+			/* In case of unsupported board */
+			new_slot->status = DevError;
+			new_slot->pci_dev = pci_get_bus_and_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
 
-				stop_it = 0;
+			for (cloop = 0; cloop < 0x20; cloop++) {
+				rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
+				if (rc)
+					return rc;
+			}
 
-				//  this loop skips to the next present function
-				//  reading in Class Code and Header type.
+			pci_dev_put(new_slot->pci_dev);
 
-				while ((function < max_functions)&&(!stop_it)) {
-					rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
-					if (ID == 0xFFFFFFFF) {	 // nothing there.
-						function++;
-					} else {  // Something there
-						rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
-						if (rc)
-							return rc;
+			function++;
 
-						rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
-						if (rc)
-							return rc;
+			stop_it = 0;
 
-						stop_it++;
-					}
+			/* this loop skips to the next present function
+			 * reading in Class Code and Header type.
+			 */
+			while ((function < max_functions) && (!stop_it)) {
+				rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
+				if (ID == 0xFFFFFFFF) {
+					function++;
+					continue;
 				}
+				rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
+				if (rc)
+					return rc;
 
-			} while (function < max_functions);
-		}		// End of IF (device in slot?)
-		else if (is_hot_plug) {
-			// Setup slot structure with entry for empty slot
-			new_slot = cpqhp_slot_create(busnumber);
+				rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
+				if (rc)
+					return rc;
 
-			if (new_slot == NULL) {
-				return(1);
+				stop_it++;
 			}
 
-			new_slot->bus = (u8) busnumber;
-			new_slot->device = (u8) device;
-			new_slot->function = 0;
-			new_slot->is_a_board = 0;
-			new_slot->presence_save = 0;
-			new_slot->switch_save = 0;
-		}
-	}			// End of FOR loop
+		} while (function < max_functions);
+	}			/* End of FOR loop */
 
-	return(0);
+	return 0;
 }
 
 
@@ -489,7 +468,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
 	u8 secondary_bus;
 	int sub_bus;
 	int max_functions;
-	int function;
+	int function = 0;
 	int cloop = 0;
 	int stop_it;
 
@@ -498,63 +477,58 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
 	ctrl->pci_bus->number = new_slot->bus;
 	pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
 
-	if (ID != 0xFFFFFFFF) {	  //  device in slot
-		pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
-		pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
-
-		if (header_type & 0x80)	// Multi-function device
-			max_functions = 8;
-		else
-			max_functions = 1;
-
-		function = 0;
-
-		do {
-			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-				//  Recurse the subordinate bus
-				pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
+	if (ID == 0xFFFFFFFF)
+		return 2;
 
-				sub_bus = (int) secondary_bus;
+	pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
+	pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
 
-				// Save the config headers for the secondary bus.
-				rc = cpqhp_save_config(ctrl, sub_bus, 0);
-				if (rc)
-					return(rc);
-				ctrl->pci_bus->number = new_slot->bus;
+	if (header_type & 0x80)	/* Multi-function device */
+		max_functions = 8;
+	else
+		max_functions = 1;
 
-			}	// End of IF
+	while (function < max_functions) {
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+			/*  Recurse the subordinate bus */
+			pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
 
-			new_slot->status = 0;
+			sub_bus = (int) secondary_bus;
 
-			for (cloop = 0; cloop < 0x20; cloop++) {
-				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
-			}
+			/* Save the config headers for the secondary
+			 * bus.
+			 */
+			rc = cpqhp_save_config(ctrl, sub_bus, 0);
+			if (rc)
+				return(rc);
+			ctrl->pci_bus->number = new_slot->bus;
 
-			function++;
+		}
 
-			stop_it = 0;
+		new_slot->status = 0;
 
-			//  this loop skips to the next present function
-			//  reading in the Class Code and the Header type.
+		for (cloop = 0; cloop < 0x20; cloop++)
+			pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
 
-			while ((function < max_functions) && (!stop_it)) {
-				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
+		function++;
 
-				if (ID == 0xFFFFFFFF) {	 // nothing there.
-					function++;
-				} else {  // Something there
-					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+		stop_it = 0;
 
-					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
+		/* this loop skips to the next present function
+		 * reading in the Class Code and the Header type.
+		 */
+		while ((function < max_functions) && (!stop_it)) {
+			pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
 
-					stop_it++;
-				}
+			if (ID == 0xFFFFFFFF)
+				function++;
+			else {
+				pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+				pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
+				stop_it++;
 			}
+		}
 
-		} while (function < max_functions);
-	}			// End of IF (device in slot?)
-	else {
-		return 2;
 	}
 
 	return 0;
@@ -590,11 +564,10 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
 		pci_bus->number = func->bus;
 		devfn = PCI_DEVFN(func->device, func->function);
 
-		// Check for Bridge
+		/* Check for Bridge */
 		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
 
 		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-			// PCI-PCI Bridge
 			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
 
 			sub_bus = (int) secondary_bus;
@@ -610,23 +583,27 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
 			}
 			pci_bus->number = func->bus;
 
-			//FIXME: this loop is duplicated in the non-bridge case.  The two could be rolled together
-			// Figure out IO and memory base lengths
+			/* FIXME: this loop is duplicated in the non-bridge
+			 * case.  The two could be rolled together Figure out
+			 * IO and memory base lengths
+			 */
 			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
 				temp_register = 0xFFFFFFFF;
 				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
-				if (base) {  // If this register is implemented
+				/* If this register is implemented */
+				if (base) {
 					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
+						/* IO base
+						 * set base = amount of IO space
+						 * requested
+						 */
 						base = base & 0xFFFFFFFE;
 						base = (~base) + 1;
 
 						type = 1;
 					} else {
-						// memory base
+						/* memory base */
 						base = base & 0xFFFFFFF0;
 						base = (~base) + 1;
 
@@ -637,32 +614,36 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
 					type = 0;
 				}
 
-				// Save information in slot structure
+				/* Save information in slot structure */
 				func->base_length[(cloop - 0x10) >> 2] =
 				base;
 				func->base_type[(cloop - 0x10) >> 2] = type;
 
-			}	// End of base register loop
+			}	/* End of base register loop */
 
-
-		} else if ((header_type & 0x7F) == 0x00) {	  // PCI-PCI Bridge
-			// Figure out IO and memory base lengths
+		} else if ((header_type & 0x7F) == 0x00) {
+			/* Figure out IO and memory base lengths */
 			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
 				temp_register = 0xFFFFFFFF;
 				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
 
-				if (base) {  // If this register is implemented
+				/* If this register is implemented */
+				if (base) {
 					if (base & 0x01L) {
-						// IO base
-						// base = amount of IO space requested
+						/* IO base
+						 * base = amount of IO space
+						 * requested
+						 */
 						base = base & 0xFFFFFFFE;
 						base = (~base) + 1;
 
 						type = 1;
 					} else {
-						// memory base
-						// base = amount of memory space requested
+						/* memory base
+						 * base = amount of memory
+						 * space requested
+						 */
 						base = base & 0xFFFFFFF0;
 						base = (~base) + 1;
 
@@ -673,16 +654,16 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
 					type = 0;
 				}
 
-				// Save information in slot structure
+				/* Save information in slot structure */
 				func->base_length[(cloop - 0x10) >> 2] = base;
 				func->base_type[(cloop - 0x10) >> 2] = type;
 
-			}	// End of base register loop
+			}	/* End of base register loop */
 
-		} else {	  // Some other unknown header type
+		} else {	  /* Some other unknown header type */
 		}
 
-		// find the next device in this slot
+		/* find the next device in this slot */
 		func = cpqhp_slot_find(func->bus, func->device, index++);
 	}
 
@@ -728,18 +709,18 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 		pci_bus->number = func->bus;
 		devfn = PCI_DEVFN(func->device, func->function);
 
-		// Save the command register
+		/* Save the command register */
 		pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
 
-		// disable card
+		/* disable card */
 		command = 0x00;
 		pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
 
-		// Check for Bridge
+		/* Check for Bridge */
 		pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
 
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// Clear Bridge Control Register
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+			/* Clear Bridge Control Register */
 			command = 0x00;
 			pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
 			pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
@@ -755,7 +736,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 			bus_node->next = func->bus_head;
 			func->bus_head = bus_node;
 
-			// Save IO base and Limit registers
+			/* Save IO base and Limit registers */
 			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &b_base);
 			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &b_length);
 
@@ -771,7 +752,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 				func->io_head = io_node;
 			}
 
-			// Save memory base and Limit registers
+			/* Save memory base and Limit registers */
 			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
 			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
 
@@ -787,7 +768,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 				func->mem_head = mem_node;
 			}
 
-			// Save prefetchable memory base and Limit registers
+			/* Save prefetchable memory base and Limit registers */
 			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
 			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
 
@@ -802,7 +783,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 				p_mem_node->next = func->p_mem_head;
 				func->p_mem_head = p_mem_node;
 			}
-			// Figure out IO and memory base lengths
+			/* Figure out IO and memory base lengths */
 			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
 
@@ -812,11 +793,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 
 				temp_register = base;
 
-				if (base) {  // If this register is implemented
+				/* If this register is implemented */
+				if (base) {
 					if (((base & 0x03L) == 0x01)
 					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
+						/* IO base
+						 * set temp_register = amount
+						 * of IO space requested
+						 */
 						temp_register = base & 0xFFFFFFFE;
 						temp_register = (~temp_register) + 1;
 
@@ -834,7 +818,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						if (((base & 0x0BL) == 0x08)
 						    && (save_command & 0x02)) {
-						// prefetchable memory base
+						/* prefetchable memory base */
 						temp_register = base & 0xFFFFFFF0;
 						temp_register = (~temp_register) + 1;
 
@@ -851,7 +835,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						if (((base & 0x0BL) == 0x00)
 						    && (save_command & 0x02)) {
-						// prefetchable memory base
+						/* prefetchable memory base */
 						temp_register = base & 0xFFFFFFF0;
 						temp_register = (~temp_register) + 1;
 
@@ -868,9 +852,10 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						return(1);
 				}
-			}	// End of base register loop
-		} else if ((header_type & 0x7F) == 0x00) {	  // Standard header
-			// Figure out IO and memory base lengths
+			}	/* End of base register loop */
+		/* Standard header */
+		} else if ((header_type & 0x7F) == 0x00) {
+			/* Figure out IO and memory base lengths */
 			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
 				pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
 
@@ -880,11 +865,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 
 				temp_register = base;
 
-				if (base) {	  // If this register is implemented
+				/* If this register is implemented */
+				if (base) {
 					if (((base & 0x03L) == 0x01)
 					    && (save_command & 0x01)) {
-						// IO base
-						// set temp_register = amount of IO space requested
+						/* IO base
+						 * set temp_register = amount
+						 * of IO space requested
+						 */
 						temp_register = base & 0xFFFFFFFE;
 						temp_register = (~temp_register) + 1;
 
@@ -901,7 +889,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						if (((base & 0x0BL) == 0x08)
 						    && (save_command & 0x02)) {
-						// prefetchable memory base
+						/* prefetchable memory base */
 						temp_register = base & 0xFFFFFFF0;
 						temp_register = (~temp_register) + 1;
 
@@ -918,7 +906,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						if (((base & 0x0BL) == 0x00)
 						    && (save_command & 0x02)) {
-						// prefetchable memory base
+						/* prefetchable memory base */
 						temp_register = base & 0xFFFFFFF0;
 						temp_register = (~temp_register) + 1;
 
@@ -935,15 +923,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
 					} else
 						return(1);
 				}
-			}	// End of base register loop
-		} else {	  // Some other unknown header type
+			}	/* End of base register loop */
 		}
 
-		// find the next device in this slot
+		/* find the next device in this slot */
 		func = cpqhp_slot_find(func->bus, func->device, index++);
 	}
 
-	return(0);
+	return 0;
 }
 
 
@@ -975,16 +962,16 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
 		pci_bus->number = func->bus;
 		devfn = PCI_DEVFN(func->device, func->function);
 
-		// Start at the top of config space so that the control
-		// registers are programmed last
-		for (cloop = 0x3C; cloop > 0; cloop -= 4) {
+		/* Start at the top of config space so that the control
+		 * registers are programmed last
+		 */
+		for (cloop = 0x3C; cloop > 0; cloop -= 4)
 			pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
-		}
 
 		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
 
-		// If this is a bridge device, restore subordinate devices
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
+		/* If this is a bridge device, restore subordinate devices */
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
 			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
 
 			sub_bus = (int) secondary_bus;
@@ -1000,8 +987,9 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
 			}
 		} else {
 
-			// Check all the base Address Registers to make sure
-			// they are the same.  If not, the board is different.
+			/* Check all the base Address Registers to make sure
+			 * they are the same.  If not, the board is different.
+			 */
 
 			for (cloop = 16; cloop < 40; cloop += 4) {
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
@@ -1058,27 +1046,28 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
 
 		pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
 
-		// No adapter present
+		/* No adapter present */
 		if (temp_register == 0xFFFFFFFF)
 			return(NO_ADAPTER_PRESENT);
 
 		if (temp_register != func->config_space[0])
 			return(ADAPTER_NOT_SAME);
 
-		// Check for same revision number and class code
+		/* Check for same revision number and class code */
 		pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
 
-		// Adapter not the same
+		/* Adapter not the same */
 		if (temp_register != func->config_space[0x08 >> 2])
 			return(ADAPTER_NOT_SAME);
 
-		// Check for Bridge
+		/* Check for Bridge */
 		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
 
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge
-			// In order to continue checking, we must program the
-			// bus registers in the bridge to respond to accesses
-			// for it's subordinate bus(es)
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+			/* In order to continue checking, we must program the
+			 * bus registers in the bridge to respond to accesses
+			 * for its subordinate bus(es)
+			 */
 
 			temp_register = func->config_space[0x18 >> 2];
 			pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
@@ -1096,35 +1085,39 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
 			}
 
 		}
-		// Check to see if it is a standard config header
+		/* Check to see if it is a standard config header */
 		else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-			// Check subsystem vendor and ID
+			/* Check subsystem vendor and ID */
 			pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
 
 			if (temp_register != func->config_space[0x2C >> 2]) {
-				// If it's a SMART-2 and the register isn't filled
-				// in, ignore the difference because
-				// they just have an old rev of the firmware
-
+				/* If it's a SMART-2 and the register isn't
+				 * filled in, ignore the difference because
+				 * they just have an old rev of the firmware
+				 */
 				if (!((func->config_space[0] == 0xAE100E11)
 				      && (temp_register == 0x00L)))
 					return(ADAPTER_NOT_SAME);
 			}
-			// Figure out IO and memory base lengths
+			/* Figure out IO and memory base lengths */
 			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
 				temp_register = 0xFFFFFFFF;
 				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
 				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-				if (base) {	  // If this register is implemented
+
+				/* If this register is implemented */
+				if (base) {
 					if (base & 0x01L) {
-						// IO base
-						// set base = amount of IO space requested
+						/* IO base
+						 * set base = amount of IO
+						 * space requested
+						 */
 						base = base & 0xFFFFFFFE;
 						base = (~base) + 1;
 
 						type = 1;
 					} else {
-						// memory base
+						/* memory base */
 						base = base & 0xFFFFFFF0;
 						base = (~base) + 1;
 
@@ -1135,23 +1128,24 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
 					type = 0;
 				}
 
-				// Check information in slot structure
+				/* Check information in slot structure */
 				if (func->base_length[(cloop - 0x10) >> 2] != base)
 					return(ADAPTER_NOT_SAME);
 
 				if (func->base_type[(cloop - 0x10) >> 2] != type)
 					return(ADAPTER_NOT_SAME);
 
-			}	// End of base register loop
+			}	/* End of base register loop */
 
-		}		// End of (type 0 config space) else
+		}		/* End of (type 0 config space) else */
 		else {
-			// this is not a type 0 or 1 config space header so
-			// we don't know how to do it
+			/* this is not a type 0 or 1 config space header so
+			 * we don't know how to do it
+			 */
 			return(DEVICE_TYPE_NOT_SUPPORTED);
 		}
 
-		// Get the next function
+		/* Get the next function */
 		func = cpqhp_slot_find(func->bus, func->device, index++);
 	}
 
@@ -1168,7 +1162,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
  * this function is for hot plug ADD!
  *
  * returns 0 if success
- */  
+ */
 int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_start)
 {
 	u8 temp;
@@ -1187,10 +1181,10 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 	rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
 	dbg("rom_resource_table = %p\n", rom_resource_table);
 
-	if (rom_resource_table == NULL) {
+	if (rom_resource_table == NULL)
 		return -ENODEV;
-	}
-	// Sum all resources and setup resource maps
+
+	/* Sum all resources and setup resource maps */
 	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
 	dbg("unused_IRQ = %x\n", unused_IRQ);
 
@@ -1222,13 +1216,11 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 
 	temp = 0;
 
-	if (!cpqhp_nic_irq) {
+	if (!cpqhp_nic_irq)
 		cpqhp_nic_irq = ctrl->cfgspc_irq;
-	}
 
-	if (!cpqhp_disk_irq) {
+	if (!cpqhp_disk_irq)
 		cpqhp_disk_irq = ctrl->cfgspc_irq;
-	}
 
 	dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
 
@@ -1262,13 +1254,13 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 		    dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
 		    primary_bus, secondary_bus, max_bus);
 
-		// If this entry isn't for our controller's bus, ignore it
+		/* If this entry isn't for our controller's bus, ignore it */
 		if (primary_bus != ctrl->bus) {
 			i--;
 			one_slot += sizeof (struct slot_rt);
 			continue;
 		}
-		// find out if this entry is for an occupied slot
+		/* find out if this entry is for an occupied slot */
 		ctrl->pci_bus->number = primary_bus;
 		pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
 		dbg("temp_D_word = %x\n", temp_dword);
@@ -1282,13 +1274,13 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 				func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
 			}
 
-			// If we can't find a match, skip this table entry
+			/* If we can't find a match, skip this table entry */
 			if (!func) {
 				i--;
 				one_slot += sizeof (struct slot_rt);
 				continue;
 			}
-			// this may not work and shouldn't be used
+			/* this may not work and shouldn't be used */
 			if (secondary_bus != primary_bus)
 				bridged_slot = 1;
 			else
@@ -1301,7 +1293,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 		}
 
 
-		// If we've got a valid IO base, use it
+		/* If we've got a valid IO base, use it */
 
 		temp_dword = io_base + io_length;
 
@@ -1325,7 +1317,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 			}
 		}
 
-		// If we've got a valid memory base, use it
+		/* If we've got a valid memory base, use it */
 		temp_dword = mem_base + mem_length;
 		if ((mem_base) && (temp_dword < 0x10000)) {
 			mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL);
@@ -1348,8 +1340,9 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 			}
 		}
 
-		// If we've got a valid prefetchable memory base, and
-		// the base + length isn't greater than 0xFFFF
+		/* If we've got a valid prefetchable memory base, and
+		 * the base + length isn't greater than 0xFFFF
+		 */
 		temp_dword = pre_mem_base + pre_mem_length;
 		if ((pre_mem_base) && (temp_dword < 0x10000)) {
 			p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL);
@@ -1372,9 +1365,10 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 			}
 		}
 
-		// If we've got a valid bus number, use it
-		// The second condition is to ignore bus numbers on
-		// populated slots that don't have PCI-PCI bridges
+		/* If we've got a valid bus number, use it
+		 * The second condition is to ignore bus numbers on
+		 * populated slots that don't have PCI-PCI bridges
+		 */
 		if (secondary_bus && (secondary_bus != primary_bus)) {
 			bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL);
 			if (!bus_node)
@@ -1398,8 +1392,9 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
 		one_slot += sizeof (struct slot_rt);
 	}
 
-	// If all of the following fail, we don't have any resources for
-	// hot plug add
+	/* If all of the following fail, we don't have any resources for
+	 * hot plug add
+	 */
 	rc = 1;
 	rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
 	rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));

+ 1 - 1
drivers/pci/hotplug/ibmphp_core.c

@@ -1318,7 +1318,6 @@ error:
 }
 
 struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
-	.owner =			THIS_MODULE,
 	.set_attention_status =		set_attention_status,
 	.enable_slot =			enable_slot,
 	.disable_slot =			ibmphp_disable_slot,
@@ -1421,3 +1420,4 @@ static void __exit ibmphp_exit(void)
 }
 
 module_init(ibmphp_init);
+module_exit(ibmphp_exit);

+ 84 - 71
drivers/pci/hotplug/pci_hotplug_core.c

@@ -347,125 +347,129 @@ static struct pci_slot_attribute hotplug_slot_attr_test = {
 	.store = test_write_file
 };
 
-static int has_power_file(struct pci_slot *pci_slot)
+static bool has_power_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if ((slot->ops->enable_slot) ||
 	    (slot->ops->disable_slot) ||
 	    (slot->ops->get_power_status))
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_attention_file(struct pci_slot *pci_slot)
+static bool has_attention_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if ((slot->ops->set_attention_status) ||
 	    (slot->ops->get_attention_status))
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_latch_file(struct pci_slot *pci_slot)
+static bool has_latch_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if (slot->ops->get_latch_status)
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_adapter_file(struct pci_slot *pci_slot)
+static bool has_adapter_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if (slot->ops->get_adapter_status)
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_max_bus_speed_file(struct pci_slot *pci_slot)
+static bool has_max_bus_speed_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if (slot->ops->get_max_bus_speed)
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_cur_bus_speed_file(struct pci_slot *pci_slot)
+static bool has_cur_bus_speed_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if (slot->ops->get_cur_bus_speed)
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
-static int has_test_file(struct pci_slot *pci_slot)
+static bool has_test_file(struct pci_slot *pci_slot)
 {
 	struct hotplug_slot *slot = pci_slot->hotplug;
 	if ((!slot) || (!slot->ops))
-		return -ENODEV;
+		return false;
 	if (slot->ops->hardware_test)
-		return 0;
-	return -ENOENT;
+		return true;
+	return false;
 }
 
 static int fs_add_slot(struct pci_slot *slot)
 {
 	int retval = 0;
 
-	if (has_power_file(slot) == 0) {
-		retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+	/* Create symbolic link to the hotplug driver module */
+	pci_hp_create_module_link(slot);
+
+	if (has_power_file(slot)) {
+		retval = sysfs_create_file(&slot->kobj,
+					   &hotplug_slot_attr_power.attr);
 		if (retval)
 			goto exit_power;
 	}
 
-	if (has_attention_file(slot) == 0) {
+	if (has_attention_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
 					   &hotplug_slot_attr_attention.attr);
 		if (retval)
 			goto exit_attention;
 	}
 
-	if (has_latch_file(slot) == 0) {
+	if (has_latch_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
 					   &hotplug_slot_attr_latch.attr);
 		if (retval)
 			goto exit_latch;
 	}
 
-	if (has_adapter_file(slot) == 0) {
+	if (has_adapter_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
 					   &hotplug_slot_attr_presence.attr);
 		if (retval)
 			goto exit_adapter;
 	}
 
-	if (has_max_bus_speed_file(slot) == 0) {
+	if (has_max_bus_speed_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
-					   &hotplug_slot_attr_max_bus_speed.attr);
+					&hotplug_slot_attr_max_bus_speed.attr);
 		if (retval)
 			goto exit_max_speed;
 	}
 
-	if (has_cur_bus_speed_file(slot) == 0) {
+	if (has_cur_bus_speed_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
-					   &hotplug_slot_attr_cur_bus_speed.attr);
+					&hotplug_slot_attr_cur_bus_speed.attr);
 		if (retval)
 			goto exit_cur_speed;
 	}
 
-	if (has_test_file(slot) == 0) {
+	if (has_test_file(slot)) {
 		retval = sysfs_create_file(&slot->kobj,
 					   &hotplug_slot_attr_test.attr);
 		if (retval)
@@ -475,55 +479,61 @@ static int fs_add_slot(struct pci_slot *slot)
 	goto exit;
 
 exit_test:
-	if (has_cur_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
-
+	if (has_cur_bus_speed_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_cur_bus_speed.attr);
 exit_cur_speed:
-	if (has_max_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
-
+	if (has_max_bus_speed_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_max_bus_speed.attr);
 exit_max_speed:
-	if (has_adapter_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
-
+	if (has_adapter_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_presence.attr);
 exit_adapter:
-	if (has_latch_file(slot) == 0)
+	if (has_latch_file(slot))
 		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
-
 exit_latch:
-	if (has_attention_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
-
+	if (has_attention_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_attention.attr);
 exit_attention:
-	if (has_power_file(slot) == 0)
+	if (has_power_file(slot))
 		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
 exit_power:
+	pci_hp_remove_module_link(slot);
 exit:
 	return retval;
 }
 
 static void fs_remove_slot(struct pci_slot *slot)
 {
-	if (has_power_file(slot) == 0)
+	if (has_power_file(slot))
 		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
 
-	if (has_attention_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+	if (has_attention_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_attention.attr);
 
-	if (has_latch_file(slot) == 0)
+	if (has_latch_file(slot))
 		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
 
-	if (has_adapter_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+	if (has_adapter_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_presence.attr);
 
-	if (has_max_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+	if (has_max_bus_speed_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_max_bus_speed.attr);
 
-	if (has_cur_bus_speed_file(slot) == 0)
-		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+	if (has_cur_bus_speed_file(slot))
+		sysfs_remove_file(&slot->kobj,
+				  &hotplug_slot_attr_cur_bus_speed.attr);
 
-	if (has_test_file(slot) == 0)
+	if (has_test_file(slot))
 		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+
+	pci_hp_remove_module_link(slot);
 }
 
 static struct hotplug_slot *get_slot_from_name (const char *name)
@@ -540,10 +550,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
 }
 
 /**
- * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
+ * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
  * @bus: bus this slot is on
  * @slot: pointer to the &struct hotplug_slot to register
- * @slot_nr: slot number
+ * @devnr: device number
  * @name: name registered with kobject core
  *
  * Registers a hotplug slot with the pci hotplug subsystem, which will allow
@@ -551,8 +561,9 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
  *
  * Returns 0 if successful, anything else for an error.
  */
-int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
-			const char *name)
+int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
+		      int devnr, const char *name,
+		      struct module *owner, const char *mod_name)
 {
 	int result;
 	struct pci_slot *pci_slot;
@@ -567,14 +578,16 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
 		return -EINVAL;
 	}
 
-	mutex_lock(&pci_hp_mutex);
+	slot->ops->owner = owner;
+	slot->ops->mod_name = mod_name;
 
+	mutex_lock(&pci_hp_mutex);
 	/*
 	 * No problems if we call this interface from both ACPI_PCI_SLOT
 	 * driver and call it here again. If we've already created the
 	 * pci_slot, the interface will simply bump the refcount.
 	 */
-	pci_slot = pci_create_slot(bus, slot_nr, name, slot);
+	pci_slot = pci_create_slot(bus, devnr, name, slot);
 	if (IS_ERR(pci_slot)) {
 		result = PTR_ERR(pci_slot);
 		goto out;
@@ -684,6 +697,6 @@ MODULE_LICENSE("GPL");
 module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
-EXPORT_SYMBOL_GPL(pci_hp_register);
+EXPORT_SYMBOL_GPL(__pci_hp_register);
 EXPORT_SYMBOL_GPL(pci_hp_deregister);
 EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);

+ 0 - 3
drivers/pci/hotplug/pciehp.h

@@ -81,7 +81,6 @@ struct slot {
 	struct hpc_ops *hpc_ops;
 	struct hotplug_slot *hotplug_slot;
 	struct list_head	slot_list;
-	unsigned long last_emi_toggle;
 	struct delayed_work work;	/* work for button event */
 	struct mutex lock;
 };
@@ -203,8 +202,6 @@ struct hpc_ops {
 	int (*set_attention_status)(struct slot *slot, u8 status);
 	int (*get_latch_status)(struct slot *slot, u8 *status);
 	int (*get_adapter_status)(struct slot *slot, u8 *status);
-	int (*get_emi_status)(struct slot *slot, u8 *status);
-	int (*toggle_emi)(struct slot *slot);
 	int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
 	int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
 	int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);

+ 1 - 111
drivers/pci/hotplug/pciehp_core.c

@@ -73,7 +73,6 @@ static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *val
 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 
 static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
-	.owner =		THIS_MODULE,
 	.set_attention_status =	set_attention_status,
 	.enable_slot =		enable_slot,
 	.disable_slot =		disable_slot,
@@ -85,99 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
   	.get_cur_bus_speed =	get_cur_bus_speed,
 };
 
-/*
- * Check the status of the Electro Mechanical Interlock (EMI)
- */
-static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
-{
-	struct slot *slot = hotplug_slot->private;
-	return (slot->hpc_ops->get_emi_status(slot, value));
-}
-
-/*
- * sysfs interface for the Electro Mechanical Interlock (EMI)
- * 1 == locked, 0 == unlocked
- */
-static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
-{
-	int retval;
-	u8 value;
-
-	retval = get_lock_status(slot, &value);
-	if (retval)
-		goto lock_read_exit;
-	retval = sprintf (buf, "%d\n", value);
-
-lock_read_exit:
-	return retval;
-}
-
-/*
- * Change the status of the Electro Mechanical Interlock (EMI)
- * This is a toggle - in addition there must be at least 1 second
- * in between toggles.
- */
-static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
-{
-	struct slot *slot = hotplug_slot->private;
-	int retval;
-	u8 value;
-
-	mutex_lock(&slot->ctrl->crit_sect);
-
-	/* has it been >1 sec since our last toggle? */
-	if ((get_seconds() - slot->last_emi_toggle) < 1) {
-		mutex_unlock(&slot->ctrl->crit_sect);
-		return -EINVAL;
-	}
-
-	/* see what our current state is */
-	retval = get_lock_status(hotplug_slot, &value);
-	if (retval || (value == status))
-		goto set_lock_exit;
-
-	slot->hpc_ops->toggle_emi(slot);
-set_lock_exit:
-	mutex_unlock(&slot->ctrl->crit_sect);
-	return 0;
-}
-
-/*
- * sysfs interface which allows the user to toggle the Electro Mechanical
- * Interlock.  Valid values are either 0 or 1.  0 == unlock, 1 == lock
- */
-static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
-		const char *buf, size_t count)
-{
-	struct slot *slot = hotplug_slot->private;
-	unsigned long llock;
-	u8 lock;
-	int retval = 0;
-
-	llock = simple_strtoul(buf, NULL, 10);
-	lock = (u8)(llock & 0xff);
-
-	switch (lock) {
-		case 0:
-		case 1:
-			retval = set_lock_status(hotplug_slot, lock);
-			break;
-		default:
-			ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
-				 lock);
-			retval = -EINVAL;
-	}
-	if (retval)
-		return retval;
-	return count;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
-	.attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
-	.show = lock_read_file,
-	.store = lock_write_file
-};
-
 /**
  * release_slot - free up the memory used by a slot
  * @hotplug_slot: slot to free
@@ -236,17 +142,6 @@ static int init_slots(struct controller *ctrl)
 		get_attention_status(hotplug_slot, &info->attention_status);
 		get_latch_status(hotplug_slot, &info->latch_status);
 		get_adapter_status(hotplug_slot, &info->adapter_status);
-		/* create additional sysfs entries */
-		if (EMI(ctrl)) {
-			retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
-				&hotplug_slot_attr_lock.attr);
-			if (retval) {
-				pci_hp_deregister(hotplug_slot);
-				ctrl_err(ctrl, "Cannot create additional sysfs "
-					 "entries\n");
-				goto error_info;
-			}
-		}
 	}
 
 	return 0;
@@ -261,13 +156,8 @@ error:
 static void cleanup_slots(struct controller *ctrl)
 {
 	struct slot *slot;
-
-	list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
-		if (EMI(ctrl))
-			sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
-				&hotplug_slot_attr_lock.attr);
+	list_for_each_entry(slot, &ctrl->slot_list, slot_list)
 		pci_hp_deregister(slot->hotplug_slot);
-	}
 }
 
 /*

+ 0 - 31
drivers/pci/hotplug/pciehp_hpc.c

@@ -422,35 +422,6 @@ static int hpc_query_power_fault(struct slot *slot)
 	return !!(slot_status & PCI_EXP_SLTSTA_PFD);
 }
 
-static int hpc_get_emi_status(struct slot *slot, u8 *status)
-{
-	struct controller *ctrl = slot->ctrl;
-	u16 slot_status;
-	int retval;
-
-	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
-	if (retval) {
-		ctrl_err(ctrl, "Cannot check EMI status\n");
-		return retval;
-	}
-	*status = !!(slot_status & PCI_EXP_SLTSTA_EIS);
-	return retval;
-}
-
-static int hpc_toggle_emi(struct slot *slot)
-{
-	u16 slot_cmd;
-	u16 cmd_mask;
-	int rc;
-
-	slot_cmd = PCI_EXP_SLTCTL_EIC;
-	cmd_mask = PCI_EXP_SLTCTL_EIC;
-	rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
-	slot->last_emi_toggle = get_seconds();
-
-	return rc;
-}
-
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
 	struct controller *ctrl = slot->ctrl;
@@ -874,8 +845,6 @@ static struct hpc_ops pciehp_hpc_ops = {
 	.get_attention_status		= hpc_get_attention_status,
 	.get_latch_status		= hpc_get_latch_status,
 	.get_adapter_status		= hpc_get_adapter_status,
-	.get_emi_status			= hpc_get_emi_status,
-	.toggle_emi			= hpc_toggle_emi,
 
 	.get_max_bus_speed		= hpc_get_max_lnk_speed,
 	.get_cur_bus_speed		= hpc_get_cur_lnk_speed,

+ 0 - 1
drivers/pci/hotplug/pcihp_skeleton.c

@@ -82,7 +82,6 @@ static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
 
 static struct hotplug_slot_ops skel_hotplug_slot_ops = {
-	.owner =		THIS_MODULE,
 	.enable_slot =		enable_slot,
 	.disable_slot =		disable_slot,
 	.set_attention_status =	set_attention_status,

+ 0 - 1
drivers/pci/hotplug/rpaphp_core.c

@@ -423,7 +423,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 }
 
 struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
-	.owner = THIS_MODULE,
 	.enable_slot = enable_slot,
 	.disable_slot = disable_slot,
 	.set_attention_status = set_attention_status,

+ 0 - 1
drivers/pci/hotplug/sgi_hotplug.c

@@ -83,7 +83,6 @@ static int disable_slot(struct hotplug_slot *slot);
 static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
 
 static struct hotplug_slot_ops sn_hotplug_slot_ops = {
-	.owner                  = THIS_MODULE,
 	.enable_slot            = enable_slot,
 	.disable_slot           = disable_slot,
 	.get_power_status       = get_power_status,

+ 0 - 1
drivers/pci/hotplug/shpchp_core.c

@@ -69,7 +69,6 @@ static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *val
 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 
 static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
-	.owner =		THIS_MODULE,
 	.set_attention_status =	set_attention_status,
 	.enable_slot =		enable_slot,
 	.disable_slot =		disable_slot,

+ 4 - 2
drivers/pci/iov.c

@@ -110,7 +110,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
 	}
 
 	if (reset)
-		pci_execute_reset_function(virtfn);
+		__pci_reset_function(virtfn);
 
 	pci_device_add(virtfn, virtfn->bus);
 	mutex_unlock(&iov->dev->sriov->lock);
@@ -164,7 +164,7 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
 
 	if (reset) {
 		device_release_driver(&virtfn->dev);
-		pci_execute_reset_function(virtfn);
+		__pci_reset_function(virtfn);
 	}
 
 	sprintf(buf, "virtfn%u", id);
@@ -487,6 +487,8 @@ found:
 	iov->self = dev;
 	pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
 	pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
+	if (dev->pcie_type == PCI_EXP_TYPE_RC_END)
+		iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link);
 
 	if (pdev)
 		iov->dev = pci_dev_get(pdev);

+ 51 - 49
drivers/pci/msi.c

@@ -75,22 +75,17 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
 }
 #endif
 
-static void __msi_set_enable(struct pci_dev *dev, int pos, int enable)
+static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
 {
 	u16 control;
 
-	if (pos) {
-		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
-		control &= ~PCI_MSI_FLAGS_ENABLE;
-		if (enable)
-			control |= PCI_MSI_FLAGS_ENABLE;
-		pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
-	}
-}
+	BUG_ON(!pos);
 
-static void msi_set_enable(struct pci_dev *dev, int enable)
-{
-	__msi_set_enable(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), enable);
+	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+	control &= ~PCI_MSI_FLAGS_ENABLE;
+	if (enable)
+		control |= PCI_MSI_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
 }
 
 static void msix_set_enable(struct pci_dev *dev, int enable)
@@ -131,9 +126,6 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
  * mask all MSI interrupts by clearing the MSI enable bit does not work
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
- *
- * Returns 1 if it succeeded in masking the interrupt and 0 if the device
- * doesn't support MSI masking.
  */
 static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
@@ -303,7 +295,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 	pos = entry->msi_attrib.pos;
 
 	pci_intx_for_msi(dev, 0);
-	msi_set_enable(dev, 0);
+	msi_set_enable(dev, pos, 0);
 	write_msi_msg(dev->irq, &entry->msg);
 
 	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
@@ -321,22 +313,22 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
 
 	if (!dev->msix_enabled)
 		return;
+	BUG_ON(list_empty(&dev->msi_list));
+	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+	pos = entry->msi_attrib.pos;
+	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
 
 	/* route the table */
 	pci_intx_for_msi(dev, 0);
-	msix_set_enable(dev, 0);
+	control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
 
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		write_msi_msg(entry->irq, &entry->msg);
 		msix_mask_irq(entry, entry->masked);
 	}
 
-	BUG_ON(list_empty(&dev->msi_list));
-	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
-	pos = entry->msi_attrib.pos;
-	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
 	control &= ~PCI_MSIX_FLAGS_MASKALL;
-	control |= PCI_MSIX_FLAGS_ENABLE;
 	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
 }
 
@@ -365,9 +357,9 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 	u16 control;
 	unsigned mask;
 
-	msi_set_enable(dev, 0);	/* Ensure msi is disabled as I set it up */
-
    	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	msi_set_enable(dev, pos, 0);	/* Disable MSI during set up */
+
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	/* MSI Entry Initialization */
 	entry = alloc_msi_entry(dev);
@@ -381,7 +373,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 	entry->msi_attrib.default_irq = dev->irq;	/* Save IOAPIC IRQ */
 	entry->msi_attrib.pos = pos;
 
-	entry->mask_pos = msi_mask_bits_reg(pos, entry->msi_attrib.is_64);
+	entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64);
 	/* All MSIs are unmasked by default, Mask them all */
 	if (entry->msi_attrib.maskbit)
 		pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
@@ -399,7 +391,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 
 	/* Set MSI enabled bits	 */
 	pci_intx_for_msi(dev, 0);
-	msi_set_enable(dev, 1);
+	msi_set_enable(dev, pos, 1);
 	dev->msi_enabled = 1;
 
 	dev->irq = entry->irq;
@@ -427,11 +419,14 @@ static int msix_capability_init(struct pci_dev *dev,
 	u8 bir;
 	void __iomem *base;
 
-	msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
-
    	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+
+	/* Ensure MSI-X is disabled while it is set up */
+	control &= ~PCI_MSIX_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
 	/* Request & Map MSI-X table region */
- 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	nr_entries = multi_msix_capable(control);
 
  	pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
@@ -442,7 +437,6 @@ static int msix_capability_init(struct pci_dev *dev,
 	if (base == NULL)
 		return -ENOMEM;
 
-	/* MSI-X Table Initialization */
 	for (i = 0; i < nvec; i++) {
 		entry = alloc_msi_entry(dev);
 		if (!entry)
@@ -455,7 +449,6 @@ static int msix_capability_init(struct pci_dev *dev,
 		entry->msi_attrib.default_irq = dev->irq;
 		entry->msi_attrib.pos = pos;
 		entry->mask_base = base;
-		msix_mask_irq(entry, 1);
 
 		list_add_tail(&entry->list, &dev->msi_list);
 	}
@@ -480,22 +473,31 @@ static int msix_capability_init(struct pci_dev *dev,
 		return ret;
 	}
 
+	/*
+	 * Some devices require MSI-X to be enabled before we can touch the
+	 * MSI-X registers.  We need to mask all the vectors to prevent
+	 * interrupts coming in before they're fully set up.
+	 */
+	control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
 	i = 0;
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		entries[i].vector = entry->irq;
 		set_irq_msi(entry->irq, entry);
+		j = entries[i].entry;
+		entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE +
+					PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+		msix_mask_irq(entry, 1);
 		i++;
 	}
-	/* Set MSI-X enabled bits */
+
+	/* Set MSI-X enabled bits and unmask the function */
 	pci_intx_for_msi(dev, 0);
-	msix_set_enable(dev, 1);
 	dev->msix_enabled = 1;
 
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		int vector = entry->msi_attrib.entry_nr;
-		entry->masked = readl(base + vector * PCI_MSIX_ENTRY_SIZE +
-					PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
-	}
+	control &= ~PCI_MSIX_FLAGS_MASKALL;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
 
 	return 0;
 }
@@ -596,17 +598,20 @@ void pci_msi_shutdown(struct pci_dev *dev)
 	struct msi_desc *desc;
 	u32 mask;
 	u16 ctrl;
+	unsigned pos;
 
 	if (!pci_msi_enable || !dev || !dev->msi_enabled)
 		return;
 
-	msi_set_enable(dev, 0);
+	BUG_ON(list_empty(&dev->msi_list));
+	desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
+	pos = desc->msi_attrib.pos;
+
+	msi_set_enable(dev, pos, 0);
 	pci_intx_for_msi(dev, 1);
 	dev->msi_enabled = 0;
 
-	BUG_ON(list_empty(&dev->msi_list));
-	desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
-	pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, &ctrl);
+	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl);
 	mask = msi_capable_mask(ctrl);
 	msi_mask_irq(desc, mask, ~mask);
 
@@ -648,10 +653,7 @@ static int msi_free_irqs(struct pci_dev* dev)
 
 	list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
 		if (entry->msi_attrib.is_msix) {
-			writel(1, entry->mask_base + entry->msi_attrib.entry_nr
-				  * PCI_MSIX_ENTRY_SIZE
-				  + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
-
+			msix_mask_irq(entry, 1);
 			if (list_is_last(&entry->list, &dev->msi_list))
 				iounmap(entry->mask_base);
 		}
@@ -691,8 +693,8 @@ int pci_msix_table_size(struct pci_dev *dev)
  * indicates the successful configuration of MSI-X capability structure
  * with new allocated MSI-X irqs. A return of < 0 indicates a failure.
  * Or a return of > 0 indicates that driver request is exceeding the number
- * of irqs available. Driver should use the returned value to re-send
- * its request.
+ * of irqs or MSI-X vectors available. Driver should use the returned value to
+ * re-send its request.
  **/
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 {
@@ -708,7 +710,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 
 	nr_entries = pci_msix_table_size(dev);
 	if (nvec > nr_entries)
-		return -EINVAL;
+		return nr_entries;
 
 	/* Check for any invalid entries */
 	for (i = 0; i < nvec; i++) {

+ 4 - 10
drivers/pci/msi.h

@@ -16,21 +16,15 @@
 #define msi_lower_address_reg(base)	(base + PCI_MSI_ADDRESS_LO)
 #define msi_upper_address_reg(base)	(base + PCI_MSI_ADDRESS_HI)
 #define msi_data_reg(base, is64bit)	\
-	( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
-#define msi_mask_bits_reg(base, is64bit) \
-	( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
-#define msi_disable(control)		control &= ~PCI_MSI_FLAGS_ENABLE
+	(base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32))
+#define msi_mask_reg(base, is64bit)	\
+	(base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32))
 #define is_64bit_address(control)	(!!(control & PCI_MSI_FLAGS_64BIT))
 #define is_mask_bit_support(control)	(!!(control & PCI_MSI_FLAGS_MASKBIT))
 
 #define msix_table_offset_reg(base)	(base + 0x04)
 #define msix_pba_offset_reg(base)	(base + 0x08)
-#define msix_enable(control)	 	control |= PCI_MSIX_FLAGS_ENABLE
-#define msix_disable(control)	 	control &= ~PCI_MSIX_FLAGS_ENABLE
 #define msix_table_size(control) 	((control & PCI_MSIX_FLAGS_QSIZE)+1)
-#define multi_msix_capable		msix_table_size
-#define msix_unmask(address)	 	(address & ~PCI_MSIX_FLAGS_BITMASK)
-#define msix_mask(address)		(address | PCI_MSIX_FLAGS_BITMASK)
-#define msix_is_pending(address) 	(address & PCI_MSIX_FLAGS_PENDMASK)
+#define multi_msix_capable(control)	msix_table_size((control))
 
 #endif /* MSI_H */

+ 158 - 88
drivers/pci/pci.c

@@ -485,6 +485,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
 		pmcsr |= state;
 		break;
+	case PCI_D3hot:
+	case PCI_D3cold:
 	case PCI_UNKNOWN: /* Boot-up */
 		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
 		 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
@@ -1208,7 +1210,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
  * Error code depending on the platform is returned if both the platform and
  * the native mechanism fail to enable the generation of wake-up events
  */
-int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
+int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 {
 	int error = 0;
 	bool pme_done = false;
@@ -1287,15 +1289,14 @@ pci_power_t pci_target_state(struct pci_dev *dev)
 		default:
 			target_state = state;
 		}
+	} else if (!dev->pm_cap) {
+		target_state = PCI_D0;
 	} else if (device_may_wakeup(&dev->dev)) {
 		/*
 		 * Find the deepest state from which the device can generate
 		 * wake-up events, make it the target state and enable device
 		 * to generate PME#.
 		 */
-		if (!dev->pm_cap)
-			return PCI_POWER_ERROR;
-
 		if (dev->pme_support) {
 			while (target_state
 			      && !(dev->pme_support & (1 << target_state)))
@@ -1532,7 +1533,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
 	if (!pin)
 		return -1;
 
-	while (dev->bus->parent) {
+	while (!pci_is_root_bus(dev->bus)) {
 		pin = pci_swizzle_interrupt_pin(dev, pin);
 		dev = dev->bus->self;
 	}
@@ -1552,7 +1553,7 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	u8 pin = *pinp;
 
-	while (dev->bus->parent) {
+	while (!pci_is_root_bus(dev->bus)) {
 		pin = pci_swizzle_interrupt_pin(dev, pin);
 		dev = dev->bus->self;
 	}
@@ -2058,111 +2059,177 @@ int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
 EXPORT_SYMBOL(pci_set_dma_seg_boundary);
 #endif
 
-static int __pcie_flr(struct pci_dev *dev, int probe)
+static int pcie_flr(struct pci_dev *dev, int probe)
 {
-	u16 status;
+	int i;
+	int pos;
 	u32 cap;
-	int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	u16 status;
 
-	if (!exppos)
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
 		return -ENOTTY;
-	pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
+
+	pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
 	if (!(cap & PCI_EXP_DEVCAP_FLR))
 		return -ENOTTY;
 
 	if (probe)
 		return 0;
 
-	pci_block_user_cfg_access(dev);
-
 	/* Wait for Transaction Pending bit clean */
-	pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
-	if (!(status & PCI_EXP_DEVSTA_TRPND))
-		goto transaction_done;
+	for (i = 0; i < 4; i++) {
+		if (i)
+			msleep((1 << (i - 1)) * 100);
 
-	msleep(100);
-	pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
-	if (!(status & PCI_EXP_DEVSTA_TRPND))
-		goto transaction_done;
-
-	dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
-			"sleeping for 1 second\n");
-	ssleep(1);
-	pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
-	if (status & PCI_EXP_DEVSTA_TRPND)
-		dev_info(&dev->dev, "Still busy after 1s; "
-				"proceeding with reset anyway\n");
-
-transaction_done:
-	pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
+		pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+		if (!(status & PCI_EXP_DEVSTA_TRPND))
+			goto clear;
+	}
+
+	dev_err(&dev->dev, "transaction is not cleared; "
+			"proceeding with reset anyway\n");
+
+clear:
+	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
 				PCI_EXP_DEVCTL_BCR_FLR);
-	mdelay(100);
+	msleep(100);
 
-	pci_unblock_user_cfg_access(dev);
 	return 0;
 }
 
-static int __pci_af_flr(struct pci_dev *dev, int probe)
+static int pci_af_flr(struct pci_dev *dev, int probe)
 {
-	int cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
-	u8 status;
+	int i;
+	int pos;
 	u8 cap;
+	u8 status;
 
-	if (!cappos)
+	pos = pci_find_capability(dev, PCI_CAP_ID_AF);
+	if (!pos)
 		return -ENOTTY;
-	pci_read_config_byte(dev, cappos + PCI_AF_CAP, &cap);
+
+	pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap);
 	if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
 		return -ENOTTY;
 
 	if (probe)
 		return 0;
 
-	pci_block_user_cfg_access(dev);
-
 	/* Wait for Transaction Pending bit clean */
-	pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
-	if (!(status & PCI_AF_STATUS_TP))
-		goto transaction_done;
+	for (i = 0; i < 4; i++) {
+		if (i)
+			msleep((1 << (i - 1)) * 100);
+
+		pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
+		if (!(status & PCI_AF_STATUS_TP))
+			goto clear;
+	}
 
+	dev_err(&dev->dev, "transaction is not cleared; "
+			"proceeding with reset anyway\n");
+
+clear:
+	pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
 	msleep(100);
-	pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
-	if (!(status & PCI_AF_STATUS_TP))
-		goto transaction_done;
-
-	dev_info(&dev->dev, "Busy after 100ms while trying to"
-			" reset; sleeping for 1 second\n");
-	ssleep(1);
-	pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
-	if (status & PCI_AF_STATUS_TP)
-		dev_info(&dev->dev, "Still busy after 1s; "
-				"proceeding with reset anyway\n");
-
-transaction_done:
-	pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
-	mdelay(100);
-
-	pci_unblock_user_cfg_access(dev);
+
 	return 0;
 }
 
-static int __pci_reset_function(struct pci_dev *pdev, int probe)
+static int pci_pm_reset(struct pci_dev *dev, int probe)
 {
-	int res;
+	u16 csr;
+
+	if (!dev->pm_cap)
+		return -ENOTTY;
 
-	res = __pcie_flr(pdev, probe);
-	if (res != -ENOTTY)
-		return res;
+	pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr);
+	if (csr & PCI_PM_CTRL_NO_SOFT_RESET)
+		return -ENOTTY;
 
-	res = __pci_af_flr(pdev, probe);
-	if (res != -ENOTTY)
-		return res;
+	if (probe)
+		return 0;
 
-	return res;
+	if (dev->current_state != PCI_D0)
+		return -EINVAL;
+
+	csr &= ~PCI_PM_CTRL_STATE_MASK;
+	csr |= PCI_D3hot;
+	pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
+	msleep(pci_pm_d3_delay);
+
+	csr &= ~PCI_PM_CTRL_STATE_MASK;
+	csr |= PCI_D0;
+	pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
+	msleep(pci_pm_d3_delay);
+
+	return 0;
+}
+
+static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
+{
+	u16 ctrl;
+	struct pci_dev *pdev;
+
+	if (dev->subordinate)
+		return -ENOTTY;
+
+	list_for_each_entry(pdev, &dev->bus->devices, bus_list)
+		if (pdev != dev)
+			return -ENOTTY;
+
+	if (probe)
+		return 0;
+
+	pci_read_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, &ctrl);
+	ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl);
+	msleep(100);
+
+	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl);
+	msleep(100);
+
+	return 0;
+}
+
+static int pci_dev_reset(struct pci_dev *dev, int probe)
+{
+	int rc;
+
+	might_sleep();
+
+	if (!probe) {
+		pci_block_user_cfg_access(dev);
+		/* block PM suspend, driver probe, etc. */
+		down(&dev->dev.sem);
+	}
+
+	rc = pcie_flr(dev, probe);
+	if (rc != -ENOTTY)
+		goto done;
+
+	rc = pci_af_flr(dev, probe);
+	if (rc != -ENOTTY)
+		goto done;
+
+	rc = pci_pm_reset(dev, probe);
+	if (rc != -ENOTTY)
+		goto done;
+
+	rc = pci_parent_bus_reset(dev, probe);
+done:
+	if (!probe) {
+		up(&dev->dev.sem);
+		pci_unblock_user_cfg_access(dev);
+	}
+
+	return rc;
 }
 
 /**
- * pci_execute_reset_function() - Reset a PCI device function
- * @dev: Device function to reset
+ * __pci_reset_function - reset a PCI device function
+ * @dev: PCI device to reset
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -2174,18 +2241,18 @@ static int __pci_reset_function(struct pci_dev *pdev, int probe)
  * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
  * etc.
  *
- * Returns 0 if the device function was successfully reset or -ENOTTY if the
+ * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_execute_reset_function(struct pci_dev *dev)
+int __pci_reset_function(struct pci_dev *dev)
 {
-	return __pci_reset_function(dev, 0);
+	return pci_dev_reset(dev, 0);
 }
-EXPORT_SYMBOL_GPL(pci_execute_reset_function);
+EXPORT_SYMBOL_GPL(__pci_reset_function);
 
 /**
- * pci_reset_function() - quiesce and reset a PCI device function
- * @dev: Device function to reset
+ * pci_reset_function - quiesce and reset a PCI device function
+ * @dev: PCI device to reset
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -2193,32 +2260,33 @@ EXPORT_SYMBOL_GPL(pci_execute_reset_function);
  *
  * This function does not just reset the PCI portion of a device, but
  * clears all the state associated with the device.  This function differs
- * from pci_execute_reset_function in that it saves and restores device state
+ * from __pci_reset_function in that it saves and restores device state
  * over the reset.
  *
- * Returns 0 if the device function was successfully reset or -ENOTTY if the
+ * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
 int pci_reset_function(struct pci_dev *dev)
 {
-	int r = __pci_reset_function(dev, 1);
+	int rc;
 
-	if (r < 0)
-		return r;
+	rc = pci_dev_reset(dev, 1);
+	if (rc)
+		return rc;
 
-	if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
-		disable_irq(dev->irq);
 	pci_save_state(dev);
 
+	/*
+	 * both INTx and MSI are disabled after the Interrupt Disable bit
+	 * is set and the Bus Master bit is cleared.
+	 */
 	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
 
-	r = pci_execute_reset_function(dev);
+	rc = pci_dev_reset(dev, 0);
 
 	pci_restore_state(dev);
-	if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
-		enable_irq(dev->irq);
 
-	return r;
+	return rc;
 }
 EXPORT_SYMBOL_GPL(pci_reset_function);
 
@@ -2591,6 +2659,8 @@ static int __init pci_setup(char *str)
 			} else if (!strncmp(str, "resource_alignment=", 19)) {
 				pci_set_resource_alignment_param(str + 19,
 							strlen(str + 19));
+			} else if (!strncmp(str, "ecrc=", 5)) {
+				pcie_ecrc_get_policy(str + 5);
 			} else {
 				printk(KERN_ERR "PCI: Unknown option `%s'\n",
 						str);

+ 15 - 0
drivers/pci/pcie/aer/Kconfig

@@ -10,3 +10,18 @@ config PCIEAER
 	  This enables PCI Express Root Port Advanced Error Reporting
 	  (AER) driver support. Error reporting messages sent to Root
 	  Port will be handled by PCI Express AER driver.
+
+
+#
+# PCI Express ECRC
+#
+config PCIE_ECRC
+	bool "PCI Express ECRC settings control"
+	depends on PCIEAER
+	help
+	  Used to override firmware/bios settings for PCI Express ECRC
+	  (transaction layer end-to-end CRC checking).
+
+	  When in doubt, say N.
+
+source "drivers/pci/pcie/aer/Kconfig.debug"

+ 18 - 0
drivers/pci/pcie/aer/Kconfig.debug

@@ -0,0 +1,18 @@
+#
+# PCI Express Root Port Device AER Debug Configuration
+#
+
+config PCIEAER_INJECT
+	tristate "PCIE AER error injector support"
+	depends on PCIEAER
+	default n
+	help
+	  This enables PCI Express Root Port Advanced Error Reporting
+	  (AER) software error injector.
+
+	  Debuging PCIE AER code is quite difficult because it is hard
+	  to trigger various real hardware errors. Software based
+	  error injection can fake almost all kinds of errors with the
+	  help of a user space helper tool aer-inject, which can be
+	  gotten from:
+	     http://www.kernel.org/pub/linux/utils/pci/aer-inject/

+ 3 - 0
drivers/pci/pcie/aer/Makefile

@@ -4,6 +4,9 @@
 
 obj-$(CONFIG_PCIEAER) += aerdriver.o
 
+obj-$(CONFIG_PCIE_ECRC)	+= ecrc.o
+
 aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
 aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
 
+obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o

+ 473 - 0
drivers/pci/pcie/aer/aer_inject.c

@@ -0,0 +1,473 @@
+/*
+ * PCIE AER software error injection support.
+ *
+ * Debuging PCIE AER code is quite difficult because it is hard to
+ * trigger various real hardware errors. Software based error
+ * injection can fake almost all kinds of errors with the help of a
+ * user space helper tool aer-inject, which can be gotten from:
+ *   http://www.kernel.org/pub/linux/utils/pci/aer-inject/
+ *
+ * Copyright 2009 Intel Corporation.
+ *     Huang Ying <ying.huang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include "aerdrv.h"
+
+struct aer_error_inj
+{
+	u8 bus;
+	u8 dev;
+	u8 fn;
+	u32 uncor_status;
+	u32 cor_status;
+	u32 header_log0;
+	u32 header_log1;
+	u32 header_log2;
+	u32 header_log3;
+};
+
+struct aer_error
+{
+	struct list_head list;
+	unsigned int bus;
+	unsigned int devfn;
+	int pos_cap_err;
+
+	u32 uncor_status;
+	u32 cor_status;
+	u32 header_log0;
+	u32 header_log1;
+	u32 header_log2;
+	u32 header_log3;
+	u32 root_status;
+	u32 source_id;
+};
+
+struct pci_bus_ops
+{
+	struct list_head list;
+	struct pci_bus *bus;
+	struct pci_ops *ops;
+};
+
+static LIST_HEAD(einjected);
+
+static LIST_HEAD(pci_bus_ops_list);
+
+/* Protect einjected and pci_bus_ops_list */
+static DEFINE_SPINLOCK(inject_lock);
+
+static void aer_error_init(struct aer_error *err, unsigned int bus,
+			   unsigned int devfn, int pos_cap_err)
+{
+	INIT_LIST_HEAD(&err->list);
+	err->bus = bus;
+	err->devfn = devfn;
+	err->pos_cap_err = pos_cap_err;
+}
+
+/* inject_lock must be held before calling */
+static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
+{
+	struct aer_error *err;
+
+	list_for_each_entry(err, &einjected, list) {
+		if (bus == err->bus && devfn == err->devfn)
+			return err;
+	}
+	return NULL;
+}
+
+/* inject_lock must be held before calling */
+static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
+{
+	return __find_aer_error(dev->bus->number, dev->devfn);
+}
+
+/* inject_lock must be held before calling */
+static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
+{
+	struct pci_bus_ops *bus_ops;
+
+	list_for_each_entry(bus_ops, &pci_bus_ops_list, list) {
+		if (bus_ops->bus == bus)
+			return bus_ops->ops;
+	}
+	return NULL;
+}
+
+static struct pci_bus_ops *pci_bus_ops_pop(void)
+{
+	unsigned long flags;
+	struct pci_bus_ops *bus_ops = NULL;
+
+	spin_lock_irqsave(&inject_lock, flags);
+	if (list_empty(&pci_bus_ops_list))
+		bus_ops = NULL;
+	else {
+		struct list_head *lh = pci_bus_ops_list.next;
+		list_del(lh);
+		bus_ops = list_entry(lh, struct pci_bus_ops, list);
+	}
+	spin_unlock_irqrestore(&inject_lock, flags);
+	return bus_ops;
+}
+
+static u32 *find_pci_config_dword(struct aer_error *err, int where,
+				  int *prw1cs)
+{
+	int rw1cs = 0;
+	u32 *target = NULL;
+
+	if (err->pos_cap_err == -1)
+		return NULL;
+
+	switch (where - err->pos_cap_err) {
+	case PCI_ERR_UNCOR_STATUS:
+		target = &err->uncor_status;
+		rw1cs = 1;
+		break;
+	case PCI_ERR_COR_STATUS:
+		target = &err->cor_status;
+		rw1cs = 1;
+		break;
+	case PCI_ERR_HEADER_LOG:
+		target = &err->header_log0;
+		break;
+	case PCI_ERR_HEADER_LOG+4:
+		target = &err->header_log1;
+		break;
+	case PCI_ERR_HEADER_LOG+8:
+	        target = &err->header_log2;
+		break;
+	case PCI_ERR_HEADER_LOG+12:
+		target = &err->header_log3;
+		break;
+	case PCI_ERR_ROOT_STATUS:
+		target = &err->root_status;
+		rw1cs = 1;
+		break;
+	case PCI_ERR_ROOT_COR_SRC:
+		target = &err->source_id;
+		break;
+	}
+	if (prw1cs)
+		*prw1cs = rw1cs;
+	return target;
+}
+
+static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 *val)
+{
+	u32 *sim;
+	struct aer_error *err;
+	unsigned long flags;
+	struct pci_ops *ops;
+
+	spin_lock_irqsave(&inject_lock, flags);
+	if (size != sizeof(u32))
+		goto out;
+	err = __find_aer_error(bus->number, devfn);
+	if (!err)
+		goto out;
+
+	sim = find_pci_config_dword(err, where, NULL);
+	if (sim) {
+		*val = *sim;
+		spin_unlock_irqrestore(&inject_lock, flags);
+		return 0;
+	}
+out:
+	ops = __find_pci_bus_ops(bus);
+	spin_unlock_irqrestore(&inject_lock, flags);
+	return ops->read(bus, devfn, where, size, val);
+}
+
+int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
+		  u32 val)
+{
+	u32 *sim;
+	struct aer_error *err;
+	unsigned long flags;
+	int rw1cs;
+	struct pci_ops *ops;
+
+	spin_lock_irqsave(&inject_lock, flags);
+	if (size != sizeof(u32))
+		goto out;
+	err = __find_aer_error(bus->number, devfn);
+	if (!err)
+		goto out;
+
+	sim = find_pci_config_dword(err, where, &rw1cs);
+	if (sim) {
+		if (rw1cs)
+			*sim ^= val;
+		else
+			*sim = val;
+		spin_unlock_irqrestore(&inject_lock, flags);
+		return 0;
+	}
+out:
+	ops = __find_pci_bus_ops(bus);
+	spin_unlock_irqrestore(&inject_lock, flags);
+	return ops->write(bus, devfn, where, size, val);
+}
+
+static struct pci_ops pci_ops_aer = {
+	.read = pci_read_aer,
+	.write = pci_write_aer,
+};
+
+static void pci_bus_ops_init(struct pci_bus_ops *bus_ops,
+			     struct pci_bus *bus,
+			     struct pci_ops *ops)
+{
+	INIT_LIST_HEAD(&bus_ops->list);
+	bus_ops->bus = bus;
+	bus_ops->ops = ops;
+}
+
+static int pci_bus_set_aer_ops(struct pci_bus *bus)
+{
+	struct pci_ops *ops;
+	struct pci_bus_ops *bus_ops;
+	unsigned long flags;
+
+	bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL);
+	if (!bus_ops)
+		return -ENOMEM;
+	ops = pci_bus_set_ops(bus, &pci_ops_aer);
+	spin_lock_irqsave(&inject_lock, flags);
+	if (ops == &pci_ops_aer)
+		goto out;
+	pci_bus_ops_init(bus_ops, bus, ops);
+	list_add(&bus_ops->list, &pci_bus_ops_list);
+	bus_ops = NULL;
+out:
+	spin_unlock_irqrestore(&inject_lock, flags);
+	if (bus_ops)
+		kfree(bus_ops);
+	return 0;
+}
+
+static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+{
+	while (1) {
+		if (!dev->is_pcie)
+			break;
+		if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+			return dev;
+		if (!dev->bus->self)
+			break;
+		dev = dev->bus->self;
+	}
+	return NULL;
+}
+
+static int find_aer_device_iter(struct device *device, void *data)
+{
+	struct pcie_device **result = data;
+	struct pcie_device *pcie_dev;
+
+	if (device->bus == &pcie_port_bus_type) {
+		pcie_dev = to_pcie_device(device);
+		if (pcie_dev->service & PCIE_PORT_SERVICE_AER) {
+			*result = pcie_dev;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int find_aer_device(struct pci_dev *dev, struct pcie_device **result)
+{
+	return device_for_each_child(&dev->dev, result, find_aer_device_iter);
+}
+
+static int aer_inject(struct aer_error_inj *einj)
+{
+	struct aer_error *err, *rperr;
+	struct aer_error *err_alloc = NULL, *rperr_alloc = NULL;
+	struct pci_dev *dev, *rpdev;
+	struct pcie_device *edev;
+	unsigned long flags;
+	unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
+	int pos_cap_err, rp_pos_cap_err;
+	u32 sever;
+	int ret = 0;
+
+	dev = pci_get_bus_and_slot(einj->bus, devfn);
+	if (!dev)
+		return -EINVAL;
+	rpdev = pcie_find_root_port(dev);
+	if (!rpdev) {
+		ret = -EINVAL;
+		goto out_put;
+	}
+
+	pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos_cap_err) {
+		ret = -EIO;
+		goto out_put;
+	}
+	pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
+
+	rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
+	if (!rp_pos_cap_err) {
+		ret = -EIO;
+		goto out_put;
+	}
+
+	err_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
+	if (!err_alloc) {
+		ret = -ENOMEM;
+		goto out_put;
+	}
+	rperr_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
+	if (!rperr_alloc) {
+		ret = -ENOMEM;
+		goto out_put;
+	}
+
+	spin_lock_irqsave(&inject_lock, flags);
+
+	err = __find_aer_error_by_dev(dev);
+	if (!err) {
+		err = err_alloc;
+		err_alloc = NULL;
+		aer_error_init(err, einj->bus, devfn, pos_cap_err);
+		list_add(&err->list, &einjected);
+	}
+	err->uncor_status |= einj->uncor_status;
+	err->cor_status |= einj->cor_status;
+	err->header_log0 = einj->header_log0;
+	err->header_log1 = einj->header_log1;
+	err->header_log2 = einj->header_log2;
+	err->header_log3 = einj->header_log3;
+
+	rperr = __find_aer_error_by_dev(rpdev);
+	if (!rperr) {
+		rperr = rperr_alloc;
+		rperr_alloc = NULL;
+		aer_error_init(rperr, rpdev->bus->number, rpdev->devfn,
+			       rp_pos_cap_err);
+		list_add(&rperr->list, &einjected);
+	}
+	if (einj->cor_status) {
+		if (rperr->root_status & PCI_ERR_ROOT_COR_RCV)
+			rperr->root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
+		else
+			rperr->root_status |= PCI_ERR_ROOT_COR_RCV;
+		rperr->source_id &= 0xffff0000;
+		rperr->source_id |= (einj->bus << 8) | devfn;
+	}
+	if (einj->uncor_status) {
+		if (rperr->root_status & PCI_ERR_ROOT_UNCOR_RCV)
+			rperr->root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
+		if (sever & einj->uncor_status) {
+			rperr->root_status |= PCI_ERR_ROOT_FATAL_RCV;
+			if (!(rperr->root_status & PCI_ERR_ROOT_UNCOR_RCV))
+				rperr->root_status |= PCI_ERR_ROOT_FIRST_FATAL;
+		} else
+			rperr->root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
+		rperr->root_status |= PCI_ERR_ROOT_UNCOR_RCV;
+		rperr->source_id &= 0x0000ffff;
+		rperr->source_id |= ((einj->bus << 8) | devfn) << 16;
+	}
+	spin_unlock_irqrestore(&inject_lock, flags);
+
+	ret = pci_bus_set_aer_ops(dev->bus);
+	if (ret)
+		goto out_put;
+	ret = pci_bus_set_aer_ops(rpdev->bus);
+	if (ret)
+		goto out_put;
+
+	if (find_aer_device(rpdev, &edev))
+		aer_irq(-1, edev);
+	else
+		ret = -EINVAL;
+out_put:
+	if (err_alloc)
+		kfree(err_alloc);
+	if (rperr_alloc)
+		kfree(rperr_alloc);
+	pci_dev_put(dev);
+	return ret;
+}
+
+static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
+				size_t usize, loff_t *off)
+{
+	struct aer_error_inj einj;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (usize != sizeof(struct aer_error_inj))
+		return -EINVAL;
+
+	if (copy_from_user(&einj, ubuf, usize))
+		return -EFAULT;
+
+	ret = aer_inject(&einj);
+	return ret ? ret : usize;
+}
+
+static const struct file_operations aer_inject_fops = {
+	.write = aer_inject_write,
+	.owner = THIS_MODULE,
+};
+
+static struct miscdevice aer_inject_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "aer_inject",
+	.fops = &aer_inject_fops,
+};
+
+static int __init aer_inject_init(void)
+{
+	return misc_register(&aer_inject_device);
+}
+
+static void __exit aer_inject_exit(void)
+{
+	struct aer_error *err, *err_next;
+	unsigned long flags;
+	struct pci_bus_ops *bus_ops;
+
+	misc_deregister(&aer_inject_device);
+
+	while ((bus_ops = pci_bus_ops_pop())) {
+		pci_bus_set_ops(bus_ops->bus, bus_ops->ops);
+		kfree(bus_ops);
+	}
+
+	spin_lock_irqsave(&inject_lock, flags);
+	list_for_each_entry_safe(err, err_next,
+				 &pci_bus_ops_list, list) {
+		list_del(&err->list);
+		kfree(err);
+	}
+	spin_unlock_irqrestore(&inject_lock, flags);
+}
+
+module_init(aer_inject_init);
+module_exit(aer_inject_exit);
+
+MODULE_DESCRIPTION("PCIE AER software error injector");
+MODULE_LICENSE("GPL");

+ 2 - 1
drivers/pci/pcie/aer/aerdrv.c

@@ -77,7 +77,7 @@ void pci_no_aer(void)
  *
  * Invoked when Root Port detects AER messages.
  **/
-static irqreturn_t aer_irq(int irq, void *context)
+irqreturn_t aer_irq(int irq, void *context)
 {
 	unsigned int status, id;
 	struct pcie_device *pdev = (struct pcie_device *)context;
@@ -126,6 +126,7 @@ static irqreturn_t aer_irq(int irq, void *context)
 
 	return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(aer_irq);
 
 /**
  * aer_alloc_rpc - allocate Root Port data structure

+ 6 - 0
drivers/pci/pcie/aer/aerdrv.h

@@ -11,6 +11,7 @@
 #include <linux/workqueue.h>
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
+#include <linux/interrupt.h>
 
 #define AER_NONFATAL			0
 #define AER_FATAL			1
@@ -56,7 +57,11 @@ struct header_log_regs {
 	unsigned int dw3;
 };
 
+#define AER_MAX_MULTI_ERR_DEVICES	5	/* Not likely to have more */
 struct aer_err_info {
+	struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
+	int error_dev_num;
+	u16 id;
 	int severity;			/* 0:NONFATAL | 1:FATAL | 2:COR */
 	int flags;
 	unsigned int status;		/* COR/UNCOR Error Status */
@@ -120,6 +125,7 @@ extern void aer_delete_rootport(struct aer_rpc *rpc);
 extern int aer_init(struct pcie_device *dev);
 extern void aer_isr(struct work_struct *work);
 extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
+extern irqreturn_t aer_irq(int irq, void *context);
 
 #ifdef CONFIG_ACPI
 extern int aer_osc_setup(struct pcie_device *pciedev);

+ 191 - 87
drivers/pci/pcie/aer/aerdrv_core.c

@@ -26,7 +26,9 @@
 #include "aerdrv.h"
 
 static int forceload;
+static int nosourceid;
 module_param(forceload, bool, 0);
+module_param(nosourceid, bool, 0);
 
 int pci_enable_pcie_error_reporting(struct pci_dev *dev)
 {
@@ -109,19 +111,23 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
 #endif  /*  0  */
 
 
-static void set_device_error_reporting(struct pci_dev *dev, void *data)
+static int set_device_error_reporting(struct pci_dev *dev, void *data)
 {
 	bool enable = *((bool *)data);
 
-	if (dev->pcie_type != PCIE_RC_PORT &&
-	    dev->pcie_type != PCIE_SW_UPSTREAM_PORT &&
-	    dev->pcie_type != PCIE_SW_DOWNSTREAM_PORT)
-		return;
+	if (dev->pcie_type == PCIE_RC_PORT ||
+	    dev->pcie_type == PCIE_SW_UPSTREAM_PORT ||
+	    dev->pcie_type == PCIE_SW_DOWNSTREAM_PORT) {
+		if (enable)
+			pci_enable_pcie_error_reporting(dev);
+		else
+			pci_disable_pcie_error_reporting(dev);
+	}
 
 	if (enable)
-		pci_enable_pcie_error_reporting(dev);
-	else
-		pci_disable_pcie_error_reporting(dev);
+		pcie_set_ecrc_checking(dev);
+
+	return 0;
 }
 
 /**
@@ -139,73 +145,148 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev,
 	pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
 }
 
-static int find_device_iter(struct device *device, void *data)
+static inline int compare_device_id(struct pci_dev *dev,
+			struct aer_err_info *e_info)
 {
-	struct pci_dev *dev;
-	u16 id = *(unsigned long *)data;
-	u8 secondary, subordinate, d_bus = id >> 8;
+	if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) {
+		/*
+		 * Device ID match
+		 */
+		return 1;
+	}
 
-	if (device->bus == &pci_bus_type) {
-		dev = to_pci_dev(device);
-		if (id == ((dev->bus->number << 8) | dev->devfn)) {
-			/*
-			 * Device ID match
-			 */
-			*(unsigned long*)data = (unsigned long)device;
-			return 1;
-		}
+	return 0;
+}
+
+static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
+{
+	if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) {
+		e_info->dev[e_info->error_dev_num] = dev;
+		e_info->error_dev_num++;
+		return 1;
+	} else
+		return 0;
+}
+
+
+#define	PCI_BUS(x)	(((x) >> 8) & 0xff)
+
+static int find_device_iter(struct pci_dev *dev, void *data)
+{
+	int pos;
+	u32 status;
+	u32 mask;
+	u16 reg16;
+	int result;
+	struct aer_err_info *e_info = (struct aer_err_info *)data;
+
+	/*
+	 * When bus id is equal to 0, it might be a bad id
+	 * reported by root port.
+	 */
+	if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
+		result = compare_device_id(dev, e_info);
+		if (result)
+			add_error_device(e_info, dev);
 
 		/*
-		 * If device is P2P, check if it is an upstream?
+		 * If there is no multiple error, we stop
+		 * or continue based on the id comparing.
 		 */
-		if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
-			pci_read_config_byte(dev, PCI_SECONDARY_BUS,
-				&secondary);
-			pci_read_config_byte(dev, PCI_SUBORDINATE_BUS,
-				&subordinate);
-			if (d_bus >= secondary && d_bus <= subordinate) {
-				*(unsigned long*)data = (unsigned long)device;
-				return 1;
-			}
+		if (!(e_info->flags & AER_MULTI_ERROR_VALID_FLAG))
+			return result;
+
+		/*
+		 * If there are multiple errors and id does match,
+		 * We need continue to search other devices under
+		 * the root port. Return 0 means that.
+		 */
+		if (result)
+			return 0;
+	}
+
+	/*
+	 * When either
+	 *      1) nosourceid==y;
+	 *      2) bus id is equal to 0. Some ports might lose the bus
+	 *              id of error source id;
+	 *      3) There are multiple errors and prior id comparing fails;
+	 * We check AER status registers to find the initial reporter.
+	 */
+	if (atomic_read(&dev->enable_cnt) == 0)
+		return 0;
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
+		return 0;
+	/* Check if AER is enabled */
+	pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
+	if (!(reg16 & (
+		PCI_EXP_DEVCTL_CERE |
+		PCI_EXP_DEVCTL_NFERE |
+		PCI_EXP_DEVCTL_FERE |
+		PCI_EXP_DEVCTL_URRE)))
+		return 0;
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return 0;
+
+	status = 0;
+	mask = 0;
+	if (e_info->severity == AER_CORRECTABLE) {
+		pci_read_config_dword(dev,
+				pos + PCI_ERR_COR_STATUS,
+				&status);
+		pci_read_config_dword(dev,
+				pos + PCI_ERR_COR_MASK,
+				&mask);
+		if (status & ERR_CORRECTABLE_ERROR_MASK & ~mask) {
+			add_error_device(e_info, dev);
+			goto added;
+		}
+	} else {
+		pci_read_config_dword(dev,
+				pos + PCI_ERR_UNCOR_STATUS,
+				&status);
+		pci_read_config_dword(dev,
+				pos + PCI_ERR_UNCOR_MASK,
+				&mask);
+		if (status & ERR_UNCORRECTABLE_ERROR_MASK & ~mask) {
+			add_error_device(e_info, dev);
+			goto added;
 		}
 	}
 
 	return 0;
+
+added:
+	if (e_info->flags & AER_MULTI_ERROR_VALID_FLAG)
+		return 0;
+	else
+		return 1;
 }
 
 /**
  * find_source_device - search through device hierarchy for source device
  * @parent: pointer to Root Port pci_dev data structure
- * @id: device ID of agent who sends an error message to this Root Port
+ * @err_info: including detailed error information such like id
  *
  * Invoked when error is detected at the Root Port.
  */
-static struct device* find_source_device(struct pci_dev *parent, u16 id)
+static void find_source_device(struct pci_dev *parent,
+		struct aer_err_info *e_info)
 {
 	struct pci_dev *dev = parent;
-	struct device *device;
-	unsigned long device_addr;
-	int status;
+	int result;
 
 	/* Is Root Port an agent that sends error message? */
-	if (id == ((dev->bus->number << 8) | dev->devfn))
-		return &dev->dev;
-
-	do {
-		device_addr = id;
- 		if ((status = device_for_each_child(&dev->dev,
-			&device_addr, find_device_iter))) {
-			device = (struct device*)device_addr;
-			dev = to_pci_dev(device);
-			if (id == ((dev->bus->number << 8) | dev->devfn))
-				return device;
-		}
- 	}while (status);
+	result = find_device_iter(dev, e_info);
+	if (result)
+		return;
 
-	return NULL;
+	pci_walk_bus(parent->subordinate, find_device_iter, e_info);
 }
 
-static void report_error_detected(struct pci_dev *dev, void *data)
+static int report_error_detected(struct pci_dev *dev, void *data)
 {
 	pci_ers_result_t vote;
 	struct pci_error_handlers *err_handler;
@@ -230,16 +311,16 @@ static void report_error_detected(struct pci_dev *dev, void *data)
 				   dev->driver ?
 				   "no AER-aware driver" : "no driver");
 		}
-		return;
+		return 0;
 	}
 
 	err_handler = dev->driver->err_handler;
 	vote = err_handler->error_detected(dev, result_data->state);
 	result_data->result = merge_result(result_data->result, vote);
-	return;
+	return 0;
 }
 
-static void report_mmio_enabled(struct pci_dev *dev, void *data)
+static int report_mmio_enabled(struct pci_dev *dev, void *data)
 {
 	pci_ers_result_t vote;
 	struct pci_error_handlers *err_handler;
@@ -249,15 +330,15 @@ static void report_mmio_enabled(struct pci_dev *dev, void *data)
 	if (!dev->driver ||
 		!dev->driver->err_handler ||
 		!dev->driver->err_handler->mmio_enabled)
-		return;
+		return 0;
 
 	err_handler = dev->driver->err_handler;
 	vote = err_handler->mmio_enabled(dev);
 	result_data->result = merge_result(result_data->result, vote);
-	return;
+	return 0;
 }
 
-static void report_slot_reset(struct pci_dev *dev, void *data)
+static int report_slot_reset(struct pci_dev *dev, void *data)
 {
 	pci_ers_result_t vote;
 	struct pci_error_handlers *err_handler;
@@ -267,15 +348,15 @@ static void report_slot_reset(struct pci_dev *dev, void *data)
 	if (!dev->driver ||
 		!dev->driver->err_handler ||
 		!dev->driver->err_handler->slot_reset)
-		return;
+		return 0;
 
 	err_handler = dev->driver->err_handler;
 	vote = err_handler->slot_reset(dev);
 	result_data->result = merge_result(result_data->result, vote);
-	return;
+	return 0;
 }
 
-static void report_resume(struct pci_dev *dev, void *data)
+static int report_resume(struct pci_dev *dev, void *data)
 {
 	struct pci_error_handlers *err_handler;
 
@@ -284,11 +365,11 @@ static void report_resume(struct pci_dev *dev, void *data)
 	if (!dev->driver ||
 		!dev->driver->err_handler ||
 		!dev->driver->err_handler->resume)
-		return;
+		return 0;
 
 	err_handler = dev->driver->err_handler;
 	err_handler->resume(dev);
-	return;
+	return 0;
 }
 
 /**
@@ -305,7 +386,7 @@ static void report_resume(struct pci_dev *dev, void *data)
 static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
 	enum pci_channel_state state,
 	char *error_mesg,
-	void (*cb)(struct pci_dev *, void *))
+	int (*cb)(struct pci_dev *, void *))
 {
 	struct aer_broadcast_data result_data;
 
@@ -497,12 +578,12 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
  */
 static void handle_error_source(struct pcie_device * aerdev,
 	struct pci_dev *dev,
-	struct aer_err_info info)
+	struct aer_err_info *info)
 {
 	pci_ers_result_t status = 0;
 	int pos;
 
-	if (info.severity == AER_CORRECTABLE) {
+	if (info->severity == AER_CORRECTABLE) {
 		/*
 		 * Correctable error does not need software intevention.
 		 * No need to go through error recovery process.
@@ -510,9 +591,9 @@ static void handle_error_source(struct pcie_device * aerdev,
 		pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
 		if (pos)
 			pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
-					info.status);
+					info->status);
 	} else {
-		status = do_recovery(aerdev, dev, info.severity);
+		status = do_recovery(aerdev, dev, info->severity);
 		if (status == PCI_ERS_RESULT_RECOVERED) {
 			dev_printk(KERN_DEBUG, &dev->dev, "AER driver "
 				   "successfully recovered\n");
@@ -661,6 +742,28 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
 	return AER_SUCCESS;
 }
 
+static inline void aer_process_err_devices(struct pcie_device *p_device,
+			struct aer_err_info *e_info)
+{
+	int i;
+
+	if (!e_info->dev[0]) {
+		dev_printk(KERN_DEBUG, &p_device->port->dev,
+				"can't find device of ID%04x\n",
+				e_info->id);
+	}
+
+	for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
+		if (get_device_error_info(e_info->dev[i], e_info) ==
+				AER_SUCCESS) {
+			aer_print_error(e_info->dev[i], e_info);
+			handle_error_source(p_device,
+					e_info->dev[i],
+					e_info);
+		}
+	}
+}
+
 /**
  * aer_isr_one_error - consume an error detected by root port
  * @p_device: pointer to error root port service device
@@ -669,10 +772,16 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
 static void aer_isr_one_error(struct pcie_device *p_device,
 		struct aer_err_source *e_src)
 {
-	struct device *s_device;
-	struct aer_err_info e_info = {0, 0, 0,};
+	struct aer_err_info *e_info;
 	int i;
-	u16 id;
+
+	/* struct aer_err_info might be big, so we allocate it with slab */
+	e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL);
+	if (e_info == NULL) {
+		dev_printk(KERN_DEBUG, &p_device->port->dev,
+			"Can't allocate mem when processing AER errors\n");
+		return;
+	}
 
 	/*
 	 * There is a possibility that both correctable error and
@@ -684,31 +793,26 @@ static void aer_isr_one_error(struct pcie_device *p_device,
 		if (!(e_src->status & i))
 			continue;
 
+		memset(e_info, 0, sizeof(struct aer_err_info));
+
 		/* Init comprehensive error information */
 		if (i & PCI_ERR_ROOT_COR_RCV) {
-			id = ERR_COR_ID(e_src->id);
-			e_info.severity = AER_CORRECTABLE;
+			e_info->id = ERR_COR_ID(e_src->id);
+			e_info->severity = AER_CORRECTABLE;
 		} else {
-			id = ERR_UNCOR_ID(e_src->id);
-			e_info.severity = ((e_src->status >> 6) & 1);
+			e_info->id = ERR_UNCOR_ID(e_src->id);
+			e_info->severity = ((e_src->status >> 6) & 1);
 		}
 		if (e_src->status &
 			(PCI_ERR_ROOT_MULTI_COR_RCV |
 			 PCI_ERR_ROOT_MULTI_UNCOR_RCV))
-			e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
-		if (!(s_device = find_source_device(p_device->port, id))) {
-			printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
-				__func__, id);
-			continue;
-		}
-		if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
-				AER_SUCCESS) {
-			aer_print_error(to_pci_dev(s_device), &e_info);
-			handle_error_source(p_device,
-				to_pci_dev(s_device),
-				e_info);
-		}
+			e_info->flags |= AER_MULTI_ERROR_VALID_FLAG;
+
+		find_source_device(p_device->port, e_info);
+		aer_process_err_devices(p_device, e_info);
 	}
+
+	kfree(e_info);
 }
 
 /**

+ 131 - 0
drivers/pci/pcie/aer/ecrc.c

@@ -0,0 +1,131 @@
+/*
+ *    Enables/disables PCIe ECRC checking.
+ *
+ *    (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ *    Andrew Patterson <andrew.patterson@hp.com>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; version 2 of the License.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *    General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *    02111-1307, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include "../../pci.h"
+
+#define ECRC_POLICY_DEFAULT 0		/* ECRC set by BIOS */
+#define ECRC_POLICY_OFF     1		/* ECRC off for performance */
+#define ECRC_POLICY_ON      2		/* ECRC on for data integrity */
+
+static int ecrc_policy = ECRC_POLICY_DEFAULT;
+
+static const char *ecrc_policy_str[] = {
+	[ECRC_POLICY_DEFAULT] = "bios",
+	[ECRC_POLICY_OFF] = "off",
+	[ECRC_POLICY_ON] = "on"
+};
+
+/**
+ * enable_ercr_checking - enable PCIe ECRC checking for a device
+ * @dev: the PCI device
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+static int enable_ecrc_checking(struct pci_dev *dev)
+{
+	int pos;
+	u32 reg32;
+
+	if (!dev->is_pcie)
+		return -ENODEV;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return -ENODEV;
+
+	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+	if (reg32 & PCI_ERR_CAP_ECRC_GENC)
+		reg32 |= PCI_ERR_CAP_ECRC_GENE;
+	if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
+		reg32 |= PCI_ERR_CAP_ECRC_CHKE;
+	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+	return 0;
+}
+
+/**
+ * disable_ercr_checking - disables PCIe ECRC checking for a device
+ * @dev: the PCI device
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+static int disable_ecrc_checking(struct pci_dev *dev)
+{
+	int pos;
+	u32 reg32;
+
+	if (!dev->is_pcie)
+		return -ENODEV;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return -ENODEV;
+
+	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+	reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+	return 0;
+}
+
+/**
+ * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
+ * @dev: the PCI device
+ */
+void pcie_set_ecrc_checking(struct pci_dev *dev)
+{
+	switch (ecrc_policy) {
+	case ECRC_POLICY_DEFAULT:
+		return;
+	case ECRC_POLICY_OFF:
+		disable_ecrc_checking(dev);
+		break;
+	case ECRC_POLICY_ON:
+		enable_ecrc_checking(dev);;
+		break;
+	default:
+		return;
+	}
+}
+
+/**
+ * pcie_ecrc_get_policy - parse kernel command-line ecrc option
+ */
+void pcie_ecrc_get_policy(char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
+		if (!strncmp(str, ecrc_policy_str[i],
+			     strlen(ecrc_policy_str[i])))
+			break;
+	if (i >= ARRAY_SIZE(ecrc_policy_str))
+		return;
+
+	ecrc_policy = i;
+}

+ 371 - 416
drivers/pci/pcie/aspm.c

@@ -26,40 +26,36 @@
 #endif
 #define MODULE_PARAM_PREFIX "pcie_aspm."
 
-struct endpoint_state {
-	unsigned int l0s_acceptable_latency;
-	unsigned int l1_acceptable_latency;
+struct aspm_latency {
+	u32 l0s;			/* L0s latency (nsec) */
+	u32 l1;				/* L1 latency (nsec) */
 };
 
 struct pcie_link_state {
-	struct list_head sibiling;
-	struct pci_dev *pdev;
-	bool downstream_has_switch;
-
-	struct pcie_link_state *parent;
-	struct list_head children;
-	struct list_head link;
+	struct pci_dev *pdev;		/* Upstream component of the Link */
+	struct pcie_link_state *root;	/* pointer to the root port link */
+	struct pcie_link_state *parent;	/* pointer to the parent Link state */
+	struct list_head sibling;	/* node in link_list */
+	struct list_head children;	/* list of child link states */
+	struct list_head link;		/* node in parent's children list */
 
 	/* ASPM state */
-	unsigned int support_state;
-	unsigned int enabled_state;
-	unsigned int bios_aspm_state;
-	/* upstream component */
-	unsigned int l0s_upper_latency;
-	unsigned int l1_upper_latency;
-	/* downstream component */
-	unsigned int l0s_down_latency;
-	unsigned int l1_down_latency;
-	/* Clock PM state*/
-	unsigned int clk_pm_capable;
-	unsigned int clk_pm_enabled;
-	unsigned int bios_clk_state;
+	u32 aspm_support:2;		/* Supported ASPM state */
+	u32 aspm_enabled:2;		/* Enabled ASPM state */
+	u32 aspm_default:2;		/* Default ASPM state by BIOS */
+
+	/* Clock PM state */
+	u32 clkpm_capable:1;		/* Clock PM capable? */
+	u32 clkpm_enabled:1;		/* Current Clock PM state */
+	u32 clkpm_default:1;		/* Default Clock PM state by BIOS */
 
+	/* Latencies */
+	struct aspm_latency latency;	/* Exit latency */
 	/*
-	 * A pcie downstream port only has one slot under it, so at most there
-	 * are 8 functions
+	 * Endpoint acceptable latencies. A pcie downstream port only
+	 * has one slot under it, so at most there are 8 functions.
 	 */
-	struct endpoint_state endpoints[8];
+	struct aspm_latency acceptable[8];
 };
 
 static int aspm_disabled, aspm_force;
@@ -78,27 +74,23 @@ static const char *policy_str[] = {
 
 #define LINK_RETRAIN_TIMEOUT HZ
 
-static int policy_to_aspm_state(struct pci_dev *pdev)
+static int policy_to_aspm_state(struct pcie_link_state *link)
 {
-	struct pcie_link_state *link_state = pdev->link_state;
-
 	switch (aspm_policy) {
 	case POLICY_PERFORMANCE:
 		/* Disable ASPM and Clock PM */
 		return 0;
 	case POLICY_POWERSAVE:
 		/* Enable ASPM L0s/L1 */
-		return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+		return PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1;
 	case POLICY_DEFAULT:
-		return link_state->bios_aspm_state;
+		return link->aspm_default;
 	}
 	return 0;
 }
 
-static int policy_to_clkpm_state(struct pci_dev *pdev)
+static int policy_to_clkpm_state(struct pcie_link_state *link)
 {
-	struct pcie_link_state *link_state = pdev->link_state;
-
 	switch (aspm_policy) {
 	case POLICY_PERFORMANCE:
 		/* Disable ASPM and Clock PM */
@@ -107,73 +99,78 @@ static int policy_to_clkpm_state(struct pci_dev *pdev)
 		/* Disable Clock PM */
 		return 1;
 	case POLICY_DEFAULT:
-		return link_state->bios_clk_state;
+		return link->clkpm_default;
 	}
 	return 0;
 }
 
-static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
 {
-	struct pci_dev *child_dev;
 	int pos;
 	u16 reg16;
-	struct pcie_link_state *link_state = pdev->link_state;
+	struct pci_dev *child;
+	struct pci_bus *linkbus = link->pdev->subordinate;
 
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
 		if (!pos)
 			return;
-		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
 		if (enable)
 			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
 		else
 			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
-		pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+		pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16);
 	}
-	link_state->clk_pm_enabled = !!enable;
+	link->clkpm_enabled = !!enable;
 }
 
-static void pcie_check_clock_pm(struct pci_dev *pdev, int blacklist)
+static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
 {
-	int pos;
+	/* Don't enable Clock PM if the link is not Clock PM capable */
+	if (!link->clkpm_capable && enable)
+		return;
+	/* Need nothing if the specified equals to current state */
+	if (link->clkpm_enabled == enable)
+		return;
+	pcie_set_clkpm_nocheck(link, enable);
+}
+
+static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
+{
+	int pos, capable = 1, enabled = 1;
 	u32 reg32;
 	u16 reg16;
-	int capable = 1, enabled = 1;
-	struct pci_dev *child_dev;
-	struct pcie_link_state *link_state = pdev->link_state;
+	struct pci_dev *child;
+	struct pci_bus *linkbus = link->pdev->subordinate;
 
 	/* All functions should have the same cap and state, take the worst */
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
 		if (!pos)
 			return;
-		pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+		pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
 		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
 			capable = 0;
 			enabled = 0;
 			break;
 		}
-		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
 		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
 			enabled = 0;
 	}
-	link_state->clk_pm_enabled = enabled;
-	link_state->bios_clk_state = enabled;
-	if (!blacklist) {
-		link_state->clk_pm_capable = capable;
-		pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-	} else {
-		link_state->clk_pm_capable = 0;
-		pcie_set_clock_pm(pdev, 0);
-	}
+	link->clkpm_enabled = enabled;
+	link->clkpm_default = enabled;
+	link->clkpm_capable = (blacklist) ? 0 : capable;
 }
 
-static bool pcie_aspm_downstream_has_switch(struct pci_dev *pdev)
+static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link)
 {
-	struct pci_dev *child_dev;
+	struct pci_dev *child;
+	struct pci_bus *linkbus = link->pdev->subordinate;
 
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		if (child_dev->pcie_type == PCI_EXP_TYPE_UPSTREAM)
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		if (child->pcie_type == PCI_EXP_TYPE_UPSTREAM)
 			return true;
 	}
 	return false;
@@ -184,289 +181,263 @@ static bool pcie_aspm_downstream_has_switch(struct pci_dev *pdev)
  *   could use common clock. If they are, configure them to use the
  *   common clock. That will reduce the ASPM state exit latency.
  */
-static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
 {
-	int pos, child_pos, i = 0;
-	u16 reg16 = 0;
-	struct pci_dev *child_dev;
-	int same_clock = 1;
+	int ppos, cpos, same_clock = 1;
+	u16 reg16, parent_reg, child_reg[8];
 	unsigned long start_jiffies;
-	u16 child_regs[8], parent_reg;
+	struct pci_dev *child, *parent = link->pdev;
+	struct pci_bus *linkbus = parent->subordinate;
 	/*
-	 * all functions of a slot should have the same Slot Clock
+	 * All functions of a slot should have the same Slot Clock
 	 * Configuration, so just check one function
-	 * */
-	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-		bus_list);
-	BUG_ON(!child_dev->is_pcie);
+	 */
+	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
+	BUG_ON(!child->is_pcie);
 
 	/* Check downstream component if bit Slot Clock Configuration is 1 */
-	child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-	pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+	cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+	pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
 	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
 		same_clock = 0;
 
 	/* Check upstream component if bit Slot Clock Configuration is 1 */
-	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+	pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
 	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
 		same_clock = 0;
 
 	/* Configure downstream component, all functions */
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-		pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-			&reg16);
-		child_regs[i] = reg16;
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+		pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
+		child_reg[PCI_FUNC(child->devfn)] = reg16;
 		if (same_clock)
 			reg16 |= PCI_EXP_LNKCTL_CCC;
 		else
 			reg16 &= ~PCI_EXP_LNKCTL_CCC;
-		pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-			reg16);
-		i++;
+		pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16);
 	}
 
 	/* Configure upstream component */
-	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, &reg16);
 	parent_reg = reg16;
 	if (same_clock)
 		reg16 |= PCI_EXP_LNKCTL_CCC;
 	else
 		reg16 &= ~PCI_EXP_LNKCTL_CCC;
-	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
 
-	/* retrain link */
+	/* Retrain link */
 	reg16 |= PCI_EXP_LNKCTL_RL;
-	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
 
-	/* Wait for link training end */
-	/* break out after waiting for timeout */
+	/* Wait for link training end. Break out after waiting for timeout */
 	start_jiffies = jiffies;
 	for (;;) {
-		pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+		pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
 		if (!(reg16 & PCI_EXP_LNKSTA_LT))
 			break;
 		if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
 			break;
 		msleep(1);
 	}
-	/* training failed -> recover */
-	if (reg16 & PCI_EXP_LNKSTA_LT) {
-		dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure"
-			    " common clock\n");
-		i = 0;
-		list_for_each_entry(child_dev, &pdev->subordinate->devices,
-				    bus_list) {
-			child_pos = pci_find_capability(child_dev,
-							PCI_CAP_ID_EXP);
-			pci_write_config_word(child_dev,
-					      child_pos + PCI_EXP_LNKCTL,
-					      child_regs[i]);
-			i++;
-		}
-		pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, parent_reg);
+	if (!(reg16 & PCI_EXP_LNKSTA_LT))
+		return;
+
+	/* Training failed. Restore common clock configurations */
+	dev_printk(KERN_ERR, &parent->dev,
+		   "ASPM: Could not configure common clock\n");
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+		pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
+				      child_reg[PCI_FUNC(child->devfn)]);
 	}
+	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg);
 }
 
-/*
- * calc_L0S_latency: Convert L0s latency encoding to ns
- */
-static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+/* Convert L0s latency encoding to ns */
+static u32 calc_l0s_latency(u32 encoding)
 {
-	unsigned int ns = 64;
+	if (encoding == 0x7)
+		return (5 * 1000);	/* > 4us */
+	return (64 << encoding);
+}
 
-	if (latency_encoding == 0x7) {
-		if (ac)
-			ns = -1U;
-		else
-			ns = 5*1000; /* > 4us */
-	} else
-		ns *= (1 << latency_encoding);
-	return ns;
+/* Convert L0s acceptable latency encoding to ns */
+static u32 calc_l0s_acceptable(u32 encoding)
+{
+	if (encoding == 0x7)
+		return -1U;
+	return (64 << encoding);
 }
 
-/*
- * calc_L1_latency: Convert L1 latency encoding to ns
- */
-static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+/* Convert L1 latency encoding to ns */
+static u32 calc_l1_latency(u32 encoding)
 {
-	unsigned int ns = 1000;
+	if (encoding == 0x7)
+		return (65 * 1000);	/* > 64us */
+	return (1000 << encoding);
+}
 
-	if (latency_encoding == 0x7) {
-		if (ac)
-			ns = -1U;
-		else
-			ns = 65*1000; /* > 64us */
-	} else
-		ns *= (1 << latency_encoding);
-	return ns;
+/* Convert L1 acceptable latency encoding to ns */
+static u32 calc_l1_acceptable(u32 encoding)
+{
+	if (encoding == 0x7)
+		return -1U;
+	return (1000 << encoding);
 }
 
 static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
-	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+				     u32 *l0s, u32 *l1, u32 *enabled)
 {
 	int pos;
 	u16 reg16;
-	u32 reg32;
-	unsigned int latency;
+	u32 reg32, encoding;
 
+	*l0s = *l1 = *enabled = 0;
 	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
 	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
 	if (*state != PCIE_LINK_STATE_L0S &&
-		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+	    *state != (PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_L0S))
 		*state = 0;
 	if (*state == 0)
 		return;
 
-	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
-	*l0s = calc_L0S_latency(latency, 0);
+	encoding = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+	*l0s = calc_l0s_latency(encoding);
 	if (*state & PCIE_LINK_STATE_L1) {
-		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
-		*l1 = calc_L1_latency(latency, 0);
+		encoding = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+		*l1 = calc_l1_latency(encoding);
 	}
 	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+	*enabled = reg16 & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
 }
 
-static void pcie_aspm_cap_init(struct pci_dev *pdev)
+static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 {
-	struct pci_dev *child_dev;
-	u32 state, tmp;
-	struct pcie_link_state *link_state = pdev->link_state;
+	u32 support, l0s, l1, enabled;
+	struct pci_dev *child, *parent = link->pdev;
+	struct pci_bus *linkbus = parent->subordinate;
+
+	if (blacklist) {
+		/* Set support state to 0, so we will disable ASPM later */
+		link->aspm_support = 0;
+		link->aspm_default = 0;
+		link->aspm_enabled = PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1;
+		return;
+	}
+
+	/* Configure common clock before checking latencies */
+	pcie_aspm_configure_common_clock(link);
 
 	/* upstream component states */
-	pcie_aspm_get_cap_device(pdev, &link_state->support_state,
-		&link_state->l0s_upper_latency,
-		&link_state->l1_upper_latency,
-		&link_state->enabled_state);
+	pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled);
+	link->aspm_support = support;
+	link->latency.l0s = l0s;
+	link->latency.l1 = l1;
+	link->aspm_enabled = enabled;
+
 	/* downstream component states, all functions have the same setting */
-	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-		bus_list);
-	pcie_aspm_get_cap_device(child_dev, &state,
-		&link_state->l0s_down_latency,
-		&link_state->l1_down_latency,
-		&tmp);
-	link_state->support_state &= state;
-	if (!link_state->support_state)
+	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
+	pcie_aspm_get_cap_device(child, &support, &l0s, &l1, &enabled);
+	link->aspm_support &= support;
+	link->latency.l0s = max_t(u32, link->latency.l0s, l0s);
+	link->latency.l1 = max_t(u32, link->latency.l1, l1);
+
+	if (!link->aspm_support)
 		return;
-	link_state->enabled_state &= link_state->support_state;
-	link_state->bios_aspm_state = link_state->enabled_state;
+
+	link->aspm_enabled &= link->aspm_support;
+	link->aspm_default = link->aspm_enabled;
 
 	/* ENDPOINT states*/
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
 		int pos;
-		u32 reg32;
-		unsigned int latency;
-		struct endpoint_state *ep_state =
-			&link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+		u32 reg32, encoding;
+		struct aspm_latency *acceptable =
+			&link->acceptable[PCI_FUNC(child->devfn)];
 
-		if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+		if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+		    child->pcie_type != PCI_EXP_TYPE_LEG_END)
 			continue;
 
-		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-		pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
-		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
-		latency = calc_L0S_latency(latency, 1);
-		ep_state->l0s_acceptable_latency = latency;
-		if (link_state->support_state & PCIE_LINK_STATE_L1) {
-			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
-			latency = calc_L1_latency(latency, 1);
-			ep_state->l1_acceptable_latency = latency;
+		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+		pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
+		encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+		acceptable->l0s = calc_l0s_acceptable(encoding);
+		if (link->aspm_support & PCIE_LINK_STATE_L1) {
+			encoding = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+			acceptable->l1 = calc_l1_acceptable(encoding);
 		}
 	}
 }
 
-static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
-	unsigned int state)
-{
-	struct pci_dev *parent_dev, *tmp_dev;
-	unsigned int latency, l1_latency = 0;
-	struct pcie_link_state *link_state;
-	struct endpoint_state *ep_state;
-
-	parent_dev = pdev->bus->self;
-	link_state = parent_dev->link_state;
-	state &= link_state->support_state;
-	if (state == 0)
-		return 0;
-	ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
-
-	/*
-	 * Check latency for endpoint device.
-	 * TBD: The latency from the endpoint to root complex vary per
-	 * switch's upstream link state above the device. Here we just do a
-	 * simple check which assumes all links above the device can be in L1
-	 * state, that is we just consider the worst case. If switch's upstream
-	 * link can't be put into L0S/L1, then our check is too strictly.
-	 */
-	tmp_dev = pdev;
-	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
-		parent_dev = tmp_dev->bus->self;
-		link_state = parent_dev->link_state;
-		if (state & PCIE_LINK_STATE_L0S) {
-			latency = max_t(unsigned int,
-					link_state->l0s_upper_latency,
-					link_state->l0s_down_latency);
-			if (latency > ep_state->l0s_acceptable_latency)
-				state &= ~PCIE_LINK_STATE_L0S;
-		}
-		if (state & PCIE_LINK_STATE_L1) {
-			latency = max_t(unsigned int,
-					link_state->l1_upper_latency,
-					link_state->l1_down_latency);
-			if (latency + l1_latency >
-					ep_state->l1_acceptable_latency)
-				state &= ~PCIE_LINK_STATE_L1;
-		}
-		if (!parent_dev->bus->self) /* parent_dev is a root port */
-			break;
-		else {
-			/*
-			 * parent_dev is the downstream port of a switch, make
-			 * tmp_dev the upstream port of the switch
-			 */
-			tmp_dev = parent_dev->bus->self;
-			/*
-			 * every switch on the path to root complex need 1 more
-			 * microsecond for L1. Spec doesn't mention L0S.
-			 */
-			if (state & PCIE_LINK_STATE_L1)
-				l1_latency += 1000;
-		}
+/**
+ * __pcie_aspm_check_state_one - check latency for endpoint device.
+ * @endpoint: pointer to the struct pci_dev of endpoint device
+ *
+ * TBD: The latency from the endpoint to root complex vary per switch's
+ * upstream link state above the device. Here we just do a simple check
+ * which assumes all links above the device can be in L1 state, that
+ * is we just consider the worst case. If switch's upstream link can't
+ * be put into L0S/L1, then our check is too strictly.
+ */
+static u32 __pcie_aspm_check_state_one(struct pci_dev *endpoint, u32 state)
+{
+	u32 l1_switch_latency = 0;
+	struct aspm_latency *acceptable;
+	struct pcie_link_state *link;
+
+	link = endpoint->bus->self->link_state;
+	state &= link->aspm_support;
+	acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)];
+
+	while (link && state) {
+		if ((state & PCIE_LINK_STATE_L0S) &&
+		    (link->latency.l0s > acceptable->l0s))
+			state &= ~PCIE_LINK_STATE_L0S;
+		if ((state & PCIE_LINK_STATE_L1) &&
+		    (link->latency.l1 + l1_switch_latency > acceptable->l1))
+			state &= ~PCIE_LINK_STATE_L1;
+		link = link->parent;
+		/*
+		 * Every switch on the path to root complex need 1
+		 * more microsecond for L1. Spec doesn't mention L0s.
+		 */
+		l1_switch_latency += 1000;
 	}
 	return state;
 }
 
-static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
-	unsigned int state)
+static u32 pcie_aspm_check_state(struct pcie_link_state *link, u32 state)
 {
-	struct pci_dev *child_dev;
+	pci_power_t power_state;
+	struct pci_dev *child;
+	struct pci_bus *linkbus = link->pdev->subordinate;
 
 	/* If no child, ignore the link */
-	if (list_empty(&pdev->subordinate->devices))
+	if (list_empty(&linkbus->devices))
 		return state;
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-			/*
-			 * If downstream component of a link is pci bridge, we
-			 * disable ASPM for now for the link
-			 * */
-			state = 0;
-			break;
-		}
-		if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		/*
+		 * If downstream component of a link is pci bridge, we
+		 * disable ASPM for now for the link
+		 */
+		if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+			return 0;
+
+		if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+		     child->pcie_type != PCI_EXP_TYPE_LEG_END))
 			continue;
 		/* Device not in D0 doesn't need check latency */
-		if (child_dev->current_state == PCI_D1 ||
-			child_dev->current_state == PCI_D2 ||
-			child_dev->current_state == PCI_D3hot ||
-			child_dev->current_state == PCI_D3cold)
+		power_state = child->current_state;
+		if (power_state == PCI_D1 || power_state == PCI_D2 ||
+		    power_state == PCI_D3hot || power_state == PCI_D3cold)
 			continue;
-		state = __pcie_aspm_check_state_one(child_dev, state);
+		state = __pcie_aspm_check_state_one(child, state);
 	}
 	return state;
 }
@@ -482,90 +453,71 @@ static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
 	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
 }
 
-static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+static void __pcie_aspm_config_link(struct pcie_link_state *link, u32 state)
 {
-	struct pci_dev *child_dev;
-	int valid = 1;
-	struct pcie_link_state *link_state = pdev->link_state;
+	struct pci_dev *child, *parent = link->pdev;
+	struct pci_bus *linkbus = parent->subordinate;
 
 	/* If no child, disable the link */
-	if (list_empty(&pdev->subordinate->devices))
+	if (list_empty(&linkbus->devices))
 		state = 0;
 	/*
-	 * if the downstream component has pci bridge function, don't do ASPM
-	 * now
+	 * If the downstream component has pci bridge function, don't
+	 * do ASPM now.
 	 */
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-			valid = 0;
-			break;
-		}
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+			return;
 	}
-	if (!valid)
-		return;
-
 	/*
-	 * spec 2.0 suggests all functions should be configured the same
-	 * setting for ASPM. Enabling ASPM L1 should be done in upstream
-	 * component first and then downstream, and vice versa for disabling
-	 * ASPM L1. Spec doesn't mention L0S.
+	 * Spec 2.0 suggests all functions should be configured the
+	 * same setting for ASPM. Enabling ASPM L1 should be done in
+	 * upstream component first and then downstream, and vice
+	 * versa for disabling ASPM L1. Spec doesn't mention L0S.
 	 */
 	if (state & PCIE_LINK_STATE_L1)
-		__pcie_aspm_config_one_dev(pdev, state);
+		__pcie_aspm_config_one_dev(parent, state);
 
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
-		__pcie_aspm_config_one_dev(child_dev, state);
+	list_for_each_entry(child, &linkbus->devices, bus_list)
+		__pcie_aspm_config_one_dev(child, state);
 
 	if (!(state & PCIE_LINK_STATE_L1))
-		__pcie_aspm_config_one_dev(pdev, state);
+		__pcie_aspm_config_one_dev(parent, state);
 
-	link_state->enabled_state = state;
+	link->aspm_enabled = state;
 }
 
-static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link)
+/* Check the whole hierarchy, and configure each link in the hierarchy */
+static void __pcie_aspm_configure_link_state(struct pcie_link_state *link,
+					     u32 state)
 {
-	struct pcie_link_state *root_port_link = link;
-	while (root_port_link->parent)
-		root_port_link = root_port_link->parent;
-	return root_port_link;
-}
+	struct pcie_link_state *leaf, *root = link->root;
 
-/* check the whole hierarchy, and configure each link in the hierarchy */
-static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
-	unsigned int state)
-{
-	struct pcie_link_state *link_state = pdev->link_state;
-	struct pcie_link_state *root_port_link = get_root_port_link(link_state);
-	struct pcie_link_state *leaf;
+	state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
 
-	state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-
-	/* check all links who have specific root port link */
-	list_for_each_entry(leaf, &link_list, sibiling) {
-		if (!list_empty(&leaf->children) ||
-			get_root_port_link(leaf) != root_port_link)
+	/* Check all links who have specific root port link */
+	list_for_each_entry(leaf, &link_list, sibling) {
+		if (!list_empty(&leaf->children) || (leaf->root != root))
 			continue;
-		state = pcie_aspm_check_state(leaf->pdev, state);
+		state = pcie_aspm_check_state(leaf, state);
 	}
-	/* check root port link too in case it hasn't children */
-	state = pcie_aspm_check_state(root_port_link->pdev, state);
-
-	if (link_state->enabled_state == state)
+	/* Check root port link too in case it hasn't children */
+	state = pcie_aspm_check_state(root, state);
+	if (link->aspm_enabled == state)
 		return;
-
 	/*
-	 * we must change the hierarchy. See comments in
+	 * We must change the hierarchy. See comments in
 	 * __pcie_aspm_config_link for the order
 	 **/
 	if (state & PCIE_LINK_STATE_L1) {
-		list_for_each_entry(leaf, &link_list, sibiling) {
-			if (get_root_port_link(leaf) == root_port_link)
-				__pcie_aspm_config_link(leaf->pdev, state);
+		list_for_each_entry(leaf, &link_list, sibling) {
+			if (leaf->root == root)
+				__pcie_aspm_config_link(leaf, state);
 		}
 	} else {
-		list_for_each_entry_reverse(leaf, &link_list, sibiling) {
-			if (get_root_port_link(leaf) == root_port_link)
-				__pcie_aspm_config_link(leaf->pdev, state);
+		list_for_each_entry_reverse(leaf, &link_list, sibling) {
+			if (leaf->root == root)
+				__pcie_aspm_config_link(leaf, state);
 		}
 	}
 }
@@ -574,45 +526,42 @@ static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
  * pcie_aspm_configure_link_state: enable/disable PCI express link state
  * @pdev: the root port or switch downstream port
  */
-static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
-	unsigned int state)
+static void pcie_aspm_configure_link_state(struct pcie_link_state *link,
+					   u32 state)
 {
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	__pcie_aspm_configure_link_state(pdev, state);
+	__pcie_aspm_configure_link_state(link, state);
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
 }
 
-static void free_link_state(struct pci_dev *pdev)
+static void free_link_state(struct pcie_link_state *link)
 {
-	kfree(pdev->link_state);
-	pdev->link_state = NULL;
+	link->pdev->link_state = NULL;
+	kfree(link);
 }
 
 static int pcie_aspm_sanity_check(struct pci_dev *pdev)
 {
-	struct pci_dev *child_dev;
-	int child_pos;
+	struct pci_dev *child;
+	int pos;
 	u32 reg32;
-
 	/*
-	 * Some functions in a slot might not all be PCIE functions, very
-	 * strange. Disable ASPM for the whole slot
+	 * Some functions in a slot might not all be PCIE functions,
+	 * very strange. Disable ASPM for the whole slot
 	 */
-	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-		if (!child_pos)
+	list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
+		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+		if (!pos)
 			return -EINVAL;
-
 		/*
 		 * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
 		 * RBER bit to determine if a function is 1.1 version device
 		 */
-		pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
-			&reg32);
+		pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
 		if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
-			dev_printk(KERN_INFO, &child_dev->dev, "disabling ASPM"
+			dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
 				" on pre-1.1 PCIe device.  You can enable it"
 				" with 'pcie_aspm=force'\n");
 			return -EINVAL;
@@ -621,6 +570,47 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
 	return 0;
 }
 
+static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link;
+	int blacklist = !!pcie_aspm_sanity_check(pdev);
+
+	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	if (!link)
+		return NULL;
+	INIT_LIST_HEAD(&link->sibling);
+	INIT_LIST_HEAD(&link->children);
+	INIT_LIST_HEAD(&link->link);
+	link->pdev = pdev;
+	if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
+		struct pcie_link_state *parent;
+		parent = pdev->bus->parent->self->link_state;
+		if (!parent) {
+			kfree(link);
+			return NULL;
+		}
+		link->parent = parent;
+		list_add(&link->link, &parent->children);
+	}
+	/* Setup a pointer to the root port link */
+	if (!link->parent)
+		link->root = link;
+	else
+		link->root = link->parent->root;
+
+	list_add(&link->sibling, &link_list);
+
+	pdev->link_state = link;
+
+	/* Check ASPM capability */
+	pcie_aspm_cap_init(link, blacklist);
+
+	/* Check Clock PM capability */
+	pcie_clkpm_cap_init(link, blacklist);
+
+	return link;
+}
+
 /*
  * pcie_aspm_init_link_state: Initiate PCI express link state.
  * It is called after the pcie and its children devices are scaned.
@@ -628,75 +618,47 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
  */
 void pcie_aspm_init_link_state(struct pci_dev *pdev)
 {
-	unsigned int state;
-	struct pcie_link_state *link_state;
-	int error = 0;
-	int blacklist;
+	u32 state;
+	struct pcie_link_state *link;
 
 	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
 		return;
 	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+	    pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+
+	/* VIA has a strange chipset, root port is under a bridge */
+	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
+	    pdev->bus->self)
 		return;
+
 	down_read(&pci_bus_sem);
 	if (list_empty(&pdev->subordinate->devices))
 		goto out;
 
-	blacklist = !!pcie_aspm_sanity_check(pdev);
-
 	mutex_lock(&aspm_lock);
-
-	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
-	if (!link_state)
-		goto unlock_out;
-
-	link_state->downstream_has_switch = pcie_aspm_downstream_has_switch(pdev);
-	INIT_LIST_HEAD(&link_state->children);
-	INIT_LIST_HEAD(&link_state->link);
-	if (pdev->bus->self) {/* this is a switch */
-		struct pcie_link_state *parent_link_state;
-
-		parent_link_state = pdev->bus->parent->self->link_state;
-		if (!parent_link_state) {
-			kfree(link_state);
-			goto unlock_out;
-		}
-		list_add(&link_state->link, &parent_link_state->children);
-		link_state->parent = parent_link_state;
-	}
-
-	pdev->link_state = link_state;
-
-	if (!blacklist) {
-		pcie_aspm_configure_common_clock(pdev);
-		pcie_aspm_cap_init(pdev);
+	link = pcie_aspm_setup_link_state(pdev);
+	if (!link)
+		goto unlock;
+	/*
+	 * Setup initial ASPM state
+	 *
+	 * If link has switch, delay the link config. The leaf link
+	 * initialization will config the whole hierarchy. But we must
+	 * make sure BIOS doesn't set unsupported link state.
+	 */
+	if (pcie_aspm_downstream_has_switch(link)) {
+		state = pcie_aspm_check_state(link, link->aspm_default);
+		__pcie_aspm_config_link(link, state);
 	} else {
-		link_state->enabled_state = PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-		link_state->bios_aspm_state = 0;
-		/* Set support state to 0, so we will disable ASPM later */
-		link_state->support_state = 0;
+		state = policy_to_aspm_state(link);
+		__pcie_aspm_configure_link_state(link, state);
 	}
 
-	link_state->pdev = pdev;
-	list_add(&link_state->sibiling, &link_list);
-
-	if (link_state->downstream_has_switch) {
-		/*
-		 * If link has switch, delay the link config. The leaf link
-		 * initialization will config the whole hierarchy. but we must
-		 * make sure BIOS doesn't set unsupported link state
-		 **/
-		state = pcie_aspm_check_state(pdev, link_state->bios_aspm_state);
-		__pcie_aspm_config_link(pdev, state);
-	} else
-		__pcie_aspm_configure_link_state(pdev,
-			policy_to_aspm_state(pdev));
-
-	pcie_check_clock_pm(pdev, blacklist);
-
-unlock_out:
-	if (error)
-		free_link_state(pdev);
+	/* Setup initial Clock PM state */
+	state = (link->clkpm_capable) ? policy_to_clkpm_state(link) : 0;
+	pcie_set_clkpm(link, state);
+unlock:
 	mutex_unlock(&aspm_lock);
 out:
 	up_read(&pci_bus_sem);
@@ -725,11 +687,11 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
 
 	/* All functions are removed, so just disable ASPM for the link */
 	__pcie_aspm_config_one_dev(parent, 0);
-	list_del(&link_state->sibiling);
+	list_del(&link_state->sibling);
 	list_del(&link_state->link);
 	/* Clock PM is for endpoint device */
 
-	free_link_state(parent);
+	free_link_state(link_state);
 out:
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
@@ -749,7 +711,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
 	 * devices changed PM state, we should recheck if latency meets all
 	 * functions' requirement
 	 */
-	pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+	pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled);
 }
 
 /*
@@ -772,14 +734,12 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
 	link_state = parent->link_state;
-	link_state->support_state &=
-		~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
-	if (state & PCIE_LINK_STATE_CLKPM)
-		link_state->clk_pm_capable = 0;
-
-	__pcie_aspm_configure_link_state(parent, link_state->enabled_state);
-	if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
-		pcie_set_clock_pm(parent, 0);
+	link_state->aspm_support &= ~state;
+	__pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled);
+	if (state & PCIE_LINK_STATE_CLKPM) {
+		link_state->clkpm_capable = 0;
+		pcie_set_clkpm(link_state, 0);
+	}
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
 }
@@ -788,7 +748,6 @@ EXPORT_SYMBOL(pci_disable_link_state);
 static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
 {
 	int i;
-	struct pci_dev *pdev;
 	struct pcie_link_state *link_state;
 
 	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
@@ -802,14 +761,10 @@ static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
 	aspm_policy = i;
-	list_for_each_entry(link_state, &link_list, sibiling) {
-		pdev = link_state->pdev;
-		__pcie_aspm_configure_link_state(pdev,
-			policy_to_aspm_state(pdev));
-		if (link_state->clk_pm_capable &&
-		    link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
-			pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-
+	list_for_each_entry(link_state, &link_list, sibling) {
+		__pcie_aspm_configure_link_state(link_state,
+			policy_to_aspm_state(link_state));
+		pcie_set_clkpm(link_state, policy_to_clkpm_state(link_state));
 	}
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
@@ -838,7 +793,7 @@ static ssize_t link_state_show(struct device *dev,
 	struct pci_dev *pci_device = to_pci_dev(dev);
 	struct pcie_link_state *link_state = pci_device->link_state;
 
-	return sprintf(buf, "%d\n", link_state->enabled_state);
+	return sprintf(buf, "%d\n", link_state->aspm_enabled);
 }
 
 static ssize_t link_state_store(struct device *dev,
@@ -846,7 +801,7 @@ static ssize_t link_state_store(struct device *dev,
 		const char *buf,
 		size_t n)
 {
-	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
 	int state;
 
 	if (n < 1)
@@ -854,7 +809,7 @@ static ssize_t link_state_store(struct device *dev,
 	state = buf[0]-'0';
 	if (state >= 0 && state <= 3) {
 		/* setup link aspm state */
-		pcie_aspm_configure_link_state(pci_device, state);
+		pcie_aspm_configure_link_state(pdev->link_state, state);
 		return n;
 	}
 
@@ -868,7 +823,7 @@ static ssize_t clk_ctl_show(struct device *dev,
 	struct pci_dev *pci_device = to_pci_dev(dev);
 	struct pcie_link_state *link_state = pci_device->link_state;
 
-	return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+	return sprintf(buf, "%d\n", link_state->clkpm_enabled);
 }
 
 static ssize_t clk_ctl_store(struct device *dev,
@@ -876,7 +831,7 @@ static ssize_t clk_ctl_store(struct device *dev,
 		const char *buf,
 		size_t n)
 {
-	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
 	int state;
 
 	if (n < 1)
@@ -885,7 +840,7 @@ static ssize_t clk_ctl_store(struct device *dev,
 
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	pcie_set_clock_pm(pci_device, !!state);
+	pcie_set_clkpm_nocheck(pdev->link_state, !!state);
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
 
@@ -904,10 +859,10 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
 		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
 		return;
 
-	if (link_state->support_state)
+	if (link_state->aspm_support)
 		sysfs_add_file_to_group(&pdev->dev.kobj,
 			&dev_attr_link_state.attr, power_group);
-	if (link_state->clk_pm_capable)
+	if (link_state->clkpm_capable)
 		sysfs_add_file_to_group(&pdev->dev.kobj,
 			&dev_attr_clk_ctl.attr, power_group);
 }
@@ -920,10 +875,10 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
 		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
 		return;
 
-	if (link_state->support_state)
+	if (link_state->aspm_support)
 		sysfs_remove_file_from_group(&pdev->dev.kobj,
 			&dev_attr_link_state.attr, power_group);
-	if (link_state->clk_pm_capable)
+	if (link_state->clkpm_capable)
 		sysfs_remove_file_from_group(&pdev->dev.kobj,
 			&dev_attr_clk_ctl.attr, power_group);
 }

+ 8 - 3
drivers/pci/probe.c

@@ -193,7 +193,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
 		res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
 		if (type == pci_bar_io) {
 			l &= PCI_BASE_ADDRESS_IO_MASK;
-			mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff;
+			mask = PCI_BASE_ADDRESS_IO_MASK & IO_SPACE_LIMIT;
 		} else {
 			l &= PCI_BASE_ADDRESS_MEM_MASK;
 			mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
@@ -237,6 +237,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
 			dev_printk(KERN_DEBUG, &dev->dev,
 				"reg %x 64bit mmio: %pR\n", pos, res);
 		}
+
+		res->flags |= IORESOURCE_MEM_64;
 	} else {
 		sz = pci_size(l, sz, mask);
 
@@ -287,7 +289,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
 	struct resource *res;
 	int i;
 
-	if (!child->parent)	/* It's a host bus, nothing to read */
+	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
 		return;
 
 	if (dev->transparent) {
@@ -362,7 +364,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
 		}
 	}
 	if (base <= limit) {
-		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
+					 IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		if (res->flags & PCI_PREF_RANGE_TYPE_64)
+			res->flags |= IORESOURCE_MEM_64;
 		res->start = base;
 		res->end = limit + 0xfffff;
 		dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",

+ 24 - 0
drivers/pci/quirks.c

@@ -1133,6 +1133,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 			switch (dev->subsystem_device) {
 			case 0x1751: /* M2N notebook */
 			case 0x1821: /* M5N notebook */
+			case 0x1897: /* A6L notebook */
 				asus_hides_smbus = 1;
 			}
 		else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
@@ -1163,6 +1164,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 			switch (dev->subsystem_device) {
 			case 0x12bc: /* HP D330L */
 			case 0x12bd: /* HP D530 */
+			case 0x006a: /* HP Compaq nx9500 */
 				asus_hides_smbus = 1;
 			}
 		else if (dev->device == PCI_DEVICE_ID_INTEL_82875_HB)
@@ -2016,6 +2018,28 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
 			PCI_DEVICE_ID_NX2_5709S,
 			quirk_brcm_570x_limit_vpd);
 
+/* Originally in EDAC sources for i82875P:
+ * Intel tells BIOS developers to hide device 6 which
+ * configures the overflow device access containing
+ * the DRBs - this is where we expose device 6.
+ * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+ */
+static void __devinit quirk_unhide_mch_dev6(struct pci_dev *dev)
+{
+	u8 reg;
+
+	if (pci_read_config_byte(dev, 0xF4, &reg) == 0 && !(reg & 0x02)) {
+		dev_info(&dev->dev, "Enabling MCH 'Overflow' Device\n");
+		pci_write_config_byte(dev, 0xF4, reg | 0x02);
+	}
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
+			quirk_unhide_mch_dev6);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
+			quirk_unhide_mch_dev6);
+
+
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
  * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually

+ 0 - 2
drivers/pci/remove.c

@@ -32,8 +32,6 @@ static void pci_stop_dev(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
-	pci_stop_dev(dev);
-
 	/* Remove the device from the device lists, and prevent any further
 	 * list accesses from this device */
 	down_write(&pci_bus_sem);

+ 1 - 31
drivers/pci/search.c

@@ -29,7 +29,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
 	if (pdev->is_pcie)
 		return NULL;
 	while (1) {
-		if (!pdev->bus->parent)
+		if (pci_is_root_bus(pdev->bus))
 			break;
 		pdev = pdev->bus->self;
 		/* a p2p bridge */
@@ -114,36 +114,6 @@ pci_find_next_bus(const struct pci_bus *from)
 }
 
 #ifdef CONFIG_PCI_LEGACY
-/**
- * pci_find_slot - locate PCI device from a given PCI slot
- * @bus: number of PCI bus on which desired PCI device resides
- * @devfn: encodes number of PCI slot in which the desired PCI
- * device resides and the logical device number within that slot
- * in case of multi-function devices.
- *
- * Given a PCI bus and slot/function number, the desired PCI device
- * is located in system global list of PCI devices.  If the device
- * is found, a pointer to its data structure is returned.  If no
- * device is found, %NULL is returned.
- *
- * NOTE: Do not use this function any more; use pci_get_slot() instead, as
- * the PCI device returned by this function can disappear at any moment in
- * time.
- */
-struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
-{
-	struct pci_dev *dev = NULL;
-
-	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number == bus && dev->devfn == devfn) {
-			pci_dev_put(dev);
-			return dev;
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL(pci_find_slot);
-
 /**
  * pci_find_device - begin or continue searching for a PCI device by vendor/device id
  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids

+ 42 - 11
drivers/pci/setup-bus.c

@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
 		res = list->res;
 		idx = res - &list->dev->resource[0];
 		if (pci_assign_resource(list->dev, idx)) {
-			/* FIXME: get rid of this */
 			res->start = 0;
 			res->end = 0;
 			res->flags = 0;
@@ -143,6 +142,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
 	struct pci_dev *bridge = bus->self;
 	struct pci_bus_region region;
 	u32 l, bu, lu, io_upper16;
+	int pref_mem64;
 
 	if (pci_is_enabled(bridge))
 		return;
@@ -198,16 +198,22 @@ static void pci_setup_bridge(struct pci_bus *bus)
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
 	/* Set up PREF base/limit. */
+	pref_mem64 = 0;
 	bu = lu = 0;
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
+		int width = 8;
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
-		bu = upper_32_bits(region.start);
-		lu = upper_32_bits(region.end);
-		dev_info(&bridge->dev, "  PREFETCH window: %#016llx-%#016llx\n",
-		    (unsigned long long)region.start,
-		    (unsigned long long)region.end);
+		if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
+			pref_mem64 = 1;
+			bu = upper_32_bits(region.start);
+			lu = upper_32_bits(region.end);
+			width = 16;
+		}
+		dev_info(&bridge->dev, "  PREFETCH window: %#0*llx-%#0*llx\n",
+				width, (unsigned long long)region.start,
+				width, (unsigned long long)region.end);
 	}
 	else {
 		l = 0x0000fff0;
@@ -215,9 +221,11 @@ static void pci_setup_bridge(struct pci_bus *bus)
 	}
 	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
-	/* Set the upper 32 bits of PREF base & limit. */
-	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
-	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
+	if (pref_mem64) {
+		/* Set the upper 32 bits of PREF base & limit. */
+		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+		pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
+	}
 
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
@@ -255,8 +263,25 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
 		pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
 		pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
 	}
-	if (pmem)
+	if (pmem) {
 		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64)
+			b_res[2].flags |= IORESOURCE_MEM_64;
+	}
+
+	/* double check if bridge does support 64 bit pref */
+	if (b_res[2].flags & IORESOURCE_MEM_64) {
+		u32 mem_base_hi, tmp;
+		pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+					 &mem_base_hi);
+		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+					       0xffffffff);
+		pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
+		if (!tmp)
+			b_res[2].flags &= ~IORESOURCE_MEM_64;
+		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+				       mem_base_hi);
+	}
 }
 
 /* Helper function for sizing routines: find first available
@@ -336,6 +361,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
+	unsigned int mem64_mask = 0;
 
 	if (!b_res)
 		return 0;
@@ -344,9 +370,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 	max_order = 0;
 	size = 0;
 
+	mem64_mask = b_res->flags & IORESOURCE_MEM_64;
+	b_res->flags &= ~IORESOURCE_MEM_64;
+
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		int i;
-		
+
 		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 			struct resource *r = &dev->resource[i];
 			resource_size_t r_size;
@@ -372,6 +401,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 				aligns[order] += align;
 			if (order > max_order)
 				max_order = order;
+			mem64_mask &= r->flags & IORESOURCE_MEM_64;
 		}
 	}
 
@@ -396,6 +426,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 	b_res->start = min_align;
 	b_res->end = size + min_align - 1;
 	b_res->flags |= IORESOURCE_STARTALIGN;
+	b_res->flags |= mem64_mask;
 	return 1;
 }
 

+ 36 - 13
drivers/pci/setup-res.c

@@ -135,23 +135,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
 }
 #endif	/* CONFIG_PCI_QUIRKS */
 
-int pci_assign_resource(struct pci_dev *dev, int resno)
+static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
+				 int resno)
 {
-	struct pci_bus *bus = dev->bus;
 	struct resource *res = dev->resource + resno;
 	resource_size_t size, min, align;
 	int ret;
 
 	size = resource_size(res);
 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
-
 	align = resource_alignment(res);
-	if (!align) {
-		dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
-			"alignment) %pR flags %#lx\n",
-			resno, res, res->flags);
-		return -EINVAL;
-	}
 
 	/* First, try exact prefetching match.. */
 	ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -169,10 +162,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
 					     pcibios_align_resource, dev);
 	}
 
-	if (ret) {
-		dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
-			resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
-	} else {
+	if (!ret) {
 		res->flags &= ~IORESOURCE_STARTALIGN;
 		if (resno < PCI_BRIDGE_RESOURCES)
 			pci_update_resource(dev, resno);
@@ -181,6 +171,39 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
 	return ret;
 }
 
+int pci_assign_resource(struct pci_dev *dev, int resno)
+{
+	struct resource *res = dev->resource + resno;
+	resource_size_t align;
+	struct pci_bus *bus;
+	int ret;
+
+	align = resource_alignment(res);
+	if (!align) {
+		dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
+			"alignment) %pR flags %#lx\n",
+			resno, res, res->flags);
+		return -EINVAL;
+	}
+
+	bus = dev->bus;
+	while ((ret = __pci_assign_resource(bus, dev, resno))) {
+		if (bus->parent && bus->self->transparent)
+			bus = bus->parent;
+		else
+			bus = NULL;
+		if (bus)
+			continue;
+		break;
+	}
+
+	if (ret)
+		dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+			resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
+
+	return ret;
+}
+
 #if 0
 int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
 {

+ 39 - 0
drivers/pci/slot.c

@@ -307,6 +307,45 @@ void pci_destroy_slot(struct pci_slot *slot)
 }
 EXPORT_SYMBOL_GPL(pci_destroy_slot);
 
+#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
+#include <linux/pci_hotplug.h>
+/**
+ * pci_hp_create_link - create symbolic link to the hotplug driver module.
+ * @slot: struct pci_slot
+ *
+ * Helper function for pci_hotplug_core.c to create symbolic link to
+ * the hotplug driver module.
+ */
+void pci_hp_create_module_link(struct pci_slot *pci_slot)
+{
+	struct hotplug_slot *slot = pci_slot->hotplug;
+	struct kobject *kobj = NULL;
+	int no_warn;
+
+	if (!slot || !slot->ops)
+		return;
+	kobj = kset_find_obj(module_kset, slot->ops->mod_name);
+	if (!kobj)
+		return;
+	no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module");
+	kobject_put(kobj);
+}
+EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
+
+/**
+ * pci_hp_remove_link - remove symbolic link to the hotplug driver module.
+ * @slot: struct pci_slot
+ *
+ * Helper function for pci_hotplug_core.c to remove symbolic link to
+ * the hotplug driver module.
+ */
+void pci_hp_remove_module_link(struct pci_slot *pci_slot)
+{
+	sysfs_remove_link(&pci_slot->kobj, "module");
+}
+EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
+#endif
+
 static int pci_slot_init(void)
 {
 	struct kset *pci_bus_kset;

+ 2 - 0
include/linux/ioport.h

@@ -49,6 +49,8 @@ struct resource_list {
 #define IORESOURCE_SIZEALIGN	0x00020000	/* size indicates alignment */
 #define IORESOURCE_STARTALIGN	0x00040000	/* start field is alignment */
 
+#define IORESOURCE_MEM_64	0x00100000
+
 #define IORESOURCE_EXCLUSIVE	0x08000000	/* Userland may not map this resource */
 #define IORESOURCE_DISABLED	0x10000000
 #define IORESOURCE_UNSET	0x20000000

+ 2 - 2
include/linux/pci-acpi.h

@@ -15,7 +15,7 @@ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
 {
 	struct pci_bus *pbus = pdev->bus;
 	/* Find a PCI root bus */
-	while (pbus->parent)
+	while (!pci_is_root_bus(pbus))
 		pbus = pbus->parent;
 	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
 					      pbus->number);
@@ -23,7 +23,7 @@ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
 
 static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 {
-	if (pbus->parent)
+	if (!pci_is_root_bus(pbus))
 		return DEVICE_ACPI_HANDLE(&(pbus->self->dev));
 	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
 					      pbus->number);

+ 24 - 11
include/linux/pci.h

@@ -607,8 +607,6 @@ extern void pci_sort_breadthfirst(void);
 struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
 					     unsigned int device,
 					     struct pci_dev *from);
-struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
-					   unsigned int devfn);
 #endif /* CONFIG_PCI_LEGACY */
 
 enum pci_lost_interrupt_reason {
@@ -647,6 +645,7 @@ int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
 			      int where, u16 val);
 int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
 			       int where, u32 val);
+struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops);
 
 static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
 {
@@ -711,8 +710,8 @@ int pcix_get_mmrbc(struct pci_dev *dev);
 int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
 int pcie_get_readrq(struct pci_dev *dev);
 int pcie_set_readrq(struct pci_dev *dev, int rq);
+int __pci_reset_function(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev);
-int pci_execute_reset_function(struct pci_dev *dev);
 void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
@@ -732,7 +731,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
 bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
 void pci_pme_active(struct pci_dev *dev, bool enable);
-int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
+int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable);
 int pci_wake_from_d3(struct pci_dev *dev, bool enable);
 pci_power_t pci_target_state(struct pci_dev *dev);
 int pci_prepare_to_sleep(struct pci_dev *dev);
@@ -798,7 +797,7 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
 int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		    int pass);
 
-void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
 		  void *userdata);
 int pci_cfg_space_size_ext(struct pci_dev *dev);
 int pci_cfg_space_size(struct pci_dev *dev);
@@ -888,6 +887,17 @@ static inline int pcie_aspm_enabled(void)
 extern int pcie_aspm_enabled(void);
 #endif
 
+#ifndef CONFIG_PCIE_ECRC
+static inline void pcie_set_ecrc_checking(struct pci_dev *dev)
+{
+	return;
+}
+static inline void pcie_ecrc_get_policy(char *str) {};
+#else
+extern void pcie_set_ecrc_checking(struct pci_dev *dev);
+extern void pcie_ecrc_get_policy(char *str);
+#endif
+
 #define pci_enable_msi(pdev)	pci_enable_msi_block(pdev, 1)
 
 #ifdef CONFIG_HT_IRQ
@@ -944,12 +954,6 @@ static inline struct pci_dev *pci_find_device(unsigned int vendor,
 	return NULL;
 }
 
-static inline struct pci_dev *pci_find_slot(unsigned int bus,
-					    unsigned int devfn)
-{
-	return NULL;
-}
-
 static inline struct pci_dev *pci_get_device(unsigned int vendor,
 					     unsigned int device,
 					     struct pci_dev *from)
@@ -1105,6 +1109,10 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
 
 #include <asm/pci.h>
 
+#ifndef PCIBIOS_MAX_MEM_32
+#define PCIBIOS_MAX_MEM_32 (-1)
+#endif
+
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
 #define pci_resource_start(dev, bar)	((dev)->resource[(bar)].start)
@@ -1261,5 +1269,10 @@ static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev)
 }
 #endif
 
+#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
+extern void pci_hp_create_module_link(struct pci_slot *pci_slot);
+extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */

+ 13 - 10
include/linux/pci_hotplug.h

@@ -66,17 +66,10 @@ enum pcie_link_speed {
 	PCIE_LNK_SPEED_UNKNOWN	= 0xFF,
 };
 
-struct hotplug_slot;
-struct hotplug_slot_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct hotplug_slot *, char *);
-	ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
-};
-#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr);
-
 /**
  * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
  * @owner: The module owner of this structure
+ * @mod_name: The module name (KBUILD_MODNAME) of this structure
  * @enable_slot: Called when the user wants to enable a specific pci slot
  * @disable_slot: Called when the user wants to disable a specific pci slot
  * @set_attention_status: Called to set the specific slot's attention LED to
@@ -109,6 +102,7 @@ struct hotplug_slot_attribute {
  */
 struct hotplug_slot_ops {
 	struct module *owner;
+	const char *mod_name;
 	int (*enable_slot)		(struct hotplug_slot *slot);
 	int (*disable_slot)		(struct hotplug_slot *slot);
 	int (*set_attention_status)	(struct hotplug_slot *slot, u8 value);
@@ -167,12 +161,21 @@ static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
 	return pci_slot_name(slot->pci_slot);
 }
 
-extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr,
-			   const char *name);
+extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus,
+			     int nr, const char *name,
+			     struct module *owner, const char *mod_name);
 extern int pci_hp_deregister(struct hotplug_slot *slot);
 extern int __must_check pci_hp_change_slot_info	(struct hotplug_slot *slot,
 						 struct hotplug_slot_info *info);
 
+static inline int pci_hp_register(struct hotplug_slot *slot,
+				  struct pci_bus *pbus,
+				  int devnr, const char *name)
+{
+	return __pci_hp_register(slot, pbus, devnr, name,
+				 THIS_MODULE, KBUILD_MODNAME);
+}
+
 /* PCI Setting Record (Type 0) */
 struct hpp_type0 {
 	u32 revision;

+ 2 - 2
include/linux/pci_regs.h

@@ -295,8 +295,9 @@
 #define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
 #define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
 #define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
+#define PCI_MSI_MASK_32		12	/* Mask bits register for 32-bit devices */
 #define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_BIT	16	/* Mask bits register */
+#define PCI_MSI_MASK_64		16	/* Mask bits register for 64-bit devices */
 
 /* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
 #define PCI_MSIX_FLAGS		2
@@ -304,7 +305,6 @@
 #define  PCI_MSIX_FLAGS_ENABLE	(1 << 15)
 #define  PCI_MSIX_FLAGS_MASKALL	(1 << 14)
 #define PCI_MSIX_FLAGS_BIRMASK	(7 << 0)
-#define PCI_MSIX_FLAGS_BITMASK	(1 << 0)
 
 /* CompactPCI Hotswap Register */