|
@@ -8,6 +8,7 @@
|
|
|
#include <linux/acpi.h>
|
|
|
#include <linux/signal.h>
|
|
|
#include <linux/kthread.h>
|
|
|
+#include <linux/dmi.h>
|
|
|
|
|
|
#include <acpi/acpi_drivers.h>
|
|
|
|
|
@@ -1032,6 +1033,41 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
|
|
|
list_add_tail(&id->list, &device->pnp.ids);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Old IBM workstations have a DSDT bug wherein the SMBus object
|
|
|
+ * lacks the SMBUS01 HID and the methods do not have the necessary "_"
|
|
|
+ * prefix. Work around this.
|
|
|
+ */
|
|
|
+static int acpi_ibm_smbus_match(struct acpi_device *device)
|
|
|
+{
|
|
|
+ acpi_handle h_dummy;
|
|
|
+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
|
|
|
+ int result;
|
|
|
+
|
|
|
+ if (!dmi_name_in_vendors("IBM"))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ /* Look for SMBS object */
|
|
|
+ result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
|
|
|
+ if (result)
|
|
|
+ return result;
|
|
|
+
|
|
|
+ if (strcmp("SMBS", path.pointer)) {
|
|
|
+ result = -ENODEV;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Does it have the necessary (but misnamed) methods? */
|
|
|
+ result = -ENODEV;
|
|
|
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
|
|
|
+ ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
|
|
|
+ ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
|
|
|
+ result = 0;
|
|
|
+out:
|
|
|
+ kfree(path.pointer);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
static void acpi_device_set_id(struct acpi_device *device)
|
|
|
{
|
|
|
acpi_status status;
|
|
@@ -1082,6 +1118,8 @@ static void acpi_device_set_id(struct acpi_device *device)
|
|
|
acpi_add_id(device, ACPI_BAY_HID);
|
|
|
else if (ACPI_SUCCESS(acpi_dock_match(device)))
|
|
|
acpi_add_id(device, ACPI_DOCK_HID);
|
|
|
+ else if (!acpi_ibm_smbus_match(device))
|
|
|
+ acpi_add_id(device, ACPI_SMBUS_IBM_HID);
|
|
|
|
|
|
break;
|
|
|
case ACPI_BUS_TYPE_POWER:
|