Merge branch 'pci/pm'

- Disable use of D3cold on Asus B1400 PCI-NVMe bridges because some BIOSes
  can't power them back on, replacing a more general ACPI sleep quirk
  (Daniel Drake)

- Allow runtime PM when the driver enables it but doesn't need any runtime
  PM callbacks (Raag Jadav)

- Drain runtime-idle callbacks before driver removal to avoid races between
  .remove() and .runtime_idle(), which caused intermittent page faults when
  the rtsx .runtime_idle() accessed registers that its .remove() had
  already unmapped (Rafael J. Wysocki)

* pci/pm:
  PCI/PM: Drain runtime-idle callbacks before driver removal
  PCI/PM: Allow runtime PM with no PM callbacks at all
  Revert "ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default"
  PCI: Disable D3cold on Asus B1400 PCI-NVMe bridge
This commit is contained in:
Bjorn Helgaas 2024-03-12 12:14:22 -05:00
commit 7dc249e7b9
3 changed files with 56 additions and 16 deletions

View file

@ -907,6 +907,54 @@ static void chromeos_fixup_apl_pci_l1ss_capability(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_save_apl_pci_l1ss_capability);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_fixup_apl_pci_l1ss_capability);
/*
* Disable D3cold on Asus B1400 PCI-NVMe bridge
*
* On this platform with VMD off, the NVMe device cannot successfully power
* back on from D3cold. This appears to be an untested transition by the
* vendor: Windows leaves the NVMe and parent bridge in D0 during suspend.
*
* We disable D3cold on the parent bridge for simplicity, and the fact that
* both parent bridge and NVMe device share the same power resource.
*
* This is only needed on BIOS versions before 308; the newer versions flip
* StorageD3Enable from 1 to 0.
*/
static const struct dmi_system_id asus_nvme_broken_d3cold_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.304"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.305"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.306"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.307"),
},
},
{}
};
static void asus_disable_nvme_d3cold(struct pci_dev *pdev)
{
if (dmi_check_system(asus_nvme_broken_d3cold_table) > 0)
pci_d3cold_disable(pdev);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x9a09, asus_disable_nvme_d3cold);
#ifdef CONFIG_SUSPEND
/*
* Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but

View file

@ -385,18 +385,6 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
},
},
/*
* ASUS B1400CEAE hangs on resume from suspend (see
* https://bugzilla.kernel.org/show_bug.cgi?id=215742).
*/
{
.callback = init_default_s3,
.ident = "ASUS B1400CEAE",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
},
},
{},
};

View file

@ -464,6 +464,13 @@ static void pci_device_remove(struct device *dev)
if (drv->remove) {
pm_runtime_get_sync(dev);
/*
* If the driver provides a .runtime_idle() callback and it has
* started to run already, it may continue to run in parallel
* with the code below, so wait until all of the runtime PM
* activity has completed.
*/
pm_runtime_barrier(dev);
drv->remove(pci_dev);
pm_runtime_put_noidle(dev);
}
@ -1373,10 +1380,7 @@ static int pci_pm_runtime_idle(struct device *dev)
if (!pci_dev->driver)
return 0;
if (!pm)
return -ENOSYS;
if (pm->runtime_idle)
if (pm && pm->runtime_idle)
return pm->runtime_idle(dev);
return 0;