Commit 9be9ed26 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v5.18-4' of...

Merge tag 'platform-drivers-x86-v5.18-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver fixes from Hans de Goede:

 - thinkpad_acpi AMD suspend/resume + fan detection fixes

 - two other small fixes

 - one hardware-id addition

* tag 'platform-drivers-x86-v5.18-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
  platform/surface: aggregator: Fix initialization order when compiling as builtin module
  platform/surface: gpe: Add support for Surface Pro 8
  platform/x86/intel: Fix 'rmmod pmt_telemetry' panic
  platform/x86: thinkpad_acpi: Correct dual fan probe
  platform/x86: thinkpad_acpi: Add a s2idle resume quirk for a number of laptops
  platform/x86: thinkpad_acpi: Convert btusb DMI list to quirks
parents c5eb0a61 44acfc22
...@@ -817,7 +817,7 @@ static int __init ssam_core_init(void) ...@@ -817,7 +817,7 @@ static int __init ssam_core_init(void)
err_bus: err_bus:
return status; return status;
} }
module_init(ssam_core_init); subsys_initcall(ssam_core_init);
static void __exit ssam_core_exit(void) static void __exit ssam_core_exit(void)
{ {
......
...@@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = { ...@@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = {
}, },
.driver_data = (void *)lid_device_props_l4D, .driver_data = (void *)lid_device_props_l4D,
}, },
{
.ident = "Surface Pro 8",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 8"),
},
.driver_data = (void *)lid_device_props_l4B,
},
{ {
.ident = "Surface Book 1", .ident = "Surface Book 1",
.matches = { .matches = {
......
...@@ -103,7 +103,7 @@ static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxilia ...@@ -103,7 +103,7 @@ static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxilia
auxiliary_set_drvdata(auxdev, priv); auxiliary_set_drvdata(auxdev, priv);
for (i = 0; i < intel_vsec_dev->num_resources; i++) { for (i = 0; i < intel_vsec_dev->num_resources; i++) {
struct intel_pmt_entry *entry = &priv->entry[i]; struct intel_pmt_entry *entry = &priv->entry[priv->num_entries];
ret = intel_pmt_dev_create(entry, &pmt_telem_ns, intel_vsec_dev, i); ret = intel_pmt_dev_create(entry, &pmt_telem_ns, intel_vsec_dev, i);
if (ret < 0) if (ret < 0)
......
...@@ -309,6 +309,20 @@ struct ibm_init_struct { ...@@ -309,6 +309,20 @@ struct ibm_init_struct {
struct ibm_struct *data; struct ibm_struct *data;
}; };
/* DMI Quirks */
struct quirk_entry {
bool btusb_bug;
u32 s2idle_bug_mmio;
};
static struct quirk_entry quirk_btusb_bug = {
.btusb_bug = true,
};
static struct quirk_entry quirk_s2idle_bug = {
.s2idle_bug_mmio = 0xfed80380,
};
static struct { static struct {
u32 bluetooth:1; u32 bluetooth:1;
u32 hotkey:1; u32 hotkey:1;
...@@ -338,6 +352,7 @@ static struct { ...@@ -338,6 +352,7 @@ static struct {
u32 hotkey_poll_active:1; u32 hotkey_poll_active:1;
u32 has_adaptive_kbd:1; u32 has_adaptive_kbd:1;
u32 kbd_lang:1; u32 kbd_lang:1;
struct quirk_entry *quirks;
} tp_features; } tp_features;
static struct { static struct {
...@@ -4359,9 +4374,10 @@ static void bluetooth_exit(void) ...@@ -4359,9 +4374,10 @@ static void bluetooth_exit(void)
bluetooth_shutdown(); bluetooth_shutdown();
} }
static const struct dmi_system_id bt_fwbug_list[] __initconst = { static const struct dmi_system_id fwbug_list[] __initconst = {
{ {
.ident = "ThinkPad E485", .ident = "ThinkPad E485",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20KU"), DMI_MATCH(DMI_BOARD_NAME, "20KU"),
...@@ -4369,6 +4385,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { ...@@ -4369,6 +4385,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = {
}, },
{ {
.ident = "ThinkPad E585", .ident = "ThinkPad E585",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20KV"), DMI_MATCH(DMI_BOARD_NAME, "20KV"),
...@@ -4376,6 +4393,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { ...@@ -4376,6 +4393,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = {
}, },
{ {
.ident = "ThinkPad A285 - 20MW", .ident = "ThinkPad A285 - 20MW",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20MW"), DMI_MATCH(DMI_BOARD_NAME, "20MW"),
...@@ -4383,6 +4401,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { ...@@ -4383,6 +4401,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = {
}, },
{ {
.ident = "ThinkPad A285 - 20MX", .ident = "ThinkPad A285 - 20MX",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20MX"), DMI_MATCH(DMI_BOARD_NAME, "20MX"),
...@@ -4390,6 +4409,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { ...@@ -4390,6 +4409,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = {
}, },
{ {
.ident = "ThinkPad A485 - 20MU", .ident = "ThinkPad A485 - 20MU",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20MU"), DMI_MATCH(DMI_BOARD_NAME, "20MU"),
...@@ -4397,14 +4417,125 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { ...@@ -4397,14 +4417,125 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = {
}, },
{ {
.ident = "ThinkPad A485 - 20MV", .ident = "ThinkPad A485 - 20MV",
.driver_data = &quirk_btusb_bug,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "20MV"), DMI_MATCH(DMI_BOARD_NAME, "20MV"),
}, },
}, },
{
.ident = "L14 Gen2 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
}
},
{
.ident = "T14s Gen2 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
}
},
{
.ident = "X13 Gen2 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
}
},
{
.ident = "T14 Gen2 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
}
},
{
.ident = "T14 Gen1 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
}
},
{
.ident = "T14 Gen1 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
}
},
{
.ident = "T14s Gen1 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
}
},
{
.ident = "P14s Gen1 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
}
},
{
.ident = "P14s Gen2 AMD",
.driver_data = &quirk_s2idle_bug,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
}
},
{} {}
}; };
#ifdef CONFIG_SUSPEND
/*
* Lenovo laptops from a variety of generations run a SMI handler during the D3->D0
* transition that occurs specifically when exiting suspend to idle which can cause
* large delays during resume when the IOMMU translation layer is enabled (the default
* behavior) for NVME devices:
*
* To avoid this firmware problem, skip the SMI handler on these machines before the
* D0 transition occurs.
*/
static void thinkpad_acpi_amd_s2idle_restore(void)
{
struct resource *res;
void __iomem *addr;
u8 val;
res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1,
"thinkpad_acpi_pm80");
if (!res)
return;
addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1);
if (!addr)
goto cleanup_resource;
val = ioread8(addr);
iowrite8(val & ~BIT(0), addr);
iounmap(addr);
cleanup_resource:
release_resource(res);
}
static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
.restore = thinkpad_acpi_amd_s2idle_restore,
};
#endif
static const struct pci_device_id fwbug_cards_ids[] __initconst = { static const struct pci_device_id fwbug_cards_ids[] __initconst = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) },
...@@ -4419,7 +4550,8 @@ static int __init have_bt_fwbug(void) ...@@ -4419,7 +4550,8 @@ static int __init have_bt_fwbug(void)
* Some AMD based ThinkPads have a firmware bug that calling * Some AMD based ThinkPads have a firmware bug that calling
* "GBDC" will cause bluetooth on Intel wireless cards blocked * "GBDC" will cause bluetooth on Intel wireless cards blocked
*/ */
if (dmi_check_system(bt_fwbug_list) && pci_dev_present(fwbug_cards_ids)) { if (tp_features.quirks && tp_features.quirks->btusb_bug &&
pci_dev_present(fwbug_cards_ids)) {
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
FW_BUG "disable bluetooth subdriver for Intel cards\n"); FW_BUG "disable bluetooth subdriver for Intel cards\n");
return 1; return 1;
...@@ -8748,24 +8880,27 @@ static int __init fan_init(struct ibm_init_struct *iibm) ...@@ -8748,24 +8880,27 @@ static int __init fan_init(struct ibm_init_struct *iibm)
fan_status_access_mode = TPACPI_FAN_RD_TPEC; fan_status_access_mode = TPACPI_FAN_RD_TPEC;
if (quirks & TPACPI_FAN_Q1) if (quirks & TPACPI_FAN_Q1)
fan_quirk1_setup(); fan_quirk1_setup();
if (quirks & TPACPI_FAN_2FAN) {
tp_features.second_fan = 1;
pr_info("secondary fan support enabled\n");
}
if (quirks & TPACPI_FAN_2CTL) {
tp_features.second_fan = 1;
tp_features.second_fan_ctl = 1;
pr_info("secondary fan control enabled\n");
}
/* Try and probe the 2nd fan */ /* Try and probe the 2nd fan */
tp_features.second_fan = 1; /* needed for get_speed to work */
res = fan2_get_speed(&speed); res = fan2_get_speed(&speed);
if (res >= 0) { if (res >= 0) {
/* It responded - so let's assume it's there */ /* It responded - so let's assume it's there */
tp_features.second_fan = 1; tp_features.second_fan = 1;
tp_features.second_fan_ctl = 1; tp_features.second_fan_ctl = 1;
pr_info("secondary fan control detected & enabled\n"); pr_info("secondary fan control detected & enabled\n");
} else {
/* Fan not auto-detected */
tp_features.second_fan = 0;
if (quirks & TPACPI_FAN_2FAN) {
tp_features.second_fan = 1;
pr_info("secondary fan support enabled\n");
}
if (quirks & TPACPI_FAN_2CTL) {
tp_features.second_fan = 1;
tp_features.second_fan_ctl = 1;
pr_info("secondary fan control enabled\n");
}
} }
} else { } else {
pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n"); pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");
return -ENODEV; return -ENODEV;
...@@ -11455,6 +11590,10 @@ static void thinkpad_acpi_module_exit(void) ...@@ -11455,6 +11590,10 @@ static void thinkpad_acpi_module_exit(void)
tpacpi_lifecycle = TPACPI_LIFE_EXITING; tpacpi_lifecycle = TPACPI_LIFE_EXITING;
#ifdef CONFIG_SUSPEND
if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio)
acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops);
#endif
if (tpacpi_hwmon) if (tpacpi_hwmon)
hwmon_device_unregister(tpacpi_hwmon); hwmon_device_unregister(tpacpi_hwmon);
if (tp_features.sensors_pdrv_registered) if (tp_features.sensors_pdrv_registered)
...@@ -11496,6 +11635,7 @@ static void thinkpad_acpi_module_exit(void) ...@@ -11496,6 +11635,7 @@ static void thinkpad_acpi_module_exit(void)
static int __init thinkpad_acpi_module_init(void) static int __init thinkpad_acpi_module_init(void)
{ {
const struct dmi_system_id *dmi_id;
int ret, i; int ret, i;
tpacpi_lifecycle = TPACPI_LIFE_INIT; tpacpi_lifecycle = TPACPI_LIFE_INIT;
...@@ -11535,6 +11675,10 @@ static int __init thinkpad_acpi_module_init(void) ...@@ -11535,6 +11675,10 @@ static int __init thinkpad_acpi_module_init(void)
return -ENODEV; return -ENODEV;
} }
dmi_id = dmi_first_match(fwbug_list);
if (dmi_id)
tp_features.quirks = dmi_id->driver_data;
/* Device initialization */ /* Device initialization */
tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1, tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1,
NULL, 0); NULL, 0);
...@@ -11623,6 +11767,13 @@ static int __init thinkpad_acpi_module_init(void) ...@@ -11623,6 +11767,13 @@ static int __init thinkpad_acpi_module_init(void)
tp_features.input_device_registered = 1; tp_features.input_device_registered = 1;
} }
#ifdef CONFIG_SUSPEND
if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) {
if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops))
pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
(dmi_id && dmi_id->ident) ? dmi_id->ident : "");
}
#endif
return 0; return 0;
} }
......
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