Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Jun 2009 18:59:51 +0000 (11:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Jun 2009 18:59:51 +0000 (11:59 -0700)
* '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
  ...

55 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/PCI/pcieaer-howto.txt
Documentation/kernel-parameters.txt
arch/powerpc/platforms/pseries/eeh_driver.c
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h
arch/x86/pci/acpi.c
arch/x86/pci/amd_bus.c
arch/x86/pci/common.c
drivers/acpi/Kconfig
drivers/pci/Makefile
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpqphp.h
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_ctrl.c
drivers/pci/hotplug/cpqphp_nvram.c
drivers/pci/hotplug/cpqphp_pci.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pcihp_skeleton.c
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/hotplug/shpchp_core.c
drivers/pci/iov.c
drivers/pci/msi.c
drivers/pci/msi.h
drivers/pci/pci.c
drivers/pci/pcie/aer/Kconfig
drivers/pci/pcie/aer/Kconfig.debug [new file with mode: 0644]
drivers/pci/pcie/aer/Makefile
drivers/pci/pcie/aer/aer_inject.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/ecrc.c [new file with mode: 0644]
drivers/pci/pcie/aspm.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pci/slot.c
include/linux/ioport.h
include/linux/pci-acpi.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/pci_regs.h

index 97ad190e13af0586a528bbb7e6dfb10e748eddcd..6bf68053e4b817491f615c0d36e787e74120bf38 100644 (file)
@@ -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.
index ddeb14beacc8fe8592334ba11303ef6fcd2a7404..be21001ab14475f8f95cafc33dd3dd3efd7ee8e8 100644 (file)
@@ -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.
index 08def8deb5f575652bffad8cc9dc7dded8ca059f..7da0899d1fb9100c383e15385dd95faaa452c9a3 100644 (file)
@@ -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.
index 9a2a6e32f00f6d0a4a89d536d8da22b676b82a4d..0e8db6771252a2f3dcb4c28891e0f6d2958389a0 100644 (file)
@@ -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;
 }
 
 /* ------------------------------------------------------- */
index b51a1e8b0baf4c1c688f45ce5a2cff50b0257a0e..927958d13c1967114ebba7ac6bd8bacc9ddbd56c 100644 (file)
@@ -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 */
index e60fd3e14bdf2c720f3c890f945a80e1828d087b..cb739cc0a08063729fb239d4d6a254f6aee08625 100644 (file)
@@ -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
index c0ecf250fe5166a82f3343b622c1ec0e07119b80..16c3fda85bbad502317bafedc37159bf9847b278 100644 (file)
@@ -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;
 }
index f893d6a6e803e266f3d36030f8744fecda130bf9..2255f880678bb198af08f8fd43452c2e3370167a 100644 (file)
@@ -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 */
index 2202b6257b82b84bb9ef17f33630ca7dac929610..4740119e4bb73389e66ff08ed47e30c7d12c56c6 100644 (file)
@@ -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;
index 431f8b4395538c510eab54399bf6f457fb3f136f..7ec7d88c5999573d169233bbf3c82232f6003dbd 100644 (file)
@@ -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
index b77ae679427503447b26c228d7356b5d1bb9070e..1ebd6b4c743bbe8c5600b68651222b0d1fabaa26 100644 (file)
@@ -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/
index 0f3706512686bb32bd6bf40cd6bf2acdc0bdca49..db23200c487426d6fd9d9b04e53e518b88ebd50f 100644 (file)
@@ -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
index 97a8194063b5d66fd754680a5c94323bec456c8c..cef28a79103f06e9178b9c86419c641cad3b74af 100644 (file)
@@ -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);
 }
index 9aa4fe100a0d03c0b04be379fcea99c266e7d730..66f29bc00be493f32a2f00ae138562a85ef8afc5 100644 (file)
@@ -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.
index 43c10bd261b48612b4ec2fa2620fa14207628805..4dd7114964ac6c85bd3db59e5382241f77c3eeb0 100644 (file)
@@ -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,
index de94f4feef8c58c30c4817957903a5db89d85323..a5b9f6ae507bb5cf23ab4cf614e97c1fa7e2c6d3 100644 (file)
@@ -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,
index afaf8f69f73ec0938f754f427822a929697b79b4..53836001d511e3af1b3e77dc76d64785f8713bf8 100644 (file)
@@ -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
index c2e1bcbb28a79edf262926174d805e23b811015e..075b4f4b6e0d88ab17cc642bb294c96032187624 100644 (file)
@@ -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);
-
-
index cc227a8c4b11911a7a1e25798d29af391ea8cd09..2fa47af992a8281ff1bfb43d5fd0e7c0c7bf2111 100644 (file)
@@ -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 */
index cb174888002ba537ee2884a46fcac24513f1b1fe..76ba8a1c774dfa716d947fc12092e82b8ebfef78 100644 (file)
@@ -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;
index 6c0ed0fcb8eef91d290e05c8d3907cbeed4e295a..6173b9a4544efec9d79ef45f6c67a68a495987d8 100644 (file)
@@ -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));
index 42e4260c3b12311e3793102b76ec136f5f94352e..7485ffda950c013505ff252889647db13e2ca345 100644 (file)
@@ -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);
index 535fce0f07f964edd1ecebc019a4347ec71cb549..844580489d4da56d63dc7015b2320206661a63d4 100644 (file)
@@ -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);
index 0a368547e6339d41ed7a80c08c9c6509d4d57007..e6cf096498be072d008bedeb42108d729771df22 100644 (file)
@@ -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);
index fb254b2454de7345ff4c0e3a73f43e2531e67b8a..2317557fdee637df956ebf957eaf0d09055f46e9 100644 (file)
@@ -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);
-       }
 }
 
 /*
index 07bd321511463653ebe0005ebdf000efd083fe4c..52813257e5bf2fc8cc1b17470529e6b0a44cc970 100644 (file)
@@ -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,
index e3dd6cf9e89f19c7e868ca3fd2ec460cf630e0a3..5175d9b26f0b827f78b405b20bd04a71704a2ab7 100644 (file)
@@ -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,
index 95d02a08fdc7f1a1558a96583043133da5f5071c..c159223389ec47664a3c57fb51e8bb580f66e96a 100644 (file)
@@ -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,
index 2d6da78fddb649849c42f9778b52e6b4ce3e7713..a4494d78e7c2355eaeb27ede4098b65a7b1aaf8e 100644 (file)
@@ -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,
index fe8d149c2293572a2d9e9b0afa68c6959aa43a55..8a520a3d0f59c4be93bc5d5f08e56abb246810d8 100644 (file)
@@ -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,
index b497daab3d4a26ebf5b818bacdcf798fa9d4f9ef..03c7706c0a09a1cf9e6dc8c2d784ba02d9f9f632 100644 (file)
@@ -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);
index 362773247fbfc3586e0025d84e006165c14613e0..d9f06fbfa0bf8fd56051d5f1bd2252fdc52377f8 100644 (file)
@@ -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++) {
index 71f4df2ef65499d84481441be24015f3b0c17398..a0662842550bcb91c008272ba7194f5b97e35388 100644 (file)
 #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 */
