diff options
25 files changed, 209 insertions, 44 deletions
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 36bed5a12750..c17f90d0f73c 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
| @@ -369,7 +369,9 @@ static void *eeh_rmv_device(void *data, void *userdata) | |||
| 369 | edev->mode |= EEH_DEV_DISCONNECTED; | 369 | edev->mode |= EEH_DEV_DISCONNECTED; |
| 370 | (*removed)++; | 370 | (*removed)++; |
| 371 | 371 | ||
| 372 | pci_lock_rescan_remove(); | ||
| 372 | pci_stop_and_remove_bus_device(dev); | 373 | pci_stop_and_remove_bus_device(dev); |
| 374 | pci_unlock_rescan_remove(); | ||
| 373 | 375 | ||
| 374 | return NULL; | 376 | return NULL; |
| 375 | } | 377 | } |
| @@ -416,10 +418,13 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
| 416 | * into pcibios_add_pci_devices(). | 418 | * into pcibios_add_pci_devices(). |
| 417 | */ | 419 | */ |
| 418 | eeh_pe_state_mark(pe, EEH_PE_KEEP); | 420 | eeh_pe_state_mark(pe, EEH_PE_KEEP); |
| 419 | if (bus) | 421 | if (bus) { |
| 422 | pci_lock_rescan_remove(); | ||
| 420 | pcibios_remove_pci_devices(bus); | 423 | pcibios_remove_pci_devices(bus); |
| 421 | else if (frozen_bus) | 424 | pci_unlock_rescan_remove(); |
| 425 | } else if (frozen_bus) { | ||
| 422 | eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed); | 426 | eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed); |
| 427 | } | ||
| 423 | 428 | ||
| 424 | /* Reset the pci controller. (Asserts RST#; resets config space). | 429 | /* Reset the pci controller. (Asserts RST#; resets config space). |
| 425 | * Reconfigure bridges and devices. Don't try to bring the system | 430 | * Reconfigure bridges and devices. Don't try to bring the system |
| @@ -429,6 +434,8 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
| 429 | if (rc) | 434 | if (rc) |
| 430 | return rc; | 435 | return rc; |
| 431 | 436 | ||
| 437 | pci_lock_rescan_remove(); | ||
| 438 | |||
| 432 | /* Restore PE */ | 439 | /* Restore PE */ |
| 433 | eeh_ops->configure_bridge(pe); | 440 | eeh_ops->configure_bridge(pe); |
| 434 | eeh_pe_restore_bars(pe); | 441 | eeh_pe_restore_bars(pe); |
| @@ -462,6 +469,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
| 462 | pe->tstamp = tstamp; | 469 | pe->tstamp = tstamp; |
| 463 | pe->freeze_count = cnt; | 470 | pe->freeze_count = cnt; |
| 464 | 471 | ||
| 472 | pci_unlock_rescan_remove(); | ||
| 465 | return 0; | 473 | return 0; |
| 466 | } | 474 | } |
| 467 | 475 | ||
| @@ -618,8 +626,11 @@ perm_error: | |||
| 618 | eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); | 626 | eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); |
| 619 | 627 | ||
| 620 | /* Shut down the device drivers for good. */ | 628 | /* Shut down the device drivers for good. */ |
| 621 | if (frozen_bus) | 629 | if (frozen_bus) { |
| 630 | pci_lock_rescan_remove(); | ||
| 622 | pcibios_remove_pci_devices(frozen_bus); | 631 | pcibios_remove_pci_devices(frozen_bus); |
| 632 | pci_unlock_rescan_remove(); | ||
| 633 | } | ||
| 623 | } | 634 | } |
| 624 | 635 | ||
| 625 | static void eeh_handle_special_event(void) | 636 | static void eeh_handle_special_event(void) |
| @@ -692,6 +703,7 @@ static void eeh_handle_special_event(void) | |||
| 692 | if (rc == 2 || rc == 1) | 703 | if (rc == 2 || rc == 1) |
| 693 | eeh_handle_normal_event(pe); | 704 | eeh_handle_normal_event(pe); |
| 694 | else { | 705 | else { |
| 706 | pci_lock_rescan_remove(); | ||
| 695 | list_for_each_entry_safe(hose, tmp, | 707 | list_for_each_entry_safe(hose, tmp, |
| 696 | &hose_list, list_node) { | 708 | &hose_list, list_node) { |
| 697 | phb_pe = eeh_phb_pe_get(hose); | 709 | phb_pe = eeh_phb_pe_get(hose); |
| @@ -703,6 +715,7 @@ static void eeh_handle_special_event(void) | |||
| 703 | eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); | 715 | eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); |
| 704 | pcibios_remove_pci_devices(bus); | 716 | pcibios_remove_pci_devices(bus); |
| 705 | } | 717 | } |
| 718 | pci_unlock_rescan_remove(); | ||
| 706 | } | 719 | } |
| 707 | } | 720 | } |
| 708 | 721 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0703bff5e60e..07ee02aa3c51 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -596,7 +596,9 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 596 | pci_assign_unassigned_root_bus_resources(root->bus); | 596 | pci_assign_unassigned_root_bus_resources(root->bus); |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | pci_lock_rescan_remove(); | ||
| 599 | pci_bus_add_devices(root->bus); | 600 | pci_bus_add_devices(root->bus); |
| 601 | pci_unlock_rescan_remove(); | ||
| 600 | return 1; | 602 | return 1; |
| 601 | 603 | ||
| 602 | end: | 604 | end: |
| @@ -608,6 +610,8 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
| 608 | { | 610 | { |
| 609 | struct acpi_pci_root *root = acpi_driver_data(device); | 611 | struct acpi_pci_root *root = acpi_driver_data(device); |
| 610 | 612 | ||
| 613 | pci_lock_rescan_remove(); | ||
| 614 | |||
| 611 | pci_stop_root_bus(root->bus); | 615 | pci_stop_root_bus(root->bus); |
| 612 | 616 | ||
| 613 | device_set_run_wake(root->bus->bridge, false); | 617 | device_set_run_wake(root->bus->bridge, false); |
| @@ -615,6 +619,8 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
| 615 | 619 | ||
| 616 | pci_remove_root_bus(root->bus); | 620 | pci_remove_root_bus(root->bus); |
| 617 | 621 | ||
| 622 | pci_unlock_rescan_remove(); | ||
| 623 | |||
| 618 | kfree(root); | 624 | kfree(root); |
| 619 | } | 625 | } |
| 620 | 626 | ||
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 767ff4d839f4..570b18a113ff 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -346,7 +346,7 @@ static int mpt_remove_dead_ioc_func(void *arg) | |||
| 346 | if ((pdev == NULL)) | 346 | if ((pdev == NULL)) |
| 347 | return -1; | 347 | return -1; |
| 348 | 348 | ||
| 349 | pci_stop_and_remove_bus_device(pdev); | 349 | pci_stop_and_remove_bus_device_locked(pdev); |
| 350 | return 0; | 350 | return 0; |
| 351 | } | 351 | } |
| 352 | 352 | ||
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 1592dbe4f904..b6162be4df40 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -77,6 +77,8 @@ struct acpiphp_bridge { | |||
| 77 | 77 | ||
| 78 | /* PCI-to-PCI bridge device */ | 78 | /* PCI-to-PCI bridge device */ |
| 79 | struct pci_dev *pci_dev; | 79 | struct pci_dev *pci_dev; |
| 80 | |||
| 81 | bool is_going_away; | ||
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| 82 | 84 | ||
| @@ -150,6 +152,7 @@ struct acpiphp_attention_info | |||
| 150 | /* slot flags */ | 152 | /* slot flags */ |
| 151 | 153 | ||
| 152 | #define SLOT_ENABLED (0x00000001) | 154 | #define SLOT_ENABLED (0x00000001) |
| 155 | #define SLOT_IS_GOING_AWAY (0x00000002) | ||
| 153 | 156 | ||
| 154 | /* function flags */ | 157 | /* function flags */ |
| 155 | 158 | ||
| @@ -169,7 +172,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | |||
| 169 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 172 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
| 170 | 173 | ||
| 171 | int acpiphp_enable_slot(struct acpiphp_slot *slot); | 174 | int acpiphp_enable_slot(struct acpiphp_slot *slot); |
| 172 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | 175 | int acpiphp_disable_slot(struct acpiphp_slot *slot); |
| 173 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); | 176 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); |
| 174 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); | 177 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); |
| 175 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); | 178 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index dca66bc44578..728c31f4c2c5 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
| @@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
| 157 | 157 | ||
| 158 | /* disable the specified slot */ | 158 | /* disable the specified slot */ |
| 159 | return acpiphp_disable_and_eject_slot(slot->acpi_slot); | 159 | return acpiphp_disable_slot(slot->acpi_slot); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | 162 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1cf605f67673..641ba6761bd7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -430,6 +430,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 430 | pr_err("failed to remove notify handler\n"); | 430 | pr_err("failed to remove notify handler\n"); |
| 431 | } | 431 | } |
| 432 | } | 432 | } |
| 433 | slot->flags |= SLOT_IS_GOING_AWAY; | ||
| 433 | if (slot->slot) | 434 | if (slot->slot) |
| 434 | acpiphp_unregister_hotplug_slot(slot); | 435 | acpiphp_unregister_hotplug_slot(slot); |
| 435 | } | 436 | } |
| @@ -437,6 +438,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 437 | mutex_lock(&bridge_mutex); | 438 | mutex_lock(&bridge_mutex); |
| 438 | list_del(&bridge->list); | 439 | list_del(&bridge->list); |
| 439 | mutex_unlock(&bridge_mutex); | 440 | mutex_unlock(&bridge_mutex); |
| 441 | |||
| 442 | bridge->is_going_away = true; | ||
| 440 | } | 443 | } |
| 441 | 444 | ||
| 442 | /** | 445 | /** |
| @@ -736,6 +739,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
| 736 | { | 739 | { |
| 737 | struct acpiphp_slot *slot; | 740 | struct acpiphp_slot *slot; |
| 738 | 741 | ||
| 742 | /* Bail out if the bridge is going away. */ | ||
| 743 | if (bridge->is_going_away) | ||
| 744 | return; | ||
| 745 | |||
| 739 | list_for_each_entry(slot, &bridge->slots, node) { | 746 | list_for_each_entry(slot, &bridge->slots, node) { |
| 740 | struct pci_bus *bus = slot->bus; | 747 | struct pci_bus *bus = slot->bus; |
| 741 | struct pci_dev *dev, *tmp; | 748 | struct pci_dev *dev, *tmp; |
| @@ -805,6 +812,8 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
| 805 | } | 812 | } |
| 806 | } | 813 | } |
| 807 | 814 | ||
| 815 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | ||
| 816 | |||
| 808 | static void hotplug_event(acpi_handle handle, u32 type, void *data) | 817 | static void hotplug_event(acpi_handle handle, u32 type, void *data) |
| 809 | { | 818 | { |
| 810 | struct acpiphp_context *context = data; | 819 | struct acpiphp_context *context = data; |
| @@ -834,6 +843,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 834 | } else { | 843 | } else { |
| 835 | struct acpiphp_slot *slot = func->slot; | 844 | struct acpiphp_slot *slot = func->slot; |
| 836 | 845 | ||
| 846 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 847 | break; | ||
| 848 | |||
| 837 | mutex_lock(&slot->crit_sect); | 849 | mutex_lock(&slot->crit_sect); |
| 838 | enable_slot(slot); | 850 | enable_slot(slot); |
| 839 | mutex_unlock(&slot->crit_sect); | 851 | mutex_unlock(&slot->crit_sect); |
| @@ -849,6 +861,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 849 | struct acpiphp_slot *slot = func->slot; | 861 | struct acpiphp_slot *slot = func->slot; |
| 850 | int ret; | 862 | int ret; |
| 851 | 863 | ||
| 864 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 865 | break; | ||
| 866 | |||
| 852 | /* | 867 | /* |
| 853 | * Check if anything has changed in the slot and rescan | 868 | * Check if anything has changed in the slot and rescan |
| 854 | * from the parent if that's the case. | 869 | * from the parent if that's the case. |
| @@ -878,9 +893,11 @@ static void hotplug_event_work(void *data, u32 type) | |||
| 878 | acpi_handle handle = context->handle; | 893 | acpi_handle handle = context->handle; |
| 879 | 894 | ||
| 880 | acpi_scan_lock_acquire(); | 895 | acpi_scan_lock_acquire(); |
| 896 | pci_lock_rescan_remove(); | ||
| 881 | 897 | ||
| 882 | hotplug_event(handle, type, context); | 898 | hotplug_event(handle, type, context); |
| 883 | 899 | ||
| 900 | pci_unlock_rescan_remove(); | ||
| 884 | acpi_scan_lock_release(); | 901 | acpi_scan_lock_release(); |
| 885 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 902 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); |
| 886 | put_bridge(context->func.parent); | 903 | put_bridge(context->func.parent); |
| @@ -1048,12 +1065,19 @@ void acpiphp_remove_slots(struct pci_bus *bus) | |||
| 1048 | */ | 1065 | */ |
| 1049 | int acpiphp_enable_slot(struct acpiphp_slot *slot) | 1066 | int acpiphp_enable_slot(struct acpiphp_slot *slot) |
| 1050 | { | 1067 | { |
| 1068 | pci_lock_rescan_remove(); | ||
| 1069 | |||
| 1070 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 1071 | return -ENODEV; | ||
| 1072 | |||
| 1051 | mutex_lock(&slot->crit_sect); | 1073 | mutex_lock(&slot->crit_sect); |
| 1052 | /* configure all functions */ | 1074 | /* configure all functions */ |
| 1053 | if (!(slot->flags & SLOT_ENABLED)) | 1075 | if (!(slot->flags & SLOT_ENABLED)) |
| 1054 | enable_slot(slot); | 1076 | enable_slot(slot); |
| 1055 | 1077 | ||
| 1056 | mutex_unlock(&slot->crit_sect); | 1078 | mutex_unlock(&slot->crit_sect); |
| 1079 | |||
| 1080 | pci_unlock_rescan_remove(); | ||
| 1057 | return 0; | 1081 | return 0; |
| 1058 | } | 1082 | } |
| 1059 | 1083 | ||
| @@ -1061,10 +1085,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
| 1061 | * acpiphp_disable_and_eject_slot - power off and eject slot | 1085 | * acpiphp_disable_and_eject_slot - power off and eject slot |
| 1062 | * @slot: ACPI PHP slot | 1086 | * @slot: ACPI PHP slot |
| 1063 | */ | 1087 | */ |
| 1064 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | 1088 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) |
| 1065 | { | 1089 | { |
| 1066 | struct acpiphp_func *func; | 1090 | struct acpiphp_func *func; |
| 1067 | int retval = 0; | 1091 | |
| 1092 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 1093 | return -ENODEV; | ||
| 1068 | 1094 | ||
| 1069 | mutex_lock(&slot->crit_sect); | 1095 | mutex_lock(&slot->crit_sect); |
| 1070 | 1096 | ||
| @@ -1082,9 +1108,18 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | |||
| 1082 | } | 1108 | } |
| 1083 | 1109 | ||
| 1084 | mutex_unlock(&slot->crit_sect); | 1110 | mutex_unlock(&slot->crit_sect); |
| 1085 | return retval; | 1111 | return 0; |
| 1086 | } | 1112 | } |
| 1087 | 1113 | ||
| 1114 | int acpiphp_disable_slot(struct acpiphp_slot *slot) | ||
| 1115 | { | ||
| 1116 | int ret; | ||
| 1117 | |||
| 1118 | pci_lock_rescan_remove(); | ||
| 1119 | ret = acpiphp_disable_and_eject_slot(slot); | ||
| 1120 | pci_unlock_rescan_remove(); | ||
| 1121 | return ret; | ||
| 1122 | } | ||
| 1088 | 1123 | ||
| 1089 | /* | 1124 | /* |
| 1090 | * slot enabled: 1 | 1125 | * slot enabled: 1 |
| @@ -1095,7 +1130,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | |||
| 1095 | return (slot->flags & SLOT_ENABLED); | 1130 | return (slot->flags & SLOT_ENABLED); |
| 1096 | } | 1131 | } |
| 1097 | 1132 | ||
| 1098 | |||
| 1099 | /* | 1133 | /* |
| 1100 | * latch open: 1 | 1134 | * latch open: 1 |
| 1101 | * latch closed: 0 | 1135 | * latch closed: 0 |
| @@ -1105,7 +1139,6 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
| 1105 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); | 1139 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); |
| 1106 | } | 1140 | } |
| 1107 | 1141 | ||
| 1108 | |||
| 1109 | /* | 1142 | /* |
| 1110 | * adapter presence : 1 | 1143 | * adapter presence : 1 |
| 1111 | * absence : 0 | 1144 | * absence : 0 |
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index d3add9819f63..8c1464851768 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
| @@ -254,9 +254,12 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 254 | { | 254 | { |
| 255 | struct pci_dev *dev; | 255 | struct pci_dev *dev; |
| 256 | struct pci_bus *parent; | 256 | struct pci_bus *parent; |
| 257 | int ret = 0; | ||
| 257 | 258 | ||
| 258 | dbg("%s - enter", __func__); | 259 | dbg("%s - enter", __func__); |
| 259 | 260 | ||
| 261 | pci_lock_rescan_remove(); | ||
| 262 | |||
| 260 | if (slot->dev == NULL) { | 263 | if (slot->dev == NULL) { |
| 261 | dbg("pci_dev null, finding %02x:%02x:%x", | 264 | dbg("pci_dev null, finding %02x:%02x:%x", |
| 262 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); | 265 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); |
| @@ -277,7 +280,8 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 277 | slot->dev = pci_get_slot(slot->bus, slot->devfn); | 280 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
| 278 | if (slot->dev == NULL) { | 281 | if (slot->dev == NULL) { |
| 279 | err("Could not find PCI device for slot %02x", slot->number); | 282 | err("Could not find PCI device for slot %02x", slot->number); |
| 280 | return -ENODEV; | 283 | ret = -ENODEV; |
| 284 | goto out; | ||
| 281 | } | 285 | } |
| 282 | } | 286 | } |
| 283 | parent = slot->dev->bus; | 287 | parent = slot->dev->bus; |
| @@ -294,8 +298,10 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 294 | 298 | ||
| 295 | pci_bus_add_devices(parent); | 299 | pci_bus_add_devices(parent); |
| 296 | 300 | ||
| 301 | out: | ||
| 302 | pci_unlock_rescan_remove(); | ||
| 297 | dbg("%s - exit", __func__); | 303 | dbg("%s - exit", __func__); |
| 298 | return 0; | 304 | return ret; |
| 299 | } | 305 | } |
| 300 | 306 | ||
| 301 | int cpci_unconfigure_slot(struct slot* slot) | 307 | int cpci_unconfigure_slot(struct slot* slot) |
| @@ -308,6 +314,8 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
| 308 | return -ENODEV; | 314 | return -ENODEV; |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | pci_lock_rescan_remove(); | ||
| 318 | |||
| 311 | list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { | 319 | list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { |
| 312 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) | 320 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) |
| 313 | continue; | 321 | continue; |
| @@ -318,6 +326,8 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
| 318 | pci_dev_put(slot->dev); | 326 | pci_dev_put(slot->dev); |
| 319 | slot->dev = NULL; | 327 | slot->dev = NULL; |
| 320 | 328 | ||
| 329 | pci_unlock_rescan_remove(); | ||
| 330 | |||
| 321 | dbg("%s - exit", __func__); | 331 | dbg("%s - exit", __func__); |
| 322 | return 0; | 332 | return 0; |
| 323 | } | 333 | } |
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 6e4a12c91adb..a3e3c2002b58 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c | |||
| @@ -86,6 +86,8 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 86 | struct pci_bus *child; | 86 | struct pci_bus *child; |
| 87 | int num; | 87 | int num; |
| 88 | 88 | ||
| 89 | pci_lock_rescan_remove(); | ||
| 90 | |||
| 89 | if (func->pci_dev == NULL) | 91 | if (func->pci_dev == NULL) |
| 90 | func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function)); | 92 | func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function)); |
| 91 | 93 | ||
| @@ -100,7 +102,7 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 100 | func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); | 102 | func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); |
| 101 | if (func->pci_dev == NULL) { | 103 | if (func->pci_dev == NULL) { |
| 102 | dbg("ERROR: pci_dev still null\n"); | 104 | dbg("ERROR: pci_dev still null\n"); |
| 103 | return 0; | 105 | goto out; |
| 104 | } | 106 | } |
| 105 | } | 107 | } |
| 106 | 108 | ||
| @@ -113,6 +115,8 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 113 | 115 | ||
| 114 | pci_dev_put(func->pci_dev); | 116 | pci_dev_put(func->pci_dev); |
| 115 | 117 | ||
| 118 | out: | ||
| 119 | pci_unlock_rescan_remove(); | ||
| 116 | return 0; | 120 | return 0; |
| 117 | } | 121 | } |
| 118 | 122 | ||
| @@ -123,6 +127,7 @@ int cpqhp_unconfigure_device(struct pci_func* func) | |||
| 123 | 127 | ||
| 124 | dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function); | 128 | dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function); |
| 125 | 129 | ||
| 130 | pci_lock_rescan_remove(); | ||
| 126 | for (j=0; j<8 ; j++) { | 131 | for (j=0; j<8 ; j++) { |
| 127 | struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); | 132 | struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); |
| 128 | if (temp) { | 133 | if (temp) { |
| @@ -130,6 +135,7 @@ int cpqhp_unconfigure_device(struct pci_func* func) | |||
| 130 | pci_stop_and_remove_bus_device(temp); | 135 | pci_stop_and_remove_bus_device(temp); |
| 131 | } | 136 | } |
| 132 | } | 137 | } |
| 138 | pci_unlock_rescan_remove(); | ||
| 133 | return 0; | 139 | return 0; |
| 134 | } | 140 | } |
| 135 | 141 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index efdc13adbe41..cf3ac1e4b099 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
| @@ -718,6 +718,8 @@ static void ibm_unconfigure_device(struct pci_func *func) | |||
| 718 | func->device, func->function); | 718 | func->device, func->function); |
| 719 | debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); | 719 | debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); |
| 720 | 720 | ||
| 721 | pci_lock_rescan_remove(); | ||
| 722 | |||
| 721 | for (j = 0; j < 0x08; j++) { | 723 | for (j = 0; j < 0x08; j++) { |
| 722 | temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); | 724 | temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); |
| 723 | if (temp) { | 725 | if (temp) { |
| @@ -725,7 +727,10 @@ static void ibm_unconfigure_device(struct pci_func *func) | |||
| 725 | pci_dev_put(temp); | 727 | pci_dev_put(temp); |
| 726 | } | 728 | } |
| 727 | } | 729 | } |
| 730 | |||
| 728 | pci_dev_put(func->dev); | 731 | pci_dev_put(func->dev); |
| 732 | |||
| 733 | pci_unlock_rescan_remove(); | ||
| 729 | } | 734 | } |
| 730 | 735 | ||
| 731 | /* | 736 | /* |
| @@ -780,6 +785,8 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 780 | int flag = 0; /* this is to make sure we don't double scan the bus, | 785 | int flag = 0; /* this is to make sure we don't double scan the bus, |
| 781 | for bridged devices primarily */ | 786 | for bridged devices primarily */ |
| 782 | 787 | ||
| 788 | pci_lock_rescan_remove(); | ||
| 789 | |||
| 783 | if (!(bus_structure_fixup(func->busno))) | 790 | if (!(bus_structure_fixup(func->busno))) |
| 784 | flag = 1; | 791 | flag = 1; |
| 785 | if (func->dev == NULL) | 792 | if (func->dev == NULL) |
| @@ -789,7 +796,7 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 789 | if (func->dev == NULL) { | 796 | if (func->dev == NULL) { |
| 790 | struct pci_bus *bus = pci_find_bus(0, func->busno); | 797 | struct pci_bus *bus = pci_find_bus(0, func->busno); |
| 791 | if (!bus) | 798 | if (!bus) |
| 792 | return 0; | 799 | goto out; |
| 793 | 800 | ||
| 794 | num = pci_scan_slot(bus, | 801 | num = pci_scan_slot(bus, |
| 795 | PCI_DEVFN(func->device, func->function)); | 802 | PCI_DEVFN(func->device, func->function)); |
| @@ -800,7 +807,7 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 800 | PCI_DEVFN(func->device, func->function)); | 807 | PCI_DEVFN(func->device, func->function)); |
| 801 | if (func->dev == NULL) { | 808 | if (func->dev == NULL) { |
| 802 | err("ERROR... : pci_dev still NULL\n"); | 809 | err("ERROR... : pci_dev still NULL\n"); |
| 803 | return 0; | 810 | goto out; |
| 804 | } | 811 | } |
| 805 | } | 812 | } |
| 806 | if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { | 813 | if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { |
| @@ -810,6 +817,8 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 810 | pci_bus_add_devices(child); | 817 | pci_bus_add_devices(child); |
| 811 | } | 818 | } |
| 812 | 819 | ||
| 820 | out: | ||
| 821 | pci_unlock_rescan_remove(); | ||
| 813 | return 0; | 822 | return 0; |
| 814 | } | 823 | } |
| 815 | 824 | ||
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 198355112ee7..b07d7cc2d697 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
| @@ -39,22 +39,26 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 39 | struct pci_dev *dev; | 39 | struct pci_dev *dev; |
| 40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; | 40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
| 41 | struct pci_bus *parent = bridge->subordinate; | 41 | struct pci_bus *parent = bridge->subordinate; |
| 42 | int num; | 42 | int num, ret = 0; |
| 43 | struct controller *ctrl = p_slot->ctrl; | 43 | struct controller *ctrl = p_slot->ctrl; |
| 44 | 44 | ||
| 45 | pci_lock_rescan_remove(); | ||
| 46 | |||
| 45 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); | 47 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); |
| 46 | if (dev) { | 48 | if (dev) { |
| 47 | ctrl_err(ctrl, "Device %s already exists " | 49 | ctrl_err(ctrl, "Device %s already exists " |
| 48 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), | 50 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), |
| 49 | pci_domain_nr(parent), parent->number); | 51 | pci_domain_nr(parent), parent->number); |
| 50 | pci_dev_put(dev); | 52 | pci_dev_put(dev); |
| 51 | return -EINVAL; | 53 | ret = -EINVAL; |
| 54 | goto out; | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | num = pci_scan_slot(parent, PCI_DEVFN(0, 0)); | 57 | num = pci_scan_slot(parent, PCI_DEVFN(0, 0)); |
| 55 | if (num == 0) { | 58 | if (num == 0) { |
| 56 | ctrl_err(ctrl, "No new device found\n"); | 59 | ctrl_err(ctrl, "No new device found\n"); |
| 57 | return -ENODEV; | 60 | ret = -ENODEV; |
| 61 | goto out; | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | list_for_each_entry(dev, &parent->devices, bus_list) | 64 | list_for_each_entry(dev, &parent->devices, bus_list) |
| @@ -73,7 +77,9 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 73 | 77 | ||
| 74 | pci_bus_add_devices(parent); | 78 | pci_bus_add_devices(parent); |
| 75 | 79 | ||
| 76 | return 0; | 80 | out: |
| 81 | pci_unlock_rescan_remove(); | ||
| 82 | return ret; | ||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | int pciehp_unconfigure_device(struct slot *p_slot) | 85 | int pciehp_unconfigure_device(struct slot *p_slot) |
| @@ -90,6 +96,8 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
| 90 | __func__, pci_domain_nr(parent), parent->number); | 96 | __func__, pci_domain_nr(parent), parent->number); |
| 91 | pciehp_get_adapter_status(p_slot, &presence); | 97 | pciehp_get_adapter_status(p_slot, &presence); |
| 92 | 98 | ||
| 99 | pci_lock_rescan_remove(); | ||
| 100 | |||
| 93 | /* | 101 | /* |
| 94 | * Stopping an SR-IOV PF device removes all the associated VFs, | 102 | * Stopping an SR-IOV PF device removes all the associated VFs, |
| 95 | * which will update the bus->devices list and confuse the | 103 | * which will update the bus->devices list and confuse the |
| @@ -124,5 +132,6 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
| 124 | pci_dev_put(dev); | 132 | pci_dev_put(dev); |
| 125 | } | 133 | } |
| 126 | 134 | ||
| 135 | pci_unlock_rescan_remove(); | ||
| 127 | return rc; | 136 | return rc; |
| 128 | } | 137 | } |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index e9c044d15add..4fcdeedda31b 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
| @@ -354,10 +354,15 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 354 | { | 354 | { |
| 355 | struct pci_bus *bus; | 355 | struct pci_bus *bus; |
| 356 | struct slot *slot; | 356 | struct slot *slot; |
| 357 | int ret = 0; | ||
| 358 | |||
| 359 | pci_lock_rescan_remove(); | ||
| 357 | 360 | ||
| 358 | bus = pcibios_find_pci_bus(dn); | 361 | bus = pcibios_find_pci_bus(dn); |
| 359 | if (!bus) | 362 | if (!bus) { |
| 360 | return -EINVAL; | 363 | ret = -EINVAL; |
| 364 | goto out; | ||
| 365 | } | ||
| 361 | 366 | ||
| 362 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", | 367 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", |
| 363 | bus->self ? pci_name(bus->self) : "<!PHB!>"); | 368 | bus->self ? pci_name(bus->self) : "<!PHB!>"); |
| @@ -371,7 +376,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 371 | printk(KERN_ERR | 376 | printk(KERN_ERR |
| 372 | "%s: unable to remove hotplug slot %s\n", | 377 | "%s: unable to remove hotplug slot %s\n", |
| 373 | __func__, drc_name); | 378 | __func__, drc_name); |
| 374 | return -EIO; | 379 | ret = -EIO; |
| 380 | goto out; | ||
| 375 | } | 381 | } |
| 376 | } | 382 | } |
| 377 | 383 | ||
| @@ -382,7 +388,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 382 | if (pcibios_unmap_io_space(bus)) { | 388 | if (pcibios_unmap_io_space(bus)) { |
| 383 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 389 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
| 384 | __func__); | 390 | __func__); |
| 385 | return -ERANGE; | 391 | ret = -ERANGE; |
| 392 | goto out; | ||
| 386 | } | 393 | } |
| 387 | 394 | ||
| 388 | /* Remove the EADS bridge device itself */ | 395 | /* Remove the EADS bridge device itself */ |
| @@ -390,7 +397,9 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 390 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); | 397 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); |
| 391 | pci_stop_and_remove_bus_device(bus->self); | 398 | pci_stop_and_remove_bus_device(bus->self); |
| 392 | 399 | ||
| 393 | return 0; | 400 | out: |
| 401 | pci_unlock_rescan_remove(); | ||
| 402 | return ret; | ||
| 394 | } | 403 | } |
| 395 | 404 | ||
| 396 | /** | 405 | /** |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index b7fc5c9255a5..4796c15fba94 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
| @@ -398,7 +398,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 398 | return retval; | 398 | return retval; |
| 399 | 399 | ||
| 400 | if (state == PRESENT) { | 400 | if (state == PRESENT) { |
| 401 | pci_lock_rescan_remove(); | ||
| 401 | pcibios_add_pci_devices(slot->bus); | 402 | pcibios_add_pci_devices(slot->bus); |
| 403 | pci_unlock_rescan_remove(); | ||
| 402 | slot->state = CONFIGURED; | 404 | slot->state = CONFIGURED; |
| 403 | } else if (state == EMPTY) { | 405 | } else if (state == EMPTY) { |
| 404 | slot->state = EMPTY; | 406 | slot->state = EMPTY; |
| @@ -418,7 +420,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 418 | if (slot->state == NOT_CONFIGURED) | 420 | if (slot->state == NOT_CONFIGURED) |
| 419 | return -EINVAL; | 421 | return -EINVAL; |
| 420 | 422 | ||
| 423 | pci_lock_rescan_remove(); | ||
| 421 | pcibios_remove_pci_devices(slot->bus); | 424 | pcibios_remove_pci_devices(slot->bus); |
| 425 | pci_unlock_rescan_remove(); | ||
| 422 | vm_unmap_aliases(); | 426 | vm_unmap_aliases(); |
| 423 | 427 | ||
| 424 | slot->state = NOT_CONFIGURED; | 428 | slot->state = NOT_CONFIGURED; |
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 3c7eb5dd91c6..8d2ce22151eb 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c | |||
| @@ -80,7 +80,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 80 | goto out_deconfigure; | 80 | goto out_deconfigure; |
| 81 | 81 | ||
| 82 | pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); | 82 | pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); |
| 83 | pci_lock_rescan_remove(); | ||
| 83 | pci_bus_add_devices(slot->zdev->bus); | 84 | pci_bus_add_devices(slot->zdev->bus); |
| 85 | pci_unlock_rescan_remove(); | ||
| 84 | 86 | ||
| 85 | return rc; | 87 | return rc; |
| 86 | 88 | ||
| @@ -98,7 +100,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 98 | return -EIO; | 100 | return -EIO; |
| 99 | 101 | ||
| 100 | if (slot->zdev->pdev) | 102 | if (slot->zdev->pdev) |
| 101 | pci_stop_and_remove_bus_device(slot->zdev->pdev); | 103 | pci_stop_and_remove_bus_device_locked(slot->zdev->pdev); |
| 102 | 104 | ||
| 103 | rc = zpci_disable_device(slot->zdev); | 105 | rc = zpci_disable_device(slot->zdev); |
| 104 | if (rc) | 106 | if (rc) |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 5b05a68cca6c..613043f7576f 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
| @@ -459,12 +459,15 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 459 | acpi_scan_lock_release(); | 459 | acpi_scan_lock_release(); |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | pci_lock_rescan_remove(); | ||
| 463 | |||
| 462 | /* Call the driver for the new device */ | 464 | /* Call the driver for the new device */ |
| 463 | pci_bus_add_devices(slot->pci_bus); | 465 | pci_bus_add_devices(slot->pci_bus); |
| 464 | /* Call the drivers for the new devices subordinate to PPB */ | 466 | /* Call the drivers for the new devices subordinate to PPB */ |
| 465 | if (new_ppb) | 467 | if (new_ppb) |
| 466 | pci_bus_add_devices(new_bus); | 468 | pci_bus_add_devices(new_bus); |
| 467 | 469 | ||
| 470 | pci_unlock_rescan_remove(); | ||
| 468 | mutex_unlock(&sn_hotplug_mutex); | 471 | mutex_unlock(&sn_hotplug_mutex); |
| 469 | 472 | ||
| 470 | if (rc == 0) | 473 | if (rc == 0) |
| @@ -540,6 +543,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 540 | acpi_scan_lock_release(); | 543 | acpi_scan_lock_release(); |
| 541 | } | 544 | } |
| 542 | 545 | ||
| 546 | pci_lock_rescan_remove(); | ||
| 543 | /* Free the SN resources assigned to the Linux device.*/ | 547 | /* Free the SN resources assigned to the Linux device.*/ |
| 544 | list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { | 548 | list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { |
| 545 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) | 549 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) |
| @@ -550,6 +554,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 550 | pci_stop_and_remove_bus_device(dev); | 554 | pci_stop_and_remove_bus_device(dev); |
| 551 | pci_dev_put(dev); | 555 | pci_dev_put(dev); |
| 552 | } | 556 | } |
| 557 | pci_unlock_rescan_remove(); | ||
| 553 | 558 | ||
| 554 | /* Remove the SSDT for the slot from the ACPI namespace */ | 559 | /* Remove the SSDT for the slot from the ACPI namespace */ |
| 555 | if (SN_ACPI_BASE_SUPPORT() && ssdt_id) { | 560 | if (SN_ACPI_BASE_SUPPORT() && ssdt_id) { |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b0e83132542e..2bf69fe1926c 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
| @@ -40,7 +40,9 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 40 | struct controller *ctrl = p_slot->ctrl; | 40 | struct controller *ctrl = p_slot->ctrl; |
| 41 | struct pci_dev *bridge = ctrl->pci_dev; | 41 | struct pci_dev *bridge = ctrl->pci_dev; |
| 42 | struct pci_bus *parent = bridge->subordinate; | 42 | struct pci_bus *parent = bridge->subordinate; |
| 43 | int num; | 43 | int num, ret = 0; |
| 44 | |||
| 45 | pci_lock_rescan_remove(); | ||
| 44 | 46 | ||
| 45 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); | 47 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
| 46 | if (dev) { | 48 | if (dev) { |
| @@ -48,13 +50,15 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 48 | "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), | 50 | "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), |
| 49 | pci_domain_nr(parent), p_slot->bus, p_slot->device); | 51 | pci_domain_nr(parent), p_slot->bus, p_slot->device); |
| 50 | pci_dev_put(dev); | 52 | pci_dev_put(dev); |
| 51 | return -EINVAL; | 53 | ret = -EINVAL; |
| 54 | goto out; | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); | 57 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
| 55 | if (num == 0) { | 58 | if (num == 0) { |
| 56 | ctrl_err(ctrl, "No new device found\n"); | 59 | ctrl_err(ctrl, "No new device found\n"); |
| 57 | return -ENODEV; | 60 | ret = -ENODEV; |
| 61 | goto out; | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | list_for_each_entry(dev, &parent->devices, bus_list) { | 64 | list_for_each_entry(dev, &parent->devices, bus_list) { |
| @@ -75,7 +79,9 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 75 | 79 | ||
| 76 | pci_bus_add_devices(parent); | 80 | pci_bus_add_devices(parent); |
| 77 | 81 | ||
| 78 | return 0; | 82 | out: |
| 83 | pci_unlock_rescan_remove(); | ||
| 84 | return ret; | ||
| 79 | } | 85 | } |
| 80 | 86 | ||
| 81 | int shpchp_unconfigure_device(struct slot *p_slot) | 87 | int shpchp_unconfigure_device(struct slot *p_slot) |
| @@ -89,6 +95,8 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
| 89 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", | 95 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", |
| 90 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); | 96 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); |
| 91 | 97 | ||
| 98 | pci_lock_rescan_remove(); | ||
| 99 | |||
| 92 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { | 100 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { |
| 93 | if (PCI_SLOT(dev->devfn) != p_slot->device) | 101 | if (PCI_SLOT(dev->devfn) != p_slot->device) |
| 94 | continue; | 102 | continue; |
| @@ -108,6 +116,8 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
| 108 | pci_stop_and_remove_bus_device(dev); | 116 | pci_stop_and_remove_bus_device(dev); |
| 109 | pci_dev_put(dev); | 117 | pci_dev_put(dev); |
| 110 | } | 118 | } |
| 119 | |||
| 120 | pci_unlock_rescan_remove(); | ||
| 111 | return rc; | 121 | return rc; |
| 112 | } | 122 | } |
| 113 | 123 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c91e6c18debc..276ef9c18802 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -297,7 +297,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
| 297 | } | 297 | } |
| 298 | static DEVICE_ATTR_RW(msi_bus); | 298 | static DEVICE_ATTR_RW(msi_bus); |
| 299 | 299 | ||
| 300 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | ||
| 301 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | 300 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, |
| 302 | size_t count) | 301 | size_t count) |
| 303 | { | 302 | { |
| @@ -308,10 +307,10 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | |||
| 308 | return -EINVAL; | 307 | return -EINVAL; |
| 309 | 308 | ||
| 310 | if (val) { | 309 | if (val) { |
| 311 | mutex_lock(&pci_remove_rescan_mutex); | 310 | pci_lock_rescan_remove(); |
| 312 | while ((b = pci_find_next_bus(b)) != NULL) | 311 | while ((b = pci_find_next_bus(b)) != NULL) |
| 313 | pci_rescan_bus(b); | 312 | pci_rescan_bus(b); |
| 314 | mutex_unlock(&pci_remove_rescan_mutex); | 313 | pci_unlock_rescan_remove(); |
| 315 | } | 314 | } |
| 316 | return count; | 315 | return count; |
| 317 | } | 316 | } |
| @@ -342,9 +341,9 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr, | |||
| 342 | return -EINVAL; | 341 | return -EINVAL; |
| 343 | 342 | ||
| 344 | if (val) { | 343 | if (val) { |
| 345 | mutex_lock(&pci_remove_rescan_mutex); | 344 | pci_lock_rescan_remove(); |
| 346 | pci_rescan_bus(pdev->bus); | 345 | pci_rescan_bus(pdev->bus); |
| 347 | mutex_unlock(&pci_remove_rescan_mutex); | 346 | pci_unlock_rescan_remove(); |
| 348 | } | 347 | } |
| 349 | return count; | 348 | return count; |
| 350 | } | 349 | } |
| @@ -354,11 +353,7 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan, | |||
| 354 | 353 | ||
| 355 | static void remove_callback(struct device *dev) | 354 | static void remove_callback(struct device *dev) |
| 356 | { | 355 | { |
| 357 | struct pci_dev *pdev = to_pci_dev(dev); | 356 | pci_stop_and_remove_bus_device_locked(to_pci_dev(dev)); |
| 358 | |||
| 359 | mutex_lock(&pci_remove_rescan_mutex); | ||
| 360 | pci_stop_and_remove_bus_device(pdev); | ||
| 361 | mutex_unlock(&pci_remove_rescan_mutex); | ||
| 362 | } | 357 | } |
| 363 | 358 | ||
| 364 | static ssize_t | 359 | static ssize_t |
| @@ -395,12 +390,12 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, | |||
| 395 | return -EINVAL; | 390 | return -EINVAL; |
| 396 | 391 | ||
| 397 | if (val) { | 392 | if (val) { |
| 398 | mutex_lock(&pci_remove_rescan_mutex); | 393 | pci_lock_rescan_remove(); |
| 399 | if (!pci_is_root_bus(bus) && list_empty(&bus->devices)) | 394 | if (!pci_is_root_bus(bus) && list_empty(&bus->devices)) |
| 400 | pci_rescan_bus_bridge_resize(bus->self); | 395 | pci_rescan_bus_bridge_resize(bus->self); |
| 401 | else | 396 | else |
| 402 | pci_rescan_bus(bus); | 397 | pci_rescan_bus(bus); |
| 403 | mutex_unlock(&pci_remove_rescan_mutex); | 398 | pci_unlock_rescan_remove(); |
| 404 | } | 399 | } |
| 405 | return count; | 400 | return count; |
| 406 | } | 401 | } |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c86c8638d3c4..04796c056d12 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -2024,6 +2024,24 @@ EXPORT_SYMBOL(pci_scan_slot); | |||
| 2024 | EXPORT_SYMBOL(pci_scan_bridge); | 2024 | EXPORT_SYMBOL(pci_scan_bridge); |
| 2025 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); | 2025 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); |
| 2026 | 2026 | ||
| 2027 | /* | ||
| 2028 | * pci_rescan_bus(), pci_rescan_bus_bridge_resize() and PCI device removal | ||
| 2029 | * routines should always be executed under this mutex. | ||
| 2030 | */ | ||
| 2031 | static DEFINE_MUTEX(pci_rescan_remove_lock); | ||
| 2032 | |||
| 2033 | void pci_lock_rescan_remove(void) | ||
| 2034 | { | ||
| 2035 | mutex_lock(&pci_rescan_remove_lock); | ||
| 2036 | } | ||
| 2037 | EXPORT_SYMBOL_GPL(pci_lock_rescan_remove); | ||
| 2038 | |||
| 2039 | void pci_unlock_rescan_remove(void) | ||
| 2040 | { | ||
| 2041 | mutex_unlock(&pci_rescan_remove_lock); | ||
| 2042 | } | ||
| 2043 | EXPORT_SYMBOL_GPL(pci_unlock_rescan_remove); | ||
| 2044 | |||
| 2027 | static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b) | 2045 | static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b) |
| 2028 | { | 2046 | { |
| 2029 | const struct pci_dev *a = to_pci_dev(d_a); | 2047 | const struct pci_dev *a = to_pci_dev(d_a); |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index f452148e6d55..4ff36bfa785e 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
| @@ -20,6 +20,9 @@ static void pci_stop_dev(struct pci_dev *dev) | |||
| 20 | 20 | ||
| 21 | static void pci_destroy_dev(struct pci_dev *dev) | 21 | static void pci_destroy_dev(struct pci_dev *dev) |
| 22 | { | 22 | { |
| 23 | if (!dev->dev.kobj.parent) | ||
| 24 | return; | ||
| 25 | |||
| 23 | device_del(&dev->dev); | 26 | device_del(&dev->dev); |
| 24 | 27 | ||
| 25 | put_device(&dev->dev); | 28 | put_device(&dev->dev); |
| @@ -95,6 +98,14 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev) | |||
| 95 | } | 98 | } |
| 96 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); | 99 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); |
| 97 | 100 | ||
| 101 | void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev) | ||
| 102 | { | ||
| 103 | pci_lock_rescan_remove(); | ||
| 104 | pci_stop_and_remove_bus_device(dev); | ||
| 105 | pci_unlock_rescan_remove(); | ||
| 106 | } | ||
| 107 | EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked); | ||
| 108 | |||
| 98 | void pci_stop_root_bus(struct pci_bus *bus) | 109 | void pci_stop_root_bus(struct pci_bus *bus) |
| 99 | { | 110 | { |
| 100 | struct pci_dev *child, *tmp; | 111 | struct pci_dev *child, *tmp; |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index f7197a790341..d1cd60f51f87 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
| @@ -471,12 +471,15 @@ static int pcifront_scan_root(struct pcifront_device *pdev, | |||
| 471 | } | 471 | } |
| 472 | pcifront_init_sd(sd, domain, bus, pdev); | 472 | pcifront_init_sd(sd, domain, bus, pdev); |
| 473 | 473 | ||
| 474 | pci_lock_rescan_remove(); | ||
| 475 | |||
| 474 | b = pci_scan_bus_parented(&pdev->xdev->dev, bus, | 476 | b = pci_scan_bus_parented(&pdev->xdev->dev, bus, |
| 475 | &pcifront_bus_ops, sd); | 477 | &pcifront_bus_ops, sd); |
| 476 | if (!b) { | 478 | if (!b) { |
| 477 | dev_err(&pdev->xdev->dev, | 479 | dev_err(&pdev->xdev->dev, |
| 478 | "Error creating PCI Frontend Bus!\n"); | 480 | "Error creating PCI Frontend Bus!\n"); |
| 479 | err = -ENOMEM; | 481 | err = -ENOMEM; |
| 482 | pci_unlock_rescan_remove(); | ||
| 480 | goto err_out; | 483 | goto err_out; |
| 481 | } | 484 | } |
| 482 | 485 | ||
| @@ -494,6 +497,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev, | |||
| 494 | /* Create SysFS and notify udev of the devices. Aka: "going live" */ | 497 | /* Create SysFS and notify udev of the devices. Aka: "going live" */ |
| 495 | pci_bus_add_devices(b); | 498 | pci_bus_add_devices(b); |
| 496 | 499 | ||
| 500 | pci_unlock_rescan_remove(); | ||
| 497 | return err; | 501 | return err; |
| 498 | 502 | ||
| 499 | err_out: | 503 | err_out: |
| @@ -556,6 +560,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev) | |||
| 556 | 560 | ||
| 557 | dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); | 561 | dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); |
| 558 | 562 | ||
| 563 | pci_lock_rescan_remove(); | ||
| 559 | list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { | 564 | list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { |
| 560 | list_del(&bus_entry->list); | 565 | list_del(&bus_entry->list); |
| 561 | 566 | ||
| @@ -568,6 +573,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev) | |||
| 568 | 573 | ||
| 569 | kfree(bus_entry); | 574 | kfree(bus_entry); |
| 570 | } | 575 | } |
| 576 | pci_unlock_rescan_remove(); | ||
| 571 | } | 577 | } |
| 572 | 578 | ||
| 573 | static pci_ers_result_t pcifront_common_process(int cmd, | 579 | static pci_ers_result_t pcifront_common_process(int cmd, |
| @@ -1043,8 +1049,10 @@ static int pcifront_detach_devices(struct pcifront_device *pdev) | |||
| 1043 | domain, bus, slot, func); | 1049 | domain, bus, slot, func); |
| 1044 | continue; | 1050 | continue; |
| 1045 | } | 1051 | } |
| 1052 | pci_lock_rescan_remove(); | ||
| 1046 | pci_stop_and_remove_bus_device(pci_dev); | 1053 | pci_stop_and_remove_bus_device(pci_dev); |
| 1047 | pci_dev_put(pci_dev); | 1054 | pci_dev_put(pci_dev); |
| 1055 | pci_unlock_rescan_remove(); | ||
| 1048 | 1056 | ||
| 1049 | dev_dbg(&pdev->xdev->dev, | 1057 | dev_dbg(&pdev->xdev->dev, |
| 1050 | "PCI device %04x:%02x:%02x.%d removed.\n", | 1058 | "PCI device %04x:%02x:%02x.%d removed.\n", |
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index b2a98cdbd0d2..8bde61952d20 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c | |||
| @@ -70,6 +70,8 @@ int __ref cb_alloc(struct pcmcia_socket *s) | |||
| 70 | struct pci_dev *dev; | 70 | struct pci_dev *dev; |
| 71 | unsigned int max, pass; | 71 | unsigned int max, pass; |
| 72 | 72 | ||
| 73 | pci_lock_rescan_remove(); | ||
| 74 | |||
| 73 | s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); | 75 | s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); |
| 74 | pci_fixup_cardbus(bus); | 76 | pci_fixup_cardbus(bus); |
| 75 | 77 | ||
| @@ -93,6 +95,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) | |||
| 93 | 95 | ||
| 94 | pci_bus_add_devices(bus); | 96 | pci_bus_add_devices(bus); |
| 95 | 97 | ||
| 98 | pci_unlock_rescan_remove(); | ||
| 96 | return 0; | 99 | return 0; |
| 97 | } | 100 | } |
| 98 | 101 | ||
| @@ -115,6 +118,10 @@ void cb_free(struct pcmcia_socket *s) | |||
| 115 | if (!bus) | 118 | if (!bus) |
| 116 | return; | 119 | return; |
| 117 | 120 | ||
| 121 | pci_lock_rescan_remove(); | ||
| 122 | |||
| 118 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) | 123 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) |
| 119 | pci_stop_and_remove_bus_device(dev); | 124 | pci_stop_and_remove_bus_device(dev); |
| 125 | |||
| 126 | pci_unlock_rescan_remove(); | ||
| 120 | } | 127 | } |
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 19c313b056c3..6fe268f6af91 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c | |||
| @@ -606,6 +606,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus) | |||
| 606 | mutex_unlock(&asus->wmi_lock); | 606 | mutex_unlock(&asus->wmi_lock); |
| 607 | 607 | ||
| 608 | mutex_lock(&asus->hotplug_lock); | 608 | mutex_lock(&asus->hotplug_lock); |
| 609 | pci_lock_rescan_remove(); | ||
| 609 | 610 | ||
| 610 | if (asus->wlan.rfkill) | 611 | if (asus->wlan.rfkill) |
| 611 | rfkill_set_sw_state(asus->wlan.rfkill, blocked); | 612 | rfkill_set_sw_state(asus->wlan.rfkill, blocked); |
| @@ -656,6 +657,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus) | |||
| 656 | } | 657 | } |
| 657 | 658 | ||
| 658 | out_unlock: | 659 | out_unlock: |
| 660 | pci_unlock_rescan_remove(); | ||
| 659 | mutex_unlock(&asus->hotplug_lock); | 661 | mutex_unlock(&asus->hotplug_lock); |
| 660 | } | 662 | } |
| 661 | 663 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index aefcc32e5634..538521b00948 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -592,6 +592,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) | |||
| 592 | rfkill_set_sw_state(eeepc->wlan_rfkill, blocked); | 592 | rfkill_set_sw_state(eeepc->wlan_rfkill, blocked); |
| 593 | 593 | ||
| 594 | mutex_lock(&eeepc->hotplug_lock); | 594 | mutex_lock(&eeepc->hotplug_lock); |
| 595 | pci_lock_rescan_remove(); | ||
| 595 | 596 | ||
| 596 | if (eeepc->hotplug_slot) { | 597 | if (eeepc->hotplug_slot) { |
| 597 | port = acpi_get_pci_dev(handle); | 598 | port = acpi_get_pci_dev(handle); |
| @@ -649,6 +650,7 @@ out_put_dev: | |||
| 649 | } | 650 | } |
| 650 | 651 | ||
| 651 | out_unlock: | 652 | out_unlock: |
| 653 | pci_unlock_rescan_remove(); | ||
| 652 | mutex_unlock(&eeepc->hotplug_lock); | 654 | mutex_unlock(&eeepc->hotplug_lock); |
| 653 | } | 655 | } |
| 654 | 656 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 3901edc35812..bde63f7452bd 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
| @@ -128,7 +128,7 @@ static int mpt2sas_remove_dead_ioc_func(void *arg) | |||
| 128 | pdev = ioc->pdev; | 128 | pdev = ioc->pdev; |
| 129 | if ((pdev == NULL)) | 129 | if ((pdev == NULL)) |
| 130 | return -1; | 130 | return -1; |
| 131 | pci_stop_and_remove_bus_device(pdev); | 131 | pci_stop_and_remove_bus_device_locked(pdev); |
| 132 | return 0; | 132 | return 0; |
| 133 | } | 133 | } |
| 134 | 134 | ||
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index fa785062e97b..0cf4f7000f94 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c | |||
| @@ -131,7 +131,7 @@ static int mpt3sas_remove_dead_ioc_func(void *arg) | |||
| 131 | pdev = ioc->pdev; | 131 | pdev = ioc->pdev; |
| 132 | if ((pdev == NULL)) | 132 | if ((pdev == NULL)) |
| 133 | return -1; | 133 | return -1; |
| 134 | pci_stop_and_remove_bus_device(pdev); | 134 | pci_stop_and_remove_bus_device_locked(pdev); |
| 135 | return 0; | 135 | return 0; |
| 136 | } | 136 | } |
| 137 | 137 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 9e3ec8b951b7..2087e6b35545 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -775,6 +775,7 @@ struct pci_dev *pci_dev_get(struct pci_dev *dev); | |||
| 775 | void pci_dev_put(struct pci_dev *dev); | 775 | void pci_dev_put(struct pci_dev *dev); |
| 776 | void pci_remove_bus(struct pci_bus *b); | 776 | void pci_remove_bus(struct pci_bus *b); |
| 777 | void pci_stop_and_remove_bus_device(struct pci_dev *dev); | 777 | void pci_stop_and_remove_bus_device(struct pci_dev *dev); |
| 778 | void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev); | ||
| 778 | void pci_stop_root_bus(struct pci_bus *bus); | 779 | void pci_stop_root_bus(struct pci_bus *bus); |
| 779 | void pci_remove_root_bus(struct pci_bus *bus); | 780 | void pci_remove_root_bus(struct pci_bus *bus); |
| 780 | void pci_setup_cardbus(struct pci_bus *bus); | 781 | void pci_setup_cardbus(struct pci_bus *bus); |
| @@ -1011,6 +1012,8 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev); | |||
| 1011 | int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap); | 1012 | int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap); |
| 1012 | unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge); | 1013 | unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge); |
| 1013 | unsigned int pci_rescan_bus(struct pci_bus *bus); | 1014 | unsigned int pci_rescan_bus(struct pci_bus *bus); |
| 1015 | void pci_lock_rescan_remove(void); | ||
| 1016 | void pci_unlock_rescan_remove(void); | ||
| 1014 | 1017 | ||
| 1015 | /* Vital product data routines */ | 1018 | /* Vital product data routines */ |
| 1016 | ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); | 1019 | ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); |
