• Rafael J. Wysocki's avatar
    PCI PM: Fix initialization and kexec breakage for some devices · b3bad72e
    Rafael J. Wysocki authored
    Recent PCI PM changes introduced a bug that causes some devices to be
    mishandled after kexec and during early initialization.  The failure
    scenario in the kexec case is the following:
    
    * Assume a PCI device is not power-manageable by the platform and has
      PCI_PM_CTRL_NO_SOFT_RESET set in PMCSR.
    * The device is put into D3 before kexec (using the native PCI PM).
    * After kexec, pci_setup_device() sets the device's power state to
      PCI_UNKNOWN.
    * pci_set_power_state(dev, PCI_D0) is called by the device's driver.
    * __pci_start_power_transition(dev, PCI_D0) is called and since the
      device is not power-manageable by the platform, it causes
      pci_update_current_state(dev, PCI_D0) to be called.  As a result
      the device's current_state field is updated to PCI_D3, in
      accordance with the contents of its PCI PM registers.
    * pci_raw_set_power_state() is called and it changes the device power
      state to D0.  *However*, it should also call pci_restore_bars() to
      reinitialize the device, but it doesn't, because the device's
      current_state field has been modified earlier.
    
    To prevent this from happening, modify pci_platform_power_transition()
    so that it doesn't use pci_update_current_state() to update the
    current_state field for devices that aren't power-manageable by the
    platform.  Instead, this field should be updated directly for devices
    that don't support the native PCI PM.
    Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
    Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
    b3bad72e
pci.c 69.1 KB