diff options
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index f6488adf3af1..0b7d23b4ad95 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -487,7 +487,6 @@ static void acpiphp_bus_add(acpi_handle handle) | |||
| 487 | { | 487 | { |
| 488 | struct acpi_device *adev = NULL; | 488 | struct acpi_device *adev = NULL; |
| 489 | 489 | ||
| 490 | acpiphp_bus_trim(handle); | ||
| 491 | acpi_bus_scan(handle); | 490 | acpi_bus_scan(handle); |
| 492 | acpi_bus_get_device(handle, &adev); | 491 | acpi_bus_get_device(handle, &adev); |
| 493 | if (adev) | 492 | if (adev) |
| @@ -529,6 +528,16 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) | |||
| 529 | } | 528 | } |
| 530 | } | 529 | } |
| 531 | 530 | ||
| 531 | static int acpiphp_rescan_slot(struct acpiphp_slot *slot) | ||
| 532 | { | ||
| 533 | struct acpiphp_func *func; | ||
| 534 | |||
| 535 | list_for_each_entry(func, &slot->funcs, sibling) | ||
| 536 | acpiphp_bus_add(func_to_handle(func)); | ||
| 537 | |||
| 538 | return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0)); | ||
| 539 | } | ||
| 540 | |||
| 532 | /** | 541 | /** |
| 533 | * enable_slot - enable, configure a slot | 542 | * enable_slot - enable, configure a slot |
| 534 | * @slot: slot to be enabled | 543 | * @slot: slot to be enabled |
| @@ -543,12 +552,9 @@ static void __ref enable_slot(struct acpiphp_slot *slot) | |||
| 543 | struct acpiphp_func *func; | 552 | struct acpiphp_func *func; |
| 544 | int max, pass; | 553 | int max, pass; |
| 545 | LIST_HEAD(add_list); | 554 | LIST_HEAD(add_list); |
| 555 | int nr_found; | ||
| 546 | 556 | ||
| 547 | list_for_each_entry(func, &slot->funcs, sibling) | 557 | nr_found = acpiphp_rescan_slot(slot); |
| 548 | acpiphp_bus_add(func_to_handle(func)); | ||
| 549 | |||
| 550 | pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); | ||
| 551 | |||
| 552 | max = acpiphp_max_busnr(bus); | 558 | max = acpiphp_max_busnr(bus); |
| 553 | for (pass = 0; pass < 2; pass++) { | 559 | for (pass = 0; pass < 2; pass++) { |
| 554 | list_for_each_entry(dev, &bus->devices, bus_list) { | 560 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| @@ -567,8 +573,11 @@ static void __ref enable_slot(struct acpiphp_slot *slot) | |||
| 567 | } | 573 | } |
| 568 | } | 574 | } |
| 569 | } | 575 | } |
| 570 | |||
| 571 | __pci_bus_assign_resources(bus, &add_list, NULL); | 576 | __pci_bus_assign_resources(bus, &add_list, NULL); |
| 577 | /* Nothing more to do here if there are no new devices on this bus. */ | ||
| 578 | if (!nr_found && (slot->flags & SLOT_ENABLED)) | ||
| 579 | return; | ||
| 580 | |||
| 572 | acpiphp_sanitize_bus(bus); | 581 | acpiphp_sanitize_bus(bus); |
| 573 | acpiphp_set_hpp_values(bus); | 582 | acpiphp_set_hpp_values(bus); |
| 574 | acpiphp_set_acpi_region(slot); | 583 | acpiphp_set_acpi_region(slot); |
| @@ -837,11 +846,22 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 837 | case ACPI_NOTIFY_DEVICE_CHECK: | 846 | case ACPI_NOTIFY_DEVICE_CHECK: |
| 838 | /* device check */ | 847 | /* device check */ |
| 839 | dbg("%s: Device check notify on %s\n", __func__, objname); | 848 | dbg("%s: Device check notify on %s\n", __func__, objname); |
| 840 | if (bridge) | 849 | if (bridge) { |
| 841 | acpiphp_check_bridge(bridge); | 850 | acpiphp_check_bridge(bridge); |
| 842 | else | 851 | } else { |
| 843 | acpiphp_check_bridge(func->parent); | 852 | struct acpiphp_slot *slot = func->slot; |
| 853 | int ret; | ||
| 844 | 854 | ||
| 855 | /* | ||
| 856 | * Check if anything has changed in the slot and rescan | ||
| 857 | * from the parent if that's the case. | ||
| 858 | */ | ||
| 859 | mutex_lock(&slot->crit_sect); | ||
| 860 | ret = acpiphp_rescan_slot(slot); | ||
| 861 | mutex_unlock(&slot->crit_sect); | ||
| 862 | if (ret) | ||
| 863 | acpiphp_check_bridge(func->parent); | ||
| 864 | } | ||
| 845 | break; | 865 | break; |
| 846 | 866 | ||
| 847 | case ACPI_NOTIFY_EJECT_REQUEST: | 867 | case ACPI_NOTIFY_EJECT_REQUEST: |
| @@ -867,6 +887,8 @@ static void hotplug_event_work(struct work_struct *work) | |||
| 867 | hotplug_event(hp_work->handle, hp_work->type, context); | 887 | hotplug_event(hp_work->handle, hp_work->type, context); |
| 868 | 888 | ||
| 869 | acpi_scan_lock_release(); | 889 | acpi_scan_lock_release(); |
| 890 | acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type, | ||
| 891 | ACPI_OST_SC_SUCCESS, NULL); | ||
| 870 | kfree(hp_work); /* allocated in handle_hotplug_event() */ | 892 | kfree(hp_work); /* allocated in handle_hotplug_event() */ |
| 871 | put_bridge(context->func.parent); | 893 | put_bridge(context->func.parent); |
| 872 | } | 894 | } |
| @@ -882,11 +904,15 @@ static void hotplug_event_work(struct work_struct *work) | |||
| 882 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | 904 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) |
| 883 | { | 905 | { |
| 884 | struct acpiphp_context *context; | 906 | struct acpiphp_context *context; |
| 907 | u32 ost_code = ACPI_OST_SC_SUCCESS; | ||
| 885 | 908 | ||
| 886 | switch (type) { | 909 | switch (type) { |
| 887 | case ACPI_NOTIFY_BUS_CHECK: | 910 | case ACPI_NOTIFY_BUS_CHECK: |
| 888 | case ACPI_NOTIFY_DEVICE_CHECK: | 911 | case ACPI_NOTIFY_DEVICE_CHECK: |
| 912 | break; | ||
| 889 | case ACPI_NOTIFY_EJECT_REQUEST: | 913 | case ACPI_NOTIFY_EJECT_REQUEST: |
| 914 | ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS; | ||
| 915 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
| 890 | break; | 916 | break; |
| 891 | 917 | ||
| 892 | case ACPI_NOTIFY_DEVICE_WAKE: | 918 | case ACPI_NOTIFY_DEVICE_WAKE: |
| @@ -895,20 +921,21 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 895 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 921 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
| 896 | acpi_handle_err(handle, "Device cannot be configured due " | 922 | acpi_handle_err(handle, "Device cannot be configured due " |
| 897 | "to a frequency mismatch\n"); | 923 | "to a frequency mismatch\n"); |
| 898 | return; | 924 | goto out; |
| 899 | 925 | ||
| 900 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 926 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
| 901 | acpi_handle_err(handle, "Device cannot be configured due " | 927 | acpi_handle_err(handle, "Device cannot be configured due " |
| 902 | "to a bus mode mismatch\n"); | 928 | "to a bus mode mismatch\n"); |
| 903 | return; | 929 | goto out; |
| 904 | 930 | ||
| 905 | case ACPI_NOTIFY_POWER_FAULT: | 931 | case ACPI_NOTIFY_POWER_FAULT: |
| 906 | acpi_handle_err(handle, "Device has suffered a power fault\n"); | 932 | acpi_handle_err(handle, "Device has suffered a power fault\n"); |
| 907 | return; | 933 | goto out; |
| 908 | 934 | ||
| 909 | default: | 935 | default: |
| 910 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); | 936 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); |
| 911 | return; | 937 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; |
| 938 | goto out; | ||
| 912 | } | 939 | } |
| 913 | 940 | ||
| 914 | mutex_lock(&acpiphp_context_lock); | 941 | mutex_lock(&acpiphp_context_lock); |
| @@ -917,8 +944,14 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 917 | get_bridge(context->func.parent); | 944 | get_bridge(context->func.parent); |
| 918 | acpiphp_put_context(context); | 945 | acpiphp_put_context(context); |
| 919 | alloc_acpi_hp_work(handle, type, context, hotplug_event_work); | 946 | alloc_acpi_hp_work(handle, type, context, hotplug_event_work); |
| 947 | mutex_unlock(&acpiphp_context_lock); | ||
| 948 | return; | ||
| 920 | } | 949 | } |
| 921 | mutex_unlock(&acpiphp_context_lock); | 950 | mutex_unlock(&acpiphp_context_lock); |
| 951 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
| 952 | |||
| 953 | out: | ||
| 954 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
| 922 | } | 955 | } |
| 923 | 956 | ||
| 924 | /* | 957 | /* |
