diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/acpi/scan.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (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.c | 118 |
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 | ||
744 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 746 | static 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 | |||
774 | static 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 | |||
791 | end: | 811 | end: |
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 | */ | ||
1042 | static 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; | ||
1067 | out: | ||
1068 | kfree(path.pointer); | ||
1069 | return result; | ||
1070 | } | ||
1071 | |||
1017 | static void acpi_device_set_id(struct acpi_device *device) | 1072 | static 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 | |||
1342 | int | 1415 | int |
1343 | acpi_bus_add(struct acpi_device **child, | 1416 | acpi_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 | } |
1354 | EXPORT_SYMBOL(acpi_bus_add); | 1426 | EXPORT_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 | } |
1366 | EXPORT_SYMBOL(acpi_bus_start); | 1440 | EXPORT_SYMBOL(acpi_bus_start); |
1367 | 1441 | ||