diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 14:24:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 14:24:19 -0400 |
commit | 8e2c4f2844c0e8dcdfe312e5f2204854ca8532c6 (patch) | |
tree | f846fcbf6b756b76834e06e412a8248bbfb55b32 | |
parent | 6a5d263866d699ebf6843105497afc86ee53de5b (diff) | |
parent | 72800360fdd782eda3489e555adf3b6b3abc064a (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.c | 5 | ||||
-rw-r--r-- | drivers/pci/bus.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 14 | ||||
-rw-r--r-- | drivers/pci/iov.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 4 | ||||
-rw-r--r-- | drivers/pci/probe.c | 2 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 62 | ||||
-rw-r--r-- | drivers/pci/setup-bus.c | 2 | ||||
-rw-r--r-- | include/linux/pci.h | 5 |
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 | |||
310 | acpi_pci_slot_remove(acpi_handle handle) | 312 | acpi_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 | */ |
845 | int pci_reenable_device(struct pci_dev *dev) | 845 | int 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 | */ |
1043 | void pci_disable_enabled_device(struct pci_dev *dev) | 1043 | void 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 | */ |
1223 | unsigned int __devinit pci_rescan_bus(struct pci_bus *bus) | 1223 | unsigned 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 | */ |
45 | static void __devinit quirk_resource_alignment(struct pci_dev *dev) | 45 | static 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 | */ | ||
2425 | static 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 | } | ||
2460 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); | ||
2461 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); | ||
2462 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); | ||
2463 | |||
2464 | #endif /* CONFIG_PCI_IOV */ | ||
2465 | |||
2414 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2466 | static 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 *); | |||
674 | int __must_check pcim_enable_device(struct pci_dev *pdev); | 674 | int __must_check pcim_enable_device(struct pci_dev *pdev); |
675 | void pcim_pin_device(struct pci_dev *pdev); | 675 | void pcim_pin_device(struct pci_dev *pdev); |
676 | 676 | ||
677 | static inline int pci_is_enabled(struct pci_dev *pdev) | ||
678 | { | ||
679 | return (atomic_read(&pdev->enable_cnt) > 0); | ||
680 | } | ||
681 | |||
677 | static inline int pci_is_managed(struct pci_dev *pdev) | 682 | static inline int pci_is_managed(struct pci_dev *pdev) |
678 | { | 683 | { |
679 | return pdev->is_managed; | 684 | return pdev->is_managed; |