Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * drivers/acpi/power.c - ACPI Power Resources management.
4 : : *
5 : : * Copyright (C) 2001 - 2015 Intel Corp.
6 : : * Author: Andy Grover <andrew.grover@intel.com>
7 : : * Author: Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
8 : : * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
9 : : */
10 : :
11 : : /*
12 : : * ACPI power-managed devices may be controlled in two ways:
13 : : * 1. via "Device Specific (D-State) Control"
14 : : * 2. via "Power Resource Control".
15 : : * The code below deals with ACPI Power Resources control.
16 : : *
17 : : * An ACPI "power resource object" represents a software controllable power
18 : : * plane, clock plane, or other resource depended on by a device.
19 : : *
20 : : * A device may rely on multiple power resources, and a power resource
21 : : * may be shared by multiple devices.
22 : : */
23 : :
24 : : #include <linux/kernel.h>
25 : : #include <linux/module.h>
26 : : #include <linux/init.h>
27 : : #include <linux/types.h>
28 : : #include <linux/slab.h>
29 : : #include <linux/pm_runtime.h>
30 : : #include <linux/sysfs.h>
31 : : #include <linux/acpi.h>
32 : : #include "sleep.h"
33 : : #include "internal.h"
34 : :
35 : : #define _COMPONENT ACPI_POWER_COMPONENT
36 : : ACPI_MODULE_NAME("power");
37 : : #define ACPI_POWER_CLASS "power_resource"
38 : : #define ACPI_POWER_DEVICE_NAME "Power Resource"
39 : : #define ACPI_POWER_FILE_INFO "info"
40 : : #define ACPI_POWER_FILE_STATUS "state"
41 : : #define ACPI_POWER_RESOURCE_STATE_OFF 0x00
42 : : #define ACPI_POWER_RESOURCE_STATE_ON 0x01
43 : : #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
44 : :
45 : : struct acpi_power_dependent_device {
46 : : struct device *dev;
47 : : struct list_head node;
48 : : };
49 : :
50 : : struct acpi_power_resource {
51 : : struct acpi_device device;
52 : : struct list_head list_node;
53 : : char *name;
54 : : u32 system_level;
55 : : u32 order;
56 : : unsigned int ref_count;
57 : : bool wakeup_enabled;
58 : : struct mutex resource_lock;
59 : : struct list_head dependents;
60 : : };
61 : :
62 : : struct acpi_power_resource_entry {
63 : : struct list_head node;
64 : : struct acpi_power_resource *resource;
65 : : };
66 : :
67 : : static LIST_HEAD(acpi_power_resource_list);
68 : : static DEFINE_MUTEX(power_resource_list_lock);
69 : :
70 : : /* --------------------------------------------------------------------------
71 : : Power Resource Management
72 : : -------------------------------------------------------------------------- */
73 : :
74 : : static inline
75 : 0 : struct acpi_power_resource *to_power_resource(struct acpi_device *device)
76 : : {
77 : 0 : return container_of(device, struct acpi_power_resource, device);
78 : : }
79 : :
80 : 0 : static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
81 : : {
82 : 0 : struct acpi_device *device;
83 : :
84 [ # # ]: 0 : if (acpi_bus_get_device(handle, &device))
85 : : return NULL;
86 : :
87 : 0 : return to_power_resource(device);
88 : : }
89 : :
90 : 0 : static int acpi_power_resources_list_add(acpi_handle handle,
91 : : struct list_head *list)
92 : : {
93 : 0 : struct acpi_power_resource *resource = acpi_power_get_context(handle);
94 : 0 : struct acpi_power_resource_entry *entry;
95 : :
96 [ # # ]: 0 : if (!resource || !list)
97 : : return -EINVAL;
98 : :
99 : 0 : entry = kzalloc(sizeof(*entry), GFP_KERNEL);
100 [ # # ]: 0 : if (!entry)
101 : : return -ENOMEM;
102 : :
103 : 0 : entry->resource = resource;
104 [ # # ]: 0 : if (!list_empty(list)) {
105 : 0 : struct acpi_power_resource_entry *e;
106 : :
107 [ # # ]: 0 : list_for_each_entry(e, list, node)
108 [ # # ]: 0 : if (e->resource->order > resource->order) {
109 : 0 : list_add_tail(&entry->node, &e->node);
110 : 0 : return 0;
111 : : }
112 : : }
113 : 0 : list_add_tail(&entry->node, list);
114 : 0 : return 0;
115 : : }
116 : :
117 : 0 : void acpi_power_resources_list_free(struct list_head *list)
118 : : {
119 : 0 : struct acpi_power_resource_entry *entry, *e;
120 : :
121 [ # # ]: 0 : list_for_each_entry_safe(entry, e, list, node) {
122 : 0 : list_del(&entry->node);
123 : 0 : kfree(entry);
124 : : }
125 : 0 : }
126 : :
127 : : static bool acpi_power_resource_is_dup(union acpi_object *package,
128 : : unsigned int start, unsigned int i)
129 : : {
130 : : acpi_handle rhandle, dup;
131 : : unsigned int j;
132 : :
133 : : /* The caller is expected to check the package element types */
134 : : rhandle = package->package.elements[i].reference.handle;
135 [ # # ]: 0 : for (j = start; j < i; j++) {
136 : 0 : dup = package->package.elements[j].reference.handle;
137 [ # # ]: 0 : if (dup == rhandle)
138 : : return true;
139 : : }
140 : :
141 : : return false;
142 : : }
143 : :
144 : 0 : int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
145 : : struct list_head *list)
146 : : {
147 : 0 : unsigned int i;
148 : 0 : int err = 0;
149 : :
150 [ # # ]: 0 : for (i = start; i < package->package.count; i++) {
151 : 0 : union acpi_object *element = &package->package.elements[i];
152 : 0 : acpi_handle rhandle;
153 : :
154 [ # # ]: 0 : if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
155 : : err = -ENODATA;
156 : : break;
157 : : }
158 : 0 : rhandle = element->reference.handle;
159 [ # # ]: 0 : if (!rhandle) {
160 : : err = -ENODEV;
161 : : break;
162 : : }
163 : :
164 : : /* Some ACPI tables contain duplicate power resource references */
165 [ # # ]: 0 : if (acpi_power_resource_is_dup(package, start, i))
166 : 0 : continue;
167 : :
168 : 0 : err = acpi_add_power_resource(rhandle);
169 [ # # ]: 0 : if (err)
170 : : break;
171 : :
172 : 0 : err = acpi_power_resources_list_add(rhandle, list);
173 [ # # ]: 0 : if (err)
174 : : break;
175 : : }
176 [ # # ]: 0 : if (err)
177 : 0 : acpi_power_resources_list_free(list);
178 : :
179 : 0 : return err;
180 : : }
181 : :
182 : 0 : static int acpi_power_get_state(acpi_handle handle, int *state)
183 : : {
184 : 0 : acpi_status status = AE_OK;
185 : 0 : unsigned long long sta = 0;
186 : 0 : char node_name[5];
187 : 0 : struct acpi_buffer buffer = { sizeof(node_name), node_name };
188 : :
189 : :
190 [ # # ]: 0 : if (!handle || !state)
191 : : return -EINVAL;
192 : :
193 : 0 : status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
194 [ # # ]: 0 : if (ACPI_FAILURE(status))
195 : : return -ENODEV;
196 : :
197 : 0 : *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
198 : : ACPI_POWER_RESOURCE_STATE_OFF;
199 : :
200 : 0 : acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
201 : :
202 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
203 : : node_name,
204 : 0 : *state ? "on" : "off"));
205 : :
206 : 0 : return 0;
207 : : }
208 : :
209 : 0 : static int acpi_power_get_list_state(struct list_head *list, int *state)
210 : : {
211 : 0 : struct acpi_power_resource_entry *entry;
212 : 0 : int cur_state;
213 : :
214 [ # # ]: 0 : if (!list || !state)
215 : : return -EINVAL;
216 : :
217 : : /* The state of the list is 'on' IFF all resources are 'on'. */
218 : 0 : cur_state = 0;
219 [ # # ]: 0 : list_for_each_entry(entry, list, node) {
220 : 0 : struct acpi_power_resource *resource = entry->resource;
221 : 0 : acpi_handle handle = resource->device.handle;
222 : 0 : int result;
223 : :
224 : 0 : mutex_lock(&resource->resource_lock);
225 : 0 : result = acpi_power_get_state(handle, &cur_state);
226 : 0 : mutex_unlock(&resource->resource_lock);
227 [ # # ]: 0 : if (result)
228 : 0 : return result;
229 : :
230 [ # # ]: 0 : if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
231 : : break;
232 : : }
233 : :
234 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
235 : 0 : cur_state ? "on" : "off"));
236 : :
237 : 0 : *state = cur_state;
238 : 0 : return 0;
239 : : }
240 : :
241 : : static int
242 : 0 : acpi_power_resource_add_dependent(struct acpi_power_resource *resource,
243 : : struct device *dev)
244 : : {
245 : 0 : struct acpi_power_dependent_device *dep;
246 : 0 : int ret = 0;
247 : :
248 : 0 : mutex_lock(&resource->resource_lock);
249 [ # # ]: 0 : list_for_each_entry(dep, &resource->dependents, node) {
250 : : /* Only add it once */
251 [ # # ]: 0 : if (dep->dev == dev)
252 : 0 : goto unlock;
253 : : }
254 : :
255 : 0 : dep = kzalloc(sizeof(*dep), GFP_KERNEL);
256 [ # # ]: 0 : if (!dep) {
257 : 0 : ret = -ENOMEM;
258 : 0 : goto unlock;
259 : : }
260 : :
261 : 0 : dep->dev = dev;
262 : 0 : list_add_tail(&dep->node, &resource->dependents);
263 : : dev_dbg(dev, "added power dependency to [%s]\n", resource->name);
264 : :
265 : 0 : unlock:
266 : 0 : mutex_unlock(&resource->resource_lock);
267 : 0 : return ret;
268 : : }
269 : :
270 : : static void
271 : 0 : acpi_power_resource_remove_dependent(struct acpi_power_resource *resource,
272 : : struct device *dev)
273 : : {
274 : 0 : struct acpi_power_dependent_device *dep;
275 : :
276 : 0 : mutex_lock(&resource->resource_lock);
277 [ # # ]: 0 : list_for_each_entry(dep, &resource->dependents, node) {
278 [ # # ]: 0 : if (dep->dev == dev) {
279 : 0 : list_del(&dep->node);
280 : 0 : kfree(dep);
281 : 0 : dev_dbg(dev, "removed power dependency to [%s]\n",
282 : : resource->name);
283 : 0 : break;
284 : : }
285 : : }
286 : 0 : mutex_unlock(&resource->resource_lock);
287 : 0 : }
288 : :
289 : : /**
290 : : * acpi_device_power_add_dependent - Add dependent device of this ACPI device
291 : : * @adev: ACPI device pointer
292 : : * @dev: Dependent device
293 : : *
294 : : * If @adev has non-empty _PR0 the @dev is added as dependent device to all
295 : : * power resources returned by it. This means that whenever these power
296 : : * resources are turned _ON the dependent devices get runtime resumed. This
297 : : * is needed for devices such as PCI to allow its driver to re-initialize
298 : : * it after it went to D0uninitialized.
299 : : *
300 : : * If @adev does not have _PR0 this does nothing.
301 : : *
302 : : * Returns %0 in case of success and negative errno otherwise.
303 : : */
304 : 0 : int acpi_device_power_add_dependent(struct acpi_device *adev,
305 : : struct device *dev)
306 : : {
307 : 0 : struct acpi_power_resource_entry *entry;
308 : 0 : struct list_head *resources;
309 : 0 : int ret;
310 : :
311 [ # # ]: 0 : if (!adev->flags.power_manageable)
312 : : return 0;
313 : :
314 : 0 : resources = &adev->power.states[ACPI_STATE_D0].resources;
315 [ # # ]: 0 : list_for_each_entry(entry, resources, node) {
316 : 0 : ret = acpi_power_resource_add_dependent(entry->resource, dev);
317 [ # # ]: 0 : if (ret)
318 : 0 : goto err;
319 : : }
320 : :
321 : : return 0;
322 : :
323 : : err:
324 [ # # ]: 0 : list_for_each_entry(entry, resources, node)
325 : 0 : acpi_power_resource_remove_dependent(entry->resource, dev);
326 : :
327 : : return ret;
328 : : }
329 : :
330 : : /**
331 : : * acpi_device_power_remove_dependent - Remove dependent device
332 : : * @adev: ACPI device pointer
333 : : * @dev: Dependent device
334 : : *
335 : : * Does the opposite of acpi_device_power_add_dependent() and removes the
336 : : * dependent device if it is found. Can be called to @adev that does not
337 : : * have _PR0 as well.
338 : : */
339 : 0 : void acpi_device_power_remove_dependent(struct acpi_device *adev,
340 : : struct device *dev)
341 : : {
342 : 0 : struct acpi_power_resource_entry *entry;
343 : 0 : struct list_head *resources;
344 : :
345 [ # # ]: 0 : if (!adev->flags.power_manageable)
346 : : return;
347 : :
348 : 0 : resources = &adev->power.states[ACPI_STATE_D0].resources;
349 [ # # ]: 0 : list_for_each_entry_reverse(entry, resources, node)
350 : 0 : acpi_power_resource_remove_dependent(entry->resource, dev);
351 : : }
352 : :
353 : 0 : static int __acpi_power_on(struct acpi_power_resource *resource)
354 : : {
355 : 0 : struct acpi_power_dependent_device *dep;
356 : 0 : acpi_status status = AE_OK;
357 : :
358 : 0 : status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL);
359 [ # # ]: 0 : if (ACPI_FAILURE(status))
360 : : return -ENODEV;
361 : :
362 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
363 : 0 : resource->name));
364 : :
365 : : /*
366 : : * If there are other dependents on this power resource we need to
367 : : * resume them now so that their drivers can re-initialize the
368 : : * hardware properly after it went back to D0.
369 : : */
370 [ # # ]: 0 : if (list_empty(&resource->dependents) ||
371 : : list_is_singular(&resource->dependents))
372 : : return 0;
373 : :
374 [ # # ]: 0 : list_for_each_entry(dep, &resource->dependents, node) {
375 : 0 : dev_dbg(dep->dev, "runtime resuming because [%s] turned on\n",
376 : : resource->name);
377 : 0 : pm_request_resume(dep->dev);
378 : : }
379 : :
380 : : return 0;
381 : : }
382 : :
383 : 0 : static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
384 : : {
385 : 0 : int result = 0;
386 : :
387 [ # # ]: 0 : if (resource->ref_count++) {
388 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
389 : : "Power resource [%s] already on\n",
390 : : resource->name));
391 : : } else {
392 : 0 : result = __acpi_power_on(resource);
393 [ # # ]: 0 : if (result)
394 : 0 : resource->ref_count--;
395 : : }
396 : 0 : return result;
397 : : }
398 : :
399 : 0 : static int acpi_power_on(struct acpi_power_resource *resource)
400 : : {
401 : 0 : int result;
402 : :
403 : 0 : mutex_lock(&resource->resource_lock);
404 : 0 : result = acpi_power_on_unlocked(resource);
405 : 0 : mutex_unlock(&resource->resource_lock);
406 : 0 : return result;
407 : : }
408 : :
409 : 0 : static int __acpi_power_off(struct acpi_power_resource *resource)
410 : : {
411 : 0 : acpi_status status;
412 : :
413 : 0 : status = acpi_evaluate_object(resource->device.handle, "_OFF",
414 : : NULL, NULL);
415 [ # # ]: 0 : if (ACPI_FAILURE(status))
416 : 0 : return -ENODEV;
417 : :
418 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n",
419 : : resource->name));
420 : : return 0;
421 : : }
422 : :
423 : 0 : static int acpi_power_off_unlocked(struct acpi_power_resource *resource)
424 : : {
425 : 0 : int result = 0;
426 : :
427 [ # # ]: 0 : if (!resource->ref_count) {
428 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
429 : : "Power resource [%s] already off\n",
430 : : resource->name));
431 : : return 0;
432 : : }
433 : :
434 [ # # ]: 0 : if (--resource->ref_count) {
435 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
436 : : "Power resource [%s] still in use\n",
437 : : resource->name));
438 : : } else {
439 : 0 : result = __acpi_power_off(resource);
440 : 0 : if (result)
441 : 0 : resource->ref_count++;
442 : : }
443 : : return result;
444 : : }
445 : :
446 : 0 : static int acpi_power_off(struct acpi_power_resource *resource)
447 : : {
448 : 0 : int result;
449 : :
450 : 0 : mutex_lock(&resource->resource_lock);
451 : 0 : result = acpi_power_off_unlocked(resource);
452 : 0 : mutex_unlock(&resource->resource_lock);
453 : 0 : return result;
454 : : }
455 : :
456 : 0 : static int acpi_power_off_list(struct list_head *list)
457 : : {
458 : 0 : struct acpi_power_resource_entry *entry;
459 : 0 : int result = 0;
460 : :
461 [ # # ]: 0 : list_for_each_entry_reverse(entry, list, node) {
462 : 0 : result = acpi_power_off(entry->resource);
463 [ # # ]: 0 : if (result)
464 : 0 : goto err;
465 : : }
466 : : return 0;
467 : :
468 : : err:
469 [ # # ]: 0 : list_for_each_entry_continue(entry, list, node)
470 : 0 : acpi_power_on(entry->resource);
471 : :
472 : : return result;
473 : : }
474 : :
475 : 0 : static int acpi_power_on_list(struct list_head *list)
476 : : {
477 : 0 : struct acpi_power_resource_entry *entry;
478 : 0 : int result = 0;
479 : :
480 [ # # ]: 0 : list_for_each_entry(entry, list, node) {
481 : 0 : result = acpi_power_on(entry->resource);
482 [ # # ]: 0 : if (result)
483 : 0 : goto err;
484 : : }
485 : : return 0;
486 : :
487 : : err:
488 [ # # ]: 0 : list_for_each_entry_continue_reverse(entry, list, node)
489 : 0 : acpi_power_off(entry->resource);
490 : :
491 : : return result;
492 : : }
493 : :
494 : : static struct attribute *attrs[] = {
495 : : NULL,
496 : : };
497 : :
498 : : static const struct attribute_group attr_groups[] = {
499 : : [ACPI_STATE_D0] = {
500 : : .name = "power_resources_D0",
501 : : .attrs = attrs,
502 : : },
503 : : [ACPI_STATE_D1] = {
504 : : .name = "power_resources_D1",
505 : : .attrs = attrs,
506 : : },
507 : : [ACPI_STATE_D2] = {
508 : : .name = "power_resources_D2",
509 : : .attrs = attrs,
510 : : },
511 : : [ACPI_STATE_D3_HOT] = {
512 : : .name = "power_resources_D3hot",
513 : : .attrs = attrs,
514 : : },
515 : : };
516 : :
517 : : static const struct attribute_group wakeup_attr_group = {
518 : : .name = "power_resources_wakeup",
519 : : .attrs = attrs,
520 : : };
521 : :
522 : 0 : static void acpi_power_hide_list(struct acpi_device *adev,
523 : : struct list_head *resources,
524 : : const struct attribute_group *attr_group)
525 : : {
526 : 0 : struct acpi_power_resource_entry *entry;
527 : :
528 [ # # ]: 0 : if (list_empty(resources))
529 : : return;
530 : :
531 [ # # ]: 0 : list_for_each_entry_reverse(entry, resources, node) {
532 : 0 : struct acpi_device *res_dev = &entry->resource->device;
533 : :
534 [ # # ]: 0 : sysfs_remove_link_from_group(&adev->dev.kobj,
535 : : attr_group->name,
536 : : dev_name(&res_dev->dev));
537 : : }
538 : 0 : sysfs_remove_group(&adev->dev.kobj, attr_group);
539 : : }
540 : :
541 : 0 : static void acpi_power_expose_list(struct acpi_device *adev,
542 : : struct list_head *resources,
543 : : const struct attribute_group *attr_group)
544 : : {
545 : 0 : struct acpi_power_resource_entry *entry;
546 : 0 : int ret;
547 : :
548 [ # # ]: 0 : if (list_empty(resources))
549 : : return;
550 : :
551 : 0 : ret = sysfs_create_group(&adev->dev.kobj, attr_group);
552 [ # # ]: 0 : if (ret)
553 : : return;
554 : :
555 [ # # ]: 0 : list_for_each_entry(entry, resources, node) {
556 : 0 : struct acpi_device *res_dev = &entry->resource->device;
557 : :
558 [ # # ]: 0 : ret = sysfs_add_link_to_group(&adev->dev.kobj,
559 : : attr_group->name,
560 : : &res_dev->dev.kobj,
561 : : dev_name(&res_dev->dev));
562 [ # # ]: 0 : if (ret) {
563 : 0 : acpi_power_hide_list(adev, resources, attr_group);
564 : 0 : break;
565 : : }
566 : : }
567 : : }
568 : :
569 : 0 : static void acpi_power_expose_hide(struct acpi_device *adev,
570 : : struct list_head *resources,
571 : : const struct attribute_group *attr_group,
572 : : bool expose)
573 : : {
574 [ # # ]: 0 : if (expose)
575 : 0 : acpi_power_expose_list(adev, resources, attr_group);
576 : : else
577 : 0 : acpi_power_hide_list(adev, resources, attr_group);
578 : 0 : }
579 : :
580 : 174 : void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
581 : : {
582 : 174 : int state;
583 : :
584 [ - + ]: 174 : if (adev->wakeup.flags.valid)
585 : 0 : acpi_power_expose_hide(adev, &adev->wakeup.resources,
586 : : &wakeup_attr_group, add);
587 : :
588 [ - + ]: 174 : if (!adev->power.flags.power_resources)
589 : : return;
590 : :
591 [ # # ]: 0 : for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
592 : 0 : acpi_power_expose_hide(adev,
593 : : &adev->power.states[state].resources,
594 : : &attr_groups[state], add);
595 : : }
596 : :
597 : 0 : int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
598 : : {
599 : 0 : struct acpi_power_resource_entry *entry;
600 : 0 : int system_level = 5;
601 : :
602 [ # # ]: 0 : list_for_each_entry(entry, list, node) {
603 : 0 : struct acpi_power_resource *resource = entry->resource;
604 : 0 : acpi_handle handle = resource->device.handle;
605 : 0 : int result;
606 : 0 : int state;
607 : :
608 : 0 : mutex_lock(&resource->resource_lock);
609 : :
610 : 0 : result = acpi_power_get_state(handle, &state);
611 [ # # ]: 0 : if (result) {
612 : 0 : mutex_unlock(&resource->resource_lock);
613 : 0 : return result;
614 : : }
615 [ # # ]: 0 : if (state == ACPI_POWER_RESOURCE_STATE_ON) {
616 : 0 : resource->ref_count++;
617 : 0 : resource->wakeup_enabled = true;
618 : : }
619 [ # # ]: 0 : if (system_level > resource->system_level)
620 : 0 : system_level = resource->system_level;
621 : :
622 : 0 : mutex_unlock(&resource->resource_lock);
623 : : }
624 : 0 : *system_level_p = system_level;
625 : 0 : return 0;
626 : : }
627 : :
628 : : /* --------------------------------------------------------------------------
629 : : Device Power Management
630 : : -------------------------------------------------------------------------- */
631 : :
632 : : /**
633 : : * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
634 : : * ACPI 3.0) _PSW (Power State Wake)
635 : : * @dev: Device to handle.
636 : : * @enable: 0 - disable, 1 - enable the wake capabilities of the device.
637 : : * @sleep_state: Target sleep state of the system.
638 : : * @dev_state: Target power state of the device.
639 : : *
640 : : * Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
641 : : * State Wake) for the device, if present. On failure reset the device's
642 : : * wakeup.flags.valid flag.
643 : : *
644 : : * RETURN VALUE:
645 : : * 0 if either _DSW or _PSW has been successfully executed
646 : : * 0 if neither _DSW nor _PSW has been found
647 : : * -ENODEV if the execution of either _DSW or _PSW has failed
648 : : */
649 : 0 : int acpi_device_sleep_wake(struct acpi_device *dev,
650 : : int enable, int sleep_state, int dev_state)
651 : : {
652 : 0 : union acpi_object in_arg[3];
653 : 0 : struct acpi_object_list arg_list = { 3, in_arg };
654 : 0 : acpi_status status = AE_OK;
655 : :
656 : : /*
657 : : * Try to execute _DSW first.
658 : : *
659 : : * Three arguments are needed for the _DSW object:
660 : : * Argument 0: enable/disable the wake capabilities
661 : : * Argument 1: target system state
662 : : * Argument 2: target device state
663 : : * When _DSW object is called to disable the wake capabilities, maybe
664 : : * the first argument is filled. The values of the other two arguments
665 : : * are meaningless.
666 : : */
667 : 0 : in_arg[0].type = ACPI_TYPE_INTEGER;
668 : 0 : in_arg[0].integer.value = enable;
669 : 0 : in_arg[1].type = ACPI_TYPE_INTEGER;
670 : 0 : in_arg[1].integer.value = sleep_state;
671 : 0 : in_arg[2].type = ACPI_TYPE_INTEGER;
672 : 0 : in_arg[2].integer.value = dev_state;
673 : 0 : status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
674 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
675 : : return 0;
676 [ # # ]: 0 : } else if (status != AE_NOT_FOUND) {
677 : 0 : printk(KERN_ERR PREFIX "_DSW execution failed\n");
678 : 0 : dev->wakeup.flags.valid = 0;
679 : 0 : return -ENODEV;
680 : : }
681 : :
682 : : /* Execute _PSW */
683 : 0 : status = acpi_execute_simple_method(dev->handle, "_PSW", enable);
684 [ # # ]: 0 : if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
685 : 0 : printk(KERN_ERR PREFIX "_PSW execution failed\n");
686 : 0 : dev->wakeup.flags.valid = 0;
687 : 0 : return -ENODEV;
688 : : }
689 : :
690 : : return 0;
691 : : }
692 : :
693 : : /*
694 : : * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
695 : : * 1. Power on the power resources required for the wakeup device
696 : : * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
697 : : * State Wake) for the device, if present
698 : : */
699 : 0 : int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
700 : : {
701 : 0 : struct acpi_power_resource_entry *entry;
702 : 0 : int err = 0;
703 : :
704 [ # # # # ]: 0 : if (!dev || !dev->wakeup.flags.valid)
705 : : return -EINVAL;
706 : :
707 : 0 : mutex_lock(&acpi_device_lock);
708 : :
709 [ # # ]: 0 : if (dev->wakeup.prepare_count++)
710 : 0 : goto out;
711 : :
712 [ # # ]: 0 : list_for_each_entry(entry, &dev->wakeup.resources, node) {
713 : 0 : struct acpi_power_resource *resource = entry->resource;
714 : :
715 : 0 : mutex_lock(&resource->resource_lock);
716 : :
717 [ # # ]: 0 : if (!resource->wakeup_enabled) {
718 : 0 : err = acpi_power_on_unlocked(resource);
719 [ # # ]: 0 : if (!err)
720 : 0 : resource->wakeup_enabled = true;
721 : : }
722 : :
723 : 0 : mutex_unlock(&resource->resource_lock);
724 : :
725 [ # # ]: 0 : if (err) {
726 : 0 : dev_err(&dev->dev,
727 : : "Cannot turn wakeup power resources on\n");
728 : 0 : dev->wakeup.flags.valid = 0;
729 : 0 : goto out;
730 : : }
731 : : }
732 : : /*
733 : : * Passing 3 as the third argument below means the device may be
734 : : * put into arbitrary power state afterward.
735 : : */
736 : 0 : err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
737 [ # # ]: 0 : if (err)
738 : 0 : dev->wakeup.prepare_count = 0;
739 : :
740 : 0 : out:
741 : 0 : mutex_unlock(&acpi_device_lock);
742 : 0 : return err;
743 : : }
744 : :
745 : : /*
746 : : * Shutdown a wakeup device, counterpart of above method
747 : : * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
748 : : * State Wake) for the device, if present
749 : : * 2. Shutdown down the power resources
750 : : */
751 : 0 : int acpi_disable_wakeup_device_power(struct acpi_device *dev)
752 : : {
753 : 0 : struct acpi_power_resource_entry *entry;
754 : 0 : int err = 0;
755 : :
756 [ # # # # ]: 0 : if (!dev || !dev->wakeup.flags.valid)
757 : : return -EINVAL;
758 : :
759 : 0 : mutex_lock(&acpi_device_lock);
760 : :
761 [ # # ]: 0 : if (--dev->wakeup.prepare_count > 0)
762 : 0 : goto out;
763 : :
764 : : /*
765 : : * Executing the code below even if prepare_count is already zero when
766 : : * the function is called may be useful, for example for initialisation.
767 : : */
768 [ # # ]: 0 : if (dev->wakeup.prepare_count < 0)
769 : 0 : dev->wakeup.prepare_count = 0;
770 : :
771 : 0 : err = acpi_device_sleep_wake(dev, 0, 0, 0);
772 [ # # ]: 0 : if (err)
773 : 0 : goto out;
774 : :
775 [ # # ]: 0 : list_for_each_entry(entry, &dev->wakeup.resources, node) {
776 : 0 : struct acpi_power_resource *resource = entry->resource;
777 : :
778 : 0 : mutex_lock(&resource->resource_lock);
779 : :
780 [ # # ]: 0 : if (resource->wakeup_enabled) {
781 : 0 : err = acpi_power_off_unlocked(resource);
782 [ # # ]: 0 : if (!err)
783 : 0 : resource->wakeup_enabled = false;
784 : : }
785 : :
786 : 0 : mutex_unlock(&resource->resource_lock);
787 : :
788 [ # # ]: 0 : if (err) {
789 : 0 : dev_err(&dev->dev,
790 : : "Cannot turn wakeup power resources off\n");
791 : 0 : dev->wakeup.flags.valid = 0;
792 : 0 : break;
793 : : }
794 : : }
795 : :
796 : 0 : out:
797 : 0 : mutex_unlock(&acpi_device_lock);
798 : 0 : return err;
799 : : }
800 : :
801 : 0 : int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
802 : : {
803 : 0 : int result = 0;
804 : 0 : int list_state = 0;
805 : 0 : int i = 0;
806 : :
807 [ # # ]: 0 : if (!device || !state)
808 : : return -EINVAL;
809 : :
810 : : /*
811 : : * We know a device's inferred power state when all the resources
812 : : * required for a given D-state are 'on'.
813 : : */
814 [ # # ]: 0 : for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
815 : 0 : struct list_head *list = &device->power.states[i].resources;
816 : :
817 [ # # ]: 0 : if (list_empty(list))
818 : 0 : continue;
819 : :
820 : 0 : result = acpi_power_get_list_state(list, &list_state);
821 [ # # ]: 0 : if (result)
822 : 0 : return result;
823 : :
824 [ # # ]: 0 : if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
825 : 0 : *state = i;
826 : 0 : return 0;
827 : : }
828 : : }
829 : :
830 : 0 : *state = device->power.states[ACPI_STATE_D3_COLD].flags.valid ?
831 : 0 : ACPI_STATE_D3_COLD : ACPI_STATE_D3_HOT;
832 : 0 : return 0;
833 : : }
834 : :
835 : 0 : int acpi_power_on_resources(struct acpi_device *device, int state)
836 : : {
837 [ # # # # ]: 0 : if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3_HOT)
838 : : return -EINVAL;
839 : :
840 : 0 : return acpi_power_on_list(&device->power.states[state].resources);
841 : : }
842 : :
843 : 0 : int acpi_power_transition(struct acpi_device *device, int state)
844 : : {
845 : 0 : int result = 0;
846 : :
847 [ # # # # ]: 0 : if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
848 : : return -EINVAL;
849 : :
850 [ # # # # ]: 0 : if (device->power.state == state || !device->flags.power_manageable)
851 : : return 0;
852 : :
853 : 0 : if ((device->power.state < ACPI_STATE_D0)
854 [ # # ]: 0 : || (device->power.state > ACPI_STATE_D3_COLD))
855 : : return -ENODEV;
856 : :
857 : : /*
858 : : * First we reference all power resources required in the target list
859 : : * (e.g. so the device doesn't lose power while transitioning). Then,
860 : : * we dereference all power resources used in the current list.
861 : : */
862 [ # # ]: 0 : if (state < ACPI_STATE_D3_COLD)
863 : 0 : result = acpi_power_on_list(
864 : : &device->power.states[state].resources);
865 : :
866 [ # # # # ]: 0 : if (!result && device->power.state < ACPI_STATE_D3_COLD)
867 : 0 : acpi_power_off_list(
868 : : &device->power.states[device->power.state].resources);
869 : :
870 : : /* We shouldn't change the state unless the above operations succeed. */
871 [ # # ]: 0 : device->power.state = result ? ACPI_STATE_UNKNOWN : state;
872 : :
873 : 0 : return result;
874 : : }
875 : :
876 : 0 : static void acpi_release_power_resource(struct device *dev)
877 : : {
878 : 0 : struct acpi_device *device = to_acpi_device(dev);
879 : 0 : struct acpi_power_resource *resource;
880 : :
881 : 0 : resource = container_of(device, struct acpi_power_resource, device);
882 : :
883 : 0 : mutex_lock(&power_resource_list_lock);
884 : 0 : list_del(&resource->list_node);
885 : 0 : mutex_unlock(&power_resource_list_lock);
886 : :
887 : 0 : acpi_free_pnp_ids(&device->pnp);
888 : 0 : kfree(resource);
889 : 0 : }
890 : :
891 : 0 : static ssize_t acpi_power_in_use_show(struct device *dev,
892 : : struct device_attribute *attr,
893 : : char *buf) {
894 : 0 : struct acpi_power_resource *resource;
895 : :
896 : 0 : resource = to_power_resource(to_acpi_device(dev));
897 : 0 : return sprintf(buf, "%u\n", !!resource->ref_count);
898 : : }
899 : : static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
900 : :
901 : 0 : static void acpi_power_sysfs_remove(struct acpi_device *device)
902 : : {
903 : 0 : device_remove_file(&device->dev, &dev_attr_resource_in_use);
904 : 0 : }
905 : :
906 : 0 : static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource)
907 : : {
908 : 0 : mutex_lock(&power_resource_list_lock);
909 : :
910 [ # # ]: 0 : if (!list_empty(&acpi_power_resource_list)) {
911 : 0 : struct acpi_power_resource *r;
912 : :
913 [ # # ]: 0 : list_for_each_entry(r, &acpi_power_resource_list, list_node)
914 [ # # ]: 0 : if (r->order > resource->order) {
915 : 0 : list_add_tail(&resource->list_node, &r->list_node);
916 : 0 : goto out;
917 : : }
918 : : }
919 : 0 : list_add_tail(&resource->list_node, &acpi_power_resource_list);
920 : :
921 : 0 : out:
922 : 0 : mutex_unlock(&power_resource_list_lock);
923 : 0 : }
924 : :
925 : 0 : int acpi_add_power_resource(acpi_handle handle)
926 : : {
927 : 0 : struct acpi_power_resource *resource;
928 : 0 : struct acpi_device *device = NULL;
929 : 0 : union acpi_object acpi_object;
930 : 0 : struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
931 : 0 : acpi_status status;
932 : 0 : int state, result = -ENODEV;
933 : :
934 : 0 : acpi_bus_get_device(handle, &device);
935 [ # # ]: 0 : if (device)
936 : : return 0;
937 : :
938 : 0 : resource = kzalloc(sizeof(*resource), GFP_KERNEL);
939 [ # # ]: 0 : if (!resource)
940 : : return -ENOMEM;
941 : :
942 : 0 : device = &resource->device;
943 : 0 : acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
944 : : ACPI_STA_DEFAULT);
945 : 0 : mutex_init(&resource->resource_lock);
946 : 0 : INIT_LIST_HEAD(&resource->list_node);
947 : 0 : INIT_LIST_HEAD(&resource->dependents);
948 : 0 : resource->name = device->pnp.bus_id;
949 : 0 : strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
950 : 0 : strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
951 : 0 : device->power.state = ACPI_STATE_UNKNOWN;
952 : :
953 : : /* Evalute the object to get the system level and resource order. */
954 : 0 : status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
955 [ # # ]: 0 : if (ACPI_FAILURE(status))
956 : 0 : goto err;
957 : :
958 : 0 : resource->system_level = acpi_object.power_resource.system_level;
959 : 0 : resource->order = acpi_object.power_resource.resource_order;
960 : :
961 : 0 : result = acpi_power_get_state(handle, &state);
962 [ # # ]: 0 : if (result)
963 : 0 : goto err;
964 : :
965 : 0 : printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
966 [ # # ]: 0 : acpi_device_bid(device), state ? "on" : "off");
967 : :
968 : 0 : device->flags.match_driver = true;
969 : 0 : result = acpi_device_add(device, acpi_release_power_resource);
970 [ # # ]: 0 : if (result)
971 : 0 : goto err;
972 : :
973 [ # # ]: 0 : if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
974 : 0 : device->remove = acpi_power_sysfs_remove;
975 : :
976 : 0 : acpi_power_add_resource_to_list(resource);
977 : 0 : acpi_device_add_finalize(device);
978 : 0 : return 0;
979 : :
980 : 0 : err:
981 : 0 : acpi_release_power_resource(&device->dev);
982 : 0 : return result;
983 : : }
984 : :
985 : : #ifdef CONFIG_ACPI_SLEEP
986 : 0 : void acpi_resume_power_resources(void)
987 : : {
988 : 0 : struct acpi_power_resource *resource;
989 : :
990 : 0 : mutex_lock(&power_resource_list_lock);
991 : :
992 [ # # ]: 0 : list_for_each_entry(resource, &acpi_power_resource_list, list_node) {
993 : 0 : int result, state;
994 : :
995 : 0 : mutex_lock(&resource->resource_lock);
996 : :
997 : 0 : result = acpi_power_get_state(resource->device.handle, &state);
998 [ # # ]: 0 : if (result) {
999 : 0 : mutex_unlock(&resource->resource_lock);
1000 : 0 : continue;
1001 : : }
1002 : :
1003 [ # # ]: 0 : if (state == ACPI_POWER_RESOURCE_STATE_OFF
1004 [ # # ]: 0 : && resource->ref_count) {
1005 : 0 : dev_info(&resource->device.dev, "Turning ON\n");
1006 : 0 : __acpi_power_on(resource);
1007 : : }
1008 : :
1009 : 0 : mutex_unlock(&resource->resource_lock);
1010 : : }
1011 : :
1012 : 0 : mutex_unlock(&power_resource_list_lock);
1013 : 0 : }
1014 : :
1015 : 0 : void acpi_turn_off_unused_power_resources(void)
1016 : : {
1017 : 0 : struct acpi_power_resource *resource;
1018 : :
1019 : 0 : mutex_lock(&power_resource_list_lock);
1020 : :
1021 [ # # ]: 0 : list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
1022 : 0 : int result, state;
1023 : :
1024 : 0 : mutex_lock(&resource->resource_lock);
1025 : :
1026 : 0 : result = acpi_power_get_state(resource->device.handle, &state);
1027 [ # # ]: 0 : if (result) {
1028 : 0 : mutex_unlock(&resource->resource_lock);
1029 : 0 : continue;
1030 : : }
1031 : :
1032 [ # # ]: 0 : if (state == ACPI_POWER_RESOURCE_STATE_ON
1033 [ # # ]: 0 : && !resource->ref_count) {
1034 : 0 : dev_info(&resource->device.dev, "Turning OFF\n");
1035 : 0 : __acpi_power_off(resource);
1036 : : }
1037 : :
1038 : 0 : mutex_unlock(&resource->resource_lock);
1039 : : }
1040 : :
1041 : 0 : mutex_unlock(&power_resource_list_lock);
1042 : 0 : }
1043 : : #endif
|