Commit 18020a0d8cccad0d3642219d6aef789420c04c1f

Authored by Linus Torvalds

Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  i2c-scmi: Provide module aliases for automatic loading
  i2c-scmi: Support IBM SMBus CMI devices
  acpi: Support IBM SMBus CMI devices

Showing 3 changed files Side-by-side Diff

... ... @@ -8,6 +8,7 @@
8 8 #include <linux/acpi.h>
9 9 #include <linux/signal.h>
10 10 #include <linux/kthread.h>
  11 +#include <linux/dmi.h>
11 12  
12 13 #include <acpi/acpi_drivers.h>
13 14  
... ... @@ -1032,6 +1033,41 @@
1032 1033 list_add_tail(&id->list, &device->pnp.ids);
1033 1034 }
1034 1035  
  1036 +/*
  1037 + * Old IBM workstations have a DSDT bug wherein the SMBus object
  1038 + * lacks the SMBUS01 HID and the methods do not have the necessary "_"
  1039 + * prefix. Work around this.
  1040 + */
  1041 +static int acpi_ibm_smbus_match(struct acpi_device *device)
  1042 +{
  1043 + acpi_handle h_dummy;
  1044 + struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
  1045 + int result;
  1046 +
  1047 + if (!dmi_name_in_vendors("IBM"))
  1048 + return -ENODEV;
  1049 +
  1050 + /* Look for SMBS object */
  1051 + result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
  1052 + if (result)
  1053 + return result;
  1054 +
  1055 + if (strcmp("SMBS", path.pointer)) {
  1056 + result = -ENODEV;
  1057 + goto out;
  1058 + }
  1059 +
  1060 + /* Does it have the necessary (but misnamed) methods? */
  1061 + result = -ENODEV;
  1062 + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
  1063 + ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
  1064 + ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
  1065 + result = 0;
  1066 +out:
  1067 + kfree(path.pointer);
  1068 + return result;
  1069 +}
  1070 +
1035 1071 static void acpi_device_set_id(struct acpi_device *device)
1036 1072 {
1037 1073 acpi_status status;
... ... @@ -1082,6 +1118,8 @@
1082 1118 acpi_add_id(device, ACPI_BAY_HID);
1083 1119 else if (ACPI_SUCCESS(acpi_dock_match(device)))
1084 1120 acpi_add_id(device, ACPI_DOCK_HID);
  1121 + else if (!acpi_ibm_smbus_match(device))
  1122 + acpi_add_id(device, ACPI_SMBUS_IBM_HID);
1085 1123  
1086 1124 break;
1087 1125 case ACPI_BUS_TYPE_POWER:
drivers/i2c/busses/i2c-scmi.c
... ... @@ -33,6 +33,7 @@
33 33 u8 cap_info:1;
34 34 u8 cap_read:1;
35 35 u8 cap_write:1;
  36 + struct smbus_methods_t *methods;
36 37 };
37 38  
38 39 static const struct smbus_methods_t smbus_methods = {
39 40  
40 41  
... ... @@ -41,10 +42,19 @@
41 42 .mt_sbw = "_SBW",
42 43 };
43 44  
  45 +/* Some IBM BIOSes omit the leading underscore */
  46 +static const struct smbus_methods_t ibm_smbus_methods = {
  47 + .mt_info = "SBI_",
  48 + .mt_sbr = "SBR_",
  49 + .mt_sbw = "SBW_",
  50 +};
  51 +
44 52 static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
45   - {"SMBUS01", 0},
  53 + {"SMBUS01", (kernel_ulong_t)&smbus_methods},
  54 + {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
46 55 {"", 0}
47 56 };
  57 +MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids);
48 58  
49 59 #define ACPI_SMBUS_STATUS_OK 0x00
50 60 #define ACPI_SMBUS_STATUS_FAIL 0x07
51 61  
... ... @@ -150,11 +160,11 @@
150 160  
151 161 if (read_write == I2C_SMBUS_READ) {
152 162 protocol |= ACPI_SMBUS_PRTCL_READ;
153   - method = smbus_methods.mt_sbr;
  163 + method = smbus_cmi->methods->mt_sbr;
154 164 input.count = 3;
155 165 } else {
156 166 protocol |= ACPI_SMBUS_PRTCL_WRITE;
157   - method = smbus_methods.mt_sbw;
  167 + method = smbus_cmi->methods->mt_sbw;
158 168 input.count = 5;
159 169 }
160 170  
161 171  
162 172  
... ... @@ -290,13 +300,13 @@
290 300 union acpi_object *obj;
291 301 acpi_status status;
292 302  
293   - if (!strcmp(name, smbus_methods.mt_info)) {
  303 + if (!strcmp(name, smbus_cmi->methods->mt_info)) {
294 304 status = acpi_evaluate_object(smbus_cmi->handle,
295   - smbus_methods.mt_info,
  305 + smbus_cmi->methods->mt_info,
296 306 NULL, &buffer);
297 307 if (ACPI_FAILURE(status)) {
298 308 ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
299   - smbus_methods.mt_info, status));
  309 + smbus_cmi->methods->mt_info, status));
300 310 return -EIO;
301 311 }
302 312  
303 313  
... ... @@ -319,9 +329,9 @@
319 329  
320 330 kfree(buffer.pointer);
321 331 smbus_cmi->cap_info = 1;
322   - } else if (!strcmp(name, smbus_methods.mt_sbr))
  332 + } else if (!strcmp(name, smbus_cmi->methods->mt_sbr))
323 333 smbus_cmi->cap_read = 1;
324   - else if (!strcmp(name, smbus_methods.mt_sbw))
  334 + else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
325 335 smbus_cmi->cap_write = 1;
326 336 else
327 337 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n",
... ... @@ -349,6 +359,7 @@
349 359 static int acpi_smbus_cmi_add(struct acpi_device *device)
350 360 {
351 361 struct acpi_smbus_cmi *smbus_cmi;
  362 + const struct acpi_device_id *id;
352 363  
353 364 smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
354 365 if (!smbus_cmi)
... ... @@ -361,6 +372,11 @@
361 372 smbus_cmi->cap_info = 0;
362 373 smbus_cmi->cap_read = 0;
363 374 smbus_cmi->cap_write = 0;
  375 +
  376 + for (id = acpi_smbus_cmi_ids; id->id[0]; id++)
  377 + if (!strcmp(id->id, acpi_device_hid(device)))
  378 + smbus_cmi->methods =
  379 + (struct smbus_methods_t *) id->driver_data;
364 380  
365 381 acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
366 382 acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
include/acpi/acpi_drivers.h
... ... @@ -65,6 +65,8 @@
65 65 #define ACPI_VIDEO_HID "LNXVIDEO"
66 66 #define ACPI_BAY_HID "LNXIOBAY"
67 67 #define ACPI_DOCK_HID "LNXDOCK"
  68 +/* Quirk for broken IBM BIOSes */
  69 +#define ACPI_SMBUS_IBM_HID "SMBUSIBM"
68 70  
69 71 /*
70 72 * For fixed hardware buttons, we fabricate acpi_devices with HID