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, ...@@ -9958,6 +9958,37 @@ static char __init tpacpi_parse_fw_id(const char * const s,
return '\0'; 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. /* returns 0 - probe ok, or < 0 - probe error.
* Probe ok doesn't mean thinkpad found. * Probe ok doesn't mean thinkpad found.
* On error, kfree() cleanup on tp->* is not performed, caller must do it */ * 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( ...@@ -9965,7 +9996,7 @@ static int __must_check __init get_thinkpad_model_data(
struct thinkpad_id_data *tp) struct thinkpad_id_data *tp)
{ {
const struct dmi_device *dev = NULL; const struct dmi_device *dev = NULL;
char ec_fw_string[18]; char ec_fw_string[18] = {0};
char const *s; char const *s;
char t; char t;
...@@ -10005,20 +10036,25 @@ static int __must_check __init get_thinkpad_model_data( ...@@ -10005,20 +10036,25 @@ static int __must_check __init get_thinkpad_model_data(
ec_fw_string) == 1) { ec_fw_string) == 1) {
ec_fw_string[sizeof(ec_fw_string) - 1] = 0; ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
break;
}
}
tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); /* Newer ThinkPads have different EC program info table */
if (!tp->ec_version_str) if (!ec_fw_string[0])
return -ENOMEM; dmi_walk(find_new_ec_fwstr, &ec_fw_string);
t = tpacpi_parse_fw_id(ec_fw_string, if (ec_fw_string[0]) {
&tp->ec_model, &tp->ec_release); tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
if (t != 'H') { if (!tp->ec_version_str)
pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n", return -ENOMEM;
ec_fw_string);
pr_notice("please report this to %s\n", t = tpacpi_parse_fw_id(ec_fw_string,
TPACPI_MAIL); &tp->ec_model, &tp->ec_release);
} if (t != 'H') {
break; 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);
} }
} }
......
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