index 07bbb9b3b93fe1a46ba4e15dcd4d309d31b54ba9..6c93af5ced186bd9a18faaea77fb0d160d37aba8 100644 (file)
@@ -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);
index c3bde588aa13db4d814785ee24e7bfe86ef4c6c6..50e94e02378ab86b8d730a0e8c4f478f7ae42add 100644 (file)
@@ -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"
diff --git a/drivers/pci/pcie/aer/Kconfig.debug b/drivers/pci/pcie/aer/Kconfig.debug
new file mode 100644 (file)
index 0000000..b8c925c
--- /dev/null
@@ -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/
index 8da3bd8455a882b334cf8d843fa4846cc9153fe3..2cba67510dc862a00979cd9cb9e669105221ff5c 100644 (file)
@@ -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
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
new file mode 100644 (file)
index 0000000..d92ae21
--- /dev/null
@@ -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");
index 32ade5af927e21c11e008be87ae7380c64a1932a..4770f13b3ca182d8381ef95b43805f286ca74d5e 100644 (file)
@@ -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
index aa14482a477923b6185bb3101da39d46622d3d42..bbd7428ca2d0eab8b954d75362a1de54d7906e93 100644 (file)
@@ -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);
index 307452f30035562cea6f290fb0fa1bac34679893..3d8872704a583d4406b3b4c1b5bf68aacfe4ee22 100644 (file)
@@ -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);
 }
 
 /**
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c
new file mode 100644 (file)
index 0000000..ece97df
--- /dev/null
@@ -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;
+}
index b0367f168af4b95ff549bdad6b31fa1a9548e113..3d27c97e0486c9ed5b6d29b3e496723181111b32 100644 (file)
 #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);
 }
index f1ae2475ffffcd827844694c0075448d62cfb3e1..40e75f6a505622fb124085aea0e207bfa4107eae 100644 (file)
@@ -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",
index bd4253f93d5a1f273e7cd947a693e2ef099029dd..56552d74abea1506e9d40df04f7ea0c0e3b3ab5b 100644 (file)
@@ -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
index 86503c14ce7e610119ae8b8f0a1e3f5148a1d0b5..176615e7231f81e13e6b4a4a738c7db3b1841ca8 100644 (file)
@@ -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);
index 710d4ea6956860bdadad1951408ae5999ae68654..e8cb5051c31163536d23880e8a82a66c0577c3b4 100644 (file)
@@ -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
index a00f85471b6ed537cc2d9a67986cb01b543e1733..b636e245445defa08b1b7a03d38d204388d6b717 100644 (file)
@@ -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;
 }
 
index 12403516776a82048acf5de0bda4950c0c0922c6..b711fb7181e241f1a744482d8151fd6ca9beb290 100644 (file)
@@ -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)
 {
index fe95ce20bcbdaed33966dfe2c1c95fa8ddd40d2d..eddb0748b0ea365b9acd4d5898a5547326bf5231 100644 (file)
@@ -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;
index 32e4b2f722949374fdeae6f863af60028a6eecc6..786e7b8cece906bb9d94355a5491bf8ecc17e31e 100644 (file)
@@ -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
index 092e82e0048c969e7b54b17dbd6dcd548969bb6c..93a7c08f869d4fcc7017862505156fdd21e24433 100644 (file)
@@ -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);
index 8e366bb0705fc5e4c386d5dea5b2a71f0bbeb58e..1365c745bdb7df5cb610f487853165455b54d4a0 100644 (file)
@@ -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 */
index 20998746518ecbf8a8cfc9c6086dbf133b9b352d..b3646cd7fd5af6a823aafce45f2c3d8290689ab8 100644 (file)
@@ -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;
index 616bf8b3c8b548707a84b6579b0d31d7f3b840ee..83b02f5a25b2ee89a38f62dba7f2ff1c329aea0e 100644 (file)
 #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
 #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 */