diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-12-31 07:41:08 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-12-31 07:41:08 -0500 |
commit | d1badf8d4323cfc9325b06651bdfcf7df09f1f0e (patch) | |
tree | 08a8a8dab1955bb07724028ece639267502a07ba | |
parent | caa73ea158de9419f08e456f2716c71d1f06012a (diff) | |
parent | f244d8b623dae7a7bc695b0336f67729b95a9736 (diff) |
Merge branch 'acpi-pci-hotplug' into acpi-hotplug
Conflicts:
include/acpi/acpi_bus.h
-rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 16 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 26 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 4 |
5 files changed, 64 insertions, 8 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 2c38ae22c17f..384da5ab5955 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -149,6 +149,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data) | |||
149 | } | 149 | } |
150 | EXPORT_SYMBOL(acpi_bus_get_private_data); | 150 | EXPORT_SYMBOL(acpi_bus_get_private_data); |
151 | 151 | ||
152 | void acpi_bus_no_hotplug(acpi_handle handle) | ||
153 | { | ||
154 | struct acpi_device *adev = NULL; | ||
155 | |||
156 | acpi_bus_get_device(handle, &adev); | ||
157 | if (adev) | ||
158 | adev->flags.no_hotplug = true; | ||
159 | } | ||
160 | EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug); | ||
161 | |||
152 | static void acpi_print_osc_error(acpi_handle handle, | 162 | static void acpi_print_osc_error(acpi_handle handle, |
153 | struct acpi_osc_context *context, char *error) | 163 | struct acpi_osc_context *context, char *error) |
154 | { | 164 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 1f0b6d238cfa..1bc996c4f121 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -46,6 +46,7 @@ static struct nouveau_dsm_priv { | |||
46 | bool dsm_detected; | 46 | bool dsm_detected; |
47 | bool optimus_detected; | 47 | bool optimus_detected; |
48 | acpi_handle dhandle; | 48 | acpi_handle dhandle; |
49 | acpi_handle other_handle; | ||
49 | acpi_handle rom_handle; | 50 | acpi_handle rom_handle; |
50 | } nouveau_dsm_priv; | 51 | } nouveau_dsm_priv; |
51 | 52 | ||
@@ -255,9 +256,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
255 | if (!dhandle) | 256 | if (!dhandle) |
256 | return false; | 257 | return false; |
257 | 258 | ||
258 | if (!acpi_has_method(dhandle, "_DSM")) | 259 | if (!acpi_has_method(dhandle, "_DSM")) { |
260 | nouveau_dsm_priv.other_handle = dhandle; | ||
259 | return false; | 261 | return false; |
260 | 262 | } | |
261 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) | 263 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) |
262 | retval |= NOUVEAU_DSM_HAS_MUX; | 264 | retval |= NOUVEAU_DSM_HAS_MUX; |
263 | 265 | ||
@@ -333,6 +335,16 @@ static bool nouveau_dsm_detect(void) | |||
333 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", | 335 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", |
334 | acpi_method_name); | 336 | acpi_method_name); |
335 | nouveau_dsm_priv.dsm_detected = true; | 337 | nouveau_dsm_priv.dsm_detected = true; |
338 | /* | ||
339 | * On some systems hotplug events are generated for the device | ||
340 | * being switched off when _DSM is executed. They cause ACPI | ||
341 | * hotplug to trigger and attempt to remove the device from | ||
342 | * the system, which causes it to break down. Prevent that from | ||
343 | * happening by setting the no_hotplug flag for the involved | ||
344 | * ACPI device objects. | ||
345 | */ | ||
346 | acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); | ||
347 | acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle); | ||
336 | ret = true; | 348 | ret = true; |
337 | } | 349 | } |
338 | 350 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 9d302eaeea15..485848f889f5 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv { | |||
33 | bool atpx_detected; | 33 | bool atpx_detected; |
34 | /* handle for device - and atpx */ | 34 | /* handle for device - and atpx */ |
35 | acpi_handle dhandle; | 35 | acpi_handle dhandle; |
36 | acpi_handle other_handle; | ||
36 | struct radeon_atpx atpx; | 37 | struct radeon_atpx atpx; |
37 | } radeon_atpx_priv; | 38 | } radeon_atpx_priv; |
38 | 39 | ||
@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) | |||
451 | return false; | 452 | return false; |
452 | 453 | ||
453 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); | 454 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); |
454 | if (ACPI_FAILURE(status)) | 455 | if (ACPI_FAILURE(status)) { |
456 | radeon_atpx_priv.other_handle = dhandle; | ||
455 | return false; | 457 | return false; |
456 | 458 | } | |
457 | radeon_atpx_priv.dhandle = dhandle; | 459 | radeon_atpx_priv.dhandle = dhandle; |
458 | radeon_atpx_priv.atpx.handle = atpx_handle; | 460 | radeon_atpx_priv.atpx.handle = atpx_handle; |
459 | return true; | 461 | return true; |
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void) | |||
530 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", | 532 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", |
531 | acpi_method_name); | 533 | acpi_method_name); |
532 | radeon_atpx_priv.atpx_detected = true; | 534 | radeon_atpx_priv.atpx_detected = true; |
535 | /* | ||
536 | * On some systems hotplug events are generated for the device | ||
537 | * being switched off when ATPX is executed. They cause ACPI | ||
538 | * hotplug to trigger and attempt to remove the device from | ||
539 | * the system, which causes it to break down. Prevent that from | ||
540 | * happening by setting the no_hotplug flag for the involved | ||
541 | * ACPI device objects. | ||
542 | */ | ||
543 | acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); | ||
544 | acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); | ||
533 | return true; | 545 | return true; |
534 | } | 546 | } |
535 | return false; | 547 | return false; |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ec4ddae1fb54..4f0c40d405fc 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -645,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot) | |||
645 | slot->flags &= (~SLOT_ENABLED); | 645 | slot->flags &= (~SLOT_ENABLED); |
646 | } | 646 | } |
647 | 647 | ||
648 | static bool acpiphp_no_hotplug(acpi_handle handle) | ||
649 | { | ||
650 | struct acpi_device *adev = NULL; | ||
651 | |||
652 | acpi_bus_get_device(handle, &adev); | ||
653 | return adev && adev->flags.no_hotplug; | ||
654 | } | ||
655 | |||
656 | static bool slot_no_hotplug(struct acpiphp_slot *slot) | ||
657 | { | ||
658 | struct acpiphp_func *func; | ||
659 | |||
660 | list_for_each_entry(func, &slot->funcs, sibling) | ||
661 | if (acpiphp_no_hotplug(func_to_handle(func))) | ||
662 | return true; | ||
663 | |||
664 | return false; | ||
665 | } | ||
648 | 666 | ||
649 | /** | 667 | /** |
650 | * get_slot_status - get ACPI slot status | 668 | * get_slot_status - get ACPI slot status |
@@ -703,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev) | |||
703 | unsigned long long sta; | 721 | unsigned long long sta; |
704 | 722 | ||
705 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 723 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
706 | alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; | 724 | alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) |
725 | || acpiphp_no_hotplug(handle); | ||
707 | } | 726 | } |
708 | if (!alive) { | 727 | if (!alive) { |
709 | u32 v; | 728 | u32 v; |
@@ -743,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
743 | struct pci_dev *dev, *tmp; | 762 | struct pci_dev *dev, *tmp; |
744 | 763 | ||
745 | mutex_lock(&slot->crit_sect); | 764 | mutex_lock(&slot->crit_sect); |
746 | /* wake up all functions */ | 765 | if (slot_no_hotplug(slot)) { |
747 | if (get_slot_status(slot) == ACPI_STA_ALL) { | 766 | ; /* do nothing */ |
767 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { | ||
748 | /* remove stale devices if any */ | 768 | /* remove stale devices if any */ |
749 | list_for_each_entry_safe(dev, tmp, &bus->devices, | 769 | list_for_each_entry_safe(dev, tmp, &bus->devices, |
750 | bus_list) | 770 | bus_list) |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 48d302501539..e4ab7be65637 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -163,7 +163,8 @@ struct acpi_device_flags { | |||
163 | u32 match_driver:1; | 163 | u32 match_driver:1; |
164 | u32 initialized:1; | 164 | u32 initialized:1; |
165 | u32 visited:1; | 165 | u32 visited:1; |
166 | u32 reserved:25; | 166 | u32 no_hotplug:1; |
167 | u32 reserved:24; | ||
167 | }; | 168 | }; |
168 | 169 | ||
169 | /* File System */ | 170 | /* File System */ |
@@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj; | |||
344 | extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); | 345 | extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); |
345 | void acpi_bus_private_data_handler(acpi_handle, void *); | 346 | void acpi_bus_private_data_handler(acpi_handle, void *); |
346 | int acpi_bus_get_private_data(acpi_handle, void **); | 347 | int acpi_bus_get_private_data(acpi_handle, void **); |
348 | void acpi_bus_no_hotplug(acpi_handle handle); | ||
347 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); | 349 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); |
348 | extern int register_acpi_notifier(struct notifier_block *); | 350 | extern int register_acpi_notifier(struct notifier_block *); |
349 | extern int unregister_acpi_notifier(struct notifier_block *); | 351 | extern int unregister_acpi_notifier(struct notifier_block *); |