diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fb7fc24fe727..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 | ||
@@ -1032,6 +1034,41 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id) | |||
1032 | list_add_tail(&id->list, &device->pnp.ids); | 1034 | list_add_tail(&id->list, &device->pnp.ids); |
1033 | } | 1035 | } |
1034 | 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 | |||
1035 | static void acpi_device_set_id(struct acpi_device *device) | 1072 | static void acpi_device_set_id(struct acpi_device *device) |
1036 | { | 1073 | { |
1037 | acpi_status status; | 1074 | acpi_status status; |
@@ -1044,12 +1081,6 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
1044 | if (ACPI_IS_ROOT_DEVICE(device)) { | 1081 | if (ACPI_IS_ROOT_DEVICE(device)) { |
1045 | acpi_add_id(device, ACPI_SYSTEM_HID); | 1082 | acpi_add_id(device, ACPI_SYSTEM_HID); |
1046 | break; | 1083 | break; |
1047 | } else if (ACPI_IS_ROOT_DEVICE(device->parent)) { | ||
1048 | /* \_SB_, the only root-level namespace device */ | ||
1049 | acpi_add_id(device, ACPI_BUS_HID); | ||
1050 | strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); | ||
1051 | strcpy(device->pnp.device_class, ACPI_BUS_CLASS); | ||
1052 | break; | ||
1053 | } | 1084 | } |
1054 | 1085 | ||
1055 | status = acpi_get_object_info(device->handle, &info); | 1086 | status = acpi_get_object_info(device->handle, &info); |
@@ -1082,6 +1113,14 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
1082 | acpi_add_id(device, ACPI_BAY_HID); | 1113 | acpi_add_id(device, ACPI_BAY_HID); |
1083 | else if (ACPI_SUCCESS(acpi_dock_match(device))) | 1114 | else if (ACPI_SUCCESS(acpi_dock_match(device))) |
1084 | 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 | } | ||
1085 | 1124 | ||
1086 | break; | 1125 | break; |
1087 | case ACPI_BUS_TYPE_POWER: | 1126 | case ACPI_BUS_TYPE_POWER: |