power.c 23.1 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * drivers/acpi/power.c - ACPI Power Resources management.
L
Linus Torvalds 已提交
3
 *
4 5 6 7
 * Copyright (C) 2001 - 2015 Intel Corp.
 * Author: Andy Grover <andrew.grover@intel.com>
 * Author: Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or (at
 *  your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

/*
 * ACPI power-managed devices may be controlled in two ways:
 * 1. via "Device Specific (D-State) Control"
 * 2. via "Power Resource Control".
28
 * The code below deals with ACPI Power Resources control.
L
Linus Torvalds 已提交
29
 * 
30 31 32
 * An ACPI "power resource object" represents a software controllable power
 * plane, clock plane, or other resource depended on by a device.
 *
L
Linus Torvalds 已提交
33 34 35 36 37 38 39 40
 * A device may rely on multiple power resources, and a power resource
 * may be shared by multiple devices.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
41
#include <linux/slab.h>
42
#include <linux/pm_runtime.h>
43
#include <linux/sysfs.h>
44
#include <linux/acpi.h>
45
#include "sleep.h"
46
#include "internal.h"
47

48
#define _COMPONENT			ACPI_POWER_COMPONENT
49
ACPI_MODULE_NAME("power");
L
Linus Torvalds 已提交
50 51 52 53 54 55 56
#define ACPI_POWER_CLASS		"power_resource"
#define ACPI_POWER_DEVICE_NAME		"Power Resource"
#define ACPI_POWER_FILE_INFO		"info"
#define ACPI_POWER_FILE_STATUS		"state"
#define ACPI_POWER_RESOURCE_STATE_OFF	0x00
#define ACPI_POWER_RESOURCE_STATE_ON	0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
57

L
Len Brown 已提交
58
struct acpi_power_resource {
59
	struct acpi_device device;
60
	struct list_head list_node;
61
	char *name;
L
Len Brown 已提交
62 63
	u32 system_level;
	u32 order;
64
	unsigned int ref_count;
65
	bool wakeup_enabled;
66
	struct mutex resource_lock;
L
Linus Torvalds 已提交
67 68
};

69 70 71 72 73
struct acpi_power_resource_entry {
	struct list_head node;
	struct acpi_power_resource *resource;
};

74 75
static LIST_HEAD(acpi_power_resource_list);
static DEFINE_MUTEX(power_resource_list_lock);
L
Linus Torvalds 已提交
76 77 78 79 80

/* --------------------------------------------------------------------------
                             Power Resource Management
   -------------------------------------------------------------------------- */

81 82 83 84 85 86
static inline
struct acpi_power_resource *to_power_resource(struct acpi_device *device)
{
	return container_of(device, struct acpi_power_resource, device);
}

87
static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
L
Linus Torvalds 已提交
88
{
89
	struct acpi_device *device;
L
Linus Torvalds 已提交
90

91 92
	if (acpi_bus_get_device(handle, &device))
		return NULL;
L
Linus Torvalds 已提交
93

94
	return to_power_resource(device);
L
Linus Torvalds 已提交
95 96
}

97 98
static int acpi_power_resources_list_add(acpi_handle handle,
					 struct list_head *list)
99 100 101 102 103
{
	struct acpi_power_resource *resource = acpi_power_get_context(handle);
	struct acpi_power_resource_entry *entry;

	if (!resource || !list)
104
		return -EINVAL;
105 106 107

	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
108
		return -ENOMEM;
109 110 111 112 113 114 115 116

	entry->resource = resource;
	if (!list_empty(list)) {
		struct acpi_power_resource_entry *e;

		list_for_each_entry(e, list, node)
			if (e->resource->order > resource->order) {
				list_add_tail(&entry->node, &e->node);
117
				return 0;
118 119 120
			}
	}
	list_add_tail(&entry->node, list);
121
	return 0;
122 123 124 125 126 127 128 129 130 131 132 133
}

void acpi_power_resources_list_free(struct list_head *list)
{
	struct acpi_power_resource_entry *entry, *e;

	list_for_each_entry_safe(entry, e, list, node) {
		list_del(&entry->node);
		kfree(entry);
	}
}

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
static bool acpi_power_resource_is_dup(union acpi_object *package,
				       unsigned int start, unsigned int i)
{
	acpi_handle rhandle, dup;
	unsigned int j;

	/* The caller is expected to check the package element types */
	rhandle = package->package.elements[i].reference.handle;
	for (j = start; j < i; j++) {
		dup = package->package.elements[j].reference.handle;
		if (dup == rhandle)
			return true;
	}

	return false;
}

151 152
int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
				 struct list_head *list)
