mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 05:34:00 +08:00
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';
|
||||
}
|
||||
|
||||
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,23 +10036,28 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
|
||||
tp->model_str = kstrdup(s, GFP_KERNEL);
|
||||
|
Loading…
Reference in New Issue
Block a user