Commit 9a4b33d4 authored by Jiaxun Yang's avatar Jiaxun Yang Committed by Andy Shevchenko

platform/x86: thinkpad_acpi: Read EC information on newer models

Newer ThinkPads have a totally different EC program information DMI
table. And thermal subdriver can't work without correct EC version.

Read from this entry if the old method failed to get EC information.
Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent f7db839f
......@@ -9958,6 +9958,37 @@ static char __init tpacpi_parse_fw_id(const char * const s,
return '\0';
}
static void find_new_ec_fwstr(const struct dmi_header *dm, void *private)
{
char *ec_fw_string = (char *) private;
const char *dmi_data = (const char *)dm;
/*
* ThinkPad Embedded Controller Program Table on newer models
*
* Offset | Name | Width | Description
* ----------------------------------------------------
* 0x00 | Type | BYTE | 0x8C
* 0x01 | Length | BYTE |
* 0x02 | Handle | WORD | Varies
* 0x04 | Signature | BYTEx6 | ASCII for "LENOVO"
* 0x0A | OEM struct offset | BYTE | 0x0B
* 0x0B | OEM struct number | BYTE | 0x07, for this structure
* 0x0C | OEM struct revision | BYTE | 0x01, for this format
* 0x0D | ECP version ID | STR ID |
* 0x0E | ECP release date | STR ID |
*/
/* Return if data structure not match */
if (dm->type != 140 || dm->length < 0x0F ||
memcmp(dmi_data + 4, "LENOVO", 6) != 0 ||
dmi_data[0x0A] != 0x0B || dmi_data[0x0B] != 0x07 ||
dmi_data[0x0C] != 0x01)
return;
/* fwstr is the first 8byte string */
strncpy(ec_fw_string, dmi_data + 0x0F, 8);
}
/* returns 0 - probe ok, or < 0 - probe error.
* Probe ok doesn't mean thinkpad found.
* On error, kfree() cleanup on tp->* is not performed, caller must do it */
......@@ -9965,7 +9996,7 @@ static int __must_check __init get_thinkpad_model_data(
struct thinkpad_id_data *tp)
{
const struct dmi_device *dev = NULL;
char ec_fw_string[18];
char ec_fw_string[18] = {0};
char const *s;
char t;
......@@ -10005,7 +10036,15 @@ static int __must_check __init get_thinkpad_model_data(
ec_fw_string) == 1) {
ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
break;
}
}
/* Newer ThinkPads have different EC program info table */
if (!ec_fw_string[0])
dmi_walk(find_new_ec_fwstr, &ec_fw_string);
if (ec_fw_string[0]) {
tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
if (!tp->ec_version_str)
return -ENOMEM;
......@@ -10015,10 +10054,7 @@ static int __must_check __init get_thinkpad_model_data(
if (t != 'H') {
pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
ec_fw_string);
pr_notice("please report this to %s\n",
TPACPI_MAIL);
}
break;
pr_notice("please report this to %s\n", TPACPI_MAIL);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment