51 lines
2 KiB
Diff
51 lines
2 KiB
Diff
|
From c31a8baf7ee53cfd6df6cc215e598cabbd7d9926 Mon Sep 17 00:00:00 2001
|
||
|
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
|
||
|
Date: Thu, 8 Jul 2021 15:25:06 +0200
|
||
|
Subject: [PATCH] PCI: Use pci_update_current_state() in
|
||
|
pci_enable_device_flags()
|
||
|
|
||
|
Updating the current_state field of struct pci_dev the way it is done
|
||
|
in pci_enable_device_flags() before calling do_pci_enable_device() may
|
||
|
not work. For example, if the given PCI device depends on an ACPI
|
||
|
power resource whose _STA method initially returns 0 ("off"), but the
|
||
|
config space of the PCI device is accessible and the power state
|
||
|
retrieved from the PCI_PM_CTRL register is D0, the current_state
|
||
|
field in the struct pci_dev representing that device will get out of
|
||
|
sync with the power.state of its ACPI companion object and that will
|
||
|
lead to power management issues going forward.
|
||
|
|
||
|
To avoid such issues, make pci_enable_device_flags() call
|
||
|
pci_update_current_state() which takes ACPI device power management
|
||
|
into account, if present, to retrieve the current power state of the
|
||
|
device.
|
||
|
|
||
|
Link: https://lore.kernel.org/lkml/20210314000439.3138941-1-luzmaximilian@gmail.com/
|
||
|
Reported-by: Maximilian Luz <luzmaximilian@gmail.com>
|
||
|
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||
|
Tested-by: Maximilian Luz <luzmaximilian@gmail.com>
|
||
|
Patchset: surface-hotplug
|
||
|
---
|
||
|
drivers/pci/pci.c | 6 +-----
|
||
|
1 file changed, 1 insertion(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
|
||
|
index 3f353572588d..a5e6759c407b 100644
|
||
|
--- a/drivers/pci/pci.c
|
||
|
+++ b/drivers/pci/pci.c
|
||
|
@@ -1906,11 +1906,7 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
|
||
|
* so that things like MSI message writing will behave as expected
|
||
|
* (e.g. if the device really is in D0 at enable time).
|
||
|
*/
|
||
|
- if (dev->pm_cap) {
|
||
|
- u16 pmcsr;
|
||
|
- pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
|
||
|
- dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
|
||
|
- }
|
||
|
+ pci_update_current_state(dev, dev->current_state);
|
||
|
|
||
|
if (atomic_inc_return(&dev->enable_cnt) > 1)
|
||
|
return 0; /* already enabled */
|
||
|
--
|
||
|
2.33.0
|
||
|
|