Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Feb 2009 03:28:58 +0000 (19:28 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Feb 2009 03:28:58 +0000 (19:28 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
  PCI hotplug: Change link order of pciehp & acpiphp
  PCI hotplug: fakephp: Allocate PCI resources before adding the device
  PCI MSI: Fix undefined shift by 32
  PCI PM: Do not wait for buses in B2 or B3 during resume
  PCI PM: Power up devices before restoring their state
  PCI PM: Fix hibernation breakage on EeePC 701
  PCI: irq and pci_ids patch for Intel Tigerpoint DeviceIDs
  PCI PM: Fix suspend error paths and testing facility breakage

arch/x86/pci/irq.c
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/fakephp.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
include/linux/pci_ids.h

index 4064345..fecbce6 100644 (file)
@@ -572,6 +572,7 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
        case PCI_DEVICE_ID_INTEL_ICH7_1:
        case PCI_DEVICE_ID_INTEL_ICH7_30:
        case PCI_DEVICE_ID_INTEL_ICH7_31:
+       case PCI_DEVICE_ID_INTEL_TGP_LPC:
        case PCI_DEVICE_ID_INTEL_ESB2_0:
        case PCI_DEVICE_ID_INTEL_ICH8_0:
        case PCI_DEVICE_ID_INTEL_ICH8_1:
index e31fb91..2aa117c 100644 (file)
@@ -5,11 +5,15 @@
 obj-$(CONFIG_HOTPLUG_PCI)              += pci_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)       += cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)          += ibmphp.o
+
+# pciehp should be linked before acpiphp in order to allow the native driver
+# to attempt to bind first. We can then fall back to generic support.
+
+obj-$(CONFIG_HOTPLUG_PCI_PCIE)         += pciehp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)     += acpiphp_ibm.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)  += cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
-obj-$(CONFIG_HOTPLUG_PCI_PCIE)         += pciehp.o
 obj-$(CONFIG_HOTPLUG_PCI_SHPC)         += shpchp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA)          += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)    += rpadlpar_io.o
index b0e7de9..d8649e1 100644 (file)
@@ -195,13 +195,13 @@ static void remove_slot_worker(struct work_struct *work)
  * Tries hard not to re-enable already existing devices;
  * also handles scanning of subfunctions.
  */
-static void pci_rescan_slot(struct pci_dev *temp)
+static int pci_rescan_slot(struct pci_dev *temp)
 {
        struct pci_bus *bus = temp->bus;
        struct pci_dev *dev;
        int func;
-       int retval;
        u8 hdr_type;
+       int count = 0;
 
        if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
                temp->hdr_type = hdr_type & 0x7f;
@@ -213,17 +213,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                dbg("New device on %s function %x:%x\n",
                                        bus->name, temp->devfn >> 3,
                                        temp->devfn & 7);
-                               retval = pci_bus_add_device(dev);
-                               if (retval)
-                                       dev_err(&dev->dev, "error adding "
-                                               "device, continuing.\n");
-                               else
-                                       add_slot(dev);
+                               count++;
                        }
                }
                /* multifunction device? */
                if (!(hdr_type & 0x80))
-                       return;
+                       return count;
 
                /* continue scanning for other functions */
                for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) {
@@ -239,16 +234,13 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                        dbg("New device on %s function %x:%x\n",
                                                bus->name, temp->devfn >> 3,
                                                temp->devfn & 7);
-                                       retval = pci_bus_add_device(dev);
-                                       if (retval)
-                                               dev_err(&dev->dev, "error adding "
-                                                       "device, continuing.\n");
-                                       else
-                                               add_slot(dev);
+                                       count++;
                                }
                        }
                }
        }
+
+       return count;
 }
 
 
@@ -262,6 +254,8 @@ static void pci_rescan_bus(const struct pci_bus *bus)
 {
        unsigned int devfn;
        struct pci_dev *dev;
+       int retval;
+       int found = 0;
        dev = alloc_pci_dev();
        if (!dev)
                return;
@@ -270,7 +264,23 @@ static void pci_rescan_bus(const struct pci_bus *bus)
        dev->sysdata = bus->sysdata;
        for (devfn = 0; devfn < 0x100; devfn += 8) {
                dev->devfn = devfn;
-               pci_rescan_slot(dev);
+               found += pci_rescan_slot(dev);
+       }
+
+       if (found) {
+               pci_bus_assign_resources(bus);
+               list_for_each_entry(dev, &bus->devices, bus_list) {
+                       /* Skip already-added devices */
+                       if (dev->is_added)
+                                       continue;
+                       retval = pci_bus_add_device(dev);
+                       if (retval)
+                               dev_err(&dev->dev,
+                                       "Error adding device, continuing\n");
+                       else
+                               add_slot(dev);
+               }
+               pci_bus_add_devices(bus);
        }
        kfree(dev);
 }
index 896a15d..44f15ff 100644 (file)
@@ -103,6 +103,16 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
        }
 }
 
