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: Jiaxun Yang <jiaxun.yang@flygoat.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
f7db839fcc
commit
9a4b33d4d2
|
@ -9958,6 +9958,37 @@ invalid:
|
||||||
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(
|
||||||
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,23 +10036,28 @@ 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;
|
||||||
|
|
||||||
tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
|
|
||||||
if (!tp->ec_version_str)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
t = tpacpi_parse_fw_id(ec_fw_string,
|
|
||||||
&tp->ec_model, &tp->ec_release);
|
|
||||||
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;
|
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;
|
||||||
|
|
||||||
|
t = tpacpi_parse_fw_id(ec_fw_string,
|
||||||
|
&tp->ec_model, &tp->ec_release);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s = dmi_get_system_info(DMI_PRODUCT_VERSION);
|
s = dmi_get_system_info(DMI_PRODUCT_VERSION);
|
||||||
if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
|
if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
|
||||||
tp->model_str = kstrdup(s, GFP_KERNEL);
|
tp->model_str = kstrdup(s, GFP_KERNEL);
|
||||||
|
|
Loading…
Reference in New Issue