Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/acpi/power.c
15109 views
1
/*
2
* acpi_power.c - ACPI Bus Power Management ($Revision: 39 $)
3
*
4
* Copyright (C) 2001, 2002 Andy Grover <[email protected]>
5
* Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
6
*
7
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or (at
12
* your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write to the Free Software Foundation, Inc.,
21
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22
*
23
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
*/
25
26
/*
27
* ACPI power-managed devices may be controlled in two ways:
28
* 1. via "Device Specific (D-State) Control"
29
* 2. via "Power Resource Control".
30
* This module is used to manage devices relying on Power Resource Control.
31
*
32
* An ACPI "power resource object" describes a software controllable power
33
* plane, clock plane, or other resource used by a power managed device.
34
* A device may rely on multiple power resources, and a power resource
35
* may be shared by multiple devices.
36
*/
37
38
#include <linux/kernel.h>
39
#include <linux/module.h>
40
#include <linux/init.h>
41
#include <linux/types.h>
42
#include <linux/slab.h>
43
#include <acpi/acpi_bus.h>
44
#include <acpi/acpi_drivers.h>
45
#include "sleep.h"
46
47
#define PREFIX "ACPI: "
48
49
#define _COMPONENT ACPI_POWER_COMPONENT
50
ACPI_MODULE_NAME("power");
51
#define ACPI_POWER_CLASS "power_resource"
52
#define ACPI_POWER_DEVICE_NAME "Power Resource"
53
#define ACPI_POWER_FILE_INFO "info"
54
#define ACPI_POWER_FILE_STATUS "state"
55
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
56
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
57
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
58
59
static int acpi_power_add(struct acpi_device *device);
60
static int acpi_power_remove(struct acpi_device *device, int type);
61
static int acpi_power_resume(struct acpi_device *device);
62
63
static const struct acpi_device_id power_device_ids[] = {
64
{ACPI_POWER_HID, 0},
65
{"", 0},
66
};
67
MODULE_DEVICE_TABLE(acpi, power_device_ids);
68
69
static struct acpi_driver acpi_power_driver = {
70
.name = "power",
71
.class = ACPI_POWER_CLASS,
72
.ids = power_device_ids,
73
.ops = {
74
.add = acpi_power_add,
75
.remove = acpi_power_remove,
76
.resume = acpi_power_resume,
77
},
78
};
79
80
struct acpi_power_resource {
81
struct acpi_device * device;
82
acpi_bus_id name;
83
u32 system_level;
84
u32 order;
85
unsigned int ref_count;
86
struct mutex resource_lock;
87
};
88
89
static struct list_head acpi_power_resource_list;
90
91
/* --------------------------------------------------------------------------
92
Power Resource Management
93
-------------------------------------------------------------------------- */
94
95
static int
96
acpi_power_get_context(acpi_handle handle,
97
struct acpi_power_resource **resource)
98
{
99
int result = 0;
100
struct acpi_device *device = NULL;
101
102
103
if (!resource)
104
return -ENODEV;
105
106
result = acpi_bus_get_device(handle, &device);
107
if (result) {
108
printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle);
109
return result;
110
}
111
112
*resource = acpi_driver_data(device);
113
if (!*resource)
114
return -ENODEV;
115
116
return 0;
117
}
118
119
static int acpi_power_get_state(acpi_handle handle, int *state)
120
{
121
acpi_status status = AE_OK;
122
unsigned long long sta = 0;
123
char node_name[5];
124
struct acpi_buffer buffer = { sizeof(node_name), node_name };
125
126
127
if (!handle || !state)
128
return -EINVAL;
129
130
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
131
if (ACPI_FAILURE(status))
132
return -ENODEV;
133
134
*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
135
ACPI_POWER_RESOURCE_STATE_OFF;
136
137
acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
138
139
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
140
node_name,
141
*state ? "on" : "off"));
142
143
return 0;
144
}
145
146
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
147
{
148
int cur_state;
149
int i = 0;
150
151
if (!list || !state)
152
return -EINVAL;
153
154
/* The state of the list is 'on' IFF all resources are 'on'. */
155
156
for (i = 0; i < list->count; i++) {
157
struct acpi_power_resource *resource;
158
acpi_handle handle = list->handles[i];
159
int result;
160
161
result = acpi_power_get_context(handle, &resource);
162
if (result)
163
return result;
164
165
mutex_lock(&resource->resource_lock);
166
167
result = acpi_power_get_state(handle, &cur_state);
168
169
mutex_unlock(&resource->resource_lock);
170
171
if (result)
172
return result;
173
174
if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
175
break;
176
}
177
178
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
179
cur_state ? "on" : "off"));
180
181
*state = cur_state;
182
183
return 0;
184
}
185
186
static int __acpi_power_on(struct acpi_power_resource *resource)
187
{
188
acpi_status status = AE_OK;
189
190
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
191
if (ACPI_FAILURE(status))
192
return -ENODEV;
193
194
/* Update the power resource's _device_ power state */
195
resource->device->power.state = ACPI_STATE_D0;
196
197
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
198
resource->name));
199
200
return 0;
201
}
202
203
static int acpi_power_on(acpi_handle handle)
204
{
205
int result = 0;
206
struct acpi_power_resource *resource = NULL;
207
208
result = acpi_power_get_context(handle, &resource);
209
if (result)
210
return result;
211
212
mutex_lock(&resource->resource_lock);
213
214
if (resource->ref_count++) {
215
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
216
"Power resource [%s] already on",
217
resource->name));
218
} else {
219
result = __acpi_power_on(resource);
220
if (result)
221
resource->ref_count--;
222
}
223
224
mutex_unlock(&resource->resource_lock);
225
226
return result;
227
}
228
229
static int acpi_power_off(acpi_handle handle)
230
{
231
int result = 0;
232
acpi_status status = AE_OK;
233
struct acpi_power_resource *resource = NULL;
234
235
result = acpi_power_get_context(handle, &resource);
236
if (result)
237
return result;
238
239
mutex_lock(&resource->resource_lock);
240
241
if (!resource->ref_count) {
242
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
243
"Power resource [%s] already off",
244
resource->name));
245
goto unlock;
246
}
247
248
if (--resource->ref_count) {
249
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
250
"Power resource [%s] still in use\n",
251
resource->name));
252
goto unlock;
253
}
254
255
status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
256
if (ACPI_FAILURE(status)) {
257
result = -ENODEV;
258
} else {
259
/* Update the power resource's _device_ power state */
260
resource->device->power.state = ACPI_STATE_D3;
261
262
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
263
"Power resource [%s] turned off\n",
264
resource->name));
265
}
266
267
unlock:
268
mutex_unlock(&resource->resource_lock);
269
270
return result;
271
}
272
273
static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
274
{
275
int i;
276
277
for (i = num_res - 1; i >= 0 ; i--)
278
acpi_power_off(list->handles[i]);
279
}
280
281
static void acpi_power_off_list(struct acpi_handle_list *list)
282
{
283
__acpi_power_off_list(list, list->count);
284
}
285
286
static int acpi_power_on_list(struct acpi_handle_list *list)
287
{
288
int result = 0;
289
int i;
290
291
for (i = 0; i < list->count; i++) {
292
result = acpi_power_on(list->handles[i]);
293
if (result) {
294
__acpi_power_off_list(list, i);
295
break;
296
}
297
}
298
299
return result;
300
}
301
302
/**
303
* acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
304
* ACPI 3.0) _PSW (Power State Wake)
305
* @dev: Device to handle.
306
* @enable: 0 - disable, 1 - enable the wake capabilities of the device.
307
* @sleep_state: Target sleep state of the system.
308
* @dev_state: Target power state of the device.
309
*
310
* Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
311
* State Wake) for the device, if present. On failure reset the device's
312
* wakeup.flags.valid flag.
313
*
314
* RETURN VALUE:
315
* 0 if either _DSW or _PSW has been successfully executed
316
* 0 if neither _DSW nor _PSW has been found
317
* -ENODEV if the execution of either _DSW or _PSW has failed
318
*/
319
int acpi_device_sleep_wake(struct acpi_device *dev,
320
int enable, int sleep_state, int dev_state)
321
{
322
union acpi_object in_arg[3];
323
struct acpi_object_list arg_list = { 3, in_arg };
324
acpi_status status = AE_OK;
325
326
/*
327
* Try to execute _DSW first.
328
*
329
* Three agruments are needed for the _DSW object:
330
* Argument 0: enable/disable the wake capabilities
331
* Argument 1: target system state
332
* Argument 2: target device state
333
* When _DSW object is called to disable the wake capabilities, maybe
334
* the first argument is filled. The values of the other two agruments
335
* are meaningless.
336
*/
337
in_arg[0].type = ACPI_TYPE_INTEGER;
338
in_arg[0].integer.value = enable;
339
in_arg[1].type = ACPI_TYPE_INTEGER;
340
in_arg[1].integer.value = sleep_state;
341
in_arg[2].type = ACPI_TYPE_INTEGER;
342
in_arg[2].integer.value = dev_state;
343
status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
344
if (ACPI_SUCCESS(status)) {
345
return 0;
346
} else if (status != AE_NOT_FOUND) {
347
printk(KERN_ERR PREFIX "_DSW execution failed\n");
348
dev->wakeup.flags.valid = 0;
349
return -ENODEV;
350
}
351
352
/* Execute _PSW */
353
arg_list.count = 1;
354
in_arg[0].integer.value = enable;
355
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
356
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
357
printk(KERN_ERR PREFIX "_PSW execution failed\n");
358
dev->wakeup.flags.valid = 0;
359
return -ENODEV;
360
}
361
362
return 0;
363
}
364
365
/*
366
* Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
367
* 1. Power on the power resources required for the wakeup device
368
* 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
369
* State Wake) for the device, if present
370
*/
371
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
372
{
373
int i, err = 0;
374
375
if (!dev || !dev->wakeup.flags.valid)
376
return -EINVAL;
377
378
mutex_lock(&acpi_device_lock);
379
380
if (dev->wakeup.prepare_count++)
381
goto out;
382
383
/* Open power resource */
384
for (i = 0; i < dev->wakeup.resources.count; i++) {
385
int ret = acpi_power_on(dev->wakeup.resources.handles[i]);
386
if (ret) {
387
printk(KERN_ERR PREFIX "Transition power state\n");
388
dev->wakeup.flags.valid = 0;
389
err = -ENODEV;
390
goto err_out;
391
}
392
}
393
394
/*
395
* Passing 3 as the third argument below means the device may be placed
396
* in arbitrary power state afterwards.
397
*/
398
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
399
400
err_out:
401
if (err)
402
dev->wakeup.prepare_count = 0;
403
404
out:
405
mutex_unlock(&acpi_device_lock);
406
return err;
407
}
408
409
/*
410
* Shutdown a wakeup device, counterpart of above method
411
* 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
412
* State Wake) for the device, if present
413
* 2. Shutdown down the power resources
414
*/
415
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
416
{
417
int i, err = 0;
418
419
if (!dev || !dev->wakeup.flags.valid)
420
return -EINVAL;
421
422
mutex_lock(&acpi_device_lock);
423
424
if (--dev->wakeup.prepare_count > 0)
425
goto out;
426
427
/*
428
* Executing the code below even if prepare_count is already zero when
429
* the function is called may be useful, for example for initialisation.
430
*/
431
if (dev->wakeup.prepare_count < 0)
432
dev->wakeup.prepare_count = 0;
433
434
err = acpi_device_sleep_wake(dev, 0, 0, 0);
435
if (err)
436
goto out;
437
438
/* Close power resource */
439
for (i = 0; i < dev->wakeup.resources.count; i++) {
440
int ret = acpi_power_off(dev->wakeup.resources.handles[i]);
441
if (ret) {
442
printk(KERN_ERR PREFIX "Transition power state\n");
443
dev->wakeup.flags.valid = 0;
444
err = -ENODEV;
445
goto out;
446
}
447
}
448
449
out:
450
mutex_unlock(&acpi_device_lock);
451
return err;
452
}
453
454
/* --------------------------------------------------------------------------
455
Device Power Management
456
-------------------------------------------------------------------------- */
457
458
int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
459
{
460
int result = 0;
461
struct acpi_handle_list *list = NULL;
462
int list_state = 0;
463
int i = 0;
464
465
if (!device || !state)
466
return -EINVAL;
467
468
/*
469
* We know a device's inferred power state when all the resources
470
* required for a given D-state are 'on'.
471
*/
472
for (i = ACPI_STATE_D0; i < ACPI_STATE_D3; i++) {
473
list = &device->power.states[i].resources;
474
if (list->count < 1)
475
continue;
476
477
result = acpi_power_get_list_state(list, &list_state);
478
if (result)
479
return result;
480
481
if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
482
*state = i;
483
return 0;
484
}
485
}
486
487
*state = ACPI_STATE_D3;
488
return 0;
489
}
490
491
int acpi_power_on_resources(struct acpi_device *device, int state)
492
{
493
if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
494
return -EINVAL;
495
496
return acpi_power_on_list(&device->power.states[state].resources);
497
}
498
499
int acpi_power_transition(struct acpi_device *device, int state)
500
{
501
int result;
502
503
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
504
return -EINVAL;
505
506
if (device->power.state == state)
507
return 0;
508
509
if ((device->power.state < ACPI_STATE_D0)
510
|| (device->power.state > ACPI_STATE_D3))
511
return -ENODEV;
512
513
/* TBD: Resources must be ordered. */
514
515
/*
516
* First we reference all power resources required in the target list
517
* (e.g. so the device doesn't lose power while transitioning). Then,
518
* we dereference all power resources used in the current list.
519
*/
520
result = acpi_power_on_list(&device->power.states[state].resources);
521
if (!result)
522
acpi_power_off_list(
523
&device->power.states[device->power.state].resources);
524
525
/* We shouldn't change the state unless the above operations succeed. */
526
device->power.state = result ? ACPI_STATE_UNKNOWN : state;
527
528
return result;
529
}
530
531
/* --------------------------------------------------------------------------
532
Driver Interface
533
-------------------------------------------------------------------------- */
534
535
static int acpi_power_add(struct acpi_device *device)
536
{
537
int result = 0, state;
538
acpi_status status = AE_OK;
539
struct acpi_power_resource *resource = NULL;
540
union acpi_object acpi_object;
541
struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
542
543
544
if (!device)
545
return -EINVAL;
546
547
resource = kzalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
548
if (!resource)
549
return -ENOMEM;
550
551
resource->device = device;
552
mutex_init(&resource->resource_lock);
553
strcpy(resource->name, device->pnp.bus_id);
554
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
555
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
556
device->driver_data = resource;
557
558
/* Evalute the object to get the system level and resource order. */
559
status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer);
560
if (ACPI_FAILURE(status)) {
561
result = -ENODEV;
562
goto end;
563
}
564
resource->system_level = acpi_object.power_resource.system_level;
565
resource->order = acpi_object.power_resource.resource_order;
566
567
result = acpi_power_get_state(device->handle, &state);
568
if (result)
569
goto end;
570
571
switch (state) {
572
case ACPI_POWER_RESOURCE_STATE_ON:
573
device->power.state = ACPI_STATE_D0;
574
break;
575
case ACPI_POWER_RESOURCE_STATE_OFF:
576
device->power.state = ACPI_STATE_D3;
577
break;
578
default:
579
device->power.state = ACPI_STATE_UNKNOWN;
580
break;
581
}
582
583
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
584
acpi_device_bid(device), state ? "on" : "off");
585
586
end:
587
if (result)
588
kfree(resource);
589
590
return result;
591
}
592
593
static int acpi_power_remove(struct acpi_device *device, int type)
594
{
595
struct acpi_power_resource *resource;
596
597
if (!device)
598
return -EINVAL;
599
600
resource = acpi_driver_data(device);
601
if (!resource)
602
return -EINVAL;
603
604
kfree(resource);
605
606
return 0;
607
}
608
609
static int acpi_power_resume(struct acpi_device *device)
610
{
611
int result = 0, state;
612
struct acpi_power_resource *resource;
613
614
if (!device)
615
return -EINVAL;
616
617
resource = acpi_driver_data(device);
618
if (!resource)
619
return -EINVAL;
620
621
mutex_lock(&resource->resource_lock);
622
623
result = acpi_power_get_state(device->handle, &state);
624
if (result)
625
goto unlock;
626
627
if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count)
628
result = __acpi_power_on(resource);
629
630
unlock:
631
mutex_unlock(&resource->resource_lock);
632
633
return result;
634
}
635
636
int __init acpi_power_init(void)
637
{
638
INIT_LIST_HEAD(&acpi_power_resource_list);
639
return acpi_bus_register_driver(&acpi_power_driver);
640
}
641
642