aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/acpi/scan.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c118
1 files changed, 96 insertions, 22 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 14a7481c97d7..0338f513a010 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -4,10 +4,12 @@
4 4
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/slab.h>
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/acpi.h> 9#include <linux/acpi.h>
9#include <linux/signal.h> 10#include <linux/signal.h>
10#include <linux/kthread.h> 11#include <linux/kthread.h>
12#include <linux/dmi.h>
11 13
12#include <acpi/acpi_drivers.h> 14#include <acpi/acpi_drivers.h>
13 15
@@ -741,19 +743,40 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
741 return AE_OK; 743 return AE_OK;
742} 744}
743 745
744static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) 746static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
745{ 747{
746 acpi_status status = 0;
747 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
748 union acpi_object *package = NULL;
749 int psw_error;
750
751 struct acpi_device_id button_device_ids[] = { 748 struct acpi_device_id button_device_ids[] = {
752 {"PNP0C0D", 0}, 749 {"PNP0C0D", 0},
753 {"PNP0C0C", 0}, 750 {"PNP0C0C", 0},
754 {"PNP0C0E", 0}, 751 {"PNP0C0E", 0},
755 {"", 0}, 752 {"", 0},
756 }; 753 };
754 acpi_status status;
755 acpi_event_status event_status;
756
757 device->wakeup.run_wake_count = 0;
758 device->wakeup.flags.notifier_present = 0;
759
760 /* Power button, Lid switch always enable wakeup */
761 if (!acpi_match_device_ids(device, button_device_ids)) {
762 device->wakeup.flags.run_wake = 1;
763 device->wakeup.flags.always_enabled = 1;
764 return;
765 }
766
767 status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number,
768 ACPI_NOT_ISR, &event_status);
769 if (status == AE_OK)
770 device->wakeup.flags.run_wake =
771 !!(event_status & ACPI_EVENT_FLAG_HANDLE);
772}
773
774static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
775{
776 acpi_status status = 0;
777 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
778 union acpi_object *package = NULL;
779 int psw_error;
757 780
758 /* _PRW */ 781 /* _PRW */
759 status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); 782 status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
@@ -773,6 +796,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
773 796
774 device->wakeup.flags.valid = 1; 797 device->wakeup.flags.valid = 1;
775 device->wakeup.prepare_count = 0; 798 device->wakeup.prepare_count = 0;
799 acpi_bus_set_run_wake_flags(device);
776 /* Call _PSW/_DSW object to disable its ability to wake the sleeping 800 /* Call _PSW/_DSW object to disable its ability to wake the sleeping
777 * system for the ACPI device with the _PRW object. 801 * system for the ACPI device with the _PRW object.
778 * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. 802 * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
@@ -784,10 +808,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
784 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 808 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
785 "error in _DSW or _PSW evaluation\n")); 809 "error in _DSW or _PSW evaluation\n"));
786 810
787 /* Power button, Lid switch always enable wakeup */
788 if (!acpi_match_device_ids(device, button_device_ids))
789 device->wakeup.flags.run_wake = 1;
790
791end: 811end:
792 if (ACPI_FAILURE(status)) 812 if (ACPI_FAILURE(status))
793 device->flags.wake_capable = 0; 813 device->flags.wake_capable = 0;
@@ -1014,6 +1034,41 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
1014 list_add_tail(&id->list, &device->pnp.ids); 1034 list_add_tail(&id->list, &device->pnp.ids);
1015} 1035}
1016 1036
1037/*
1038 * Old IBM workstations have a DSDT bug wherein the SMBus object
1039 * lacks the SMBUS01 HID and the methods do not have the necessary "_"
1040 * prefix. Work around this.
1041 */
1042static int acpi_ibm_smbus_match(struct acpi_device *device)
1043{
1044 acpi_handle h_dummy;
1045 struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
1046 int result;
1047
1048 if (!dmi_name_in_vendors("IBM"))
1049 return -ENODEV;
1050
1051 /* Look for SMBS object */
1052 result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
1053 if (result)
1054 return result;
1055
1056 if (strcmp("SMBS", path.pointer)) {
1057 result = -ENODEV;
1058 goto out;
1059 }
1060
1061 /* Does it have the necessary (but misnamed) methods? */
1062 result = -ENODEV;
1063 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
1064 ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
1065 ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
1066 result = 0;
1067out:
1068 kfree(path.pointer);
1069 return result;
1070}
1071
1017static void acpi_device_set_id(struct acpi_device *device) 1072static void acpi_device_set_id(struct acpi_device *device)
1018{ 1073{
1019 acpi_status status; 1074 acpi_status status;
@@ -1026,12 +1081,6 @@ static void acpi_device_set_id(struct acpi_device *device)
1026 if (ACPI_IS_ROOT_DEVICE(device)) { 1081 if (ACPI_IS_ROOT_DEVICE(device)) {
1027 acpi_add_id(device, ACPI_SYSTEM_HID); 1082 acpi_add_id(device, ACPI_SYSTEM_HID);
1028 break; 1083 break;
1029 } else if (ACPI_IS_ROOT_DEVICE(device->parent)) {
1030 /* \_SB_, the only root-level namespace device */
1031 acpi_add_id(device, ACPI_BUS_HID);
1032 strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
1033 strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
1034 break;
1035 } 1084 }
1036 1085
1037 status = acpi_get_object_info(device->handle, &info); 1086 status = acpi_get_object_info(device->handle, &info);
@@ -1064,6 +1113,14 @@ static void acpi_device_set_id(struct acpi_device *device)
1064 acpi_add_id(device, ACPI_BAY_HID); 1113 acpi_add_id(device, ACPI_BAY_HID);
1065 else if (ACPI_SUCCESS(acpi_dock_match(device))) 1114 else if (ACPI_SUCCESS(acpi_dock_match(device)))
1066 acpi_add_id(device, ACPI_DOCK_HID); 1115 acpi_add_id(device, ACPI_DOCK_HID);
1116 else if (!acpi_ibm_smbus_match(device))
1117 acpi_add_id(device, ACPI_SMBUS_IBM_HID);
1118 else if (!acpi_device_hid(device) &&
1119 ACPI_IS_ROOT_DEVICE(device->parent)) {
1120 acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
1121 strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
1122 strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
1123 }
1067 1124
1068 break; 1125 break;
1069 case ACPI_BUS_TYPE_POWER: 1126 case ACPI_BUS_TYPE_POWER:
@@ -1332,13 +1389,29 @@ static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
1332 status = acpi_bus_check_add(handle, 0, ops, &device); 1389 status = acpi_bus_check_add(handle, 0, ops, &device);
1333 if (ACPI_SUCCESS(status)) 1390 if (ACPI_SUCCESS(status))
1334 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, 1391 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
1335 acpi_bus_check_add, ops, &device); 1392 acpi_bus_check_add, NULL, ops, &device);
1336 1393
1337 if (child) 1394 if (child)
1338 *child = device; 1395 *child = device;
1339 return 0; 1396
1397 if (device)
1398 return 0;
1399 else
1400 return -ENODEV;
1340} 1401}
1341 1402
1403/*
1404 * acpi_bus_add and acpi_bus_start
1405 *
1406 * scan a given ACPI tree and (probably recently hot-plugged)
1407 * create and add or starts found devices.
1408 *
1409 * If no devices were found -ENODEV is returned which does not
1410 * mean that this is a real error, there just have been no suitable
1411 * ACPI objects in the table trunk from which the kernel could create
1412 * a device and add/start an appropriate driver.
1413 */
1414
1342int 1415int
1343acpi_bus_add(struct acpi_device **child, 1416acpi_bus_add(struct acpi_device **child,
1344 struct acpi_device *parent, acpi_handle handle, int type) 1417 struct acpi_device *parent, acpi_handle handle, int type)
@@ -1348,8 +1421,7 @@ acpi_bus_add(struct acpi_device **child,
1348 memset(&ops, 0, sizeof(ops)); 1421 memset(&ops, 0, sizeof(ops));
1349 ops.acpi_op_add = 1; 1422 ops.acpi_op_add = 1;
1350 1423
1351 acpi_bus_scan(handle, &ops, child); 1424 return acpi_bus_scan(handle, &ops, child);
1352 return 0;
1353} 1425}
1354EXPORT_SYMBOL(acpi_bus_add); 1426EXPORT_SYMBOL(acpi_bus_add);
1355 1427
@@ -1357,11 +1429,13 @@ int acpi_bus_start(struct acpi_device *device)
1357{ 1429{
1358 struct acpi_bus_ops ops; 1430 struct acpi_bus_ops ops;
1359 1431
1432 if (!device)
1433 return -EINVAL;
1434
1360 memset(&ops, 0, sizeof(ops)); 1435 memset(&ops, 0, sizeof(ops));
1361 ops.acpi_op_start = 1; 1436 ops.acpi_op_start = 1;
1362 1437
1363 acpi_bus_scan(device->handle, &ops, NULL); 1438 return acpi_bus_scan(device->handle, &ops, NULL);
1364 return 0;
1365} 1439}
1366EXPORT_SYMBOL(acpi_bus_start); 1440EXPORT_SYMBOL(acpi_bus_start);
1367 1441