+/*
+ * Essentially, this is ((1 << (1 << x)) - 1), but without the
+ * undefinedness of a << 32.
+ */
+static inline __attribute_const__ u32 msi_mask(unsigned x)
+{
+       static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff };
+       return mask[x];
+}
+
 static void msix_flush_writes(struct irq_desc *desc)
 {
        struct msi_desc *entry;
@@ -407,8 +417,7 @@ static int msi_capability_init(struct pci_dev *dev)
 
                /* All MSIs are unmasked by default, Mask them all */
                pci_read_config_dword(dev, base, &maskbits);
-               temp = (1 << multi_msi_capable(control));
-               temp = ((temp - 1) & ~temp);
+               temp = msi_mask((control & PCI_MSI_FLAGS_QMASK) >> 1);
                maskbits |= temp;
                pci_write_config_dword(dev, base, maskbits);
                entry->msi_attrib.maskbits_mask = temp;
index 9de07b7..ab1d615 100644 (file)
@@ -370,6 +370,7 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
        }
 
        pci_save_state(pci_dev);
+       pci_dev->state_saved = true;
        /*
         * This is for compatibility with existing code with legacy PM support.
         */
@@ -419,6 +420,7 @@ static int pci_legacy_resume(struct device *dev)
 static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
 {
        pci_restore_standard_config(pci_dev);
+       pci_dev->state_saved = false;
        pci_fixup_device(pci_fixup_resume_early, pci_dev);
 }
 
@@ -555,6 +557,13 @@ static int pci_pm_resume(struct device *dev)
        struct device_driver *drv = dev->driver;
        int error = 0;
 
+       /*
+        * This is necessary for the suspend error path in which resume is
+        * called without restoring the standard config registers of the device.
+        */
+       if (pci_dev->state_saved)
+               pci_restore_standard_config(pci_dev);
+
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_resume(dev);
 
@@ -660,7 +669,10 @@ static int pci_pm_poweroff(struct device *dev)
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_suspend(dev, PMSG_HIBERNATE);
 
-       if (drv && drv->pm && drv->pm->poweroff) {
+       if (!drv || !drv->pm)
+               return 0;
+
+       if (drv->pm->poweroff) {
                error = drv->pm->poweroff(dev);
                suspend_report_result(drv->pm->poweroff, error);
        }
@@ -710,6 +722,13 @@ static int pci_pm_restore(struct device *dev)
        struct device_driver *drv = dev->driver;
        int error = 0;
 
+       /*
+        * This is necessary for the hibernation error path in which restore is
+        * called without restoring the standard config registers of the device.
+        */
+       if (pci_dev->state_saved)
+               pci_restore_standard_config(pci_dev);
+
        if (pci_has_legacy_pm_support(pci_dev))
                return pci_legacy_resume(dev);
 
index 17bd932..4880755 100644 (file)
@@ -1393,35 +1393,35 @@ int pci_restore_standard_config(struct pci_dev *dev)
        pci_power_t prev_state;
        int error;
 
-       pci_restore_state(dev);
        pci_update_current_state(dev, PCI_D0);
 
        prev_state = dev->current_state;
        if (prev_state == PCI_D0)
-               return 0;
+               goto Restore;
 
        error = pci_raw_set_power_state(dev, PCI_D0, false);
        if (error)
                return error;
 
-       if (pci_is_bridge(dev)) {
-               if (prev_state > PCI_D1)
-                       mdelay(PCI_PM_BUS_WAIT);
-       } else {
-               switch(prev_state) {
-               case PCI_D3cold:
-               case PCI_D3hot:
-                       mdelay(pci_pm_d3_delay);
-                       break;
-               case PCI_D2:
-                       udelay(PCI_PM_D2_DELAY);
-                       break;
-               }
+       /*
+        * This assumes that we won't get a bus in B2 or B3 from the BIOS, but
+        * we've made this assumption forever and it appears to be universally
+        * satisfied.
+        */
+       switch(prev_state) {
+       case PCI_D3cold:
+       case PCI_D3hot:
+               mdelay(pci_pm_d3_delay);
+               break;
+       case PCI_D2:
+               udelay(PCI_PM_D2_DELAY);
+               break;
        }
 
        dev->current_state = PCI_D0;
 
-       return 0;
+ Restore:
+       return pci_restore_state(dev);
 }
 
 /**
index febc10e..52a9fe0 100644 (file)
 #define PCI_DEVICE_ID_INTEL_ICH7_0     0x27b8
 #define PCI_DEVICE_ID_INTEL_ICH7_1     0x27b9
 #define PCI_DEVICE_ID_INTEL_ICH7_30    0x27b0
+#define PCI_DEVICE_ID_INTEL_TGP_LPC    0x27bc
 #define PCI_DEVICE_ID_INTEL_ICH7_31    0x27bd
 #define PCI_DEVICE_ID_INTEL_ICH7_17    0x27da
 #define PCI_DEVICE_ID_INTEL_ICH7_19    0x27dd