}
 }
 
+/**
+ * pci_platform_power_transition - Use platform to change device power state
+ * @dev: PCI device to handle.
+ * @state: State to put the device into.
+ */
+static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
+{
+       int error;
+
+       if (platform_pci_power_manageable(dev)) {
+               error = platform_pci_set_power_state(dev, state);
+               if (!error)
+                       pci_update_current_state(dev, state);
+       } else {
+               error = -ENODEV;
+               /* Fall back to PCI_D0 if native PM is not supported */
+               pci_update_current_state(dev, PCI_D0);
+       }
+
+       return error;
+}
+
+/**
+ * __pci_start_power_transition - Start power transition of a PCI device
+ * @dev: PCI device to handle.
+ * @state: State to put the device into.
+ */
+static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
+{
+       if (state == PCI_D0)
+               pci_platform_power_transition(dev, PCI_D0);
+}
+
+/**
+ * __pci_complete_power_transition - Complete power transition of a PCI device
+ * @dev: PCI device to handle.
+ * @state: State to put the device into.
+ *
+ * This function should not be called directly by device drivers.
+ */
+int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state)
+{
+       return state > PCI_D0 ?
+                       pci_platform_power_transition(dev, state) : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(__pci_complete_power_transition);
+
 /**
  * pci_set_power_state - Set the power state of a PCI device
  * @dev: PCI device to handle.
        if (dev->current_state == state)
                return 0;
 
-       if (state == PCI_D0) {
-               /*
-                * Allow the platform to change the state, for example via ACPI
-                * _PR0, _PS0 and some such, but do not trust it.
-                */
-               int ret = platform_pci_power_manageable(dev) ?
-                       platform_pci_set_power_state(dev, PCI_D0) : 0;
-               if (!ret)
-                       pci_update_current_state(dev, PCI_D0);
-       }
+       __pci_start_power_transition(dev, state);
+
        /* This device is quirked not to be put into D3, so
           don't put it in D3 */
        if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
 
        error = pci_raw_set_power_state(dev, state);
 
-       if (state > PCI_D0 && platform_pci_power_manageable(dev)) {
-               /* Allow the platform to finalize the transition */
-               int ret = platform_pci_set_power_state(dev, state);
-               if (!ret) {
-                       pci_update_current_state(dev, state);
-                       error = 0;
-               }
-       }
+       if (!__pci_complete_power_transition(dev, state))
+               error = 0;
 
        return error;
 }
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
 int pci_restore_state(struct pci_dev *dev);
+int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
 int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
 bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);