153 154
{
	unsigned int i;
155
	int err = 0;
156 157 158 159 160 161

	for (i = start; i < package->package.count; i++) {
		union acpi_object *element = &package->package.elements[i];
		acpi_handle rhandle;

		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
162
			err = -ENODATA;
163 164 165 166
			break;
		}
		rhandle = element->reference.handle;
		if (!rhandle) {
167
			err = -ENODEV;
168 169
			break;
		}
170 171 172 173 174

		/* Some ACPI tables contain duplicate power resource references */
		if (acpi_power_resource_is_dup(package, start, i))
			continue;

175 176 177 178 179 180 181
		err = acpi_add_power_resource(rhandle);
		if (err)
			break;

		err = acpi_power_resources_list_add(rhandle, list);
		if (err)
			break;
182
	}
183
	if (err)
184 185
		acpi_power_resources_list_free(list);

186
	return err;
187 188
}

189
static int acpi_power_get_state(acpi_handle handle, int *state)
L
Linus Torvalds 已提交
190
{
L
Len Brown 已提交
191
	acpi_status status = AE_OK;
192
	unsigned long long sta = 0;
193 194
	char node_name[5];
	struct acpi_buffer buffer = { sizeof(node_name), node_name };
L
Linus Torvalds 已提交
195 196


197
	if (!handle || !state)
198
		return -EINVAL;
L
Linus Torvalds 已提交
199

200
	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
L
Linus Torvalds 已提交
201
	if (ACPI_FAILURE(status))
202
		return -ENODEV;
L
Linus Torvalds 已提交
203

204 205
	*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
			      ACPI_POWER_RESOURCE_STATE_OFF;
L
Linus Torvalds 已提交
206

207 208
	acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);

L
Linus Torvalds 已提交
209
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
210
			  node_name,
211
				*state ? "on" : "off"));
L
Linus Torvalds 已提交
212

213
	return 0;
L
Linus Torvalds 已提交
214 215
}

216
static int acpi_power_get_list_state(struct list_head *list, int *state)
L
Linus Torvalds 已提交
217
{
218
	struct acpi_power_resource_entry *entry;
219
	int cur_state;
L
Linus Torvalds 已提交
220 221

	if (!list || !state)
222
		return -EINVAL;
L
Linus Torvalds 已提交
223 224

	/* The state of the list is 'on' IFF all resources are 'on'. */
225
	cur_state = 0;
226 227 228
	list_for_each_entry(entry, list, node) {
		struct acpi_power_resource *resource = entry->resource;
		acpi_handle handle = resource->device.handle;
229 230 231 232 233 234 235 236 237
		int result;

		mutex_lock(&resource->resource_lock);
		result = acpi_power_get_state(handle, &cur_state);
		mutex_unlock(&resource->resource_lock);
		if (result)
			return result;

		if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
L
Linus Torvalds 已提交
238 239 240 241
			break;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
242
			  cur_state ? "on" : "off"));
L
Linus Torvalds 已提交
243

244 245
	*state = cur_state;
	return 0;
L
Linus Torvalds 已提交
246 247
}

248
static int __acpi_power_on(struct acpi_power_resource *resource)
L
Linus Torvalds 已提交
249
{
L
Len Brown 已提交
250
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
251

252
	status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL);
253 254 255 256 257 258 259 260 261
	if (ACPI_FAILURE(status))
		return -ENODEV;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
			  resource->name));

	return 0;
}

262
static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
263
{
264
	int result = 0;
265

266 267
	if (resource->ref_count++) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
268
				  "Power resource [%s] already on\n",
269 270 271
				  resource->name));
	} else {
		result = __acpi_power_on(resource);
272
		if (result)
273
			resource->ref_count--;
274
	}
275 276
	return result;
}
277

