aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 14:24:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 14:24:19 -0400
commit8e2c4f2844c0e8dcdfe312e5f2204854ca8532c6 (patch)
treef846fcbf6b756b76834e06e412a8248bbfb55b32
parent6a5d263866d699ebf6843105497afc86ee53de5b (diff)
parent72800360fdd782eda3489e555adf3b6b3abc064a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* '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
-rw-r--r--drivers/acpi/pci_slot.c5
-rw-r--r--drivers/pci/bus.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c14
-rw-r--r--drivers/pci/iov.c1
-rw-r--r--drivers/pci/pci-sysfs.c6
-rw-r--r--drivers/pci/pci.c4
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/quirks.c62
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--include/linux/pci.h5
10 files changed, 88 insertions, 15 deletions
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index cd1f4467be7b..12158e0d009b 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -164,6 +164,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
164 list_add(&slot->list, &slot_list); 164 list_add(&slot->list, &slot_list);
165 mutex_unlock(&slot_list_lock); 165 mutex_unlock(&slot_list_lock);
166 166
167 get_device(&pci_bus->dev);
168
167 dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n", 169 dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
168 pci_slot, pci_bus->number, device, name); 170 pci_slot, pci_bus->number, device, name);
169 171
@@ -310,12 +312,15 @@ static void
310acpi_pci_slot_remove(acpi_handle handle) 312acpi_pci_slot_remove(acpi_handle handle)
311{ 313{
312 struct acpi_pci_slot *slot, *tmp; 314 struct acpi_pci_slot *slot, *tmp;
315 struct pci_bus *pbus;
313 316
314 mutex_lock(&slot_list_lock); 317 mutex_lock(&slot_list_lock);
315 list_for_each_entry_safe(slot, tmp, &slot_list, list) { 318 list_for_each_entry_safe(slot, tmp, &slot_list, list) {
316 if (slot->root_handle == handle) { 319 if (slot->root_handle == handle) {
317 list_del(&slot->list); 320 list_del(&slot->list);
321 pbus = slot->pci_slot->bus;
318 pci_destroy_slot(slot->pci_slot); 322 pci_destroy_slot(slot->pci_slot);
323 put_device(&pbus->dev);
319 kfree(slot); 324 kfree(slot);
320 } 325 }
321 } 326 }
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 68f91a252595..97a8194063b5 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
184 184
185 list_for_each_entry(dev, &bus->devices, bus_list) { 185 list_for_each_entry(dev, &bus->devices, bus_list) {
186 if (dev->subordinate) { 186 if (dev->subordinate) {
187 if (atomic_read(&dev->enable_cnt) == 0) { 187 if (!pci_is_enabled(dev)) {
188 retval = pci_enable_device(dev); 188 retval = pci_enable_device(dev);
189 pci_set_master(dev); 189 pci_set_master(dev);
190 } 190 }
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 803d9ddd6e75..a33794d9e0dc 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -38,6 +38,8 @@
38 * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() 38 * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
39 * when the bridge is scanned and it loses a refcount when the bridge 39 * when the bridge is scanned and it loses a refcount when the bridge
40 * is removed. 40 * is removed.
41 * - When a P2P bridge is present, we elevate the refcount on the subordinate
42 * bus. It loses the refcount when the the driver unloads.
41 */ 43 */
42 44
43#include <linux/init.h> 45#include <linux/init.h>
@@ -440,6 +442,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
440 goto err; 442 goto err;
441 } 443 }
442 444
445 /*
446 * Grab a ref to the subordinate PCI bus in case the bus is
447 * removed via PCI core logical hotplug. The ref pins the bus
448 * (which we access during module unload).
449 */
450 get_device(&bridge->pci_bus->dev);
443 spin_lock_init(&bridge->res_lock); 451 spin_lock_init(&bridge->res_lock);
444 452
445 init_bridge_misc(bridge); 453 init_bridge_misc(bridge);
@@ -619,6 +627,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
619 slot = next; 627 slot = next;
620 } 628 }
621 629
630 /*
631 * Only P2P bridges have a pci_dev
632 */
633 if (bridge->pci_dev)
634 put_device(&bridge->pci_bus->dev);
635
622 pci_dev_put(bridge->pci_dev); 636 pci_dev_put(bridge->pci_dev);
623 list_del(&bridge->list); 637 list_del(&bridge->list);
624 kfree(bridge); 638 kfree(bridge);
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 7227efc760db..b497daab3d4a 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -631,6 +631,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
631/** 631/**
632 * pci_enable_sriov - enable the SR-IOV capability 632 * pci_enable_sriov - enable the SR-IOV capability
633 * @dev: the PCI device 633 * @dev: the PCI device
634 * @nr_virtfn: number of virtual functions to enable
634 * 635 *
635 * Returns 0 on success, or negative on failure. 636 * Returns 0 on success, or negative on failure.
636 */ 637 */
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index e9a8706a6401..a7eb1b46a5a8 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
148 return -EPERM; 148 return -EPERM;
149 149
150 if (!val) { 150 if (!val) {
151 if (atomic_read(&pdev->enable_cnt) != 0) 151 if (pci_is_enabled(pdev))
152 pci_disable_device(pdev); 152 pci_disable_device(pdev);
153 else 153 else
154 result = -EIO; 154 result = -EIO;
@@ -277,14 +277,10 @@ remove_store(struct device *dev, struct device_attribute *dummy,
277{ 277{
278 int ret = 0; 278 int ret = 0;
279 unsigned long val; 279 unsigned long val;
280 struct pci_dev *pdev = to_pci_dev(dev);
281 280
282 if (strict_strtoul(buf, 0, &val) < 0) 281 if (strict_strtoul(buf, 0, &val) < 0)
283 return -EINVAL; 282 return -EINVAL;
284 283
285 if (pci_is_root_bus(pdev->bus))
286 return -EBUSY;
287
288 /* An attribute cannot be unregistered by one of its own methods, 284 /* An attribute cannot be unregistered by one of its own methods,
289 * so we have to use this roundabout approach. 285 * so we have to use this roundabout approach.
290 */ 286 */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 445fb6f7ea3f..16fd0d4c3166 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
844 */ 844 */
845int pci_reenable_device(struct pci_dev *dev) 845int pci_reenable_device(struct pci_dev *dev)
846{ 846{
847 if (atomic_read(&dev->enable_cnt)) 847 if (pci_is_enabled(dev))
848 return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); 848 return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
849 return 0; 849 return 0;
850} 850}
@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
1042 */ 1042 */
1043void pci_disable_enabled_device(struct pci_dev *dev) 1043void pci_disable_enabled_device(struct pci_dev *dev)
1044{ 1044{
1045 if (atomic_read(&dev->enable_cnt)) 1045 if (pci_is_enabled(dev))
1046 do_pci_disable_device(dev); 1046 do_pci_disable_device(dev);
1047} 1047}
1048 1048
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e2f3dd098cfa..8eb50dffb78a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1220,7 +1220,7 @@ EXPORT_SYMBOL(pci_scan_bus_parented);
1220 * 1220 *
1221 * Returns the max number of subordinate bus discovered. 1221 * Returns the max number of subordinate bus discovered.
1222 */ 1222 */
1223unsigned int __devinit pci_rescan_bus(struct pci_bus *bus) 1223unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1224{ 1224{
1225 unsigned int max; 1225 unsigned int max;
1226 struct pci_dev *dev; 1226 struct pci_dev *dev;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 9b2f0d96900d..0254741bece0 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -36,17 +36,18 @@ EXPORT_SYMBOL(pcie_mch_quirk);
36 36
37#ifdef CONFIG_PCI_QUIRKS 37#ifdef CONFIG_PCI_QUIRKS
38/* 38/*
39 * This quirk function disables the device and releases resources 39 * This quirk function disables memory decoding and releases memory resources
40 * which is specified by kernel's boot parameter 'pci=resource_alignment='. 40 * of the device specified by kernel's boot parameter 'pci=resource_alignment='.
41 * It also rounds up size to specified alignment. 41 * It also rounds up size to specified alignment.
42 * Later on, the kernel will assign page-aligned memory resource back 42 * Later on, the kernel will assign page-aligned memory resource back
43 * to that device. 43 * to the device.
44 */ 44 */
45static void __devinit quirk_resource_alignment(struct pci_dev *dev) 45static void __devinit quirk_resource_alignment(struct pci_dev *dev)
46{ 46{
47 int i; 47 int i;
48 struct resource *r; 48 struct resource *r;
49 resource_size_t align, size; 49 resource_size_t align, size;
50 u16 command;
50 51
51 if (!pci_is_reassigndev(dev)) 52 if (!pci_is_reassigndev(dev))
52 return; 53 return;
@@ -58,8 +59,11 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
58 return; 59 return;
59 } 60 }
60 61
61 dev_info(&dev->dev, "Disabling device and release resources.\n"); 62 dev_info(&dev->dev,
62 pci_disable_device(dev); 63 "Disabling memory decoding and releasing memory resources.\n");
64 pci_read_config_word(dev, PCI_COMMAND, &command);
65 command &= ~PCI_COMMAND_MEMORY;
66 pci_write_config_word(dev, PCI_COMMAND, command);
63 67
64 align = pci_specified_resource_alignment(dev); 68 align = pci_specified_resource_alignment(dev);
65 for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { 69 for (i=0; i < PCI_BRIDGE_RESOURCES; i++) {
@@ -2411,6 +2415,54 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
2411 2415
2412#endif /* CONFIG_PCI_MSI */ 2416#endif /* CONFIG_PCI_MSI */
2413 2417
2418#ifdef CONFIG_PCI_IOV
2419
2420/*
2421 * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
2422 * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
2423 * old Flash Memory Space.
2424 */
2425static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
2426{
2427 int pos, flags;
2428 u32 bar, start, size;
2429
2430 if (PAGE_SIZE > 0x10000)
2431 return;
2432
2433 flags = pci_resource_flags(dev, 0);
2434 if ((flags & PCI_BASE_ADDRESS_SPACE) !=
2435 PCI_BASE_ADDRESS_SPACE_MEMORY ||
2436 (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
2437 PCI_BASE_ADDRESS_MEM_TYPE_32)
2438 return;
2439
2440 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
2441 if (!pos)
2442 return;
2443
2444 pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
2445 if (bar & PCI_BASE_ADDRESS_MEM_MASK)
2446 return;
2447
2448 start = pci_resource_start(dev, 1);
2449 size = pci_resource_len(dev, 1);
2450 if (!start || size != 0x400000 || start & (size - 1))
2451 return;
2452
2453 pci_resource_flags(dev, 1) = 0;
2454 pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
2455 pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
2456 pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
2457
2458 dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
2459}
2460DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
2461DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
2462DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
2463
2464#endif /* CONFIG_PCI_IOV */
2465
2414static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, 2466static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
2415 struct pci_fixup *end) 2467 struct pci_fixup *end)
2416{ 2468{
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 334285a8e237..8d9da9d30a61 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
144 struct pci_bus_region region; 144 struct pci_bus_region region;
145 u32 l, bu, lu, io_upper16; 145 u32 l, bu, lu, io_upper16;
146 146
147 if (!pci_is_root_bus(bus) && bus->is_added) 147 if (pci_is_enabled(bridge))
148 return; 148 return;
149 149
150 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", 150 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a7fe4bbd7ff1..72698d89e767 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
674int __must_check pcim_enable_device(struct pci_dev *pdev); 674int __must_check pcim_enable_device(struct pci_dev *pdev);
675void pcim_pin_device(struct pci_dev *pdev); 675void pcim_pin_device(struct pci_dev *pdev);
676 676
677static inline int pci_is_enabled(struct pci_dev *pdev)
678{
679 return (atomic_read(&pdev->enable_cnt) > 0);
680}
681
677static inline int pci_is_managed(struct pci_dev *pdev) 682static inline int pci_is_managed(struct pci_dev *pdev)
678{ 683{
679 return pdev->is_managed; 684 return pdev->is_managed;