12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- From b57c1784927f0ef467efdee4cb2a026d7eea3c1c Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Sun, 19 Feb 2023 22:12:24 +0100
- Subject: [PATCH] PCI: Add quirk to prevent calling shutdown mehtod
- Work around buggy EFI firmware: On some Microsoft Surface devices
- (Surface Pro 9 and Surface Laptop 5) the EFI ResetSystem call with
- EFI_RESET_SHUTDOWN doesn't function properly. Instead of shutting the
- system down, it returns and the system stays on.
- It turns out that this only happens after PCI shutdown callbacks ran for
- specific devices. Excluding those devices from the shutdown process
- makes the ResetSystem call work as expected.
- TODO: Maybe we can find a better way or the root cause of this?
- Not-Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Patchset: surface-shutdown
- ---
- drivers/pci/pci-driver.c | 3 +++
- drivers/pci/quirks.c | 36 ++++++++++++++++++++++++++++++++++++
- include/linux/pci.h | 1 +
- 3 files changed, 40 insertions(+)
- diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
- index 51ec9e7e784f0..40554890d7211 100644
- --- a/drivers/pci/pci-driver.c
- +++ b/drivers/pci/pci-driver.c
- @@ -507,6 +507,9 @@ static void pci_device_shutdown(struct device *dev)
- struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
-
- + if (pci_dev->no_shutdown)
- + return;
- +
- pm_runtime_resume(dev);
-
- if (drv && drv->shutdown)
- diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
- index ae95d09507722..036af941b5e6b 100644
- --- a/drivers/pci/quirks.c
- +++ b/drivers/pci/quirks.c
- @@ -6223,3 +6223,39 @@ static void pci_fixup_d3cold_delay_1sec(struct pci_dev *pdev)
- pdev->d3cold_delay = 1000;
- }
- DECLARE_PCI_FIXUP_FINAL(0x5555, 0x0004, pci_fixup_d3cold_delay_1sec);
- +
- +static const struct dmi_system_id no_shutdown_dmi_table[] = {
- + /*
- + * Systems on which some devices should not be touched during shutdown.
- + */
- + {
- + .ident = "Microsoft Surface Pro 9",
- + .matches = {
- + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Pro 9"),
- + },
- + },
- + {
- + .ident = "Microsoft Surface Laptop 5",
- + .matches = {
- + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 5"),
- + },
- + },
- + {}
- +};
- +
- +static void quirk_no_shutdown(struct pci_dev *dev)
- +{
- + if (!dmi_check_system(no_shutdown_dmi_table))
- + return;
- +
- + dev->no_shutdown = 1;
- + pci_info(dev, "disabling shutdown ops for [%04x:%04x]\n",
- + dev->vendor, dev->device);
- +}
- +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x461e, quirk_no_shutdown); // Thunderbolt 4 USB Controller
- +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x461f, quirk_no_shutdown); // Thunderbolt 4 PCI Express Root Port
- +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x462f, quirk_no_shutdown); // Thunderbolt 4 PCI Express Root Port
- +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x466d, quirk_no_shutdown); // Thunderbolt 4 NHI
- +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x46a8, quirk_no_shutdown); // GPU
- diff --git a/include/linux/pci.h b/include/linux/pci.h
- index 1596b1205b8d8..608ab04a0b6c9 100644
- --- a/include/linux/pci.h
- +++ b/include/linux/pci.h
- @@ -465,6 +465,7 @@ struct pci_dev {
- unsigned int no_command_memory:1; /* No PCI_COMMAND_MEMORY */
- unsigned int rom_bar_overlap:1; /* ROM BAR disable broken */
- unsigned int rom_attr_enabled:1; /* Display of ROM attribute enabled? */
- + unsigned int no_shutdown:1; /* Do not touch device on shutdown */
- pci_dev_flags_t dev_flags;
- atomic_t enable_cnt; /* pci_enable_device has been called */
-
- --
- 2.43.0
|