278 279 280
static int acpi_power_on(struct acpi_power_resource *resource)
{
	int result;
281

282 283 284
	mutex_lock(&resource->resource_lock);
	result = acpi_power_on_unlocked(resource);
	mutex_unlock(&resource->resource_lock);
285
	return result;
L
Linus Torvalds 已提交
286 287
}

288 289 290 291 292 293 294 295 296 297 298 299 300 301
static int __acpi_power_off(struct acpi_power_resource *resource)
{
	acpi_status status;

	status = acpi_evaluate_object(resource->device.handle, "_OFF",
				      NULL, NULL);
	if (ACPI_FAILURE(status))
		return -ENODEV;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n",
			  resource->name));
	return 0;
}

302
static int acpi_power_off_unlocked(struct acpi_power_resource *resource)
L
Linus Torvalds 已提交
303
{
304
	int result = 0;
L
Linus Torvalds 已提交
305

306 307
	if (!resource->ref_count) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
308
				  "Power resource [%s] already off\n",
309
				  resource->name));
310
		return 0;
311
	}
L
Linus Torvalds 已提交
312

313 314 315 316
	if (--resource->ref_count) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Power resource [%s] still in use\n",
				  resource->name));
317 318 319 320
	} else {
		result = __acpi_power_off(resource);
		if (result)
			resource->ref_count++;
L
Linus Torvalds 已提交
321
	}
322 323
	return result;
}
L
Linus Torvalds 已提交
324

325 326 327
static int acpi_power_off(struct acpi_power_resource *resource)
{
	int result;
L
Linus Torvalds 已提交
328

329 330 331
	mutex_lock(&resource->resource_lock);
	result = acpi_power_off_unlocked(resource);
	mutex_unlock(&resource->resource_lock);
332
	return result;
L
Linus Torvalds 已提交
333 334
}

335
static int acpi_power_off_list(struct list_head *list)
336
{
337 338
	struct acpi_power_resource_entry *entry;
	int result = 0;
339

340 341 342 343 344 345
	list_for_each_entry_reverse(entry, list, node) {
		result = acpi_power_off(entry->resource);
		if (result)
			goto err;
	}
	return 0;
346

347 348 349 350 351
 err:
	list_for_each_entry_continue(entry, list, node)
		acpi_power_on(entry->resource);

	return result;
352 353
}

354
static int acpi_power_on_list(struct list_head *list)
355
{
356
	struct acpi_power_resource_entry *entry;
357 358
	int result = 0;

359 360 361 362
	list_for_each_entry(entry, list, node) {
		result = acpi_power_on(entry->resource);
		if (result)
			goto err;
363
	}
364 365 366 367 368
	return 0;

 err:
	list_for_each_entry_continue_reverse(entry, list, node)
		acpi_power_off(entry->resource);
369 370 371 372

	return result;
}

373 374 375 376
static struct attribute *attrs[] = {
	NULL,
};

377
static const struct attribute_group attr_groups[] = {
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
	[ACPI_STATE_D0] = {
		.name = "power_resources_D0",
		.attrs = attrs,
	},
	[ACPI_STATE_D1] = {
		.name = "power_resources_D1",
		.attrs = attrs,
	},
	[ACPI_STATE_D2] = {
		.name = "power_resources_D2",
		.attrs = attrs,
	},
	[ACPI_STATE_D3_HOT] = {
		.name = "power_resources_D3hot",
		.attrs = attrs,
	},
};

396
static const struct attribute_group wakeup_attr_group = {
397 398 399 400 401 402
	.name = "power_resources_wakeup",
	.attrs = attrs,
};

static void acpi_power_hide_list(struct acpi_device *adev,
				 struct list_head *resources,
403
				 const struct attribute_group *attr_group)
404 405 406
{
	struct acpi_power_resource_entry *entry;

407
	if (list_empty(resources))
408 409
		return;

410
	list_for_each_entry_reverse(entry, resources, node) {
411 412 413
		struct acpi_device *res_dev = &entry->resource->device;

		sysfs_remove_link_from_group(&adev->dev.kobj,
414
					     attr_group->name,
415 416
					     dev_name(&res_dev->dev));
	}
417
	sysfs_remove_group(&adev->dev.kobj, attr_group);
418 419
}

420 421
static void acpi_power_expose_list(struct acpi_device *adev,
				   struct list_head *resources,
422
				   const struct attribute_group *attr_group)
423
{
424 425 426
	struct acpi_power_resource_entry *entry;
	int ret;

427
	if (list_empty(resources))
428 429
		return;

430
	ret = sysfs_create_group(&adev->dev.kobj, attr_group);
431 432 433
	if (ret)
		return;

434
	list_for_each_entry(entry, resources, node) {
435 436 437
		struct acpi_device *res_dev = &entry->resource->device;

		ret = sysfs_add_link_to_group(&adev->dev.kobj,
438
					      attr_group->name,
439 440 441
					      &res_dev->dev.kobj,
					      dev_name(&res_dev->dev));
		if (ret) {
442
			acpi_power_hide_list(adev, resources, attr_group);
443
			break;
444 445 446
		}
	}
}
447

448 449
static void acpi_power_expose_hide(struct acpi_device *adev,
				   struct list_head *resources,
450
				   const struct attribute_group *attr_group,
451 452 453 454 455 456 457 458
				   bool expose)
{
	if (expose)
		acpi_power_expose_list(adev, resources, attr_group);
	else
		acpi_power_hide_list(adev, resources, attr_group);
}

459 460 461 462
void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
{
	int state;

463 464 465 466
	if (adev->wakeup.flags.valid)
		acpi_power_expose_hide(adev, &adev->wakeup.resources,
				       &wakeup_attr_group, add);

467 468 469
	if (!adev->power.flags.power_resources)
		return;

470 471 472 473
	for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
		acpi_power_expose_hide(adev,
				       &adev->power.states[state].resources,
				       &attr_groups[state], add);
474 475
}

476
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
477 478 479 480 481 482
{
	struct acpi_power_resource_entry *entry;
	int system_level = 5;

	list_for_each_entry(entry, list, node) {
		struct acpi_power_resource *resource = entry->resource;
483 484 485
		acpi_handle handle = resource->device.handle;
		int result;
		int state;
486

487 488 489 490 491 492 493 494 495 496 497
		mutex_lock(&resource->resource_lock);

		result = acpi_power_get_state(handle, &state);
		if (result) {
			mutex_unlock(&resource->resource_lock);
			return result;
		}
		if (state == ACPI_POWER_RESOURCE_STATE_ON) {
			resource->ref_count++;
			resource->wakeup_enabled = true;
		}
498 499
		if (system_level > resource->system_level)
			system_level = resource->system_level;
500 501

		mutex_unlock(&resource->resource_lock);
502
	}
503 504
	*system_level_p = system_level;
	return 0;
505 506
}

507 508 509
/* --------------------------------------------------------------------------
                             Device Power Management
   -------------------------------------------------------------------------- */
510

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
/**
 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
 *                          ACPI 3.0) _PSW (Power State Wake)
 * @dev: Device to handle.
 * @enable: 0 - disable, 1 - enable the wake capabilities of the device.
 * @sleep_state: Target sleep state of the system.
 * @dev_state: Target power state of the device.
 *
 * Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
 * State Wake) for the device, if present.  On failure reset the device's
 * wakeup.flags.valid flag.
 *
 * RETURN VALUE:
 * 0 if either _DSW or _PSW has been successfully executed
 * 0 if neither _DSW nor _PSW has been found
 * -ENODEV if the execution of either _DSW or _PSW has failed
 */
int acpi_device_sleep_wake(struct acpi_device *dev,
                           int enable, int sleep_state, int dev_state)
{
	union acpi_object in_arg[3];
	struct acpi_object_list arg_list = { 3, in_arg };
	acpi_status status = AE_OK;

	/*
	 * Try to execute _DSW first.
	 *
	 * Three agruments are needed for the _DSW object:
	 * Argument 0: enable/disable the wake capabilities
	 * Argument 1: target system state
	 * Argument 2: target device state
	 * When _DSW object is called to disable the wake capabilities, maybe
	 * the first argument is filled. The values of the other two agruments
	 * are meaningless.
	 */
	in_arg[0].type = ACPI_TYPE_INTEGER;
	in_arg[0].integer.value = enable;
	in_arg[1].type = ACPI_TYPE_INTEGER;
	in_arg[1].integer.value = sleep_state;
	in_arg[2].type = ACPI_TYPE_INTEGER;
	in_arg[2].integer.value = dev_state;
	status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
	if (ACPI_SUCCESS(status)) {
		return 0;
	} else if (status != AE_NOT_FOUND) {
		printk(KERN_ERR PREFIX "_DSW execution failed\n");
		dev->wakeup.flags.valid = 0;
		return -ENODEV;
	}

	/* Execute _PSW */
562
	status = acpi_execute_simple_method(dev->handle, "_PSW", enable);
563 564 565 566 567 568 569 570 571
	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
		printk(KERN_ERR PREFIX "_PSW execution failed\n");
		dev->wakeup.flags.valid = 0;
		return -ENODEV;
	}

	return 0;
}

L
Linus Torvalds 已提交
572 573 574
/*
 * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
 * 1. Power on the power resources required for the wakeup device 
575 576
 * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
 *    State Wake) for the device, if present
L
Linus Torvalds 已提交
577
 */
578
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
L
Linus Torvalds 已提交
579
{
580
	struct acpi_power_resource_entry *entry;
581
	int err = 0;
L
Linus Torvalds 已提交
582 583

	if (!dev || !dev->wakeup.flags.valid)
584
		return -EINVAL;
L
Linus Torvalds 已提交
585

586 587 588 589
	mutex_lock(&acpi_device_lock);

	if (dev->wakeup.prepare_count++)
		goto out;
590

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
	list_for_each_entry(entry, &dev->wakeup.resources, node) {
		struct acpi_power_resource *resource = entry->resource;

		mutex_lock(&resource->resource_lock);

		if (!resource->wakeup_enabled) {
			err = acpi_power_on_unlocked(resource);
			if (!err)
				resource->wakeup_enabled = true;
		}

		mutex_unlock(&resource->resource_lock);

		if (err) {
			dev_err(&dev->dev,
				"Cannot turn wakeup power resources on\n");
			dev->wakeup.flags.valid = 0;
			goto out;
		}
L
Linus Torvalds 已提交
610
	}
611 612 613 614 615
	/*
	 * Passing 3 as the third argument below means the device may be
	 * put into arbitrary power state afterward.
	 */
	err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
616 617 618 619 620
	if (err)
		dev->wakeup.prepare_count = 0;

 out:
	mutex_unlock(&acpi_device_lock);
621
	return err;
L
Linus Torvalds 已提交
622 623 624 625
}

/*
 * Shutdown a wakeup device, counterpart of above method
626 627
 * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
 *    State Wake) for the device, if present
L
Linus Torvalds 已提交
628 629
 * 2. Shutdown down the power resources
 */
L
Len Brown 已提交
630
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
L
Linus Torvalds 已提交
631
{
632
	struct acpi_power_resource_entry *entry;
633
	int err = 0;
L
Linus Torvalds 已提交
634 635

	if (!dev || !dev->wakeup.flags.valid)
636
		return -EINVAL;
L
Linus Torvalds 已提交
637

638 639 640 641 642
	mutex_lock(&acpi_device_lock);

	if (--dev->wakeup.prepare_count > 0)
		goto out;

643
	/*
644 645
	 * Executing the code below even if prepare_count is already zero when
	 * the function is called may be useful, for example for initialisation.
646
	 */
647 648
	if (dev->wakeup.prepare_count < 0)
		dev->wakeup.prepare_count = 0;
649

650 651 652
	err = acpi_device_sleep_wake(dev, 0, 0, 0);
	if (err)
		goto out;
L
Linus Torvalds 已提交
653

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
	list_for_each_entry(entry, &dev->wakeup.resources, node) {
		struct acpi_power_resource *resource = entry->resource;

		mutex_lock(&resource->resource_lock);

		if (resource->wakeup_enabled) {
			err = acpi_power_off_unlocked(resource);
			if (!err)
				resource->wakeup_enabled = false;
		}

		mutex_unlock(&resource->resource_lock);

		if (err) {
			dev_err(&dev->dev,
				"Cannot turn wakeup power resources off\n");
			dev->wakeup.flags.valid = 0;
			break;
		}
L
Linus Torvalds 已提交
673 674
	}

675 676 677
 out:
	mutex_unlock(&acpi_device_lock);
	return err;
L
Linus Torvalds 已提交
678 679
}

680
int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
L
Linus Torvalds 已提交
681
{
L
Len Brown 已提交
682 683 684
	int result = 0;
	int list_state = 0;
	int i = 0;
L
Linus Torvalds 已提交
685

686
	if (!device || !state)
687
		return -EINVAL;
L
Linus Torvalds 已提交
688 689 690 691 692

	/*
	 * We know a device's inferred power state when all the resources
	 * required for a given D-state are 'on'.
	 */
693
	for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
694 695 696
		struct list_head *list = &device->power.states[i].resources;

		if (list_empty(list))
L
Linus Torvalds 已提交
697 698 699 700
			continue;

		result = acpi_power_get_list_state(list, &list_state);
		if (result)
701
			return result;
L
Linus Torvalds 已提交
702 703

		if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
704
			*state = i;
705
			return 0;
L
Linus Torvalds 已提交
706 707 708
		}
	}

709 710
	*state = device->power.states[ACPI_STATE_D3_COLD].flags.valid ?
		ACPI_STATE_D3_COLD : ACPI_STATE_D3_HOT;
711
	return 0;
L
Linus Torvalds 已提交
712 713
}

714 715
int acpi_power_on_resources(struct acpi_device *device, int state)
{
716
	if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3_HOT)
717 718 719 720 721
		return -EINVAL;

	return acpi_power_on_list(&device->power.states[state].resources);
}

L
Len Brown 已提交
722
int acpi_power_transition(struct acpi_device *device, int state)
L
Linus Torvalds 已提交
723
{
724
	int result = 0;
L
Linus Torvalds 已提交
725

726
	if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
727
		return -EINVAL;
L
Linus Torvalds 已提交
728

729
	if (device->power.state == state || !device->flags.power_manageable)
730 731
		return 0;

L
Len Brown 已提交
732
	if ((device->power.state < ACPI_STATE_D0)
733
	    || (device->power.state > ACPI_STATE_D3_COLD))
734
		return -ENODEV;
L
Linus Torvalds 已提交
735 736 737

	/*
	 * First we reference all power resources required in the target list
738 739
	 * (e.g. so the device doesn't lose power while transitioning).  Then,
	 * we dereference all power resources used in the current list.
L
Linus Torvalds 已提交
740
	 */
741 742 743 744 745
	if (state < ACPI_STATE_D3_COLD)
		result = acpi_power_on_list(
			&device->power.states[state].resources);

	if (!result && device->power.state < ACPI_STATE_D3_COLD)
746 747
		acpi_power_off_list(
			&device->power.states[device->power.state].resources);
L
Linus Torvalds 已提交
748

749 750
	/* We shouldn't change the state unless the above operations succeed. */
	device->power.state = result ? ACPI_STATE_UNKNOWN : state;
L
Linus Torvalds 已提交
751

752
	return result;
L
Linus Torvalds 已提交
753 754
}

755 756 757 758 759 760
static void acpi_release_power_resource(struct device *dev)
{
	struct acpi_device *device = to_acpi_device(dev);
	struct acpi_power_resource *resource;

	resource = container_of(device, struct acpi_power_resource, device);
761 762 763 764 765

	mutex_lock(&power_resource_list_lock);
	list_del(&resource->list_node);
	mutex_unlock(&power_resource_list_lock);

766
	acpi_free_pnp_ids(&device->pnp);
767 768
	kfree(resource);
}
L
Linus Torvalds 已提交
769

770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
static ssize_t acpi_power_in_use_show(struct device *dev,
				      struct device_attribute *attr,
				      char *buf) {
	struct acpi_power_resource *resource;

	resource = to_power_resource(to_acpi_device(dev));
	return sprintf(buf, "%u\n", !!resource->ref_count);
}
static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);

static void acpi_power_sysfs_remove(struct acpi_device *device)
{
	device_remove_file(&device->dev, &dev_attr_resource_in_use);
}

785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource)
{
	mutex_lock(&power_resource_list_lock);

	if (!list_empty(&acpi_power_resource_list)) {
		struct acpi_power_resource *r;

		list_for_each_entry(r, &acpi_power_resource_list, list_node)
			if (r->order > resource->order) {
				list_add_tail(&resource->list_node, &r->list_node);
				goto out;
			}
	}
	list_add_tail(&resource->list_node, &acpi_power_resource_list);

 out:
	mutex_unlock(&power_resource_list_lock);
}

