• Huang Ying's avatar
    PCI/PM: Fix deadlock when unbinding device if parent in D3cold · 90b5c1d7
    Huang Ying authored
    If a PCI device and its parents are put into D3cold, unbinding the
    device will trigger deadlock as follow:
    
    - driver_unbind
      - device_release_driver
        - device_lock(dev)				<--- previous lock here
        - __device_release_driver
          - pm_runtime_get_sync
            ...
              - rpm_resume(dev)
                - rpm_resume(dev->parent)
                  ...
                    - pci_pm_runtime_resume
                      ...
                      - pci_set_power_state
                        - __pci_start_power_transition
                          - pci_wakeup_bus(dev->parent->subordinate)
                            - pci_walk_bus
                              - device_lock(dev)	<--- deadlock here
    
    
    If we do not do device_lock in pci_walk_bus, we can avoid deadlock.
    Device_lock in pci_walk_bus is introduced in commit:
    d71374da, corresponding email thread
    is: https://lkml.org/lkml/2006/5/26/38.  The patch author Zhang Yanmin
    said device_lock is added to pci_walk_bus because:
    
      Some error handling functions call pci_walk_bus. For example, PCIe
      aer. Here we lock the device, so the driver wouldn't detach from the
      device, as the cb might call driver's callback function.
    
    So I fixed the deadlock as follows:
    
    - remove device_lock from pci_walk_bus
    - add device_lock into callback if callback will call driver's callback
    
    I checked pci_walk_bus users one by one, and found only PCIe aer needs
    device lock.
    Signed-off-by: default avatarHuang Ying <ying.huang@intel.com>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    CC: stable@vger.kernel.org		# v3.6+
    CC: Zhang Yanmin <yanmin.zhang@intel.com>
    90b5c1d7
bus.c 7.94 KB