11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ec2cd81cSRafael J. Wysocki /* 3ec2cd81cSRafael J. Wysocki * drivers/acpi/device_pm.c - ACPI device power management routines. 4ec2cd81cSRafael J. Wysocki * 5ec2cd81cSRafael J. Wysocki * Copyright (C) 2012, Intel Corp. 6ec2cd81cSRafael J. Wysocki * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> 7ec2cd81cSRafael J. Wysocki * 8ec2cd81cSRafael J. Wysocki * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9ec2cd81cSRafael J. Wysocki * 10ec2cd81cSRafael J. Wysocki * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11ec2cd81cSRafael J. Wysocki */ 12ec2cd81cSRafael J. Wysocki 137b199811SRafael J. Wysocki #include <linux/acpi.h> 1486b3832cSRafael J. Wysocki #include <linux/export.h> 15ec2cd81cSRafael J. Wysocki #include <linux/mutex.h> 1686b3832cSRafael J. Wysocki #include <linux/pm_qos.h> 17989561deSTomeu Vizoso #include <linux/pm_domain.h> 18cd7bd02dSRafael J. Wysocki #include <linux/pm_runtime.h> 1933e4f80eSRafael J. Wysocki #include <linux/suspend.h> 20ec2cd81cSRafael J. Wysocki 219ce4e607SRafael J. Wysocki #include "internal.h" 229ce4e607SRafael J. Wysocki 239ce4e607SRafael J. Wysocki #define _COMPONENT ACPI_POWER_COMPONENT 249ce4e607SRafael J. Wysocki ACPI_MODULE_NAME("device_pm"); 25ec2cd81cSRafael J. Wysocki 2686b3832cSRafael J. Wysocki /** 279ce4e607SRafael J. Wysocki * acpi_power_state_string - String representation of ACPI device power state. 289ce4e607SRafael J. Wysocki * @state: ACPI device power state to return the string representation of. 299ce4e607SRafael J. Wysocki */ 309ce4e607SRafael J. Wysocki const char *acpi_power_state_string(int state) 319ce4e607SRafael J. Wysocki { 329ce4e607SRafael J. Wysocki switch (state) { 339ce4e607SRafael J. Wysocki case ACPI_STATE_D0: 349ce4e607SRafael J. Wysocki return "D0"; 359ce4e607SRafael J. Wysocki case ACPI_STATE_D1: 369ce4e607SRafael J. Wysocki return "D1"; 379ce4e607SRafael J. Wysocki case ACPI_STATE_D2: 389ce4e607SRafael J. Wysocki return "D2"; 399ce4e607SRafael J. Wysocki case ACPI_STATE_D3_HOT: 409ce4e607SRafael J. Wysocki return "D3hot"; 419ce4e607SRafael J. Wysocki case ACPI_STATE_D3_COLD: 42898fee4fSRafael J. Wysocki return "D3cold"; 439ce4e607SRafael J. Wysocki default: 449ce4e607SRafael J. Wysocki return "(unknown)"; 459ce4e607SRafael J. Wysocki } 469ce4e607SRafael J. Wysocki } 479ce4e607SRafael J. Wysocki 489ce4e607SRafael J. Wysocki /** 499ce4e607SRafael J. Wysocki * acpi_device_get_power - Get power state of an ACPI device. 509ce4e607SRafael J. Wysocki * @device: Device to get the power state of. 519ce4e607SRafael J. Wysocki * @state: Place to store the power state of the device. 529ce4e607SRafael J. Wysocki * 539ce4e607SRafael J. Wysocki * This function does not update the device's power.state field, but it may 549ce4e607SRafael J. Wysocki * update its parent's power.state field (when the parent's power state is 559ce4e607SRafael J. Wysocki * unknown and the device's power state turns out to be D0). 569ce4e607SRafael J. Wysocki */ 579ce4e607SRafael J. Wysocki int acpi_device_get_power(struct acpi_device *device, int *state) 589ce4e607SRafael J. Wysocki { 599ce4e607SRafael J. Wysocki int result = ACPI_STATE_UNKNOWN; 609ce4e607SRafael J. Wysocki 619ce4e607SRafael J. Wysocki if (!device || !state) 629ce4e607SRafael J. Wysocki return -EINVAL; 639ce4e607SRafael J. Wysocki 649ce4e607SRafael J. Wysocki if (!device->flags.power_manageable) { 659ce4e607SRafael J. Wysocki /* TBD: Non-recursive algorithm for walking up hierarchy. */ 669ce4e607SRafael J. Wysocki *state = device->parent ? 679ce4e607SRafael J. Wysocki device->parent->power.state : ACPI_STATE_D0; 689ce4e607SRafael J. Wysocki goto out; 699ce4e607SRafael J. Wysocki } 709ce4e607SRafael J. Wysocki 719ce4e607SRafael J. Wysocki /* 7275eb2d13SRafael J. Wysocki * Get the device's power state from power resources settings and _PSC, 7375eb2d13SRafael J. Wysocki * if available. 749ce4e607SRafael J. Wysocki */ 7575eb2d13SRafael J. Wysocki if (device->power.flags.power_resources) { 769ce4e607SRafael J. Wysocki int error = acpi_power_get_inferred_state(device, &result); 779ce4e607SRafael J. Wysocki if (error) 789ce4e607SRafael J. Wysocki return error; 7975eb2d13SRafael J. Wysocki } 8075eb2d13SRafael J. Wysocki if (device->power.flags.explicit_get) { 8175eb2d13SRafael J. Wysocki acpi_handle handle = device->handle; 8275eb2d13SRafael J. Wysocki unsigned long long psc; 8375eb2d13SRafael J. Wysocki acpi_status status; 8475eb2d13SRafael J. Wysocki 8575eb2d13SRafael J. Wysocki status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc); 8675eb2d13SRafael J. Wysocki if (ACPI_FAILURE(status)) 8775eb2d13SRafael J. Wysocki return -ENODEV; 8875eb2d13SRafael J. Wysocki 8975eb2d13SRafael J. Wysocki /* 9075eb2d13SRafael J. Wysocki * The power resources settings may indicate a power state 9120dacb71SRafael J. Wysocki * shallower than the actual power state of the device, because 9220dacb71SRafael J. Wysocki * the same power resources may be referenced by other devices. 9375eb2d13SRafael J. Wysocki * 9420dacb71SRafael J. Wysocki * For systems predating ACPI 4.0 we assume that D3hot is the 9520dacb71SRafael J. Wysocki * deepest state that can be supported. 9675eb2d13SRafael J. Wysocki */ 9775eb2d13SRafael J. Wysocki if (psc > result && psc < ACPI_STATE_D3_COLD) 9875eb2d13SRafael J. Wysocki result = psc; 9975eb2d13SRafael J. Wysocki else if (result == ACPI_STATE_UNKNOWN) 10020dacb71SRafael J. Wysocki result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_HOT : psc; 1019ce4e607SRafael J. Wysocki } 1029ce4e607SRafael J. Wysocki 1039ce4e607SRafael J. Wysocki /* 1049ce4e607SRafael J. Wysocki * If we were unsure about the device parent's power state up to this 1059ce4e607SRafael J. Wysocki * point, the fact that the device is in D0 implies that the parent has 106644f17adSMika Westerberg * to be in D0 too, except if ignore_parent is set. 1079ce4e607SRafael J. Wysocki */ 108644f17adSMika Westerberg if (!device->power.flags.ignore_parent && device->parent 109644f17adSMika Westerberg && device->parent->power.state == ACPI_STATE_UNKNOWN 1109ce4e607SRafael J. Wysocki && result == ACPI_STATE_D0) 1119ce4e607SRafael J. Wysocki device->parent->power.state = ACPI_STATE_D0; 1129ce4e607SRafael J. Wysocki 1139ce4e607SRafael J. Wysocki *state = result; 1149ce4e607SRafael J. Wysocki 1159ce4e607SRafael J. Wysocki out: 1169ce4e607SRafael J. Wysocki ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", 1179ce4e607SRafael J. Wysocki device->pnp.bus_id, acpi_power_state_string(*state))); 1189ce4e607SRafael J. Wysocki 1199ce4e607SRafael J. Wysocki return 0; 1209ce4e607SRafael J. Wysocki } 121fe650c8bSHans de Goede EXPORT_SYMBOL(acpi_device_get_power); 1229ce4e607SRafael J. Wysocki 1239c0f45e3SRafael J. Wysocki static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) 1249c0f45e3SRafael J. Wysocki { 1259c0f45e3SRafael J. Wysocki if (adev->power.states[state].flags.explicit_set) { 1269c0f45e3SRafael J. Wysocki char method[5] = { '_', 'P', 'S', '0' + state, '\0' }; 1279c0f45e3SRafael J. Wysocki acpi_status status; 1289c0f45e3SRafael J. Wysocki 1299c0f45e3SRafael J. Wysocki status = acpi_evaluate_object(adev->handle, method, NULL, NULL); 1309c0f45e3SRafael J. Wysocki if (ACPI_FAILURE(status)) 1319c0f45e3SRafael J. Wysocki return -ENODEV; 1329c0f45e3SRafael J. Wysocki } 1339c0f45e3SRafael J. Wysocki return 0; 1349c0f45e3SRafael J. Wysocki } 1359c0f45e3SRafael J. Wysocki 1369ce4e607SRafael J. Wysocki /** 1379ce4e607SRafael J. Wysocki * acpi_device_set_power - Set power state of an ACPI device. 1389ce4e607SRafael J. Wysocki * @device: Device to set the power state of. 1399ce4e607SRafael J. Wysocki * @state: New power state to set. 1409ce4e607SRafael J. Wysocki * 1419ce4e607SRafael J. Wysocki * Callers must ensure that the device is power manageable before using this 1429ce4e607SRafael J. Wysocki * function. 1439ce4e607SRafael J. Wysocki */ 1449ce4e607SRafael J. Wysocki int acpi_device_set_power(struct acpi_device *device, int state) 1459ce4e607SRafael J. Wysocki { 14620dacb71SRafael J. Wysocki int target_state = state; 1479ce4e607SRafael J. Wysocki int result = 0; 1489ce4e607SRafael J. Wysocki 1492c7d132aSRafael J. Wysocki if (!device || !device->flags.power_manageable 1502c7d132aSRafael J. Wysocki || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) 1519ce4e607SRafael J. Wysocki return -EINVAL; 1529ce4e607SRafael J. Wysocki 1539ce4e607SRafael J. Wysocki /* Make sure this is a valid target state */ 1549ce4e607SRafael J. Wysocki 1559ce4e607SRafael J. Wysocki if (state == device->power.state) { 156b69137a7SRafael J. Wysocki ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already in %s\n", 157b69137a7SRafael J. Wysocki device->pnp.bus_id, 1589ce4e607SRafael J. Wysocki acpi_power_state_string(state))); 1599ce4e607SRafael J. Wysocki return 0; 1609ce4e607SRafael J. Wysocki } 1619ce4e607SRafael J. Wysocki 16220dacb71SRafael J. Wysocki if (state == ACPI_STATE_D3_COLD) { 16320dacb71SRafael J. Wysocki /* 16420dacb71SRafael J. Wysocki * For transitions to D3cold we need to execute _PS3 and then 16520dacb71SRafael J. Wysocki * possibly drop references to the power resources in use. 16620dacb71SRafael J. Wysocki */ 16720dacb71SRafael J. Wysocki state = ACPI_STATE_D3_HOT; 16820dacb71SRafael J. Wysocki /* If _PR3 is not available, use D3hot as the target state. */ 16920dacb71SRafael J. Wysocki if (!device->power.states[ACPI_STATE_D3_COLD].flags.valid) 17020dacb71SRafael J. Wysocki target_state = state; 17120dacb71SRafael J. Wysocki } else if (!device->power.states[state].flags.valid) { 172b69137a7SRafael J. Wysocki dev_warn(&device->dev, "Power state %s not supported\n", 1739ce4e607SRafael J. Wysocki acpi_power_state_string(state)); 1749ce4e607SRafael J. Wysocki return -ENODEV; 1759ce4e607SRafael J. Wysocki } 17620dacb71SRafael J. Wysocki 177644f17adSMika Westerberg if (!device->power.flags.ignore_parent && 178644f17adSMika Westerberg device->parent && (state < device->parent->power.state)) { 179b69137a7SRafael J. Wysocki dev_warn(&device->dev, 180593298e6SAaron Lu "Cannot transition to power state %s for parent in %s\n", 181593298e6SAaron Lu acpi_power_state_string(state), 182593298e6SAaron Lu acpi_power_state_string(device->parent->power.state)); 1839ce4e607SRafael J. Wysocki return -ENODEV; 1849ce4e607SRafael J. Wysocki } 1859ce4e607SRafael J. Wysocki 186e78adb75SRafael J. Wysocki /* 187e78adb75SRafael J. Wysocki * Transition Power 188e78adb75SRafael J. Wysocki * ---------------- 18920dacb71SRafael J. Wysocki * In accordance with ACPI 6, _PSx is executed before manipulating power 19020dacb71SRafael J. Wysocki * resources, unless the target state is D0, in which case _PS0 is 19120dacb71SRafael J. Wysocki * supposed to be executed after turning the power resources on. 192e78adb75SRafael J. Wysocki */ 19320dacb71SRafael J. Wysocki if (state > ACPI_STATE_D0) { 19420dacb71SRafael J. Wysocki /* 19520dacb71SRafael J. Wysocki * According to ACPI 6, devices cannot go from lower-power 19620dacb71SRafael J. Wysocki * (deeper) states to higher-power (shallower) states. 19720dacb71SRafael J. Wysocki */ 19820dacb71SRafael J. Wysocki if (state < device->power.state) { 19920dacb71SRafael J. Wysocki dev_warn(&device->dev, "Cannot transition from %s to %s\n", 20020dacb71SRafael J. Wysocki acpi_power_state_string(device->power.state), 20120dacb71SRafael J. Wysocki acpi_power_state_string(state)); 20220dacb71SRafael J. Wysocki return -ENODEV; 2039ce4e607SRafael J. Wysocki } 20420dacb71SRafael J. Wysocki 205e78adb75SRafael J. Wysocki result = acpi_dev_pm_explicit_set(device, state); 206e78adb75SRafael J. Wysocki if (result) 207e78adb75SRafael J. Wysocki goto end; 2089ce4e607SRafael J. Wysocki 20920dacb71SRafael J. Wysocki if (device->power.flags.power_resources) 21020dacb71SRafael J. Wysocki result = acpi_power_transition(device, target_state); 21120dacb71SRafael J. Wysocki } else { 21220dacb71SRafael J. Wysocki if (device->power.flags.power_resources) { 21320dacb71SRafael J. Wysocki result = acpi_power_transition(device, ACPI_STATE_D0); 21420dacb71SRafael J. Wysocki if (result) 21520dacb71SRafael J. Wysocki goto end; 21620dacb71SRafael J. Wysocki } 21720dacb71SRafael J. Wysocki result = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0); 218e5656271SRafael J. Wysocki } 2199ce4e607SRafael J. Wysocki 2209ce4e607SRafael J. Wysocki end: 221e78adb75SRafael J. Wysocki if (result) { 222b69137a7SRafael J. Wysocki dev_warn(&device->dev, "Failed to change power state to %s\n", 2239ce4e607SRafael J. Wysocki acpi_power_state_string(state)); 224e78adb75SRafael J. Wysocki } else { 22571b65445SMika Westerberg device->power.state = target_state; 2269ce4e607SRafael J. Wysocki ACPI_DEBUG_PRINT((ACPI_DB_INFO, 2279ce4e607SRafael J. Wysocki "Device [%s] transitioned to %s\n", 2289ce4e607SRafael J. Wysocki device->pnp.bus_id, 2299ce4e607SRafael J. Wysocki acpi_power_state_string(state))); 2309ce4e607SRafael J. Wysocki } 2319ce4e607SRafael J. Wysocki 2329ce4e607SRafael J. Wysocki return result; 2339ce4e607SRafael J. Wysocki } 2349ce4e607SRafael J. Wysocki EXPORT_SYMBOL(acpi_device_set_power); 2359ce4e607SRafael J. Wysocki 2369ce4e607SRafael J. Wysocki int acpi_bus_set_power(acpi_handle handle, int state) 2379ce4e607SRafael J. Wysocki { 2389ce4e607SRafael J. Wysocki struct acpi_device *device; 2399ce4e607SRafael J. Wysocki int result; 2409ce4e607SRafael J. Wysocki 2419ce4e607SRafael J. Wysocki result = acpi_bus_get_device(handle, &device); 2429ce4e607SRafael J. Wysocki if (result) 2439ce4e607SRafael J. Wysocki return result; 2449ce4e607SRafael J. Wysocki 2459ce4e607SRafael J. Wysocki return acpi_device_set_power(device, state); 2469ce4e607SRafael J. Wysocki } 2479ce4e607SRafael J. Wysocki EXPORT_SYMBOL(acpi_bus_set_power); 2489ce4e607SRafael J. Wysocki 2499ce4e607SRafael J. Wysocki int acpi_bus_init_power(struct acpi_device *device) 2509ce4e607SRafael J. Wysocki { 2519ce4e607SRafael J. Wysocki int state; 2529ce4e607SRafael J. Wysocki int result; 2539ce4e607SRafael J. Wysocki 2549ce4e607SRafael J. Wysocki if (!device) 2559ce4e607SRafael J. Wysocki return -EINVAL; 2569ce4e607SRafael J. Wysocki 2579ce4e607SRafael J. Wysocki device->power.state = ACPI_STATE_UNKNOWN; 258cde1f95fSSakari Ailus if (!acpi_device_is_present(device)) { 259cde1f95fSSakari Ailus device->flags.initialized = false; 2601b1f3e16SRafael J. Wysocki return -ENXIO; 261cde1f95fSSakari Ailus } 2629ce4e607SRafael J. Wysocki 2639ce4e607SRafael J. Wysocki result = acpi_device_get_power(device, &state); 2649ce4e607SRafael J. Wysocki if (result) 2659ce4e607SRafael J. Wysocki return result; 2669ce4e607SRafael J. Wysocki 267a2367807SRafael J. Wysocki if (state < ACPI_STATE_D3_COLD && device->power.flags.power_resources) { 26820dacb71SRafael J. Wysocki /* Reference count the power resources. */ 2699ce4e607SRafael J. Wysocki result = acpi_power_on_resources(device, state); 270a2367807SRafael J. Wysocki if (result) 2719ce4e607SRafael J. Wysocki return result; 272a2367807SRafael J. Wysocki 27320dacb71SRafael J. Wysocki if (state == ACPI_STATE_D0) { 27420dacb71SRafael J. Wysocki /* 27520dacb71SRafael J. Wysocki * If _PSC is not present and the state inferred from 27620dacb71SRafael J. Wysocki * power resources appears to be D0, it still may be 27720dacb71SRafael J. Wysocki * necessary to execute _PS0 at this point, because 27820dacb71SRafael J. Wysocki * another device using the same power resources may 27920dacb71SRafael J. Wysocki * have been put into D0 previously and that's why we 28020dacb71SRafael J. Wysocki * see D0 here. 28120dacb71SRafael J. Wysocki */ 2829c0f45e3SRafael J. Wysocki result = acpi_dev_pm_explicit_set(device, state); 2839c0f45e3SRafael J. Wysocki if (result) 2849c0f45e3SRafael J. Wysocki return result; 28520dacb71SRafael J. Wysocki } 286b3785492SRafael J. Wysocki } else if (state == ACPI_STATE_UNKNOWN) { 2877cd8407dSRafael J. Wysocki /* 2887cd8407dSRafael J. Wysocki * No power resources and missing _PSC? Cross fingers and make 2897cd8407dSRafael J. Wysocki * it D0 in hope that this is what the BIOS put the device into. 2907cd8407dSRafael J. Wysocki * [We tried to force D0 here by executing _PS0, but that broke 2917cd8407dSRafael J. Wysocki * Toshiba P870-303 in a nasty way.] 2927cd8407dSRafael J. Wysocki */ 293b3785492SRafael J. Wysocki state = ACPI_STATE_D0; 294a2367807SRafael J. Wysocki } 295a2367807SRafael J. Wysocki device->power.state = state; 296a2367807SRafael J. Wysocki return 0; 2979ce4e607SRafael J. Wysocki } 2989ce4e607SRafael J. Wysocki 299b9e95fc6SRafael J. Wysocki /** 300b9e95fc6SRafael J. Wysocki * acpi_device_fix_up_power - Force device with missing _PSC into D0. 301b9e95fc6SRafael J. Wysocki * @device: Device object whose power state is to be fixed up. 302b9e95fc6SRafael J. Wysocki * 303b9e95fc6SRafael J. Wysocki * Devices without power resources and _PSC, but having _PS0 and _PS3 defined, 304b9e95fc6SRafael J. Wysocki * are assumed to be put into D0 by the BIOS. However, in some cases that may 305b9e95fc6SRafael J. Wysocki * not be the case and this function should be used then. 306b9e95fc6SRafael J. Wysocki */ 307b9e95fc6SRafael J. Wysocki int acpi_device_fix_up_power(struct acpi_device *device) 308b9e95fc6SRafael J. Wysocki { 309b9e95fc6SRafael J. Wysocki int ret = 0; 310b9e95fc6SRafael J. Wysocki 311b9e95fc6SRafael J. Wysocki if (!device->power.flags.power_resources 312b9e95fc6SRafael J. Wysocki && !device->power.flags.explicit_get 313b9e95fc6SRafael J. Wysocki && device->power.state == ACPI_STATE_D0) 314b9e95fc6SRafael J. Wysocki ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0); 315b9e95fc6SRafael J. Wysocki 316b9e95fc6SRafael J. Wysocki return ret; 317b9e95fc6SRafael J. Wysocki } 31878a898d0SUlf Hansson EXPORT_SYMBOL_GPL(acpi_device_fix_up_power); 319b9e95fc6SRafael J. Wysocki 320202317a5SRafael J. Wysocki int acpi_device_update_power(struct acpi_device *device, int *state_p) 3219ce4e607SRafael J. Wysocki { 3229ce4e607SRafael J. Wysocki int state; 3239ce4e607SRafael J. Wysocki int result; 3249ce4e607SRafael J. Wysocki 325202317a5SRafael J. Wysocki if (device->power.state == ACPI_STATE_UNKNOWN) { 326202317a5SRafael J. Wysocki result = acpi_bus_init_power(device); 327202317a5SRafael J. Wysocki if (!result && state_p) 328202317a5SRafael J. Wysocki *state_p = device->power.state; 329202317a5SRafael J. Wysocki 3309ce4e607SRafael J. Wysocki return result; 331202317a5SRafael J. Wysocki } 3329ce4e607SRafael J. Wysocki 3339ce4e607SRafael J. Wysocki result = acpi_device_get_power(device, &state); 3349ce4e607SRafael J. Wysocki if (result) 3359ce4e607SRafael J. Wysocki return result; 3369ce4e607SRafael J. Wysocki 33791bdad0bSRafael J. Wysocki if (state == ACPI_STATE_UNKNOWN) { 338511d5c42SRafael J. Wysocki state = ACPI_STATE_D0; 3399ce4e607SRafael J. Wysocki result = acpi_device_set_power(device, state); 34091bdad0bSRafael J. Wysocki if (result) 34191bdad0bSRafael J. Wysocki return result; 34291bdad0bSRafael J. Wysocki } else { 34391bdad0bSRafael J. Wysocki if (device->power.flags.power_resources) { 34491bdad0bSRafael J. Wysocki /* 34591bdad0bSRafael J. Wysocki * We don't need to really switch the state, bu we need 34691bdad0bSRafael J. Wysocki * to update the power resources' reference counters. 34791bdad0bSRafael J. Wysocki */ 34891bdad0bSRafael J. Wysocki result = acpi_power_transition(device, state); 34991bdad0bSRafael J. Wysocki if (result) 35091bdad0bSRafael J. Wysocki return result; 35191bdad0bSRafael J. Wysocki } 35291bdad0bSRafael J. Wysocki device->power.state = state; 35391bdad0bSRafael J. Wysocki } 35491bdad0bSRafael J. Wysocki if (state_p) 3559ce4e607SRafael J. Wysocki *state_p = state; 3569ce4e607SRafael J. Wysocki 35791bdad0bSRafael J. Wysocki return 0; 3589ce4e607SRafael J. Wysocki } 3592bb3a2bfSAaron Lu EXPORT_SYMBOL_GPL(acpi_device_update_power); 360202317a5SRafael J. Wysocki 361202317a5SRafael J. Wysocki int acpi_bus_update_power(acpi_handle handle, int *state_p) 362202317a5SRafael J. Wysocki { 363202317a5SRafael J. Wysocki struct acpi_device *device; 364202317a5SRafael J. Wysocki int result; 365202317a5SRafael J. Wysocki 366202317a5SRafael J. Wysocki result = acpi_bus_get_device(handle, &device); 367202317a5SRafael J. Wysocki return result ? result : acpi_device_update_power(device, state_p); 368202317a5SRafael J. Wysocki } 3699ce4e607SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_bus_update_power); 3709ce4e607SRafael J. Wysocki 3719ce4e607SRafael J. Wysocki bool acpi_bus_power_manageable(acpi_handle handle) 3729ce4e607SRafael J. Wysocki { 3739ce4e607SRafael J. Wysocki struct acpi_device *device; 3749ce4e607SRafael J. Wysocki int result; 3759ce4e607SRafael J. Wysocki 3769ce4e607SRafael J. Wysocki result = acpi_bus_get_device(handle, &device); 3779ce4e607SRafael J. Wysocki return result ? false : device->flags.power_manageable; 3789ce4e607SRafael J. Wysocki } 3799ce4e607SRafael J. Wysocki EXPORT_SYMBOL(acpi_bus_power_manageable); 3809ce4e607SRafael J. Wysocki 381ec4602a9SRafael J. Wysocki #ifdef CONFIG_PM 382ec4602a9SRafael J. Wysocki static DEFINE_MUTEX(acpi_pm_notifier_lock); 383ff165679SVille Syrjälä static DEFINE_MUTEX(acpi_pm_notifier_install_lock); 384ec4602a9SRafael J. Wysocki 38533e4f80eSRafael J. Wysocki void acpi_pm_wakeup_event(struct device *dev) 38633e4f80eSRafael J. Wysocki { 38733e4f80eSRafael J. Wysocki pm_wakeup_dev_event(dev, 0, acpi_s2idle_wakeup()); 38833e4f80eSRafael J. Wysocki } 38933e4f80eSRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_pm_wakeup_event); 39033e4f80eSRafael J. Wysocki 391c072530fSRafael J. Wysocki static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) 392c072530fSRafael J. Wysocki { 393c072530fSRafael J. Wysocki struct acpi_device *adev; 394c072530fSRafael J. Wysocki 395c072530fSRafael J. Wysocki if (val != ACPI_NOTIFY_DEVICE_WAKE) 396c072530fSRafael J. Wysocki return; 397c072530fSRafael J. Wysocki 398020a6375SRafael J. Wysocki acpi_handle_debug(handle, "Wake notify\n"); 399020a6375SRafael J. Wysocki 400c072530fSRafael J. Wysocki adev = acpi_bus_get_acpi_device(handle); 401c072530fSRafael J. Wysocki if (!adev) 402c072530fSRafael J. Wysocki return; 403c072530fSRafael J. Wysocki 404c072530fSRafael J. Wysocki mutex_lock(&acpi_pm_notifier_lock); 405c072530fSRafael J. Wysocki 406c072530fSRafael J. Wysocki if (adev->wakeup.flags.notifier_present) { 40733e4f80eSRafael J. Wysocki pm_wakeup_ws_event(adev->wakeup.ws, 0, acpi_s2idle_wakeup()); 408020a6375SRafael J. Wysocki if (adev->wakeup.context.func) { 409d75f773cSSakari Ailus acpi_handle_debug(handle, "Running %pS for %s\n", 410020a6375SRafael J. Wysocki adev->wakeup.context.func, 411020a6375SRafael J. Wysocki dev_name(adev->wakeup.context.dev)); 41264fd1c70SRafael J. Wysocki adev->wakeup.context.func(&adev->wakeup.context); 413c072530fSRafael J. Wysocki } 414020a6375SRafael J. Wysocki } 415c072530fSRafael J. Wysocki 416c072530fSRafael J. Wysocki mutex_unlock(&acpi_pm_notifier_lock); 417c072530fSRafael J. Wysocki 418c072530fSRafael J. Wysocki acpi_bus_put_acpi_device(adev); 419c072530fSRafael J. Wysocki } 420c072530fSRafael J. Wysocki 421ec4602a9SRafael J. Wysocki /** 422c072530fSRafael J. Wysocki * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. 423c072530fSRafael J. Wysocki * @adev: ACPI device to add the notify handler for. 424c072530fSRafael J. Wysocki * @dev: Device to generate a wakeup event for while handling the notification. 42564fd1c70SRafael J. Wysocki * @func: Work function to execute when handling the notification. 426ec4602a9SRafael J. Wysocki * 427ec4602a9SRafael J. Wysocki * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of 428ec4602a9SRafael J. Wysocki * PM wakeup events. For example, wakeup events may be generated for bridges 429ec4602a9SRafael J. Wysocki * if one of the devices below the bridge is signaling wakeup, even if the 430ec4602a9SRafael J. Wysocki * bridge itself doesn't have a wakeup GPE associated with it. 431ec4602a9SRafael J. Wysocki */ 432c072530fSRafael J. Wysocki acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, 43364fd1c70SRafael J. Wysocki void (*func)(struct acpi_device_wakeup_context *context)) 434ec4602a9SRafael J. Wysocki { 435ec4602a9SRafael J. Wysocki acpi_status status = AE_ALREADY_EXISTS; 436ec4602a9SRafael J. Wysocki 43764fd1c70SRafael J. Wysocki if (!dev && !func) 438c072530fSRafael J. Wysocki return AE_BAD_PARAMETER; 439c072530fSRafael J. Wysocki 440ff165679SVille Syrjälä mutex_lock(&acpi_pm_notifier_install_lock); 441ec4602a9SRafael J. Wysocki 442ec4602a9SRafael J. Wysocki if (adev->wakeup.flags.notifier_present) 443ec4602a9SRafael J. Wysocki goto out; 444ec4602a9SRafael J. Wysocki 445c072530fSRafael J. Wysocki status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, 446c072530fSRafael J. Wysocki acpi_pm_notify_handler, NULL); 447ec4602a9SRafael J. Wysocki if (ACPI_FAILURE(status)) 448ec4602a9SRafael J. Wysocki goto out; 449ec4602a9SRafael J. Wysocki 450ff165679SVille Syrjälä mutex_lock(&acpi_pm_notifier_lock); 451ff165679SVille Syrjälä adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); 452ff165679SVille Syrjälä adev->wakeup.context.dev = dev; 453ff165679SVille Syrjälä adev->wakeup.context.func = func; 454ec4602a9SRafael J. Wysocki adev->wakeup.flags.notifier_present = true; 455ff165679SVille Syrjälä mutex_unlock(&acpi_pm_notifier_lock); 456ec4602a9SRafael J. Wysocki 457ec4602a9SRafael J. Wysocki out: 458ff165679SVille Syrjälä mutex_unlock(&acpi_pm_notifier_install_lock); 459ec4602a9SRafael J. Wysocki return status; 460ec4602a9SRafael J. Wysocki } 461ec4602a9SRafael J. Wysocki 462ec4602a9SRafael J. Wysocki /** 463ec4602a9SRafael J. Wysocki * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. 464ec4602a9SRafael J. Wysocki * @adev: ACPI device to remove the notifier from. 465ec4602a9SRafael J. Wysocki */ 466c072530fSRafael J. Wysocki acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) 467ec4602a9SRafael J. Wysocki { 468ec4602a9SRafael J. Wysocki acpi_status status = AE_BAD_PARAMETER; 469ec4602a9SRafael J. Wysocki 470ff165679SVille Syrjälä mutex_lock(&acpi_pm_notifier_install_lock); 471ec4602a9SRafael J. Wysocki 472ec4602a9SRafael J. Wysocki if (!adev->wakeup.flags.notifier_present) 473ec4602a9SRafael J. Wysocki goto out; 474ec4602a9SRafael J. Wysocki 475ec4602a9SRafael J. Wysocki status = acpi_remove_notify_handler(adev->handle, 476ec4602a9SRafael J. Wysocki ACPI_SYSTEM_NOTIFY, 477c072530fSRafael J. Wysocki acpi_pm_notify_handler); 478ec4602a9SRafael J. Wysocki if (ACPI_FAILURE(status)) 479ec4602a9SRafael J. Wysocki goto out; 480ec4602a9SRafael J. Wysocki 481ff165679SVille Syrjälä mutex_lock(&acpi_pm_notifier_lock); 48264fd1c70SRafael J. Wysocki adev->wakeup.context.func = NULL; 483c072530fSRafael J. Wysocki adev->wakeup.context.dev = NULL; 484c072530fSRafael J. Wysocki wakeup_source_unregister(adev->wakeup.ws); 485ec4602a9SRafael J. Wysocki adev->wakeup.flags.notifier_present = false; 486ff165679SVille Syrjälä mutex_unlock(&acpi_pm_notifier_lock); 487ec4602a9SRafael J. Wysocki 488ec4602a9SRafael J. Wysocki out: 489ff165679SVille Syrjälä mutex_unlock(&acpi_pm_notifier_install_lock); 490ec4602a9SRafael J. Wysocki return status; 491ec4602a9SRafael J. Wysocki } 492ec4602a9SRafael J. Wysocki 4939ce4e607SRafael J. Wysocki bool acpi_bus_can_wakeup(acpi_handle handle) 4949ce4e607SRafael J. Wysocki { 4959ce4e607SRafael J. Wysocki struct acpi_device *device; 4969ce4e607SRafael J. Wysocki int result; 4979ce4e607SRafael J. Wysocki 4989ce4e607SRafael J. Wysocki result = acpi_bus_get_device(handle, &device); 4999ce4e607SRafael J. Wysocki return result ? false : device->wakeup.flags.valid; 5009ce4e607SRafael J. Wysocki } 5019ce4e607SRafael J. Wysocki EXPORT_SYMBOL(acpi_bus_can_wakeup); 5029ce4e607SRafael J. Wysocki 5038370c2dcSRafael J. Wysocki bool acpi_pm_device_can_wakeup(struct device *dev) 5048370c2dcSRafael J. Wysocki { 5058370c2dcSRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(dev); 5068370c2dcSRafael J. Wysocki 5078370c2dcSRafael J. Wysocki return adev ? acpi_device_can_wakeup(adev) : false; 5088370c2dcSRafael J. Wysocki } 5098370c2dcSRafael J. Wysocki 5109ce4e607SRafael J. Wysocki /** 511b25c77efSRafael J. Wysocki * acpi_dev_pm_get_state - Get preferred power state of ACPI device. 51286b3832cSRafael J. Wysocki * @dev: Device whose preferred target power state to return. 51386b3832cSRafael J. Wysocki * @adev: ACPI device node corresponding to @dev. 51486b3832cSRafael J. Wysocki * @target_state: System state to match the resultant device state. 515fa1675b5SRafael J. Wysocki * @d_min_p: Location to store the highest power state available to the device. 516fa1675b5SRafael J. Wysocki * @d_max_p: Location to store the lowest power state available to the device. 51786b3832cSRafael J. Wysocki * 518fa1675b5SRafael J. Wysocki * Find the lowest power (highest number) and highest power (lowest number) ACPI 519fa1675b5SRafael J. Wysocki * device power states that the device can be in while the system is in the 520fa1675b5SRafael J. Wysocki * state represented by @target_state. Store the integer numbers representing 521fa1675b5SRafael J. Wysocki * those stats in the memory locations pointed to by @d_max_p and @d_min_p, 522fa1675b5SRafael J. Wysocki * respectively. 52386b3832cSRafael J. Wysocki * 52486b3832cSRafael J. Wysocki * Callers must ensure that @dev and @adev are valid pointers and that @adev 52586b3832cSRafael J. Wysocki * actually corresponds to @dev before using this function. 526fa1675b5SRafael J. Wysocki * 527fa1675b5SRafael J. Wysocki * Returns 0 on success or -ENODATA when one of the ACPI methods fails or 528fa1675b5SRafael J. Wysocki * returns a value that doesn't make sense. The memory locations pointed to by 529fa1675b5SRafael J. Wysocki * @d_max_p and @d_min_p are only modified on success. 53086b3832cSRafael J. Wysocki */ 531b25c77efSRafael J. Wysocki static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, 532fa1675b5SRafael J. Wysocki u32 target_state, int *d_min_p, int *d_max_p) 53386b3832cSRafael J. Wysocki { 534fa1675b5SRafael J. Wysocki char method[] = { '_', 'S', '0' + target_state, 'D', '\0' }; 535fa1675b5SRafael J. Wysocki acpi_handle handle = adev->handle; 536fa1675b5SRafael J. Wysocki unsigned long long ret; 537fa1675b5SRafael J. Wysocki int d_min, d_max; 53886b3832cSRafael J. Wysocki bool wakeup = false; 539bf8c6184SDaniel Drake bool has_sxd = false; 540fa1675b5SRafael J. Wysocki acpi_status status; 54186b3832cSRafael J. Wysocki 54286b3832cSRafael J. Wysocki /* 543fa1675b5SRafael J. Wysocki * If the system state is S0, the lowest power state the device can be 544fa1675b5SRafael J. Wysocki * in is D3cold, unless the device has _S0W and is supposed to signal 545fa1675b5SRafael J. Wysocki * wakeup, in which case the return value of _S0W has to be used as the 546fa1675b5SRafael J. Wysocki * lowest power state available to the device. 54786b3832cSRafael J. Wysocki */ 54886b3832cSRafael J. Wysocki d_min = ACPI_STATE_D0; 5494c164ae7SRafael J. Wysocki d_max = ACPI_STATE_D3_COLD; 55086b3832cSRafael J. Wysocki 55186b3832cSRafael J. Wysocki /* 55286b3832cSRafael J. Wysocki * If present, _SxD methods return the minimum D-state (highest power 55386b3832cSRafael J. Wysocki * state) we can use for the corresponding S-states. Otherwise, the 55486b3832cSRafael J. Wysocki * minimum D-state is D0 (ACPI 3.x). 55586b3832cSRafael J. Wysocki */ 55686b3832cSRafael J. Wysocki if (target_state > ACPI_STATE_S0) { 557fa1675b5SRafael J. Wysocki /* 558fa1675b5SRafael J. Wysocki * We rely on acpi_evaluate_integer() not clobbering the integer 559fa1675b5SRafael J. Wysocki * provided if AE_NOT_FOUND is returned. 560fa1675b5SRafael J. Wysocki */ 561fa1675b5SRafael J. Wysocki ret = d_min; 562fa1675b5SRafael J. Wysocki status = acpi_evaluate_integer(handle, method, NULL, &ret); 563fa1675b5SRafael J. Wysocki if ((ACPI_FAILURE(status) && status != AE_NOT_FOUND) 564fa1675b5SRafael J. Wysocki || ret > ACPI_STATE_D3_COLD) 565fa1675b5SRafael J. Wysocki return -ENODATA; 566fa1675b5SRafael J. Wysocki 567fa1675b5SRafael J. Wysocki /* 568fa1675b5SRafael J. Wysocki * We need to handle legacy systems where D3hot and D3cold are 569fa1675b5SRafael J. Wysocki * the same and 3 is returned in both cases, so fall back to 570fa1675b5SRafael J. Wysocki * D3cold if D3hot is not a valid state. 571fa1675b5SRafael J. Wysocki */ 572fa1675b5SRafael J. Wysocki if (!adev->power.states[ret].flags.valid) { 573fa1675b5SRafael J. Wysocki if (ret == ACPI_STATE_D3_HOT) 574fa1675b5SRafael J. Wysocki ret = ACPI_STATE_D3_COLD; 575fa1675b5SRafael J. Wysocki else 576fa1675b5SRafael J. Wysocki return -ENODATA; 577fa1675b5SRafael J. Wysocki } 578bf8c6184SDaniel Drake 579bf8c6184SDaniel Drake if (status == AE_OK) 580bf8c6184SDaniel Drake has_sxd = true; 581bf8c6184SDaniel Drake 582fa1675b5SRafael J. Wysocki d_min = ret; 58386b3832cSRafael J. Wysocki wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid 58486b3832cSRafael J. Wysocki && adev->wakeup.sleep_state >= target_state; 58520f97cafSRafael J. Wysocki } else { 58686b3832cSRafael J. Wysocki wakeup = adev->wakeup.flags.valid; 58786b3832cSRafael J. Wysocki } 58886b3832cSRafael J. Wysocki 58986b3832cSRafael J. Wysocki /* 59086b3832cSRafael J. Wysocki * If _PRW says we can wake up the system from the target sleep state, 59186b3832cSRafael J. Wysocki * the D-state returned by _SxD is sufficient for that (we assume a 59286b3832cSRafael J. Wysocki * wakeup-aware driver if wake is set). Still, if _SxW exists 59386b3832cSRafael J. Wysocki * (ACPI 3.x), it should return the maximum (lowest power) D-state that 59486b3832cSRafael J. Wysocki * can wake the system. _S0W may be valid, too. 59586b3832cSRafael J. Wysocki */ 59686b3832cSRafael J. Wysocki if (wakeup) { 597fa1675b5SRafael J. Wysocki method[3] = 'W'; 598fa1675b5SRafael J. Wysocki status = acpi_evaluate_integer(handle, method, NULL, &ret); 599fa1675b5SRafael J. Wysocki if (status == AE_NOT_FOUND) { 600bf8c6184SDaniel Drake /* No _SxW. In this case, the ACPI spec says that we 601bf8c6184SDaniel Drake * must not go into any power state deeper than the 602bf8c6184SDaniel Drake * value returned from _SxD. 603bf8c6184SDaniel Drake */ 604bf8c6184SDaniel Drake if (has_sxd && target_state > ACPI_STATE_S0) 60586b3832cSRafael J. Wysocki d_max = d_min; 606fa1675b5SRafael J. Wysocki } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) { 607fa1675b5SRafael J. Wysocki /* Fall back to D3cold if ret is not a valid state. */ 608fa1675b5SRafael J. Wysocki if (!adev->power.states[ret].flags.valid) 609fa1675b5SRafael J. Wysocki ret = ACPI_STATE_D3_COLD; 610fa1675b5SRafael J. Wysocki 611fa1675b5SRafael J. Wysocki d_max = ret > d_min ? ret : d_min; 612fa1675b5SRafael J. Wysocki } else { 613fa1675b5SRafael J. Wysocki return -ENODATA; 61486b3832cSRafael J. Wysocki } 61586b3832cSRafael J. Wysocki } 61686b3832cSRafael J. Wysocki 61786b3832cSRafael J. Wysocki if (d_min_p) 61886b3832cSRafael J. Wysocki *d_min_p = d_min; 619fa1675b5SRafael J. Wysocki 620fa1675b5SRafael J. Wysocki if (d_max_p) 621fa1675b5SRafael J. Wysocki *d_max_p = d_max; 622fa1675b5SRafael J. Wysocki 623fa1675b5SRafael J. Wysocki return 0; 62486b3832cSRafael J. Wysocki } 625cd7bd02dSRafael J. Wysocki 626a6ae7594SRafael J. Wysocki /** 627a6ae7594SRafael J. Wysocki * acpi_pm_device_sleep_state - Get preferred power state of ACPI device. 628a6ae7594SRafael J. Wysocki * @dev: Device whose preferred target power state to return. 629a6ae7594SRafael J. Wysocki * @d_min_p: Location to store the upper limit of the allowed states range. 630a6ae7594SRafael J. Wysocki * @d_max_in: Deepest low-power state to take into consideration. 631a6ae7594SRafael J. Wysocki * Return value: Preferred power state of the device on success, -ENODEV 632fa1675b5SRafael J. Wysocki * if there's no 'struct acpi_device' for @dev, -EINVAL if @d_max_in is 633fa1675b5SRafael J. Wysocki * incorrect, or -ENODATA on ACPI method failure. 634a6ae7594SRafael J. Wysocki * 635a6ae7594SRafael J. Wysocki * The caller must ensure that @dev is valid before using this function. 636a6ae7594SRafael J. Wysocki */ 637a6ae7594SRafael J. Wysocki int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) 638a6ae7594SRafael J. Wysocki { 639a6ae7594SRafael J. Wysocki struct acpi_device *adev; 6409b5c7a5aSRafael J. Wysocki int ret, d_min, d_max; 641fa1675b5SRafael J. Wysocki 642fa1675b5SRafael J. Wysocki if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) 643fa1675b5SRafael J. Wysocki return -EINVAL; 644fa1675b5SRafael J. Wysocki 64520dacb71SRafael J. Wysocki if (d_max_in > ACPI_STATE_D2) { 646fa1675b5SRafael J. Wysocki enum pm_qos_flags_status stat; 647fa1675b5SRafael J. Wysocki 648fa1675b5SRafael J. Wysocki stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF); 649fa1675b5SRafael J. Wysocki if (stat == PM_QOS_FLAGS_ALL) 65020dacb71SRafael J. Wysocki d_max_in = ACPI_STATE_D2; 651fa1675b5SRafael J. Wysocki } 652a6ae7594SRafael J. Wysocki 65317653a3eSRafael J. Wysocki adev = ACPI_COMPANION(dev); 65417653a3eSRafael J. Wysocki if (!adev) { 65517653a3eSRafael J. Wysocki dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); 656a6ae7594SRafael J. Wysocki return -ENODEV; 657a6ae7594SRafael J. Wysocki } 658a6ae7594SRafael J. Wysocki 659fa1675b5SRafael J. Wysocki ret = acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), 6609b5c7a5aSRafael J. Wysocki &d_min, &d_max); 661fa1675b5SRafael J. Wysocki if (ret) 662fa1675b5SRafael J. Wysocki return ret; 663fa1675b5SRafael J. Wysocki 6649b5c7a5aSRafael J. Wysocki if (d_max_in < d_min) 665fa1675b5SRafael J. Wysocki return -EINVAL; 666fa1675b5SRafael J. Wysocki 667fa1675b5SRafael J. Wysocki if (d_max > d_max_in) { 6689b5c7a5aSRafael J. Wysocki for (d_max = d_max_in; d_max > d_min; d_max--) { 669fa1675b5SRafael J. Wysocki if (adev->power.states[d_max].flags.valid) 670fa1675b5SRafael J. Wysocki break; 671fa1675b5SRafael J. Wysocki } 672fa1675b5SRafael J. Wysocki } 6739b5c7a5aSRafael J. Wysocki 6749b5c7a5aSRafael J. Wysocki if (d_min_p) 6759b5c7a5aSRafael J. Wysocki *d_min_p = d_min; 6769b5c7a5aSRafael J. Wysocki 677fa1675b5SRafael J. Wysocki return d_max; 678a6ae7594SRafael J. Wysocki } 679a6ae7594SRafael J. Wysocki EXPORT_SYMBOL(acpi_pm_device_sleep_state); 680a6ae7594SRafael J. Wysocki 681cd7bd02dSRafael J. Wysocki /** 682c072530fSRafael J. Wysocki * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. 68364fd1c70SRafael J. Wysocki * @context: Device wakeup context. 684e5cc8ef3SRafael J. Wysocki */ 68564fd1c70SRafael J. Wysocki static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context) 686e5cc8ef3SRafael J. Wysocki { 68764fd1c70SRafael J. Wysocki struct device *dev = context->dev; 688e5cc8ef3SRafael J. Wysocki 689c072530fSRafael J. Wysocki if (dev) { 690e5cc8ef3SRafael J. Wysocki pm_wakeup_event(dev, 0); 69164fd1c70SRafael J. Wysocki pm_request_resume(dev); 692e5cc8ef3SRafael J. Wysocki } 693e5cc8ef3SRafael J. Wysocki } 694e5cc8ef3SRafael J. Wysocki 69599d8845eSRafael J. Wysocki static DEFINE_MUTEX(acpi_wakeup_lock); 69699d8845eSRafael J. Wysocki 6971ba51a7cSRafael J. Wysocki static int __acpi_device_wakeup_enable(struct acpi_device *adev, 6981ba51a7cSRafael J. Wysocki u32 target_state, int max_count) 6991ba51a7cSRafael J. Wysocki { 7001ba51a7cSRafael J. Wysocki struct acpi_device_wakeup *wakeup = &adev->wakeup; 7011ba51a7cSRafael J. Wysocki acpi_status status; 7021ba51a7cSRafael J. Wysocki int error = 0; 7031ba51a7cSRafael J. Wysocki 7041ba51a7cSRafael J. Wysocki mutex_lock(&acpi_wakeup_lock); 7051ba51a7cSRafael J. Wysocki 7061ba51a7cSRafael J. Wysocki if (wakeup->enable_count >= max_count) 7071ba51a7cSRafael J. Wysocki goto out; 7081ba51a7cSRafael J. Wysocki 7091ba51a7cSRafael J. Wysocki if (wakeup->enable_count > 0) 7101ba51a7cSRafael J. Wysocki goto inc; 7111ba51a7cSRafael J. Wysocki 7121ba51a7cSRafael J. Wysocki error = acpi_enable_wakeup_device_power(adev, target_state); 7131ba51a7cSRafael J. Wysocki if (error) 7141ba51a7cSRafael J. Wysocki goto out; 7151ba51a7cSRafael J. Wysocki 7161ba51a7cSRafael J. Wysocki status = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); 7171ba51a7cSRafael J. Wysocki if (ACPI_FAILURE(status)) { 7181ba51a7cSRafael J. Wysocki acpi_disable_wakeup_device_power(adev); 7191ba51a7cSRafael J. Wysocki error = -EIO; 7201ba51a7cSRafael J. Wysocki goto out; 7211ba51a7cSRafael J. Wysocki } 7221ba51a7cSRafael J. Wysocki 723fbc9418fSRafael J. Wysocki acpi_handle_debug(adev->handle, "GPE%2X enabled for wakeup\n", 724fbc9418fSRafael J. Wysocki (unsigned int)wakeup->gpe_number); 725fbc9418fSRafael J. Wysocki 7261ba51a7cSRafael J. Wysocki inc: 7271ba51a7cSRafael J. Wysocki wakeup->enable_count++; 7281ba51a7cSRafael J. Wysocki 7291ba51a7cSRafael J. Wysocki out: 7301ba51a7cSRafael J. Wysocki mutex_unlock(&acpi_wakeup_lock); 7311ba51a7cSRafael J. Wysocki return error; 7321ba51a7cSRafael J. Wysocki } 7331ba51a7cSRafael J. Wysocki 734e5cc8ef3SRafael J. Wysocki /** 73599d8845eSRafael J. Wysocki * acpi_device_wakeup_enable - Enable wakeup functionality for device. 73699d8845eSRafael J. Wysocki * @adev: ACPI device to enable wakeup functionality for. 737f35cec25SRafael J. Wysocki * @target_state: State the system is transitioning into. 738cd7bd02dSRafael J. Wysocki * 73999d8845eSRafael J. Wysocki * Enable the GPE associated with @adev so that it can generate wakeup signals 74099d8845eSRafael J. Wysocki * for the device in response to external (remote) events and enable wakeup 74199d8845eSRafael J. Wysocki * power for it. 742dee8370cSRafael J. Wysocki * 743dee8370cSRafael J. Wysocki * Callers must ensure that @adev is a valid ACPI device node before executing 744dee8370cSRafael J. Wysocki * this function. 745dee8370cSRafael J. Wysocki */ 74699d8845eSRafael J. Wysocki static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state) 747dee8370cSRafael J. Wysocki { 7481ba51a7cSRafael J. Wysocki return __acpi_device_wakeup_enable(adev, target_state, 1); 74999d8845eSRafael J. Wysocki } 75099d8845eSRafael J. Wysocki 75199d8845eSRafael J. Wysocki /** 75299d8845eSRafael J. Wysocki * acpi_device_wakeup_disable - Disable wakeup functionality for device. 75399d8845eSRafael J. Wysocki * @adev: ACPI device to disable wakeup functionality for. 75499d8845eSRafael J. Wysocki * 75599d8845eSRafael J. Wysocki * Disable the GPE associated with @adev and disable wakeup power for it. 75699d8845eSRafael J. Wysocki * 75799d8845eSRafael J. Wysocki * Callers must ensure that @adev is a valid ACPI device node before executing 75899d8845eSRafael J. Wysocki * this function. 75999d8845eSRafael J. Wysocki */ 76099d8845eSRafael J. Wysocki static void acpi_device_wakeup_disable(struct acpi_device *adev) 76199d8845eSRafael J. Wysocki { 76299d8845eSRafael J. Wysocki struct acpi_device_wakeup *wakeup = &adev->wakeup; 76399d8845eSRafael J. Wysocki 76499d8845eSRafael J. Wysocki mutex_lock(&acpi_wakeup_lock); 76599d8845eSRafael J. Wysocki 76699d8845eSRafael J. Wysocki if (!wakeup->enable_count) 76799d8845eSRafael J. Wysocki goto out; 76899d8845eSRafael J. Wysocki 769dee8370cSRafael J. Wysocki acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); 770dee8370cSRafael J. Wysocki acpi_disable_wakeup_device_power(adev); 77199d8845eSRafael J. Wysocki 77299d8845eSRafael J. Wysocki wakeup->enable_count--; 77399d8845eSRafael J. Wysocki 77499d8845eSRafael J. Wysocki out: 77599d8845eSRafael J. Wysocki mutex_unlock(&acpi_wakeup_lock); 776dee8370cSRafael J. Wysocki } 777dee8370cSRafael J. Wysocki 7781ba51a7cSRafael J. Wysocki static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable, 7791ba51a7cSRafael J. Wysocki int max_count) 780a6ae7594SRafael J. Wysocki { 781a6ae7594SRafael J. Wysocki struct acpi_device *adev; 782a6ae7594SRafael J. Wysocki int error; 783a6ae7594SRafael J. Wysocki 78417653a3eSRafael J. Wysocki adev = ACPI_COMPANION(dev); 78517653a3eSRafael J. Wysocki if (!adev) { 78617653a3eSRafael J. Wysocki dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); 787a6ae7594SRafael J. Wysocki return -ENODEV; 788a6ae7594SRafael J. Wysocki } 789a6ae7594SRafael J. Wysocki 7904d183d04SRafael J. Wysocki if (!acpi_device_can_wakeup(adev)) 7914d183d04SRafael J. Wysocki return -EINVAL; 7924d183d04SRafael J. Wysocki 79399d8845eSRafael J. Wysocki if (!enable) { 79499d8845eSRafael J. Wysocki acpi_device_wakeup_disable(adev); 79599d8845eSRafael J. Wysocki dev_dbg(dev, "Wakeup disabled by ACPI\n"); 79699d8845eSRafael J. Wysocki return 0; 79799d8845eSRafael J. Wysocki } 79899d8845eSRafael J. Wysocki 7991ba51a7cSRafael J. Wysocki error = __acpi_device_wakeup_enable(adev, acpi_target_system_state(), 8001ba51a7cSRafael J. Wysocki max_count); 801a6ae7594SRafael J. Wysocki if (!error) 80299d8845eSRafael J. Wysocki dev_dbg(dev, "Wakeup enabled by ACPI\n"); 803a6ae7594SRafael J. Wysocki 804a6ae7594SRafael J. Wysocki return error; 805a6ae7594SRafael J. Wysocki } 8061ba51a7cSRafael J. Wysocki 8071ba51a7cSRafael J. Wysocki /** 8081ba51a7cSRafael J. Wysocki * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. 8091ba51a7cSRafael J. Wysocki * @dev: Device to enable/disable to generate wakeup events. 8101ba51a7cSRafael J. Wysocki * @enable: Whether to enable or disable the wakeup functionality. 8111ba51a7cSRafael J. Wysocki */ 8121ba51a7cSRafael J. Wysocki int acpi_pm_set_device_wakeup(struct device *dev, bool enable) 8131ba51a7cSRafael J. Wysocki { 8141ba51a7cSRafael J. Wysocki return __acpi_pm_set_device_wakeup(dev, enable, 1); 8151ba51a7cSRafael J. Wysocki } 8161ba51a7cSRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup); 8171ba51a7cSRafael J. Wysocki 8181ba51a7cSRafael J. Wysocki /** 8191ba51a7cSRafael J. Wysocki * acpi_pm_set_bridge_wakeup - Enable/disable remote wakeup for given bridge. 8201ba51a7cSRafael J. Wysocki * @dev: Bridge device to enable/disable to generate wakeup events. 8211ba51a7cSRafael J. Wysocki * @enable: Whether to enable or disable the wakeup functionality. 8221ba51a7cSRafael J. Wysocki */ 8231ba51a7cSRafael J. Wysocki int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable) 8241ba51a7cSRafael J. Wysocki { 8251ba51a7cSRafael J. Wysocki return __acpi_pm_set_device_wakeup(dev, enable, INT_MAX); 8261ba51a7cSRafael J. Wysocki } 8271ba51a7cSRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_pm_set_bridge_wakeup); 828e5cc8ef3SRafael J. Wysocki 829e5cc8ef3SRafael J. Wysocki /** 830e5cc8ef3SRafael J. Wysocki * acpi_dev_pm_low_power - Put ACPI device into a low-power state. 831e5cc8ef3SRafael J. Wysocki * @dev: Device to put into a low-power state. 832e5cc8ef3SRafael J. Wysocki * @adev: ACPI device node corresponding to @dev. 833e5cc8ef3SRafael J. Wysocki * @system_state: System state to choose the device state for. 834e5cc8ef3SRafael J. Wysocki */ 835e5cc8ef3SRafael J. Wysocki static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, 836e5cc8ef3SRafael J. Wysocki u32 system_state) 837e5cc8ef3SRafael J. Wysocki { 838fa1675b5SRafael J. Wysocki int ret, state; 839e5cc8ef3SRafael J. Wysocki 840e5cc8ef3SRafael J. Wysocki if (!acpi_device_power_manageable(adev)) 841e5cc8ef3SRafael J. Wysocki return 0; 842e5cc8ef3SRafael J. Wysocki 843fa1675b5SRafael J. Wysocki ret = acpi_dev_pm_get_state(dev, adev, system_state, NULL, &state); 844fa1675b5SRafael J. Wysocki return ret ? ret : acpi_device_set_power(adev, state); 845e5cc8ef3SRafael J. Wysocki } 846e5cc8ef3SRafael J. Wysocki 847e5cc8ef3SRafael J. Wysocki /** 848e5cc8ef3SRafael J. Wysocki * acpi_dev_pm_full_power - Put ACPI device into the full-power state. 849e5cc8ef3SRafael J. Wysocki * @adev: ACPI device node to put into the full-power state. 850e5cc8ef3SRafael J. Wysocki */ 851e5cc8ef3SRafael J. Wysocki static int acpi_dev_pm_full_power(struct acpi_device *adev) 852e5cc8ef3SRafael J. Wysocki { 853e5cc8ef3SRafael J. Wysocki return acpi_device_power_manageable(adev) ? 854e5cc8ef3SRafael J. Wysocki acpi_device_set_power(adev, ACPI_STATE_D0) : 0; 855e5cc8ef3SRafael J. Wysocki } 856e5cc8ef3SRafael J. Wysocki 857e5cc8ef3SRafael J. Wysocki /** 858cbe25ce3SRafael J. Wysocki * acpi_dev_suspend - Put device into a low-power state using ACPI. 859e5cc8ef3SRafael J. Wysocki * @dev: Device to put into a low-power state. 860cbe25ce3SRafael J. Wysocki * @wakeup: Whether or not to enable wakeup for the device. 861e5cc8ef3SRafael J. Wysocki * 862cbe25ce3SRafael J. Wysocki * Put the given device into a low-power state using the standard ACPI 863e5cc8ef3SRafael J. Wysocki * mechanism. Set up remote wakeup if desired, choose the state to put the 864e5cc8ef3SRafael J. Wysocki * device into (this checks if remote wakeup is expected to work too), and set 865e5cc8ef3SRafael J. Wysocki * the power state of the device. 866e5cc8ef3SRafael J. Wysocki */ 867cbe25ce3SRafael J. Wysocki int acpi_dev_suspend(struct device *dev, bool wakeup) 868e5cc8ef3SRafael J. Wysocki { 86979c0373fSRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(dev); 870cbe25ce3SRafael J. Wysocki u32 target_state = acpi_target_system_state(); 871e5cc8ef3SRafael J. Wysocki int error; 872e5cc8ef3SRafael J. Wysocki 873e5cc8ef3SRafael J. Wysocki if (!adev) 874e5cc8ef3SRafael J. Wysocki return 0; 875e5cc8ef3SRafael J. Wysocki 876cbe25ce3SRafael J. Wysocki if (wakeup && acpi_device_can_wakeup(adev)) { 877cbe25ce3SRafael J. Wysocki error = acpi_device_wakeup_enable(adev, target_state); 87899d8845eSRafael J. Wysocki if (error) 879e5cc8ef3SRafael J. Wysocki return -EAGAIN; 880cbe25ce3SRafael J. Wysocki } else { 881cbe25ce3SRafael J. Wysocki wakeup = false; 88299d8845eSRafael J. Wysocki } 883e5cc8ef3SRafael J. Wysocki 884cbe25ce3SRafael J. Wysocki error = acpi_dev_pm_low_power(dev, adev, target_state); 885cbe25ce3SRafael J. Wysocki if (error && wakeup) 88699d8845eSRafael J. Wysocki acpi_device_wakeup_disable(adev); 887e5cc8ef3SRafael J. Wysocki 888e5cc8ef3SRafael J. Wysocki return error; 889e5cc8ef3SRafael J. Wysocki } 890cbe25ce3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_dev_suspend); 891e5cc8ef3SRafael J. Wysocki 892e5cc8ef3SRafael J. Wysocki /** 89363705c40SRafael J. Wysocki * acpi_dev_resume - Put device into the full-power state using ACPI. 894e5cc8ef3SRafael J. Wysocki * @dev: Device to put into the full-power state. 895e5cc8ef3SRafael J. Wysocki * 896e5cc8ef3SRafael J. Wysocki * Put the given device into the full-power state using the standard ACPI 89763705c40SRafael J. Wysocki * mechanism. Set the power state of the device to ACPI D0 and disable wakeup. 898e5cc8ef3SRafael J. Wysocki */ 89963705c40SRafael J. Wysocki int acpi_dev_resume(struct device *dev) 900e5cc8ef3SRafael J. Wysocki { 90179c0373fSRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(dev); 902e5cc8ef3SRafael J. Wysocki int error; 903e5cc8ef3SRafael J. Wysocki 904e5cc8ef3SRafael J. Wysocki if (!adev) 905e5cc8ef3SRafael J. Wysocki return 0; 906e5cc8ef3SRafael J. Wysocki 907e5cc8ef3SRafael J. Wysocki error = acpi_dev_pm_full_power(adev); 90899d8845eSRafael J. Wysocki acpi_device_wakeup_disable(adev); 909e5cc8ef3SRafael J. Wysocki return error; 910e5cc8ef3SRafael J. Wysocki } 91163705c40SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_dev_resume); 912e5cc8ef3SRafael J. Wysocki 913e5cc8ef3SRafael J. Wysocki /** 914e5cc8ef3SRafael J. Wysocki * acpi_subsys_runtime_suspend - Suspend device using ACPI. 915e5cc8ef3SRafael J. Wysocki * @dev: Device to suspend. 916e5cc8ef3SRafael J. Wysocki * 917e5cc8ef3SRafael J. Wysocki * Carry out the generic runtime suspend procedure for @dev and use ACPI to put 918e5cc8ef3SRafael J. Wysocki * it into a runtime low-power state. 919e5cc8ef3SRafael J. Wysocki */ 920e5cc8ef3SRafael J. Wysocki int acpi_subsys_runtime_suspend(struct device *dev) 921e5cc8ef3SRafael J. Wysocki { 922e5cc8ef3SRafael J. Wysocki int ret = pm_generic_runtime_suspend(dev); 923cbe25ce3SRafael J. Wysocki return ret ? ret : acpi_dev_suspend(dev, true); 924e5cc8ef3SRafael J. Wysocki } 925e5cc8ef3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); 926e5cc8ef3SRafael J. Wysocki 927e5cc8ef3SRafael J. Wysocki /** 928e5cc8ef3SRafael J. Wysocki * acpi_subsys_runtime_resume - Resume device using ACPI. 929e5cc8ef3SRafael J. Wysocki * @dev: Device to Resume. 930e5cc8ef3SRafael J. Wysocki * 931e5cc8ef3SRafael J. Wysocki * Use ACPI to put the given device into the full-power state and carry out the 932e5cc8ef3SRafael J. Wysocki * generic runtime resume procedure for it. 933e5cc8ef3SRafael J. Wysocki */ 934e5cc8ef3SRafael J. Wysocki int acpi_subsys_runtime_resume(struct device *dev) 935e5cc8ef3SRafael J. Wysocki { 93663705c40SRafael J. Wysocki int ret = acpi_dev_resume(dev); 937e5cc8ef3SRafael J. Wysocki return ret ? ret : pm_generic_runtime_resume(dev); 938e5cc8ef3SRafael J. Wysocki } 939e5cc8ef3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume); 940e5cc8ef3SRafael J. Wysocki 941e5cc8ef3SRafael J. Wysocki #ifdef CONFIG_PM_SLEEP 942c2ebf788SUlf Hansson static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev) 943c2ebf788SUlf Hansson { 944c2ebf788SUlf Hansson u32 sys_target = acpi_target_system_state(); 945c2ebf788SUlf Hansson int ret, state; 946c2ebf788SUlf Hansson 9479a51c6b1SRafael J. Wysocki if (!pm_runtime_suspended(dev) || !adev || (adev->wakeup.flags.valid && 9489a51c6b1SRafael J. Wysocki device_may_wakeup(dev) != !!adev->wakeup.prepare_count)) 949c2ebf788SUlf Hansson return true; 950c2ebf788SUlf Hansson 951c2ebf788SUlf Hansson if (sys_target == ACPI_STATE_S0) 952c2ebf788SUlf Hansson return false; 953c2ebf788SUlf Hansson 954c2ebf788SUlf Hansson if (adev->power.flags.dsw_present) 955c2ebf788SUlf Hansson return true; 956c2ebf788SUlf Hansson 957c2ebf788SUlf Hansson ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state); 958c2ebf788SUlf Hansson if (ret) 959c2ebf788SUlf Hansson return true; 960c2ebf788SUlf Hansson 961c2ebf788SUlf Hansson return state != adev->power.state; 962c2ebf788SUlf Hansson } 963c2ebf788SUlf Hansson 964e5cc8ef3SRafael J. Wysocki /** 965e5cc8ef3SRafael J. Wysocki * acpi_subsys_prepare - Prepare device for system transition to a sleep state. 966e5cc8ef3SRafael J. Wysocki * @dev: Device to prepare. 967e5cc8ef3SRafael J. Wysocki */ 968e5cc8ef3SRafael J. Wysocki int acpi_subsys_prepare(struct device *dev) 969e5cc8ef3SRafael J. Wysocki { 970f25c0ae2SRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(dev); 97192858c47SRafael J. Wysocki 97208810a41SRafael J. Wysocki if (dev->driver && dev->driver->pm && dev->driver->pm->prepare) { 97308810a41SRafael J. Wysocki int ret = dev->driver->pm->prepare(dev); 97408810a41SRafael J. Wysocki 975f25c0ae2SRafael J. Wysocki if (ret < 0) 976f25c0ae2SRafael J. Wysocki return ret; 977f25c0ae2SRafael J. Wysocki 97808810a41SRafael J. Wysocki if (!ret && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE)) 979f25c0ae2SRafael J. Wysocki return 0; 98008810a41SRafael J. Wysocki } 981f25c0ae2SRafael J. Wysocki 982c2ebf788SUlf Hansson return !acpi_dev_needs_resume(dev, adev); 983e5cc8ef3SRafael J. Wysocki } 984e5cc8ef3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_prepare); 985e5cc8ef3SRafael J. Wysocki 986e5cc8ef3SRafael J. Wysocki /** 987e4da817dSUlf Hansson * acpi_subsys_complete - Finalize device's resume during system resume. 988e4da817dSUlf Hansson * @dev: Device to handle. 989e4da817dSUlf Hansson */ 990e4da817dSUlf Hansson void acpi_subsys_complete(struct device *dev) 991e4da817dSUlf Hansson { 992e4da817dSUlf Hansson pm_generic_complete(dev); 993e4da817dSUlf Hansson /* 994e4da817dSUlf Hansson * If the device had been runtime-suspended before the system went into 995e4da817dSUlf Hansson * the sleep state it is going out of and it has never been resumed till 996e4da817dSUlf Hansson * now, resume it in case the firmware powered it up. 997e4da817dSUlf Hansson */ 998db68daffSRafael J. Wysocki if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) 999e4da817dSUlf Hansson pm_request_resume(dev); 1000e4da817dSUlf Hansson } 1001e4da817dSUlf Hansson EXPORT_SYMBOL_GPL(acpi_subsys_complete); 1002e4da817dSUlf Hansson 1003e4da817dSUlf Hansson /** 100492858c47SRafael J. Wysocki * acpi_subsys_suspend - Run the device driver's suspend callback. 100592858c47SRafael J. Wysocki * @dev: Device to handle. 100692858c47SRafael J. Wysocki * 100705087360SRafael J. Wysocki * Follow PCI and resume devices from runtime suspend before running their 100805087360SRafael J. Wysocki * system suspend callbacks, unless the driver can cope with runtime-suspended 100905087360SRafael J. Wysocki * devices during system suspend and there are no ACPI-specific reasons for 101005087360SRafael J. Wysocki * resuming them. 101192858c47SRafael J. Wysocki */ 101292858c47SRafael J. Wysocki int acpi_subsys_suspend(struct device *dev) 101392858c47SRafael J. Wysocki { 101405087360SRafael J. Wysocki if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 101505087360SRafael J. Wysocki acpi_dev_needs_resume(dev, ACPI_COMPANION(dev))) 101692858c47SRafael J. Wysocki pm_runtime_resume(dev); 101705087360SRafael J. Wysocki 101892858c47SRafael J. Wysocki return pm_generic_suspend(dev); 101992858c47SRafael J. Wysocki } 10204cf563c5SHeikki Krogerus EXPORT_SYMBOL_GPL(acpi_subsys_suspend); 102192858c47SRafael J. Wysocki 102292858c47SRafael J. Wysocki /** 1023e5cc8ef3SRafael J. Wysocki * acpi_subsys_suspend_late - Suspend device using ACPI. 1024e5cc8ef3SRafael J. Wysocki * @dev: Device to suspend. 1025e5cc8ef3SRafael J. Wysocki * 1026e5cc8ef3SRafael J. Wysocki * Carry out the generic late suspend procedure for @dev and use ACPI to put 1027e5cc8ef3SRafael J. Wysocki * it into a low-power state during system transition into a sleep state. 1028e5cc8ef3SRafael J. Wysocki */ 1029e5cc8ef3SRafael J. Wysocki int acpi_subsys_suspend_late(struct device *dev) 1030e5cc8ef3SRafael J. Wysocki { 103105087360SRafael J. Wysocki int ret; 103205087360SRafael J. Wysocki 103305087360SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 103405087360SRafael J. Wysocki return 0; 103505087360SRafael J. Wysocki 103605087360SRafael J. Wysocki ret = pm_generic_suspend_late(dev); 1037cbe25ce3SRafael J. Wysocki return ret ? ret : acpi_dev_suspend(dev, device_may_wakeup(dev)); 1038e5cc8ef3SRafael J. Wysocki } 1039e5cc8ef3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); 1040e5cc8ef3SRafael J. Wysocki 1041e5cc8ef3SRafael J. Wysocki /** 104205087360SRafael J. Wysocki * acpi_subsys_suspend_noirq - Run the device driver's "noirq" suspend callback. 104305087360SRafael J. Wysocki * @dev: Device to suspend. 104405087360SRafael J. Wysocki */ 104505087360SRafael J. Wysocki int acpi_subsys_suspend_noirq(struct device *dev) 104605087360SRafael J. Wysocki { 1047db68daffSRafael J. Wysocki int ret; 104805087360SRafael J. Wysocki 1049db68daffSRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) { 1050db68daffSRafael J. Wysocki dev->power.may_skip_resume = true; 1051db68daffSRafael J. Wysocki return 0; 1052db68daffSRafael J. Wysocki } 1053db68daffSRafael J. Wysocki 1054db68daffSRafael J. Wysocki ret = pm_generic_suspend_noirq(dev); 1055db68daffSRafael J. Wysocki if (ret) 1056db68daffSRafael J. Wysocki return ret; 1057db68daffSRafael J. Wysocki 1058db68daffSRafael J. Wysocki /* 1059db68daffSRafael J. Wysocki * If the target system sleep state is suspend-to-idle, it is sufficient 1060db68daffSRafael J. Wysocki * to check whether or not the device's wakeup settings are good for 1061db68daffSRafael J. Wysocki * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause 1062db68daffSRafael J. Wysocki * acpi_subsys_complete() to take care of fixing up the device's state 1063db68daffSRafael J. Wysocki * anyway, if need be. 1064db68daffSRafael J. Wysocki */ 1065db68daffSRafael J. Wysocki dev->power.may_skip_resume = device_may_wakeup(dev) || 1066db68daffSRafael J. Wysocki !device_can_wakeup(dev); 1067db68daffSRafael J. Wysocki 1068db68daffSRafael J. Wysocki return 0; 106905087360SRafael J. Wysocki } 107005087360SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq); 107105087360SRafael J. Wysocki 107205087360SRafael J. Wysocki /** 107305087360SRafael J. Wysocki * acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback. 107405087360SRafael J. Wysocki * @dev: Device to handle. 107505087360SRafael J. Wysocki */ 10763cd7957eSRafael J. Wysocki static int acpi_subsys_resume_noirq(struct device *dev) 107705087360SRafael J. Wysocki { 1078db68daffSRafael J. Wysocki if (dev_pm_may_skip_resume(dev)) 1079db68daffSRafael J. Wysocki return 0; 1080db68daffSRafael J. Wysocki 108105087360SRafael J. Wysocki /* 108205087360SRafael J. Wysocki * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend 108305087360SRafael J. Wysocki * during system suspend, so update their runtime PM status to "active" 108405087360SRafael J. Wysocki * as they will be put into D0 going forward. 108505087360SRafael J. Wysocki */ 108605087360SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 108705087360SRafael J. Wysocki pm_runtime_set_active(dev); 108805087360SRafael J. Wysocki 108905087360SRafael J. Wysocki return pm_generic_resume_noirq(dev); 109005087360SRafael J. Wysocki } 109105087360SRafael J. Wysocki 109205087360SRafael J. Wysocki /** 1093e5cc8ef3SRafael J. Wysocki * acpi_subsys_resume_early - Resume device using ACPI. 1094e5cc8ef3SRafael J. Wysocki * @dev: Device to Resume. 1095e5cc8ef3SRafael J. Wysocki * 1096e5cc8ef3SRafael J. Wysocki * Use ACPI to put the given device into the full-power state and carry out the 1097e5cc8ef3SRafael J. Wysocki * generic early resume procedure for it during system transition into the 1098e5cc8ef3SRafael J. Wysocki * working state. 1099e5cc8ef3SRafael J. Wysocki */ 11003cd7957eSRafael J. Wysocki static int acpi_subsys_resume_early(struct device *dev) 1101e5cc8ef3SRafael J. Wysocki { 110263705c40SRafael J. Wysocki int ret = acpi_dev_resume(dev); 1103e5cc8ef3SRafael J. Wysocki return ret ? ret : pm_generic_resume_early(dev); 1104e5cc8ef3SRafael J. Wysocki } 110592858c47SRafael J. Wysocki 110692858c47SRafael J. Wysocki /** 110792858c47SRafael J. Wysocki * acpi_subsys_freeze - Run the device driver's freeze callback. 110892858c47SRafael J. Wysocki * @dev: Device to handle. 110992858c47SRafael J. Wysocki */ 111092858c47SRafael J. Wysocki int acpi_subsys_freeze(struct device *dev) 111192858c47SRafael J. Wysocki { 111292858c47SRafael J. Wysocki /* 1113501debd4SRafael J. Wysocki * Resume all runtime-suspended devices before creating a snapshot 1114501debd4SRafael J. Wysocki * image of system memory, because the restore kernel generally cannot 1115501debd4SRafael J. Wysocki * be expected to always handle them consistently and they need to be 1116501debd4SRafael J. Wysocki * put into the runtime-active metastate during system resume anyway, 1117501debd4SRafael J. Wysocki * so it is better to ensure that the state saved in the image will be 1118501debd4SRafael J. Wysocki * always consistent with that. 111992858c47SRafael J. Wysocki */ 112092858c47SRafael J. Wysocki pm_runtime_resume(dev); 112105087360SRafael J. Wysocki 112292858c47SRafael J. Wysocki return pm_generic_freeze(dev); 112392858c47SRafael J. Wysocki } 11244cf563c5SHeikki Krogerus EXPORT_SYMBOL_GPL(acpi_subsys_freeze); 112592858c47SRafael J. Wysocki 112605087360SRafael J. Wysocki /** 11273cd7957eSRafael J. Wysocki * acpi_subsys_restore_early - Restore device using ACPI. 11283cd7957eSRafael J. Wysocki * @dev: Device to restore. 112905087360SRafael J. Wysocki */ 11303cd7957eSRafael J. Wysocki int acpi_subsys_restore_early(struct device *dev) 113105087360SRafael J. Wysocki { 11323cd7957eSRafael J. Wysocki int ret = acpi_dev_resume(dev); 11333cd7957eSRafael J. Wysocki return ret ? ret : pm_generic_restore_early(dev); 113405087360SRafael J. Wysocki } 11353cd7957eSRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_restore_early); 1136*c95b7595SRafael J. Wysocki 1137*c95b7595SRafael J. Wysocki /** 1138*c95b7595SRafael J. Wysocki * acpi_subsys_poweroff - Run the device driver's poweroff callback. 1139*c95b7595SRafael J. Wysocki * @dev: Device to handle. 1140*c95b7595SRafael J. Wysocki * 1141*c95b7595SRafael J. Wysocki * Follow PCI and resume devices from runtime suspend before running their 1142*c95b7595SRafael J. Wysocki * system poweroff callbacks, unless the driver can cope with runtime-suspended 1143*c95b7595SRafael J. Wysocki * devices during system suspend and there are no ACPI-specific reasons for 1144*c95b7595SRafael J. Wysocki * resuming them. 1145*c95b7595SRafael J. Wysocki */ 1146*c95b7595SRafael J. Wysocki int acpi_subsys_poweroff(struct device *dev) 1147*c95b7595SRafael J. Wysocki { 1148*c95b7595SRafael J. Wysocki if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 1149*c95b7595SRafael J. Wysocki acpi_dev_needs_resume(dev, ACPI_COMPANION(dev))) 1150*c95b7595SRafael J. Wysocki pm_runtime_resume(dev); 1151*c95b7595SRafael J. Wysocki 1152*c95b7595SRafael J. Wysocki return pm_generic_poweroff(dev); 1153*c95b7595SRafael J. Wysocki } 1154*c95b7595SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_subsys_poweroff); 1155*c95b7595SRafael J. Wysocki 1156*c95b7595SRafael J. Wysocki /** 1157*c95b7595SRafael J. Wysocki * acpi_subsys_poweroff_late - Run the device driver's poweroff callback. 1158*c95b7595SRafael J. Wysocki * @dev: Device to handle. 1159*c95b7595SRafael J. Wysocki * 1160*c95b7595SRafael J. Wysocki * Carry out the generic late poweroff procedure for @dev and use ACPI to put 1161*c95b7595SRafael J. Wysocki * it into a low-power state during system transition into a sleep state. 1162*c95b7595SRafael J. Wysocki */ 1163*c95b7595SRafael J. Wysocki static int acpi_subsys_poweroff_late(struct device *dev) 1164*c95b7595SRafael J. Wysocki { 1165*c95b7595SRafael J. Wysocki int ret; 1166*c95b7595SRafael J. Wysocki 1167*c95b7595SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 1168*c95b7595SRafael J. Wysocki return 0; 1169*c95b7595SRafael J. Wysocki 1170*c95b7595SRafael J. Wysocki ret = pm_generic_poweroff_late(dev); 1171*c95b7595SRafael J. Wysocki if (ret) 1172*c95b7595SRafael J. Wysocki return ret; 1173*c95b7595SRafael J. Wysocki 1174*c95b7595SRafael J. Wysocki return acpi_dev_suspend(dev, device_may_wakeup(dev)); 1175*c95b7595SRafael J. Wysocki } 1176*c95b7595SRafael J. Wysocki 1177*c95b7595SRafael J. Wysocki /** 1178*c95b7595SRafael J. Wysocki * acpi_subsys_poweroff_noirq - Run the driver's "noirq" poweroff callback. 1179*c95b7595SRafael J. Wysocki * @dev: Device to suspend. 1180*c95b7595SRafael J. Wysocki */ 1181*c95b7595SRafael J. Wysocki static int acpi_subsys_poweroff_noirq(struct device *dev) 1182*c95b7595SRafael J. Wysocki { 1183*c95b7595SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 1184*c95b7595SRafael J. Wysocki return 0; 1185*c95b7595SRafael J. Wysocki 1186*c95b7595SRafael J. Wysocki return pm_generic_poweroff_noirq(dev); 1187*c95b7595SRafael J. Wysocki } 1188e5cc8ef3SRafael J. Wysocki #endif /* CONFIG_PM_SLEEP */ 1189e5cc8ef3SRafael J. Wysocki 1190e5cc8ef3SRafael J. Wysocki static struct dev_pm_domain acpi_general_pm_domain = { 1191e5cc8ef3SRafael J. Wysocki .ops = { 1192e5cc8ef3SRafael J. Wysocki .runtime_suspend = acpi_subsys_runtime_suspend, 1193e5cc8ef3SRafael J. Wysocki .runtime_resume = acpi_subsys_runtime_resume, 1194e5cc8ef3SRafael J. Wysocki #ifdef CONFIG_PM_SLEEP 1195e5cc8ef3SRafael J. Wysocki .prepare = acpi_subsys_prepare, 1196e4da817dSUlf Hansson .complete = acpi_subsys_complete, 119792858c47SRafael J. Wysocki .suspend = acpi_subsys_suspend, 1198e5cc8ef3SRafael J. Wysocki .suspend_late = acpi_subsys_suspend_late, 119905087360SRafael J. Wysocki .suspend_noirq = acpi_subsys_suspend_noirq, 120005087360SRafael J. Wysocki .resume_noirq = acpi_subsys_resume_noirq, 1201e5cc8ef3SRafael J. Wysocki .resume_early = acpi_subsys_resume_early, 120292858c47SRafael J. Wysocki .freeze = acpi_subsys_freeze, 1203*c95b7595SRafael J. Wysocki .poweroff = acpi_subsys_poweroff, 1204*c95b7595SRafael J. Wysocki .poweroff_late = acpi_subsys_poweroff_late, 1205*c95b7595SRafael J. Wysocki .poweroff_noirq = acpi_subsys_poweroff_noirq, 12063cd7957eSRafael J. Wysocki .restore_early = acpi_subsys_restore_early, 1207e5cc8ef3SRafael J. Wysocki #endif 1208e5cc8ef3SRafael J. Wysocki }, 1209e5cc8ef3SRafael J. Wysocki }; 1210e5cc8ef3SRafael J. Wysocki 1211e5cc8ef3SRafael J. Wysocki /** 121291d66cd2SUlf Hansson * acpi_dev_pm_detach - Remove ACPI power management from the device. 121391d66cd2SUlf Hansson * @dev: Device to take care of. 121491d66cd2SUlf Hansson * @power_off: Whether or not to try to remove power from the device. 121591d66cd2SUlf Hansson * 121691d66cd2SUlf Hansson * Remove the device from the general ACPI PM domain and remove its wakeup 121791d66cd2SUlf Hansson * notifier. If @power_off is set, additionally remove power from the device if 121891d66cd2SUlf Hansson * possible. 121991d66cd2SUlf Hansson * 122091d66cd2SUlf Hansson * Callers must ensure proper synchronization of this function with power 122191d66cd2SUlf Hansson * management callbacks. 122291d66cd2SUlf Hansson */ 122391d66cd2SUlf Hansson static void acpi_dev_pm_detach(struct device *dev, bool power_off) 122491d66cd2SUlf Hansson { 122591d66cd2SUlf Hansson struct acpi_device *adev = ACPI_COMPANION(dev); 122691d66cd2SUlf Hansson 122791d66cd2SUlf Hansson if (adev && dev->pm_domain == &acpi_general_pm_domain) { 1228989561deSTomeu Vizoso dev_pm_domain_set(dev, NULL); 122991d66cd2SUlf Hansson acpi_remove_pm_notifier(adev); 123091d66cd2SUlf Hansson if (power_off) { 123191d66cd2SUlf Hansson /* 123291d66cd2SUlf Hansson * If the device's PM QoS resume latency limit or flags 123391d66cd2SUlf Hansson * have been exposed to user space, they have to be 123491d66cd2SUlf Hansson * hidden at this point, so that they don't affect the 123591d66cd2SUlf Hansson * choice of the low-power state to put the device into. 123691d66cd2SUlf Hansson */ 123791d66cd2SUlf Hansson dev_pm_qos_hide_latency_limit(dev); 123891d66cd2SUlf Hansson dev_pm_qos_hide_flags(dev); 123999d8845eSRafael J. Wysocki acpi_device_wakeup_disable(adev); 124091d66cd2SUlf Hansson acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); 124191d66cd2SUlf Hansson } 124291d66cd2SUlf Hansson } 124391d66cd2SUlf Hansson } 124491d66cd2SUlf Hansson 124591d66cd2SUlf Hansson /** 1246e5cc8ef3SRafael J. Wysocki * acpi_dev_pm_attach - Prepare device for ACPI power management. 1247e5cc8ef3SRafael J. Wysocki * @dev: Device to prepare. 1248b88ce2a4SRafael J. Wysocki * @power_on: Whether or not to power on the device. 1249e5cc8ef3SRafael J. Wysocki * 1250e5cc8ef3SRafael J. Wysocki * If @dev has a valid ACPI handle that has a valid struct acpi_device object 1251e5cc8ef3SRafael J. Wysocki * attached to it, install a wakeup notification handler for the device and 1252b88ce2a4SRafael J. Wysocki * add it to the general ACPI PM domain. If @power_on is set, the device will 1253b88ce2a4SRafael J. Wysocki * be put into the ACPI D0 state before the function returns. 1254e5cc8ef3SRafael J. Wysocki * 1255e5cc8ef3SRafael J. Wysocki * This assumes that the @dev's bus type uses generic power management callbacks 1256e5cc8ef3SRafael J. Wysocki * (or doesn't use any power management callbacks at all). 1257e5cc8ef3SRafael J. Wysocki * 1258e5cc8ef3SRafael J. Wysocki * Callers must ensure proper synchronization of this function with power 1259e5cc8ef3SRafael J. Wysocki * management callbacks. 1260e5cc8ef3SRafael J. Wysocki */ 1261b88ce2a4SRafael J. Wysocki int acpi_dev_pm_attach(struct device *dev, bool power_on) 1262e5cc8ef3SRafael J. Wysocki { 126379c0373fSRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(dev); 1264e5cc8ef3SRafael J. Wysocki 1265e5cc8ef3SRafael J. Wysocki if (!adev) 1266919b7308SUlf Hansson return 0; 1267e5cc8ef3SRafael J. Wysocki 1268712e960fSMika Westerberg /* 1269712e960fSMika Westerberg * Only attach the power domain to the first device if the 1270712e960fSMika Westerberg * companion is shared by multiple. This is to prevent doing power 1271712e960fSMika Westerberg * management twice. 1272712e960fSMika Westerberg */ 1273712e960fSMika Westerberg if (!acpi_device_is_first_physical_node(adev, dev)) 1274919b7308SUlf Hansson return 0; 1275712e960fSMika Westerberg 1276c072530fSRafael J. Wysocki acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); 1277989561deSTomeu Vizoso dev_pm_domain_set(dev, &acpi_general_pm_domain); 1278b88ce2a4SRafael J. Wysocki if (power_on) { 1279b88ce2a4SRafael J. Wysocki acpi_dev_pm_full_power(adev); 128099d8845eSRafael J. Wysocki acpi_device_wakeup_disable(adev); 1281b88ce2a4SRafael J. Wysocki } 128286f1e15fSUlf Hansson 128386f1e15fSUlf Hansson dev->pm_domain->detach = acpi_dev_pm_detach; 1284919b7308SUlf Hansson return 1; 1285e5cc8ef3SRafael J. Wysocki } 1286e5cc8ef3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_dev_pm_attach); 1287ec4602a9SRafael J. Wysocki #endif /* CONFIG_PM */ 1288