Skip to content

Commit

Permalink
acpi: Support IBM SMBus CMI devices
Browse files Browse the repository at this point in the history
On some old IBM workstations and desktop computers, the BIOS presents in the
DSDT an SMBus object that is missing the HID identifier that the i2c-scmi
driver looks for.  Modify the ACPI device scan code to insert the missing HID
if it finds an IBM system with such an object.

Affected machines: IntelliStation Z20/Z30.  Note that the i2c-i801 driver no
longer works on these machines because of ACPI resource conflicts.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
  • Loading branch information
Darrick J. Wong authored and Jean Delvare committed Mar 24, 2010
1 parent ae6be51 commit 222e82a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
38 changes: 38 additions & 0 deletions drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions include/acpi/acpi_drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#define ACPI_VIDEO_HID "LNXVIDEO"
#define ACPI_BAY_HID "LNXIOBAY"
#define ACPI_DOCK_HID "LNXDOCK"
/* Quirk for broken IBM BIOSes */
#define ACPI_SMBUS_IBM_HID "SMBUSIBM"

/*
* For fixed hardware buttons, we fabricate acpi_devices with HID
Expand Down

0 comments on commit 222e82a

Please sign in to comment.