]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 18:24:19 +0000 (11:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 18:24:19 +0000 (11:24 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
  PCI: pci_slot: grab refcount on slot's bus
  PCI Hotplug: acpiphp: grab refcount on p2p subordinate bus
  PCI: allow PCI core hotplug to remove PCI root bus
  PCI: Fix oops in pci_vpd_truncate
  PCI: don't corrupt enable_cnt when doing manual resource alignment
  PCI: annotate pci_rescan_bus as __ref, not __devinit
  PCI-IOV: fix missing kernel-doc
  PCI: Setup disabled bridges even if buses are added
  PCI: SR-IOV quirk for Intel 82576 NIC

drivers/acpi/pci_slot.c
drivers/pci/bus.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/iov.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
include/linux/pci.h

index cd1f4467be7ba828162246d0596175652e8e7a25..12158e0d009bc9fe8cd9fee9867500a84a0804a3 100644 (file)
@@ -164,6 +164,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        list_add(&slot->list, &slot_list);
        mutex_unlock(&slot_list_lock);
 
+       get_device(&pci_bus->dev);
+
        dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
                pci_slot, pci_bus->number, device, name);
 
@@ -310,12 +312,15 @@ static void
 acpi_pci_slot_remove(acpi_handle handle)
 {
        struct acpi_pci_slot *slot, *tmp;
+       struct pci_bus *pbus;
 
        mutex_lock(&slot_list_lock);
        list_for_each_entry_safe(slot, tmp, &slot_list, list) {
                if (slot->root_handle == handle) {
                        list_del(&slot->list);
+                       pbus = slot->pci_slot->bus;
                        pci_destroy_slot(slot->pci_slot);
+                       put_device(&pbus->dev);
                        kfree(slot);
                }
        }
index 68f91a25259563c6bb7250d8ea3acfd636ad0b29..97a8194063b5d66fd754680a5c94323bec456c8c 100644 (file)
@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                if (dev->subordinate) {
-                       if (atomic_read(&dev->enable_cnt) == 0) {
+                       if (!pci_is_enabled(dev)) {
                                retval = pci_enable_device(dev);
                                pci_set_master(dev);
                        }
index 803d9ddd6e75f0fb2334c905c89c6f626657e656..a33794d9e0dce60d3ae57948122e1e53efa57aa5 100644 (file)
@@ -38,6 +38,8 @@
  *  - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
  *    when the bridge is scanned and it loses a refcount when the bridge
  *    is removed.
+ *  - When a P2P bridge is present, we elevate the refcount on the subordinate
+ *    bus. It loses the refcount when the the driver unloads.
  */
 
 #include <linux/init.h>
@@ -440,6 +442,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
                goto err;
        }
 
+       /*
+        * Grab a ref to the subordinate PCI bus in case the bus is
+        * removed via PCI core logical hotplug. The ref pins the bus
+        * (which we access during module unload).
+        */
+       get_device(&bridge->pci_bus->dev);
        spin_lock_init(&bridge->res_lock);
 
        init_bridge_misc(bridge);
@@ -619,6 +627,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
                slot = next;
        }
 
+       /*
+        * Only P2P bridges have a pci_dev
+        */
+       if (bridge->pci_dev)
+               put_device(&bridge->pci_bus->dev);
+
        pci_dev_put(bridge->pci_dev);
        list_del(&bridge->list);
        kfree(bridge);
index 7227efc760dbae2841225ff5e7a10438e56898e0..b497daab3d4a26ebf5b818bacdcf798fa9d4f9ef 100644 (file)
@@ -631,6 +631,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
 /**
  * pci_enable_sriov - enable the SR-IOV capability
  * @dev: the PCI device
+ * @nr_virtfn: number of virtual functions to enable
  *
  * Returns 0 on success, or negative on failure.
  */
index e9a8706a640182de0da0257cf2d82b590245eaf5..a7eb1b46a5a849b1c18f6d40fa15030b68a53d95 100644 (file)
@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
                return -EPERM;
 
        if (!val) {
-               if (atomic_read(&pdev->enable_cnt) != 0)
+               if (pci_is_enabled(pdev))
                        pci_disable_device(pdev);
                else
                        result = -EIO;
@@ -277,14 +277,10 @@ remove_store(struct device *dev, struct device_attribute *dummy,
 {
        int ret = 0;
        unsigned long val;
-       struct pci_dev *pdev = to_pci_dev(dev);
 
        if (strict_strtoul(buf, 0, &val) < 0)
                return -EINVAL;
 
-       if (pci_is_root_bus(pdev->bus))
-               return -EBUSY;
-
        /* An attribute cannot be unregistered by one of its own methods,
         * so we have to use this roundabout approach.
         */
index 445fb6f7ea3fa01dc79beabc6d5685c48fa064fe..16fd0d4c316655dbcfb8729f82a9aef5cabb7e8c 100644 (file)
@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
  */
 int pci_reenable_device(struct pci_dev *dev)
 {
-       if (atomic_read(&dev->enable_cnt))
+       if (pci_is_enabled(dev))
                return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
        return 0;
 }
@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
  */
 void pci_disable_enabled_device(struct pci_dev *dev)
 {
-       if (atomic_read(&dev->enable_cnt))
+       if (pci_is_enabled(dev))
                do_pci_disable_device(dev);
 }
 
index e2f3dd098cfa16c710814dcffbb1f294f7197b0c..8eb50dffb78a177c02954442074d97118261db3c 100644 (file)
@@ -1220,7 +1220,7 @@ EXPORT_SYMBOL(pci_scan_bus_parented);
  *
  * Returns the max number of subordinate bus discovered.
  */
-unsigned int __devinit pci_rescan_bus(struct pci_bus *bus)
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
 {
        unsigned int max;
        struct pci_dev *dev;
index 9b2f0d96900def68ff56606f27e056e6d77dff7d..0254741bece0827fa70e7a74143c2953b6538546 100644 (file)
@@ -36,17 +36,18 @@ EXPORT_SYMBOL(pcie_mch_quirk);
 
 #ifdef CONFIG_PCI_QUIRKS
 /*
- * This quirk function disables the device and releases resources
- * which is specified by kernel's boot parameter 'pci=resource_alignment='.
+ * This quirk function disables memory decoding and releases memory resources
+ * of the device specified by kernel's boot parameter 'pci=resource_alignment='.
  * It also rounds up size to specified alignment.
  * Later on, the kernel will assign page-aligned memory resource back
- * to that device.
+ * to the device.
  */
 static void __devinit quirk_resource_alignment(struct pci_dev *dev)
 {
        int i;
        struct resource *r;
        resource_size_t align, size;
+       u16 command;
 
        if (!pci_is_reassigndev(dev))
                return;
@@ -58,8 +59,11 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
                return;
        }
 
-       dev_info(&dev->dev, "Disabling device and release resources.\n");
-       pci_disable_device(dev);
+       dev_info(&dev->dev,
+               "Disabling memory decoding and releasing memory resources.\n");
+       pci_read_config_word(dev, PCI_COMMAND, &command);
+       command &= ~PCI_COMMAND_MEMORY;
+       pci_write_config_word(dev, PCI_COMMAND, command);
 
        align = pci_specified_resource_alignment(dev);
        for (i=0; i < PCI_BRIDGE_RESOURCES; i++) {
@@ -2411,6 +2415,54 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
 
 #endif /* CONFIG_PCI_MSI */
 
+#ifdef CONFIG_PCI_IOV
+
+/*
+ * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
+ * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
+ * old Flash Memory Space.
+ */
+static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
+{
+       int pos, flags;
+       u32 bar, start, size;
+
+       if (PAGE_SIZE > 0x10000)
+               return;
+
+       flags = pci_resource_flags(dev, 0);
+       if ((flags & PCI_BASE_ADDRESS_SPACE) !=
+                       PCI_BASE_ADDRESS_SPACE_MEMORY ||
+           (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
+                       PCI_BASE_ADDRESS_MEM_TYPE_32)
+               return;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
+       if (!pos)
+               return;
+
+       pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
+       if (bar & PCI_BASE_ADDRESS_MEM_MASK)
+               return;
+
+       start = pci_resource_start(dev, 1);
+       size = pci_resource_len(dev, 1);
+       if (!start || size != 0x400000 || start & (size - 1))
+               return;
+
+       pci_resource_flags(dev, 1) = 0;
+       pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
+       pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
+       pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
+
+       dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
+
+#endif /* CONFIG_PCI_IOV */
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                          struct pci_fixup *end)
 {
index 334285a8e23760f7b36eda595e9ef7aa0da0ecf4..8d9da9d30a61ffcd058c352f22cc6baab8f9e9a4 100644 (file)
@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
        struct pci_bus_region region;
        u32 l, bu, lu, io_upper16;
 
-       if (!pci_is_root_bus(bus) && bus->is_added)
+       if (pci_is_enabled(bridge))
                return;
 
        dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
index a7fe4bbd7ff1f7be9eb28952bffd8802c55e6ff8..72698d89e767c76909fb0b4cdb65f292c93e0b76 100644 (file)
@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
 int __must_check pcim_enable_device(struct pci_dev *pdev);
 void pcim_pin_device(struct pci_dev *pdev);
 
+static inline int pci_is_enabled(struct pci_dev *pdev)
+{
+       return (atomic_read(&pdev->enable_cnt) > 0);
+}
+
 static inline int pci_is_managed(struct pci_dev *pdev)
 {
        return pdev->is_managed;