diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-15 15:18:36 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-15 15:18:36 -0400 |
commit | 6de8eee17a324a4fd8d1a4588a18e976b68f330c (patch) | |
tree | 153ab542d89e5905badb062d106b7739de5852d2 | |
parent | fd7155fc9fca6464a5aa668965a3741b963f805f (diff) | |
parent | f91ce35e471ae17552ce7bfe355cfd997e3ad781 (diff) |
Merge branch 'pci/hotplug-vga' into for-linus
* pci/hotplug-vga:
ACPIPHP / radeon / nouveau: Remove acpi_bus_no_hotplug()
PCI: Add pci_ignore_hotplug() to ignore hotplug events for a device
-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/nouveau/nouveau_drm.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 16 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 12 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 4 | ||||
-rw-r--r-- | include/linux/pci.h | 6 |
9 files changed, 31 insertions, 51 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 8581f5b84f48..8b67bd0f6bb5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -177,16 +177,6 @@ void acpi_bus_detach_private_data(acpi_handle handle) | |||
177 | } | 177 | } |
178 | EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data); | 178 | EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data); |
179 | 179 | ||
180 | void acpi_bus_no_hotplug(acpi_handle handle) | ||
181 | { | ||
182 | struct acpi_device *adev = NULL; | ||
183 | |||
184 | acpi_bus_get_device(handle, &adev); | ||
185 | if (adev) | ||
186 | adev->flags.no_hotplug = true; | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug); | ||
189 | |||
190 | static void acpi_print_osc_error(acpi_handle handle, | 180 | static void acpi_print_osc_error(acpi_handle handle, |
191 | struct acpi_osc_context *context, char *error) | 181 | struct acpi_osc_context *context, char *error) |
192 | { | 182 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 279206997e5c..622424692b3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -46,7 +46,6 @@ 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; | ||
50 | acpi_handle rom_handle; | 49 | acpi_handle rom_handle; |
51 | } nouveau_dsm_priv; | 50 | } nouveau_dsm_priv; |
52 | 51 | ||
@@ -222,10 +221,9 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
222 | if (!dhandle) | 221 | if (!dhandle) |
223 | return false; | 222 | return false; |
224 | 223 | ||
225 | if (!acpi_has_method(dhandle, "_DSM")) { | 224 | if (!acpi_has_method(dhandle, "_DSM")) |
226 | nouveau_dsm_priv.other_handle = dhandle; | ||
227 | return false; | 225 | return false; |
228 | } | 226 | |
229 | if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, | 227 | if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, |
230 | 1 << NOUVEAU_DSM_POWER)) | 228 | 1 << NOUVEAU_DSM_POWER)) |
231 | retval |= NOUVEAU_DSM_HAS_MUX; | 229 | retval |= NOUVEAU_DSM_HAS_MUX; |
@@ -301,16 +299,6 @@ static bool nouveau_dsm_detect(void) | |||
301 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", | 299 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", |
302 | acpi_method_name); | 300 | acpi_method_name); |
303 | nouveau_dsm_priv.dsm_detected = true; | 301 | nouveau_dsm_priv.dsm_detected = true; |
304 | /* | ||
305 | * On some systems hotplug events are generated for the device | ||
306 | * being switched off when _DSM is executed. They cause ACPI | ||
307 | * hotplug to trigger and attempt to remove the device from | ||
308 | * the system, which causes it to break down. Prevent that from | ||
309 | * happening by setting the no_hotplug flag for the involved | ||
310 | * ACPI device objects. | ||
311 | */ | ||
312 | acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); | ||
313 | acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle); | ||
314 | ret = true; | 302 | ret = true; |
315 | } | 303 | } |
316 | 304 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 250a5e88c751..9c3af96a7153 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -627,6 +627,7 @@ int nouveau_pmops_suspend(struct device *dev) | |||
627 | 627 | ||
628 | pci_save_state(pdev); | 628 | pci_save_state(pdev); |
629 | pci_disable_device(pdev); | 629 | pci_disable_device(pdev); |
630 | pci_ignore_hotplug(pdev); | ||
630 | pci_set_power_state(pdev, PCI_D3hot); | 631 | pci_set_power_state(pdev, PCI_D3hot); |
631 | return 0; | 632 | return 0; |
632 | } | 633 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index a9fb0d016d38..8bc7d0bbd3c8 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -33,7 +33,6 @@ 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; | ||
37 | struct radeon_atpx atpx; | 36 | struct radeon_atpx atpx; |
38 | } radeon_atpx_priv; | 37 | } radeon_atpx_priv; |
39 | 38 | ||
@@ -453,10 +452,9 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) | |||
453 | return false; | 452 | return false; |
454 | 453 | ||
455 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); | 454 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); |
456 | if (ACPI_FAILURE(status)) { | 455 | if (ACPI_FAILURE(status)) |
457 | radeon_atpx_priv.other_handle = dhandle; | ||
458 | return false; | 456 | return false; |
459 | } | 457 | |
460 | radeon_atpx_priv.dhandle = dhandle; | 458 | radeon_atpx_priv.dhandle = dhandle; |
461 | radeon_atpx_priv.atpx.handle = atpx_handle; | 459 | radeon_atpx_priv.atpx.handle = atpx_handle; |
462 | return true; | 460 | return true; |
@@ -540,16 +538,6 @@ static bool radeon_atpx_detect(void) | |||
540 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", | 538 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", |
541 | acpi_method_name); | 539 | acpi_method_name); |
542 | radeon_atpx_priv.atpx_detected = true; | 540 | radeon_atpx_priv.atpx_detected = true; |
543 | /* | ||
544 | * On some systems hotplug events are generated for the device | ||
545 | * being switched off when ATPX is executed. They cause ACPI | ||
546 | * hotplug to trigger and attempt to remove the device from | ||
547 | * the system, which causes it to break down. Prevent that from | ||
548 | * happening by setting the no_hotplug flag for the involved | ||
549 | * ACPI device objects. | ||
550 | */ | ||
551 | acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); | ||
552 | acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); | ||
553 | return true; | 541 | return true; |
554 | } | 542 | } |
555 | return false; | 543 | return false; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8df888908833..abbd87adfd75 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -440,6 +440,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev) | |||
440 | ret = radeon_suspend_kms(drm_dev, false, false); | 440 | ret = radeon_suspend_kms(drm_dev, false, false); |
441 | pci_save_state(pdev); | 441 | pci_save_state(pdev); |
442 | pci_disable_device(pdev); | 442 | pci_disable_device(pdev); |
443 | pci_ignore_hotplug(pdev); | ||
443 | pci_set_power_state(pdev, PCI_D3cold); | 444 | pci_set_power_state(pdev, PCI_D3cold); |
444 | drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; | 445 | drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; |
445 | 446 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 70741c8c46a0..6cd5160fc057 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -560,19 +560,15 @@ static void disable_slot(struct acpiphp_slot *slot) | |||
560 | slot->flags &= (~SLOT_ENABLED); | 560 | slot->flags &= (~SLOT_ENABLED); |
561 | } | 561 | } |
562 | 562 | ||
563 | static bool acpiphp_no_hotplug(struct acpi_device *adev) | ||
564 | { | ||
565 | return adev && adev->flags.no_hotplug; | ||
566 | } | ||
567 | |||
568 | static bool slot_no_hotplug(struct acpiphp_slot *slot) | 563 | static bool slot_no_hotplug(struct acpiphp_slot *slot) |
569 | { | 564 | { |
570 | struct acpiphp_func *func; | 565 | struct pci_bus *bus = slot->bus; |
566 | struct pci_dev *dev; | ||
571 | 567 | ||
572 | list_for_each_entry(func, &slot->funcs, sibling) | 568 | list_for_each_entry(dev, &bus->devices, bus_list) { |
573 | if (acpiphp_no_hotplug(func_to_acpi_device(func))) | 569 | if (PCI_SLOT(dev->devfn) == slot->device && dev->ignore_hotplug) |
574 | return true; | 570 | return true; |
575 | 571 | } | |
576 | return false; | 572 | return false; |
577 | } | 573 | } |
578 | 574 | ||
@@ -645,7 +641,7 @@ static void trim_stale_devices(struct pci_dev *dev) | |||
645 | 641 | ||
646 | status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); | 642 | status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); |
647 | alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) | 643 | alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) |
648 | || acpiphp_no_hotplug(adev); | 644 | || dev->ignore_hotplug; |
649 | } | 645 | } |
650 | if (!alive) | 646 | if (!alive) |
651 | alive = pci_device_is_present(dev); | 647 | alive = pci_device_is_present(dev); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9da84b8b27d8..5e01ae39ec46 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -506,6 +506,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
506 | { | 506 | { |
507 | struct controller *ctrl = (struct controller *)dev_id; | 507 | struct controller *ctrl = (struct controller *)dev_id; |
508 | struct pci_dev *pdev = ctrl_dev(ctrl); | 508 | struct pci_dev *pdev = ctrl_dev(ctrl); |
509 | struct pci_bus *subordinate = pdev->subordinate; | ||
510 | struct pci_dev *dev; | ||
509 | struct slot *slot = ctrl->slot; | 511 | struct slot *slot = ctrl->slot; |
510 | u16 detected, intr_loc; | 512 | u16 detected, intr_loc; |
511 | 513 | ||
@@ -539,6 +541,16 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
539 | wake_up(&ctrl->queue); | 541 | wake_up(&ctrl->queue); |
540 | } | 542 | } |
541 | 543 | ||
544 | if (subordinate) { | ||
545 | list_for_each_entry(dev, &subordinate->devices, bus_list) { | ||
546 | if (dev->ignore_hotplug) { | ||
547 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", | ||
548 | intr_loc, pci_name(dev)); | ||
549 | return IRQ_HANDLED; | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | |||
542 | if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) | 554 | if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) |
543 | return IRQ_HANDLED; | 555 | return IRQ_HANDLED; |
544 | 556 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index bcfd808b1098..95c506961a13 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -204,10 +204,9 @@ struct acpi_device_flags { | |||
204 | u32 match_driver:1; | 204 | u32 match_driver:1; |
205 | u32 initialized:1; | 205 | u32 initialized:1; |
206 | u32 visited:1; | 206 | u32 visited:1; |
207 | u32 no_hotplug:1; | ||
208 | u32 hotplug_notify:1; | 207 | u32 hotplug_notify:1; |
209 | u32 is_dock_station:1; | 208 | u32 is_dock_station:1; |
210 | u32 reserved:22; | 209 | u32 reserved:23; |
211 | }; | 210 | }; |
212 | 211 | ||
213 | /* File System */ | 212 | /* File System */ |
@@ -412,7 +411,6 @@ void acpi_bus_private_data_handler(acpi_handle, void *); | |||
412 | int acpi_bus_get_private_data(acpi_handle, void **); | 411 | int acpi_bus_get_private_data(acpi_handle, void **); |
413 | int acpi_bus_attach_private_data(acpi_handle, void *); | 412 | int acpi_bus_attach_private_data(acpi_handle, void *); |
414 | void acpi_bus_detach_private_data(acpi_handle); | 413 | void acpi_bus_detach_private_data(acpi_handle); |
415 | void acpi_bus_no_hotplug(acpi_handle handle); | ||
416 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); | 414 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); |
417 | extern int register_acpi_notifier(struct notifier_block *); | 415 | extern int register_acpi_notifier(struct notifier_block *); |
418 | extern int unregister_acpi_notifier(struct notifier_block *); | 416 | extern int unregister_acpi_notifier(struct notifier_block *); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 61978a460841..96453f9bc8ba 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -303,6 +303,7 @@ struct pci_dev { | |||
303 | D3cold, not set for devices | 303 | D3cold, not set for devices |
304 | powered on/off by the | 304 | powered on/off by the |
305 | corresponding bridge */ | 305 | corresponding bridge */ |
306 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ | ||
306 | unsigned int d3_delay; /* D3->D0 transition time in ms */ | 307 | unsigned int d3_delay; /* D3->D0 transition time in ms */ |
307 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ | 308 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ |
308 | 309 | ||
@@ -1021,6 +1022,11 @@ bool pci_dev_run_wake(struct pci_dev *dev); | |||
1021 | bool pci_check_pme_status(struct pci_dev *dev); | 1022 | bool pci_check_pme_status(struct pci_dev *dev); |
1022 | void pci_pme_wakeup_bus(struct pci_bus *bus); | 1023 | void pci_pme_wakeup_bus(struct pci_bus *bus); |
1023 | 1024 | ||
1025 | static inline void pci_ignore_hotplug(struct pci_dev *dev) | ||
1026 | { | ||
1027 | dev->ignore_hotplug = 1; | ||
1028 | } | ||
1029 | |||
1024 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, | 1030 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, |
1025 | bool enable) | 1031 | bool enable) |
1026 | { | 1032 | { |