Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Aug 2010 18:44:36 +0000 (11:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Aug 2010 18:44:36 +0000 (11:44 -0700)
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (30 commits)
  PCI: update for owner removal from struct device_attribute
  PCI: Fix warnings when CONFIG_DMI unset
  PCI: Do not run NVidia quirks related to MSI with MSI disabled
  x86/PCI: use for_each_pci_dev()
  PCI: use for_each_pci_dev()
  PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
  PCI: export SMBIOS provided firmware instance and label to sysfs
  PCI: Allow read/write access to sysfs I/O port resources
  x86/PCI: use host bridge _CRS info on ASRock ALiveSATA2-GLAN
  PCI: remove unused HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_{SIZE|BOUNDARY}
  PCI: disable mmio during bar sizing
  PCI: MSI: Remove unsafe and unnecessary hardware access
  PCI: Default PCIe ASPM control to on and require !EMBEDDED to disable
  PCI: kernel oops on access to pci proc file while hot-removal
  PCI: pci-sysfs: remove casts from void*
  ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
  PCI hotplug: make sure child bridges are enabled at hotplug time
  PCI hotplug: shpchp: Removed check for hotplug of display devices
  PCI hotplug: pciehp: Fixed return value sign for pciehp_unconfigure_device
  PCI: Don't enable aspm before drivers have had a chance to veto it
  ...

39 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/filesystems/sysfs-pci.txt
Documentation/kernel-parameters.txt
arch/ia64/kernel/msi_ia64.c
arch/ia64/sn/kernel/msi_sn.c
arch/x86/include/asm/pci_x86.h
arch/x86/kernel/apic/io_apic.c
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/irq.c
arch/x86/pci/legacy.c
drivers/acpi/pci_root.c
drivers/firmware/dmi_scan.c
drivers/net/e1000e/netdev.c
drivers/net/r8169.c
drivers/pci/Makefile
drivers/pci/bus.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/hotplug/shpchp_pci.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-label.c [new file with mode: 0644]
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/setup-irq.c
include/linux/dmi.h
include/linux/msi.h
include/linux/pci.h

index 25be3250f7d66f17c0a4d88974441ced8f4ca633..f979d825d112109e03db36cf44ad170a7743fd06 100644 (file)
@@ -139,3 +139,30 @@ Contact:   linux-pci@vger.kernel.org
 Description:
                This symbolic link points to the PCI hotplug controller driver
                module that manages the hotplug slot.
+
+What:          /sys/bus/pci/devices/.../label
+Date:          July 2010
+Contact:       Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
+Description:
+               Reading this attribute will provide the firmware
+               given name(SMBIOS type 41 string) of the PCI device.
+               The attribute will be created only if the firmware
+               has given a name to the PCI device.
+Users:
+               Userspace applications interested in knowing the
+               firmware assigned name of the PCI device.
+
+What:          /sys/bus/pci/devices/.../index
+Date:          July 2010
+Contact:       Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
+Description:
+               Reading this attribute will provide the firmware
+               given instance(SMBIOS type 41 device type instance)
+               of the PCI device. The attribute will be created
+               only if the firmware has given a device type instance
+               to the PCI device.
+Users:
+               Userspace applications interested in knowing the
+               firmware assigned device type instance of the PCI
+               device that can help in understanding the firmware
+               intended order of the PCI device.
index 85354b32d731cc409dfcc082c30277fefdf11850..74eaac26f8b8c3c4f45b083fe5ffc1b76f5589dd 100644 (file)
@@ -39,7 +39,7 @@ files, each with their own function.
        local_cpus         nearby CPU mask (cpumask, ro)
        remove             remove device from kernel's list (ascii, wo)
        resource                   PCI resource host addresses (ascii, ro)
-       resource0..N       PCI resource N, if present (binary, mmap)
+       resource0..N       PCI resource N, if present (binary, mmap, rw[1])
        resource0_wc..N_wc  PCI WC map resource N, if prefetchable (binary, mmap)
        rom                PCI ROM resource, if present (binary, ro)
        subsystem_device           PCI subsystem device (ascii, ro)
@@ -54,13 +54,16 @@ files, each with their own function.
   binary - file contains binary data
   cpumask - file contains a cpumask type
 
+[1] rw for RESOURCE_IO (I/O port) regions only
+
 The read only files are informational, writes to them will be ignored, with
 the exception of the 'rom' file.  Writable files can be used to perform
 actions on the device (e.g. changing config space, detaching a device).
 mmapable files are available via an mmap of the file at offset 0 and can be
 used to do actual device programming from userspace.  Note that some platforms
 don't support mmapping of certain resources, so be sure to check the return
-value from any attempted mmap.
+value from any attempted mmap.  The most notable of these are I/O port
+resources, which also provide read/write access.
 
 The 'enable' file provides a counter that indicates how many times the device 
 has been enabled.  If the 'enable' file currently returns '4', and a '1' is
index f20c7abc0329ca520d524a5c135a5597a8484086..cbd4059305228a95a1c3a46399ecc7b861da1f77 100644 (file)
@@ -1976,6 +1976,8 @@ and is between 256 and 4096 characters. It is defined in the file
                norom           [X86] Do not assign address space to
                                expansion ROMs that do not already have
                                BIOS assigned address ranges.
+               nobar           [X86] Do not assign address space to the
+                               BARs that weren't assigned by the BIOS.
                irqmask=0xMMMM  [X86] Set a bit mask of IRQs allowed to be
                                assigned automatically to PCI devices. You can
                                make the kernel exclude IRQs of your ISA cards
index 6c89228560493df8d17d6e0f7d1b65d28ee543ad..4a746ea838ff37b423f92f31a8eecc8207f6217a 100644 (file)
@@ -25,7 +25,7 @@ static int ia64_set_msi_irq_affinity(unsigned int irq,
        if (irq_prepare_move(irq, cpu))
                return -1;
 
-       read_msi_msg(irq, &msg);
+       get_cached_msi_msg(irq, &msg);
 
        addr = msg.address_lo;
        addr &= MSI_ADDR_DEST_ID_MASK;
index ebfdd6a9ae1a0ac6401581ab8de42592175a87c5..0c72dd4638314523eeb8a71b6204826fc9777303 100644 (file)
@@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq,
         * Release XIO resources for the old MSI PCI address
         */
 
-       read_msi_msg(irq, &msg);
+       get_cached_msi_msg(irq, &msg);
         sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
        pdev = sn_pdev->pdi_linux_pcidev;
        provider = SN_PCIDEV_BUSPROVIDER(pdev);
index cd2a31dc5fb8e4a956c8c34125534540d51b08f4..49c7219826f918d10dae4f08d4c474988706a6ae 100644 (file)
@@ -30,6 +30,7 @@
 #define PCI_HAS_IO_ECS         0x40000
 #define PCI_NOASSIGN_ROMS      0x80000
 #define PCI_ROOT_NO_CRS                0x100000
+#define PCI_NOASSIGN_BARS      0x200000
 
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;
index e41ed24ab26d5b51490ffa8f9a7c58a653b829d8..4dc0084ec1b108c6325f7df782c5a4b562035f63 100644 (file)
@@ -3397,7 +3397,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
 
        cfg = desc->chip_data;
 
-       read_msi_msg_desc(desc, &msg);
+       get_cached_msi_msg_desc(desc, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
index 2ec04c424a6229f7d830e78fb49f5532b804d212..15466c096ba5f56fabc7f174eabd1c40996e4b6d 100644 (file)
@@ -34,6 +34,15 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
                },
        },
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */
+       /* 2006 AMD HT/VIA system with two host bridges */
+        {
+               .callback = set_use_crs,
+               .ident = "ASRock ALiveSATA2-GLAN",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"),
+                },
+        },
        {}
 };
 
index 215a27ae050d430c0deac4a29f75c08449249c96..a0772af64efbef7de6f230bea7c5ccd47d1c0951 100644 (file)
@@ -125,6 +125,23 @@ void __init dmi_check_skip_isa_align(void)
 static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
 {
        struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
+       struct resource *bar_r;
+       int bar;
+
+       if (pci_probe & PCI_NOASSIGN_BARS) {
+               /*
+               * If the BIOS did not assign the BAR, zero out the
+               * resource so the kernel doesn't attmept to assign
+               * it later on in pci_assign_unassigned_resources
+               */
+               for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
+                       bar_r = &dev->resource[bar];
+                       if (bar_r->start == 0 && bar_r->end != 0) {
+                               bar_r->flags = 0;
+                               bar_r->end = 0;
+                       }
+               }
+       }
 
        if (pci_probe & PCI_NOASSIGN_ROMS) {
                if (rom_r->parent)
@@ -509,6 +526,9 @@ char * __devinit  pcibios_setup(char *str)
        } else if (!strcmp(str, "norom")) {
                pci_probe |= PCI_NOASSIGN_ROMS;
                return NULL;
+       } else if (!strcmp(str, "nobar")) {
+               pci_probe |= PCI_NOASSIGN_BARS;
+               return NULL;
        } else if (!strcmp(str, "assign-busses")) {
                pci_probe |= PCI_ASSIGN_ALL_BUSSES;
                return NULL;
index 9810a0f76c91ccd58491e36051678fcf6dd40ad3..f547ee05f7150aa30a1b3f052e22a6e959e17b5d 100644 (file)
@@ -989,7 +989,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
        dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
 
        /* Update IRQ for all devices with the same pirq value */
-       while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
+       for_each_pci_dev(dev2) {
                pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
                if (!pin)
                        continue;
@@ -1028,7 +1028,7 @@ void __init pcibios_fixup_irqs(void)
        u8 pin;
 
        DBG(KERN_DEBUG "PCI: IRQ fixup\n");
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev) {
                /*
                 * If the BIOS has set an out of range IRQ number, just
                 * ignore it.  Also keep track of which IRQ's are
@@ -1052,7 +1052,7 @@ void __init pcibios_fixup_irqs(void)
                return;
 
        dev = NULL;
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev) {
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
                if (!pin)
                        continue;
index 8d460eaf524f1d6f1a54b3853de221e7b38d9e6d..c89266be6048ec0794d85047eabf7714096cee5d 100644 (file)
@@ -36,7 +36,7 @@ int __init pci_legacy_init(void)
        return 0;
 }
 
-void pcibios_scan_specific_bus(int busn)
+void __devinit pcibios_scan_specific_bus(int busn)
 {
        int devfn;
        long node;
index 4eac59393edc5b13e3c25283f08e6cf899fb61d7..1f67057af2a571991481bb761d157320b9d3f329 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
+#include <linux/pci-aspm.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
@@ -543,6 +544,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
        if (flags != base_flags)
                acpi_pci_osc_support(root, flags);
 
+       status = acpi_pci_osc_control_set(root->device->handle,
+                                         OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
+               pcie_no_aspm();
+       }
+
        pci_acpi_add_bus_pm_notifier(device, root->bus);
        if (device->wakeup.flags.run_wake)
                device_set_run_wake(root->bus->bridge, true);
index d46467271349d79adbabd04a76bb55a7b7cff19f..b3d22d6599901756a694d8eac124cf0326eba399 100644 (file)
@@ -277,6 +277,29 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
        list_add_tail(&dev->list, &dmi_devices);
 }
 
+static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
+                                       int devfn, const char *name)
+{
+       struct dmi_dev_onboard *onboard_dev;
+
+       onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
+       if (!onboard_dev) {
+               printk(KERN_ERR "dmi_save_dev_onboard: out of memory.\n");
+               return;
+       }
+       onboard_dev->instance = instance;
+       onboard_dev->segment = segment;
+       onboard_dev->bus = bus;
+       onboard_dev->devfn = devfn;
+
+       strcpy((char *)&onboard_dev[1], name);
+       onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
+       onboard_dev->dev.name = (char *)&onboard_dev[1];
+       onboard_dev->dev.device_data = onboard_dev;
+
+       list_add(&onboard_dev->dev.list, &dmi_devices);
+}
+
 static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 {
        const u8 *d = (u8*) dm + 5;
@@ -285,6 +308,8 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
        if ((*d & 0x80) == 0)
                return;
 
+       dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
+                            dmi_string_nosave(dm, *(d-1)));
        dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
index 36d31a41632050f7e75d8f79a4ad16e79a02e59c..521c6ee1f32af75a0abb5950d10c941376d60116 100644 (file)
@@ -5825,11 +5825,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 
        e1000_print_device_info(adapter);
 
-       if (pci_dev_run_wake(pdev)) {
-               pm_runtime_set_active(&pdev->dev);
-               pm_runtime_enable(&pdev->dev);
-       }
-       pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
+       if (pci_dev_run_wake(pdev))
+               pm_runtime_put_noidle(&pdev->dev);
 
        return 0;
 
@@ -5875,8 +5872,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        bool down = test_bit(__E1000_DOWN, &adapter->state);
 
-       pm_runtime_get_sync(&pdev->dev);
-
        /*
         * flush_scheduled work may reschedule our watchdog task, so
         * explicitly disable watchdog tasks from being rescheduled
@@ -5901,11 +5896,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
                clear_bit(__E1000_DOWN, &adapter->state);
        unregister_netdev(netdev);
 
-       if (pci_dev_run_wake(pdev)) {
-               pm_runtime_disable(&pdev->dev);
-               pm_runtime_set_suspended(&pdev->dev);
-       }
-       pm_runtime_put_noidle(&pdev->dev);
+       if (pci_dev_run_wake(pdev))
+               pm_runtime_get_noresume(&pdev->dev);
 
        /*
         * Release control of h/w to f/w.  If f/w is AMT enabled, this
index 35540411990d5867f1ed9d44164fc8b7e47a8a11..078bbf4e6f1933f3ee1e95e2c0dccfea92157088 100644 (file)
@@ -3219,11 +3219,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
 
-       if (pci_dev_run_wake(pdev)) {
-               pm_runtime_set_active(&pdev->dev);
-               pm_runtime_enable(&pdev->dev);
-       }
-       pm_runtime_idle(&pdev->dev);
+       if (pci_dev_run_wake(pdev))
+               pm_runtime_put_noidle(&pdev->dev);
 
 out:
        return rc;
@@ -3246,17 +3243,12 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       pm_runtime_get_sync(&pdev->dev);
-
        flush_scheduled_work();
 
        unregister_netdev(dev);
 
-       if (pci_dev_run_wake(pdev)) {
-               pm_runtime_disable(&pdev->dev);
-               pm_runtime_set_suspended(&pdev->dev);
-       }
-       pm_runtime_put_noidle(&pdev->dev);
+       if (pci_dev_run_wake(pdev))
+               pm_runtime_get_noresume(&pdev->dev);
 
        /* restore original MAC address */
        rtl_rar_set(tp, dev->perm_addr);
index 0b51857fbaf74842433d1eddef7b51cb54209ec3..dc1aa09228684b8881241c91fde01111df04bdb1 100644 (file)
@@ -55,6 +55,9 @@ obj-$(CONFIG_MICROBLAZE) += setup-bus.o
 #
 obj-$(CONFIG_ACPI)    += pci-acpi.o
 
+# SMBIOS provided firmware instance and labels
+obj-$(CONFIG_DMI)    += pci-label.o
+
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
 
index 628ea20a884190afbbffff2f80e0faf5cbaade1b..7f0af0e9b826dafa2e64d8302c130ea87e5af00b 100644 (file)
@@ -56,7 +56,7 @@ void pci_bus_remove_resources(struct pci_bus *bus)
        int i;
 
        for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
-               bus->resource[i] = 0;
+               bus->resource[i] = NULL;
 
        list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
                list_del(&bus_res->list);
@@ -240,6 +240,8 @@ void pci_enable_bridges(struct pci_bus *bus)
                if (dev->subordinate) {
                        if (!pci_is_enabled(dev)) {
                                retval = pci_enable_device(dev);
+                               if (retval)
+                                       dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval);
                                pci_set_master(dev);
                        }
                        pci_enable_bridges(dev->subordinate);
index 5317e4d7d96eab58ac6c24a450022ae82a5c13e5..17d10e2e8fb692f2f605fc6a63571df63ff46a14 100644 (file)
@@ -135,7 +135,7 @@ static int __init init_legacy(void)
        struct pci_dev *pdev = NULL;
 
        /* Add existing devices */
-       while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)))
+       for_each_pci_dev(pdev)
                legacy_add_slot(pdev);
 
        /* Be alerted of any new ones */
index 2fce726758d2f1bc0c5d24dff8ca3690707c4a56..a4031dfe938ecd037227896fac3fabe5ca24e56b 100644 (file)
@@ -137,7 +137,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
                                         "Cannot remove display device %s\n",
                                         pci_name(temp));
                                pci_dev_put(temp);
-                               rc = EINVAL;
+                               rc = -EINVAL;
                                break;
                        }
                }
index 5f5e8d2e35529a2ca9ec92be86eda94f28b4e86f..d3985e7deab7db44f8e2674f34da37a810c2d06d 100644 (file)
 #define CON_PFAULT_INTR_MASK   (1 << 28)
 #define MRL_CHANGE_SERR_MASK   (1 << 29)
 #define CON_PFAULT_SERR_MASK   (1 << 30)
-#define SLOT_REG_RSVDZ_MASK    (1 << 15) | (7 << 21)
+#define SLOT_REG_RSVDZ_MASK    ((1 << 15) | (7 << 21))
 
 /*
  * SHPC Command Code definitnions
index 8c3d3219f22777d709ed2eefc6fe1e3cb2b30b9e..a2ccfcd3c29840ea9bfa6384b79e813cba67e21e 100644 (file)
@@ -60,12 +60,6 @@ int __ref shpchp_configure_device(struct slot *p_slot)
                dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
                if (!dev)
                        continue;
-               if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-                       ctrl_err(ctrl, "Cannot hot-add display device %s\n",
-                                pci_name(dev));
-                       pci_dev_put(dev);
-                       continue;
-               }
                if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
                                (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
                        /* Find an unused bus number for the new bridge */
@@ -114,17 +108,11 @@ int shpchp_unconfigure_device(struct slot *p_slot)
        ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
                 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
 
-       for (j=0; j<8 ; j++) {
-               struct pci_devtemp = pci_get_slot(parent,
+       for (j = 0; j < 8 ; j++) {
+               struct pci_dev *temp = pci_get_slot(parent,
                                (p_slot->device << 3) | j);
                if (!temp)
                        continue;
-               if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-                       ctrl_err(ctrl, "Cannot remove display device %s\n",
-                                pci_name(temp));
-                       pci_dev_put(temp);
-                       continue;
-               }
                if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                        pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
                        if (bctl & PCI_BRIDGE_CTL_VGA) {
@@ -132,7 +120,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)
                                         "Cannot remove display device %s\n",
                                         pci_name(temp));
                                pci_dev_put(temp);
-                               continue;
+                               rc = -EINVAL;
+                               break;
                        }
                }
                pci_remove_bus_device(temp);
index 77b68eaf021e43152c4bbd257bd190a4a210473c..69b7be33b3a24768a460843a13c17a88c96a8024 100644 (file)
@@ -196,6 +196,9 @@ void unmask_msi_irq(unsigned int irq)
 void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 {
        struct msi_desc *entry = get_irq_desc_msi(desc);
+
+       BUG_ON(entry->dev->current_state != PCI_D0);
+
        if (entry->msi_attrib.is_msix) {
                void __iomem *base = entry->mask_base +
                        entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
@@ -229,10 +232,32 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
        read_msi_msg_desc(desc, msg);
 }
 
+void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+{
+       struct msi_desc *entry = get_irq_desc_msi(desc);
+
+       /* Assert that the cache is valid, assuming that
+        * valid messages are not all-zeroes. */
+       BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
+                entry->msg.data));
+
+       *msg = entry->msg;
+}
+
+void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       get_cached_msi_msg_desc(desc, msg);
+}
+
 void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 {
        struct msi_desc *entry = get_irq_desc_msi(desc);
-       if (entry->msi_attrib.is_msix) {
+
+       if (entry->dev->current_state != PCI_D0) {
+               /* Don't touch the hardware now */
+       } else if (entry->msi_attrib.is_msix) {
                void __iomem *base;
                base = entry->mask_base +
                        entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
@@ -435,7 +460,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos,
                                                        unsigned nr_entries)
 {
-       unsigned long phys_addr;
+       resource_size_t phys_addr;
        u32 table_offset;
        u8 bir;
 
index f9a0aec3abcf68c1594ee99d082dcab4a6560ff8..8a6f797de8e55af1b3d0380aefb2173b58ab9fa5 100644 (file)
@@ -289,8 +289,26 @@ struct drv_dev_and_id {
 static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
-
-       return ddi->drv->probe(ddi->dev, ddi->id);
+       struct device *dev = &ddi->dev->dev;
+       int rc;
+
+       /* Unbound PCI devices are always set to disabled and suspended.
+        * During probe, the device is set to enabled and active and the
+        * usage count is incremented.  If the driver supports runtime PM,
+        * it should call pm_runtime_put_noidle() in its probe routine and
+        * pm_runtime_get_noresume() in its remove routine.
+        */
+       pm_runtime_get_noresume(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       rc = ddi->drv->probe(ddi->dev, ddi->id);
+       if (rc) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_suspended(dev);
+               pm_runtime_put_noidle(dev);
+       }
+       return rc;
 }
 
 static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
@@ -369,11 +387,19 @@ static int pci_device_remove(struct device * dev)
        struct pci_driver * drv = pci_dev->driver;
 
        if (drv) {
-               if (drv->remove)
+               if (drv->remove) {
+                       pm_runtime_get_sync(dev);
                        drv->remove(pci_dev);
+                       pm_runtime_put_noidle(dev);
+               }
                pci_dev->driver = NULL;
        }
 
+       /* Undo the runtime PM settings in local_pci_probe() */
+       pm_runtime_disable(dev);
+       pm_runtime_set_suspended(dev);
+       pm_runtime_put_noidle(dev);
+
        /*
         * If the device is still on, set the power state as "unknown",
         * since it might change by the next time we load the driver.
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
new file mode 100644 (file)
index 0000000..90c0a72
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Purpose: Export the firmware instance and label associated with
+ * a pci device to sysfs
+ * Copyright (C) 2010 Dell Inc.
+ * by Narendra K <Narendra_K@dell.com>,
+ * Jordan Hargrave <Jordan_Hargrave@dell.com>
+ *
+ * SMBIOS defines type 41 for onboard pci devices. This code retrieves
+ * the instance number and string from the type 41 record and exports
+ * it to sysfs.
+ *
+ * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more
+ * information.
+ */
+
+#include <linux/dmi.h>
+#include <linux/sysfs.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include "pci.h"
+
+enum smbios_attr_enum {
+       SMBIOS_ATTR_NONE = 0,
+       SMBIOS_ATTR_LABEL_SHOW,
+       SMBIOS_ATTR_INSTANCE_SHOW,
+};
+
+static mode_t
+find_smbios_instance_string(struct pci_dev *pdev, char *buf,
+                           enum smbios_attr_enum attribute)
+{
+       const struct dmi_device *dmi;
+       struct dmi_dev_onboard *donboard;
+       int bus;
+       int devfn;
+
+       bus = pdev->bus->number;
+       devfn = pdev->devfn;
+
+       dmi = NULL;
+       while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD,
+                                     NULL, dmi)) != NULL) {
+               donboard = dmi->device_data;
+               if (donboard && donboard->bus == bus &&
+                                       donboard->devfn == devfn) {
+                       if (buf) {
+                               if (attribute == SMBIOS_ATTR_INSTANCE_SHOW)
+                                       return scnprintf(buf, PAGE_SIZE,
+                                                        "%d\n",
+                                                        donboard->instance);
+                               else if (attribute == SMBIOS_ATTR_LABEL_SHOW)
+                                       return scnprintf(buf, PAGE_SIZE,
+                                                        "%s\n",
+                                                        dmi->name);
+                       }
+                       return strlen(dmi->name);
+               }
+       }
+       return 0;
+}
+
+static mode_t
+smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr,
+                            int n)
+{
+       struct device *dev;
+       struct pci_dev *pdev;
+
+       dev = container_of(kobj, struct device, kobj);
+       pdev = to_pci_dev(dev);
+
+       return find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE) ?
+                                          S_IRUGO : 0;
+}
+
+static ssize_t
+smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev;
+       pdev = to_pci_dev(dev);
+
+       return find_smbios_instance_string(pdev, buf,
+                                          SMBIOS_ATTR_LABEL_SHOW);
+}
+
+static ssize_t
+smbiosinstance_show(struct device *dev,
+                   struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev;
+       pdev = to_pci_dev(dev);
+
+       return find_smbios_instance_string(pdev, buf,
+                                          SMBIOS_ATTR_INSTANCE_SHOW);
+}
+
+static struct device_attribute smbios_attr_label = {
+       .attr = {.name = "label", .mode = 0444},
+       .show = smbioslabel_show,
+};
+
+static struct device_attribute smbios_attr_instance = {
+       .attr = {.name = "index", .mode = 0444},
+       .show = smbiosinstance_show,
+};
+
+static struct attribute *smbios_attributes[] = {
+       &smbios_attr_label.attr,
+       &smbios_attr_instance.attr,
+       NULL,
+};
+
+static struct attribute_group smbios_attr_group = {
+       .attrs = smbios_attributes,
+       .is_visible = smbios_instance_string_exist,
+};
+
+static int
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+       if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group))
+               return 0;
+       return -ENODEV;
+}
+
+static void
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+       sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
+}
+
+void pci_create_firmware_label_files(struct pci_dev *pdev)
+{
+       if (!pci_create_smbiosname_file(pdev))
+               ;
+}
+
+void pci_remove_firmware_label_files(struct pci_dev *pdev)
+{
+       pci_remove_smbiosname_file(pdev);
+}
index c9957f68ac9bd574964271b363012aa62c8c8bc3..b5a7d9bfcb24a70523a33793e60d217475fc9a91 100644 (file)
@@ -734,7 +734,7 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
 {
        struct pci_dev *pdev = to_pci_dev(container_of(kobj,
                                                       struct device, kobj));
-       struct resource *res = (struct resource *)attr->private;
+       struct resource *res = attr->private;
        enum pci_mmap_state mmap_type;
        resource_size_t start, end;
        int i;
@@ -778,6 +778,70 @@ pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
        return pci_mmap_resource(kobj, attr, vma, 1);
 }
 
+static ssize_t
+pci_resource_io(struct file *filp, struct kobject *kobj,
+               struct bin_attribute *attr, char *buf,
+               loff_t off, size_t count, bool write)
+{
+       struct pci_dev *pdev = to_pci_dev(container_of(kobj,
+                                                      struct device, kobj));
+       struct resource *res = attr->private;
+       unsigned long port = off;
+       int i;
+
+       for (i = 0; i < PCI_ROM_RESOURCE; i++)
+               if (res == &pdev->resource[i])
+                       break;
+       if (i >= PCI_ROM_RESOURCE)
+               return -ENODEV;
+
+       port += pci_resource_start(pdev, i);
+
+       if (port > pci_resource_end(pdev, i))
+               return 0;
+
+       if (port + count - 1 > pci_resource_end(pdev, i))
+               return -EINVAL;
+
+       switch (count) {
+       case 1:
+               if (write)
+                       outb(*(u8 *)buf, port);
+               else
+                       *(u8 *)buf = inb(port);
+               return 1;
+       case 2:
+               if (write)
+                       outw(*(u16 *)buf, port);
+               else
+                       *(u16 *)buf = inw(port);
+               return 2;
+       case 4:
+               if (write)
+                       outl(*(u32 *)buf, port);
+               else
+                       *(u32 *)buf = inl(port);
+               return 4;
+       }
+       return -EINVAL;
+}
+
+static ssize_t
+pci_read_resource_io(struct file *filp, struct kobject *kobj,
+                    struct bin_attribute *attr, char *buf,
+                    loff_t off, size_t count)
+{
+       return pci_resource_io(filp, kobj, attr, buf, off, count, false);
+}
+
+static ssize_t
+pci_write_resource_io(struct file *filp, struct kobject *kobj,
+                     struct bin_attribute *attr, char *buf,
+                     loff_t off, size_t count)
+{
+       return pci_resource_io(filp, kobj, attr, buf, off, count, true);
+}
+
 /**
  * pci_remove_resource_files - cleanup resource files
  * @pdev: dev to cleanup
@@ -828,6 +892,10 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
                        sprintf(res_attr_name, "resource%d", num);
                        res_attr->mmap = pci_mmap_resource_uc;
                }
+               if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
+                       res_attr->read = pci_read_resource_io;
+                       res_attr->write = pci_write_resource_io;
+               }
                res_attr->attr.name = res_attr_name;
                res_attr->attr.mode = S_IRUSR | S_IWUSR;
                res_attr->size = pci_resource_len(pdev, num);
@@ -1097,6 +1165,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
        if (retval)
                goto err_vga_file;
 
+       pci_create_firmware_label_files(pdev);
+
        return 0;
 
 err_vga_file:
@@ -1164,6 +1234,9 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
                kfree(pdev->rom_attr);
        }
+
+       pci_remove_firmware_label_files(pdev);
+
 }
 
 static int __init pci_sysfs_init(void)
index 130ed1daf0f8db10637649cd47d6c2c5a4673dd7..7fa3cbd742c53bd34a871355320cecc56906277f 100644 (file)
@@ -2312,21 +2312,17 @@ void pci_msi_off(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_msi_off);
 
-#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
 int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
 {
        return dma_set_max_seg_size(&dev->dev, size);
 }
 EXPORT_SYMBOL(pci_set_dma_max_seg_size);
-#endif
 
-#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY
 int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
 {
        return dma_set_seg_boundary(&dev->dev, mask);
 }
 EXPORT_SYMBOL(pci_set_dma_seg_boundary);
-#endif
 
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
index c8b7fd056ccdc3fbd53c798e02b0e89c90d13076..679c39de6a89124e96a36252f32e8ff45991b7aa 100644 (file)
 extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+#ifndef CONFIG_DMI
+static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
+{ return; }
+static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
+{ return; }
+#else
+extern void pci_create_firmware_label_files(struct pci_dev *pdev);
+extern void pci_remove_firmware_label_files(struct pci_dev *pdev);
+#endif
 extern void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef HAVE_PCI_MMAP
 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
index b8b494b3e0d058c0a1f42e51c81ee15e24ed82cb..dda70981b7a6f4ef3f4a29fc84f826111b1d0306 100644 (file)
@@ -31,14 +31,22 @@ source "drivers/pci/pcie/aer/Kconfig"
 # PCI Express ASPM
 #
 config PCIEASPM
-       bool "PCI Express ASPM support(Experimental)"
-       depends on PCI && EXPERIMENTAL && PCIEPORTBUS
-       default n
+       bool "PCI Express ASPM control" if EMBEDDED
+       depends on PCI && PCIEPORTBUS
+       default y
        help
-         This enables PCI Express ASPM (Active State Power Management) and
-         Clock Power Management. ASPM supports state L0/L0s/L1.
+         This enables OS control over PCI Express ASPM (Active State
+         Power Management) and Clock Power Management. ASPM supports
+         state L0/L0s/L1.
 
-         When in doubt, say N.
+         ASPM is initially set up the the firmware. With this option enabled,
+         Linux can modify this state in order to disable ASPM on known-bad
+         hardware or configurations and enable it when known-safe.
+
+         ASPM can be disabled or enabled at runtime via
+         /sys/module/pcie_aspm/parameters/policy
+
+         When in doubt, say Y.
 config PCIEASPM_DEBUG
        bool "Debug PCI Express ASPM"
        depends on PCIEASPM
index 8af4f619bba2ceb8871e4b34674ab0678c988c4b..fc0b5a93e1deaf3895ef671ae1f30892980c9352 100644 (file)
@@ -727,20 +727,21 @@ static void aer_isr_one_error(struct pcie_device *p_device,
 static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
 {
        unsigned long flags;
-       int ret = 0;
 
        /* Lock access to Root error producer/consumer index */
        spin_lock_irqsave(&rpc->e_lock, flags);
-       if (rpc->prod_idx != rpc->cons_idx) {
-               *e_src = rpc->e_sources[rpc->cons_idx];
-               rpc->cons_idx++;
-               if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
-                       rpc->cons_idx = 0;
-               ret = 1;
+       if (rpc->prod_idx == rpc->cons_idx) {
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return 0;
        }
+
+       *e_src = rpc->e_sources[rpc->cons_idx];
+       rpc->cons_idx++;
+       if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
+               rpc->cons_idx = 0;
        spin_unlock_irqrestore(&rpc->e_lock, flags);
 
-       return ret;
+       return 1;
 }
 
 /**
index be53d98fa38466992e762ca029d7c32007998d88..71222814c1ecf602880352d8cb3df7ff7930d5db 100644 (file)
@@ -588,11 +588,23 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
         * update through pcie_aspm_cap_init().
         */
        pcie_aspm_cap_init(link, blacklist);
-       pcie_config_aspm_path(link);
 
        /* Setup initial Clock PM state */
        pcie_clkpm_cap_init(link, blacklist);
-       pcie_set_clkpm(link, policy_to_clkpm_state(link));
+
+       /*
+        * At this stage drivers haven't had an opportunity to change the
+        * link policy setting. Enabling ASPM on broken hardware can cripple
+        * it even before the driver has had a chance to disable ASPM, so
+        * default to a safe level right now. If we're enabling ASPM beyond
+        * the BIOS's expectation, we'll do so once pci_enable_device() is
+        * called.
+        */
+       if (aspm_policy != POLICY_POWERSAVE) {
+               pcie_config_aspm_path(link);
+               pcie_set_clkpm(link, policy_to_clkpm_state(link));
+       }
+
 unlock:
        mutex_unlock(&aspm_lock);
 out:
index f4adba2d1dd3e6671b08c3a3ccb156a841829dfa..12625d90f8b573785f1a05a0a719fad46aa3155f 100644 (file)
@@ -163,9 +163,16 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        struct resource *res, unsigned int pos)
 {
        u32 l, sz, mask;
+       u16 orig_cmd;
 
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
+       if (!dev->mmio_always_on) {
+               pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
+               pci_write_config_word(dev, PCI_COMMAND,
+                       orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+       }
+
        res->name = pci_name(dev);
 
        pci_read_config_dword(dev, pos, &l);
@@ -173,6 +180,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        pci_read_config_dword(dev, pos, &sz);
        pci_write_config_dword(dev, pos, l);
 
+       if (!dev->mmio_always_on)
+               pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
+
        /*
         * All bits set in sz means the device isn't working properly.
         * If the BAR isn't implemented, all bits must be 0.  If it's a
index 449e890267a2bae74de8a2b6b0bedf30023b7de0..01f0306525a504a7ed2a9f954f7376e06170c57e 100644 (file)
@@ -431,8 +431,6 @@ int pci_proc_detach_device(struct pci_dev *dev)
        struct proc_dir_entry *e;
 
        if ((e = dev->procent)) {
-               if (atomic_read(&e->count) > 1)
-                       return -EBUSY;
                remove_proc_entry(e->name, dev->bus->procdir);
                dev->procent = NULL;
        }
@@ -485,9 +483,9 @@ static int __init pci_proc_init(void)
        proc_create("devices", 0, proc_bus_pci_dir,
                    &proc_bus_pci_dev_operations);
        proc_initialized = 1;
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev)
                pci_proc_attach_device(dev);
-       }
+
        return 0;
 }
 
index a0c20d9e83966af1a4c5b72bffcc2247ea568535..89ed181cd90cd9cd68506a212eb423ba60f9c8e2 100644 (file)
@@ -91,6 +91,19 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment);
 
+/*
+ * Decoding should be disabled for a PCI device during BAR sizing to avoid
+ * conflict. But doing so may cause problems on host bridge and perhaps other
+ * key system devices. For devices that need to have mmio decoding always-on,
+ * we need to set the dev->mmio_always_on bit.
+ */
+static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
+{
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+               dev->mmio_always_on = 1;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on);
+
 /* The Mellanox Tavor device gives false positive parity errors
  * Mark this device with a broken_parity_status, to allow
  * PCI scanning code to "skip" this now blacklisted device.
@@ -2121,6 +2134,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disabl
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
 
 /* Disable MSI on chipsets that are known to not support it */
 static void __devinit quirk_disable_msi(struct pci_dev *dev)
@@ -2132,12 +2146,29 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev)
        }
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
 
+/*
+ * The APC bridge device in AMD 780 family northbridges has some random
+ * OEM subsystem ID in its vendor ID register (erratum 18), so instead
+ * we use the possible vendor/device IDs of the host bridge for the
+ * declared quirk, and search for the APC bridge by slot number.
+ */
+static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
+{
+       struct pci_dev *apc_bridge;
+
+       apc_bridge = pci_get_slot(host_bridge->bus, PCI_DEVFN(1, 0));
+       if (apc_bridge) {
+               if (apc_bridge->device == 0x9602)
+                       quirk_disable_msi(apc_bridge);
+               pci_dev_put(apc_bridge);
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9600, quirk_amd_780_apc_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
+
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
 static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
@@ -2396,6 +2427,9 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
        int pos;
        int found;
 
+       if (!pci_msi_enabled())
+               return;
+
        /* check if there is HT MSI cap or enabled on this device */
        found = ht_check_msi_mapping(dev);
 
@@ -2748,7 +2782,7 @@ static int __init pci_apply_final_quirks(void)
                printk(KERN_DEBUG "PCI: CLS %u bytes\n",
                       pci_cache_line_size << 2);
 
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev) {
                pci_fixup_device(pci_fixup_final, dev);
                /*
                 * If arch hasn't set it explicitly yet, use the CLS
index 20d03f7722890807b5a128a2032878180794435d..9d75dc8ca602995826b80c842e40edfea1a2d866 100644 (file)
@@ -169,7 +169,7 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
 {
        struct pci_dev *dev = NULL;
 
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev) {
                if (pci_domain_nr(dev->bus) == domain &&
                    (dev->bus->number == bus && dev->devfn == devfn))
                        return dev;
index 19b111383f62fe63c9859dfd509de2cda3801d9e..66cb8f4cc5f4b37fbfc965fda9c63fc1fb1da913 100644 (file)
@@ -874,19 +874,16 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
 again:
        pci_bus_size_bridges(parent);
        __pci_bridge_assign_resources(bridge, &head);
-       retval = pci_reenable_device(bridge);
-       pci_set_master(bridge);
-       pci_enable_bridges(parent);
 
        tried_times++;
 
        if (!head.next)
-               return;
+               goto enable_all;
 
        if (tried_times >= 2) {
                /* still fail, don't need to try more */
                free_failed_list(&head);
-               return;
+               goto enable_all;
        }
 
        printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
@@ -919,5 +916,10 @@ again:
        free_failed_list(&head);
 
        goto again;
+
+enable_all:
+       retval = pci_reenable_device(bridge);
+       pci_set_master(bridge);
+       pci_enable_bridges(parent);
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
index aa795fd428ded07fd01d25755fe6680e6091041c..eec9738f34927c7a3b87c6f9d647a5c3b1207877 100644 (file)
@@ -59,7 +59,6 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(struct pci_dev *, u8, u8))
 {
        struct pci_dev *dev = NULL;
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev)
                pdev_fixup_irq(dev, swizzle, map_irq);
-       }
 }
index a8a3e1ac281dfb1cb27df81200fb2055d6c71ae4..90e087f8d951808724a1207de64681f556216bf1 100644 (file)
@@ -20,6 +20,7 @@ enum dmi_device_type {
        DMI_DEV_TYPE_SAS,
        DMI_DEV_TYPE_IPMI = -1,
        DMI_DEV_TYPE_OEM_STRING = -2,
+       DMI_DEV_TYPE_DEV_ONBOARD = -3,
 };
 
 struct dmi_header {
@@ -37,6 +38,14 @@ struct dmi_device {
 
 #ifdef CONFIG_DMI
 
+struct dmi_dev_onboard {
+       struct dmi_device dev;
+       int instance;
+       int segment;
+       int bus;
+       int devfn;
+};
+
 extern int dmi_check_system(const struct dmi_system_id *list);
 const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
 extern const char * dmi_get_system_info(int field);
index 6991ab5b24d1bbfd736df4d27315a83ee7271779..91b05c171854f12488e92c8fe2d23812bb1f03e5 100644 (file)
@@ -14,8 +14,10 @@ struct irq_desc;
 extern void mask_msi_irq(unsigned int irq);
 extern void unmask_msi_irq(unsigned int irq);
 extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
+extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
 extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
 extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
+extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
 
 struct msi_desc {
index f26fda76b87fc66816f2fa286e97d760c545f165..b1d17956a1536ff9f1e913cc6f33410f2e54cfa8 100644 (file)
@@ -270,6 +270,8 @@ struct pci_dev {
        unsigned int    d1_support:1;   /* Low power state D1 is supported */
        unsigned int    d2_support:1;   /* Low power state D2 is supported */
        unsigned int    no_d1d2:1;      /* Only allow D0 and D3 */
+       unsigned int    mmio_always_on:1;       /* disallow turning off io/mem
+                                                  decoding during bar sizing */
        unsigned int    wakeup_prepared:1;
        unsigned int    d3_delay;       /* D3->D0 transition time in ms */