Patch "PCI: Do not wait for disconnected devices when resuming" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    PCI: Do not wait for disconnected devices when resuming

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     pci-do-not-wait-for-disconnected-devices-when-resumi.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 35540e540c808c5e7783bfa14f8d5d04443550c7
Author: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx>
Date:   Thu Feb 8 15:23:21 2024 +0200

    PCI: Do not wait for disconnected devices when resuming
    
    [ Upstream commit 6613443ffc49d03e27f0404978f685c4eac43fba ]
    
    On runtime resume, pci_dev_wait() is called:
    
      pci_pm_runtime_resume()
        pci_pm_bridge_power_up_actions()
          pci_bridge_wait_for_secondary_bus()
            pci_dev_wait()
    
    While a device is runtime suspended along with its PCI hierarchy, the
    device could get disconnected. In such case, the link will not come up no
    matter how long pci_dev_wait() waits for it.
    
    Besides the above mentioned case, there could be other ways to get the
    device disconnected while pci_dev_wait() is waiting for the link to come
    up.
    
    Make pci_dev_wait() exit if the device is already disconnected to avoid
    unnecessary delay.
    
    The use cases of pci_dev_wait() boil down to two:
    
      1. Waiting for the device after reset
      2. pci_bridge_wait_for_secondary_bus()
    
    The callers in both cases seem to benefit from propagating the
    disconnection as error even if device disconnection would be more
    analoguous to the case where there is no device in the first place which
    return 0 from pci_dev_wait(). In the case 2, it results in unnecessary
    marking of the devices disconnected again but that is just harmless extra
    work.
    
    Also make sure compiler does not become too clever with dev->error_state
    and use READ_ONCE() to force a fetch for the up-to-date value.
    
    Link: https://lore.kernel.org/r/20240208132322.4811-1-ilpo.jarvinen@xxxxxxxxxxxxxxx
    Reported-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
    Tested-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
    Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx>
    Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a41a1a6155411..cd759e19cc18e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1190,6 +1190,11 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
 	for (;;) {
 		u32 id;
 
+		if (pci_dev_is_disconnected(dev)) {
+			pci_dbg(dev, "disconnected; not waiting\n");
+			return -ENOTTY;
+		}
+
 		pci_read_config_dword(dev, PCI_COMMAND, &id);
 		if (!PCI_POSSIBLE_ERROR(id))
 			break;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ee89a69817aaf..512cb40150dfe 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2484,7 +2484,12 @@ static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
 
 static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
 {
-	return dev->error_state == pci_channel_io_perm_failure;
+	/*
+	 * error_state is set in pci_dev_set_io_state() using xchg/cmpxchg()
+	 * and read w/o common lock. READ_ONCE() ensures compiler cannot cache
+	 * the value (e.g. inside the loop in pci_dev_wait()).
+	 */
+	return READ_ONCE(dev->error_state) == pci_channel_io_perm_failure;
 }
 
 void pci_request_acs(void);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux