aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/bus.c14
-rw-r--r--drivers/acpi/fan.c40
-rw-r--r--drivers/acpi/scan.c110
-rw-r--r--drivers/acpi/thermal.c16
-rw-r--r--include/acpi/acpi_bus.h6
5 files changed, 178 insertions, 8 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b77f03d51f0b..dd3983cece92 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -205,12 +205,14 @@ int acpi_bus_set_power(acpi_handle handle, int state)
205 * Get device's current power state if it's unknown 205 * Get device's current power state if it's unknown
206 * This means device power state isn't initialized or previous setting failed 206 * This means device power state isn't initialized or previous setting failed
207 */ 207 */
208 if (device->power.state == ACPI_STATE_UNKNOWN) 208 if (!device->flags.force_power_state) {
209 acpi_bus_get_power(device->handle, &device->power.state); 209 if (device->power.state == ACPI_STATE_UNKNOWN)
210 if (state == device->power.state) { 210 acpi_bus_get_power(device->handle, &device->power.state);
211 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", 211 if (state == device->power.state) {
212 state)); 212 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
213 return_VALUE(0); 213 state));
214 return_VALUE(0);
215 }
214 } 216 }
215 if (!device->power.states[state].flags.valid) { 217 if (!device->power.states[state].flags.valid) {
216 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", 218 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n",
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index e8165c4f162a..1cd25784b7a4 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -48,6 +48,8 @@ MODULE_LICENSE("GPL");
48 48
49static int acpi_fan_add(struct acpi_device *device); 49static int acpi_fan_add(struct acpi_device *device);
50static int acpi_fan_remove(struct acpi_device *device, int type); 50static int acpi_fan_remove(struct acpi_device *device, int type);
51static int acpi_fan_suspend(struct acpi_device *device, int state);
52static int acpi_fan_resume(struct acpi_device *device, int state);
51 53
52static struct acpi_driver acpi_fan_driver = { 54static struct acpi_driver acpi_fan_driver = {
53 .name = ACPI_FAN_DRIVER_NAME, 55 .name = ACPI_FAN_DRIVER_NAME,
@@ -56,6 +58,8 @@ static struct acpi_driver acpi_fan_driver = {
56 .ops = { 58 .ops = {
57 .add = acpi_fan_add, 59 .add = acpi_fan_add,
58 .remove = acpi_fan_remove, 60 .remove = acpi_fan_remove,
61 .suspend = acpi_fan_suspend,
62 .resume = acpi_fan_resume,
59 }, 63 },
60}; 64};
61 65
@@ -206,6 +210,10 @@ static int acpi_fan_add(struct acpi_device *device)
206 goto end; 210 goto end;
207 } 211 }
208 212
213 device->flags.force_power_state = 1;
214 acpi_bus_set_power(device->handle, state);
215 device->flags.force_power_state = 0;
216
209 result = acpi_fan_add_fs(device); 217 result = acpi_fan_add_fs(device);
210 if (result) 218 if (result)
211 goto end; 219 goto end;
@@ -239,6 +247,38 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
239 return_VALUE(0); 247 return_VALUE(0);
240} 248}
241 249
250static int acpi_fan_suspend(struct acpi_device *device, int state)
251{
252 if (!device)
253 return -EINVAL;
254
255 acpi_bus_set_power(device->handle, ACPI_STATE_D0);
256
257 return AE_OK;
258}
259
260static int acpi_fan_resume(struct acpi_device *device, int state)
261{
262 int result = 0;
263 int power_state = 0;
264
265 if (!device)
266 return -EINVAL;
267
268 result = acpi_bus_get_power(device->handle, &power_state);
269 if (result) {
270 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
271 "Error reading fan power state\n"));
272 return result;
273 }
274
275 device->flags.force_power_state = 1;
276 acpi_bus_set_power(device->handle, power_state);
277 device->flags.force_power_state = 0;
278
279 return result;
280}
281
242static int __init acpi_fan_init(void) 282static int __init acpi_fan_init(void)
243{ 283{
244 int result = 0; 284 int result = 0;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index fe3693de7ba3..f8316a05ede7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1341,6 +1341,100 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
1341 return_VALUE(result); 1341 return_VALUE(result);
1342} 1342}
1343 1343
1344
1345static inline struct acpi_device * to_acpi_dev(struct device * dev)
1346{
1347 return container_of(dev, struct acpi_device, dev);
1348}
1349
1350
1351static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state)
1352{
1353 struct acpi_device * dev, * next;
1354 int result;
1355
1356 spin_lock(&acpi_device_lock);
1357 list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) {
1358 if (dev->driver && dev->driver->ops.suspend) {
1359 spin_unlock(&acpi_device_lock);
1360 result = dev->driver->ops.suspend(dev, 0);
1361 if (result) {
1362 printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n",
1363 acpi_device_name(dev),
1364 acpi_device_bid(dev), result);
1365 }
1366 spin_lock(&acpi_device_lock);
1367 }
1368 }
1369 spin_unlock(&acpi_device_lock);
1370 return 0;
1371}
1372
1373
1374static int acpi_device_suspend(struct device * dev, pm_message_t state)
1375{
1376 struct acpi_device * acpi_dev = to_acpi_dev(dev);
1377
1378 /*
1379 * For now, we should only register 1 generic device -
1380 * the ACPI root device - and from there, we walk the
1381 * tree of ACPI devices to suspend each one using the
1382 * ACPI driver methods.
1383 */
1384 if (acpi_dev->handle == ACPI_ROOT_OBJECT)
1385 root_suspend(acpi_dev, state);
1386 return 0;
1387}
1388
1389
1390
1391static int root_resume(struct acpi_device * acpi_dev)
1392{
1393 struct acpi_device * dev, * next;
1394 int result;
1395
1396 spin_lock(&acpi_device_lock);
1397 list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) {
1398 if (dev->driver && dev->driver->ops.resume) {
1399 spin_unlock(&acpi_device_lock);
1400 result = dev->driver->ops.resume(dev, 0);
1401 if (result) {
1402 printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n",
1403 acpi_device_name(dev),
1404 acpi_device_bid(dev), result);
1405 }
1406 spin_lock(&acpi_device_lock);
1407 }
1408 }
1409 spin_unlock(&acpi_device_lock);
1410 return 0;
1411}
1412
1413
1414static int acpi_device_resume(struct device * dev)
1415{
1416 struct acpi_device * acpi_dev = to_acpi_dev(dev);
1417
1418 /*
1419 * For now, we should only register 1 generic device -
1420 * the ACPI root device - and from there, we walk the
1421 * tree of ACPI devices to resume each one using the
1422 * ACPI driver methods.
1423 */
1424 if (acpi_dev->handle == ACPI_ROOT_OBJECT)
1425 root_resume(acpi_dev);
1426 return 0;
1427}
1428
1429
1430struct bus_type acpi_bus_type = {
1431 .name = "acpi",
1432 .suspend = acpi_device_suspend,
1433 .resume = acpi_device_resume,
1434};
1435
1436
1437
1344static int __init acpi_scan_init(void) 1438static int __init acpi_scan_init(void)
1345{ 1439{
1346 int result; 1440 int result;
@@ -1353,6 +1447,12 @@ static int __init acpi_scan_init(void)
1353 1447
1354 kset_register(&acpi_namespace_kset); 1448 kset_register(&acpi_namespace_kset);
1355 1449
1450 result = bus_register(&acpi_bus_type);
1451 if (result) {
1452 /* We don't want to quit even if we failed to add suspend/resume */
1453 printk(KERN_ERR PREFIX "Could not register bus type\n");
1454 }
1455
1356 /* 1456 /*
1357 * Create the root device in the bus's device tree 1457 * Create the root device in the bus's device tree
1358 */ 1458 */
@@ -1362,6 +1462,16 @@ static int __init acpi_scan_init(void)
1362 goto Done; 1462 goto Done;
1363 1463
1364 result = acpi_start_single_object(acpi_root); 1464 result = acpi_start_single_object(acpi_root);
1465 if (result)
1466 goto Done;
1467
1468 acpi_root->dev.bus = &acpi_bus_type;
1469 snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name);
1470 result = device_register(&acpi_root->dev);
1471 if (result) {
1472 /* We don't want to quit even if we failed to add suspend/resume */
1473 printk(KERN_ERR PREFIX "Could not register device\n");
1474 }
1365 1475
1366 /* 1476 /*
1367 * Enumerate devices in the ACPI namespace. 1477 * Enumerate devices in the ACPI namespace.
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index f003763de7bb..e7fe3a14fdaf 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -82,6 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
82 82
83static int acpi_thermal_add(struct acpi_device *device); 83static int acpi_thermal_add(struct acpi_device *device);
84static int acpi_thermal_remove(struct acpi_device *device, int type); 84static int acpi_thermal_remove(struct acpi_device *device, int type);
85static int acpi_thermal_resume(struct acpi_device *device, int state);
85static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); 86static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
86static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); 87static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
87static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); 88static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
@@ -103,6 +104,7 @@ static struct acpi_driver acpi_thermal_driver = {
103 .ops = { 104 .ops = {
104 .add = acpi_thermal_add, 105 .add = acpi_thermal_add,
105 .remove = acpi_thermal_remove, 106 .remove = acpi_thermal_remove,
107 .resume = acpi_thermal_resume,
106 }, 108 },
107}; 109};
108 110
@@ -1417,6 +1419,20 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
1417 return_VALUE(0); 1419 return_VALUE(0);
1418} 1420}
1419 1421
1422static int acpi_thermal_resume(struct acpi_device *device, int state)
1423{
1424 struct acpi_thermal *tz = NULL;
1425
1426 if (!device || !acpi_driver_data(device))
1427 return_VALUE(-EINVAL);
1428
1429 tz = (struct acpi_thermal *)acpi_driver_data(device);
1430
1431 acpi_thermal_check(tz);
1432
1433 return AE_OK;
1434}
1435
1420static int __init acpi_thermal_init(void) 1436static int __init acpi_thermal_init(void)
1421{ 1437{
1422 int result = 0; 1438 int result = 0;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8c7590fdd822..a2b3e390a503 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -26,7 +26,7 @@
26#ifndef __ACPI_BUS_H__ 26#ifndef __ACPI_BUS_H__
27#define __ACPI_BUS_H__ 27#define __ACPI_BUS_H__
28 28
29#include <linux/kobject.h> 29#include <linux/device.h>
30 30
31#include <acpi/acpi.h> 31#include <acpi/acpi.h>
32 32
@@ -169,7 +169,8 @@ struct acpi_device_flags {
169 u32 power_manageable:1; 169 u32 power_manageable:1;
170 u32 performance_manageable:1; 170 u32 performance_manageable:1;
171 u32 wake_capable:1; /* Wakeup(_PRW) supported? */ 171 u32 wake_capable:1; /* Wakeup(_PRW) supported? */
172 u32 reserved:20; 172 u32 force_power_state:1;
173 u32 reserved:19;
173}; 174};
174 175
175/* File System */ 176/* File System */
@@ -296,6 +297,7 @@ struct acpi_device {
296 struct acpi_driver *driver; 297 struct acpi_driver *driver;
297 void *driver_data; 298 void *driver_data;
298 struct kobject kobj; 299 struct kobject kobj;
300 struct device dev;
299}; 301};
300 302
301#define acpi_driver_data(d) ((d)->driver_data) 303#define acpi_driver_data(d) ((d)->driver_data)