aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-12-31 07:41:08 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-12-31 07:41:08 -0500
commitd1badf8d4323cfc9325b06651bdfcf7df09f1f0e (patch)
tree08a8a8dab1955bb07724028ece639267502a07ba
parentcaa73ea158de9419f08e456f2716c71d1f06012a (diff)
parentf244d8b623dae7a7bc695b0336f67729b95a9736 (diff)
Merge branch 'acpi-pci-hotplug' into acpi-hotplug
Conflicts: include/acpi/acpi_bus.h
-rw-r--r--drivers/acpi/bus.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c16
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c26
-rw-r--r--include/acpi/acpi_bus.h4
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}
150EXPORT_SYMBOL(acpi_bus_get_private_data); 150EXPORT_SYMBOL(acpi_bus_get_private_data);
151 151
152void 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}
160EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
161
152static void acpi_print_osc_error(acpi_handle handle, 162static 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
648static 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
656static 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;
344extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); 345extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
345void acpi_bus_private_data_handler(acpi_handle, void *); 346void acpi_bus_private_data_handler(acpi_handle, void *);
346int acpi_bus_get_private_data(acpi_handle, void **); 347int acpi_bus_get_private_data(acpi_handle, void **);
348void acpi_bus_no_hotplug(acpi_handle handle);
347extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); 349extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
348extern int register_acpi_notifier(struct notifier_block *); 350extern int register_acpi_notifier(struct notifier_block *);
349extern int unregister_acpi_notifier(struct notifier_block *); 351extern int unregister_acpi_notifier(struct notifier_block *);