804
int acpi_add_power_resource(acpi_handle handle)
L
Linus Torvalds 已提交
805
{
806 807
	struct acpi_power_resource *resource;
	struct acpi_device *device = NULL;
L
Len Brown 已提交
808 809
	union acpi_object acpi_object;
	struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
810 811
	acpi_status status;
	int state, result = -ENODEV;
L
Linus Torvalds 已提交
812

813 814
	acpi_bus_get_device(handle, &device);
	if (device)
815
		return 0;
L
Linus Torvalds 已提交
816

817
	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
L
Linus Torvalds 已提交
818
	if (!resource)
819
		return -ENOMEM;
L
Linus Torvalds 已提交
820

821 822 823
	device = &resource->device;
	acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
				ACPI_STA_DEFAULT);
824
	mutex_init(&resource->resource_lock);
825
	INIT_LIST_HEAD(&resource->list_node);
826
	resource->name = device->pnp.bus_id;
L
Linus Torvalds 已提交
827 828
	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
829
	device->power.state = ACPI_STATE_UNKNOWN;
L
Linus Torvalds 已提交
830 831

	/* Evalute the object to get the system level and resource order. */
832 833
	status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
	if (ACPI_FAILURE(status))
834
		goto err;
835

L
Linus Torvalds 已提交
836 837 838
	resource->system_level = acpi_object.power_resource.system_level;
	resource->order = acpi_object.power_resource.resource_order;

839
	result = acpi_power_get_state(handle, &state);
L
Linus Torvalds 已提交
840
	if (result)
841
		goto err;
L
Linus Torvalds 已提交
842 843

	printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
844
	       acpi_device_bid(device), state ? "on" : "off");
L
Linus Torvalds 已提交
845

846
	device->flags.match_driver = true;
847
	result = acpi_device_add(device, acpi_release_power_resource);
L
Linus Torvalds 已提交
848
	if (result)
849
		goto err;
L
Len Brown 已提交
850

851 852 853
	if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
		device->remove = acpi_power_sysfs_remove;

854
	acpi_power_add_resource_to_list(resource);
855
	acpi_device_add_finalize(device);
856
	return 0;
L
Linus Torvalds 已提交
857

858 859
 err:
	acpi_release_power_resource(&device->dev);
860
	return result;
861
}
L
Linus Torvalds 已提交
862

863 864
#ifdef CONFIG_ACPI_SLEEP
void acpi_resume_power_resources(void)
865
{
866
	struct acpi_power_resource *resource;
867

868
	mutex_lock(&power_resource_list_lock);
869

870 871
	list_for_each_entry(resource, &acpi_power_resource_list, list_node) {
		int result, state;
872

873
		mutex_lock(&resource->resource_lock);
874

875
		result = acpi_power_get_state(resource->device.handle, &state);
876 877
		if (result) {
			mutex_unlock(&resource->resource_lock);
878
			continue;
879
		}
880 881

		if (state == ACPI_POWER_RESOURCE_STATE_OFF
882 883 884
		    && resource->ref_count) {
			dev_info(&resource->device.dev, "Turning ON\n");
			__acpi_power_on(resource);
885 886 887 888
		}

		mutex_unlock(&resource->resource_lock);
	}
889 890 891 892 893 894 895 896 897 898

	mutex_unlock(&power_resource_list_lock);
}

void acpi_turn_off_unused_power_resources(void)
{
	struct acpi_power_resource *resource;

	mutex_lock(&power_resource_list_lock);

899 900 901 902 903 904 905 906 907 908 909 910
	list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
		int result, state;

		mutex_lock(&resource->resource_lock);

		result = acpi_power_get_state(resource->device.handle, &state);
		if (result) {
			mutex_unlock(&resource->resource_lock);
			continue;
		}

		if (state == ACPI_POWER_RESOURCE_STATE_ON
911 912 913
		    && !resource->ref_count) {
			dev_info(&resource->device.dev, "Turning OFF\n");
			__acpi_power_off(resource);
914
		}
915

916 917
		mutex_unlock(&resource->resource_lock);
	}
918

919
	mutex_unlock(&power_resource_list_lock);
920
}
921
#endif