aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-13 17:27:26 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-22 22:00:26 -0400
commitbc805a55392a7cb3e9b1251d00449c70e3967fc5 (patch)
treed8ba2760f921df667ce90217257cf04ec0bbae77
parent5c8d0e1dc475f0f35b5a774c92c68c3f7dbd3f5f (diff)
ACPI / hotplug / PCI: Do not exectute _PS0 and _PS3 directly
The ACPI-based PCI hotplug (acpiphp) core code need not and really should not execute _PS0 and _PS3 directly for devices it handles. First of all, it is not necessary to put devices into D3 after acpi_bus_trim() has walked through them, because acpi_device_unregister() invoked by it puts each device into D3cold before returning. Thus after disable_device() the slot should be powered down already. Second, calling _PS0 directly on ACPI device objects may not be appropriate, because it may require power resources to be set up in a specific way in advance and that must be taken care of by the ACPI core. Thus modify acpiphp_bus_add() to power up the device using the appropriate interface after it has run acpi_bus_scan() on its handle. After that, the functions executing _PS0 and _PS3, power_on_slot() and power_off_slot(), are not necessary any more, so drop them and update the code calling them accordingly. Also drop the function flags related to device power states, since they aren't useful any more too. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/pci/hotplug/acpiphp.h7
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c106
2 files changed, 10 insertions, 103 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index fe6c79bb8eed..ca2c91df3d1a 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -162,7 +162,6 @@ struct acpiphp_attention_info
162 162
163/* slot flags */ 163/* slot flags */
164 164
165#define SLOT_POWEREDON (0x00000001)
166#define SLOT_ENABLED (0x00000002) 165#define SLOT_ENABLED (0x00000002)
167#define SLOT_MULTIFUNCTION (0x00000004) 166#define SLOT_MULTIFUNCTION (0x00000004)
168 167
@@ -170,11 +169,7 @@ struct acpiphp_attention_info
170 169
171#define FUNC_HAS_STA (0x00000001) 170#define FUNC_HAS_STA (0x00000001)
172#define FUNC_HAS_EJ0 (0x00000002) 171#define FUNC_HAS_EJ0 (0x00000002)
173#define FUNC_HAS_PS0 (0x00000010) 172#define FUNC_HAS_DCK (0x00000004)
174#define FUNC_HAS_PS1 (0x00000020)
175#define FUNC_HAS_PS2 (0x00000040)
176#define FUNC_HAS_PS3 (0x00000080)
177#define FUNC_HAS_DCK (0x00000100)
178 173
179/* function prototypes */ 174/* function prototypes */
180 175
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 44191db1f050..b6691cc8230b 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -303,12 +303,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
303 if (acpi_has_method(handle, "_STA")) 303 if (acpi_has_method(handle, "_STA"))
304 newfunc->flags |= FUNC_HAS_STA; 304 newfunc->flags |= FUNC_HAS_STA;
305 305
306 if (acpi_has_method(handle, "_PS0"))
307 newfunc->flags |= FUNC_HAS_PS0;
308
309 if (acpi_has_method(handle, "_PS3"))
310 newfunc->flags |= FUNC_HAS_PS3;
311
312 if (acpi_has_method(handle, "_DCK")) 306 if (acpi_has_method(handle, "_DCK"))
313 newfunc->flags |= FUNC_HAS_DCK; 307 newfunc->flags |= FUNC_HAS_DCK;
314 308
@@ -366,7 +360,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
366 360
367 if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), 361 if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function),
368 &val, 60*1000)) 362 &val, 60*1000))
369 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 363 slot->flags |= SLOT_ENABLED;
370 364
371 if (is_dock_device(handle)) { 365 if (is_dock_device(handle)) {
372 /* we don't want to call this device's _EJ0 366 /* we don't want to call this device's _EJ0
@@ -446,73 +440,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
446 mutex_unlock(&bridge_mutex); 440 mutex_unlock(&bridge_mutex);
447} 441}
448 442
449static int power_on_slot(struct acpiphp_slot *slot)
450{
451 acpi_status status;
452 struct acpiphp_func *func;
453 int retval = 0;
454
455 /* if already enabled, just skip */
456 if (slot->flags & SLOT_POWEREDON)
457 goto err_exit;
458
459 list_for_each_entry(func, &slot->funcs, sibling) {
460 if (func->flags & FUNC_HAS_PS0) {
461 dbg("%s: executing _PS0\n", __func__);
462 status = acpi_evaluate_object(func_to_handle(func),
463 "_PS0", NULL, NULL);
464 if (ACPI_FAILURE(status)) {
465 warn("%s: _PS0 failed\n", __func__);
466 retval = -1;
467 goto err_exit;
468 } else
469 break;
470 }
471 }
472
473 /* TBD: evaluate _STA to check if the slot is enabled */
474
475 slot->flags |= SLOT_POWEREDON;
476
477 err_exit:
478 return retval;
479}
480
481
482static int power_off_slot(struct acpiphp_slot *slot)
483{
484 acpi_status status;
485 struct acpiphp_func *func;
486
487 int retval = 0;
488
489 /* if already disabled, just skip */
490 if ((slot->flags & SLOT_POWEREDON) == 0)
491 goto err_exit;
492
493 list_for_each_entry(func, &slot->funcs, sibling) {
494 if (func->flags & FUNC_HAS_PS3) {
495 status = acpi_evaluate_object(func_to_handle(func),
496 "_PS3", NULL, NULL);
497 if (ACPI_FAILURE(status)) {
498 warn("%s: _PS3 failed\n", __func__);
499 retval = -1;
500 goto err_exit;
501 } else
502 break;
503 }
504 }
505
506 /* TBD: evaluate _STA to check if the slot is disabled */
507
508 slot->flags &= (~SLOT_POWEREDON);
509
510 err_exit:
511 return retval;
512}
513
514
515
516/** 443/**
517 * acpiphp_max_busnr - return the highest reserved bus number under the given bus. 444 * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
518 * @bus: bus to start search with 445 * @bus: bus to start search with
@@ -559,8 +486,13 @@ static void acpiphp_bus_trim(acpi_handle handle)
559 */ 486 */
560static void acpiphp_bus_add(acpi_handle handle) 487static void acpiphp_bus_add(acpi_handle handle)
561{ 488{
489 struct acpi_device *adev = NULL;
490
562 acpiphp_bus_trim(handle); 491 acpiphp_bus_trim(handle);
563 acpi_bus_scan(handle); 492 acpi_bus_scan(handle);
493 acpi_bus_get_device(handle, &adev);
494 if (adev)
495 acpi_device_set_power(adev, ACPI_STATE_D0);
564} 496}
565 497
566static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) 498static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
@@ -1095,23 +1027,8 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
1095 int retval; 1027 int retval;
1096 1028
1097 mutex_lock(&slot->crit_sect); 1029 mutex_lock(&slot->crit_sect);
1098 1030 /* configure all functions */
1099 /* wake up all functions */ 1031 retval = enable_device(slot);
1100 retval = power_on_slot(slot);
1101 if (retval)
1102 goto err_exit;
1103
1104 if (get_slot_status(slot) == ACPI_STA_ALL) {
1105 /* configure all functions */
1106 retval = enable_device(slot);
1107 if (retval)
1108 power_off_slot(slot);
1109 } else {
1110 dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
1111 power_off_slot(slot);
1112 }
1113
1114 err_exit:
1115 mutex_unlock(&slot->crit_sect); 1032 mutex_unlock(&slot->crit_sect);
1116 return retval; 1033 return retval;
1117} 1034}
@@ -1132,11 +1049,6 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
1132 if (retval) 1049 if (retval)
1133 goto err_exit; 1050 goto err_exit;
1134 1051
1135 /* power off all functions */
1136 retval = power_off_slot(slot);
1137 if (retval)
1138 goto err_exit;
1139
1140 list_for_each_entry(func, &slot->funcs, sibling) 1052 list_for_each_entry(func, &slot->funcs, sibling)
1141 if (func->flags & FUNC_HAS_EJ0) { 1053 if (func->flags & FUNC_HAS_EJ0) {
1142 acpi_handle handle = func_to_handle(func); 1054 acpi_handle handle = func_to_handle(func);
@@ -1159,7 +1071,7 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
1159 */ 1071 */
1160u8 acpiphp_get_power_status(struct acpiphp_slot *slot) 1072u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
1161{ 1073{
1162 return (slot->flags & SLOT_POWEREDON); 1074 return (slot->flags & SLOT_ENABLED);
1163} 1075}
1164 1076
1165 1077