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: |
