PCI: Export pci_dev_lock()
[platform/kernel/linux-starfive.git] / drivers / pci / pci.c
index e55d944..193bfcd 100644 (file)
@@ -269,7 +269,7 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
                                  const char **endptr)
 {
        int ret;
-       int seg, bus, slot, func;
+       unsigned int seg, bus, slot, func;
        char *wpath, *p;
        char end;
 
@@ -972,61 +972,67 @@ static void pci_restore_bars(struct pci_dev *dev)
                pci_update_resource(dev, i);
 }
 
-static const struct pci_platform_pm_ops *pci_platform_pm;
-
-int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
-{
-       if (!ops->is_manageable || !ops->set_state  || !ops->get_state ||
-           !ops->choose_state  || !ops->set_wakeup || !ops->need_resume)
-               return -EINVAL;
-       pci_platform_pm = ops;
-       return 0;
-}
-
 static inline bool platform_pci_power_manageable(struct pci_dev *dev)
 {
-       return pci_platform_pm ? pci_platform_pm->is_manageable(dev) : false;
+       if (pci_use_mid_pm())
+               return true;
+
+       return acpi_pci_power_manageable(dev);
 }
 
 static inline int platform_pci_set_power_state(struct pci_dev *dev,
                                               pci_power_t t)
 {
-       return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS;
+       if (pci_use_mid_pm())
+               return mid_pci_set_power_state(dev, t);
+
+       return acpi_pci_set_power_state(dev, t);
 }
 
 static inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev)
 {
-       return pci_platform_pm ? pci_platform_pm->get_state(dev) : PCI_UNKNOWN;
+       if (pci_use_mid_pm())
+               return mid_pci_get_power_state(dev);
+
+       return acpi_pci_get_power_state(dev);
 }
 
 static inline void platform_pci_refresh_power_state(struct pci_dev *dev)
 {
-       if (pci_platform_pm && pci_platform_pm->refresh_state)
-               pci_platform_pm->refresh_state(dev);
+       if (!pci_use_mid_pm())
+               acpi_pci_refresh_power_state(dev);
 }
 
 static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
 {
-       return pci_platform_pm ?
-                       pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
+       if (pci_use_mid_pm())
+               return PCI_POWER_ERROR;
+
+       return acpi_pci_choose_state(dev);
 }
 
 static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable)
 {
-       return pci_platform_pm ?
-                       pci_platform_pm->set_wakeup(dev, enable) : -ENODEV;
+       if (pci_use_mid_pm())
+               return PCI_POWER_ERROR;
+
+       return acpi_pci_wakeup(dev, enable);
 }
 
 static inline bool platform_pci_need_resume(struct pci_dev *dev)
 {
-       return pci_platform_pm ? pci_platform_pm->need_resume(dev) : false;
+       if (pci_use_mid_pm())
+               return false;
+
+       return acpi_pci_need_resume(dev);
 }
 
 static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
 {
-       if (pci_platform_pm && pci_platform_pm->bridge_d3)
-               return pci_platform_pm->bridge_d3(dev);
-       return false;
+       if (pci_use_mid_pm())
+               return false;
+
+       return acpi_pci_bridge_d3(dev);
 }
 
 /**
@@ -1185,9 +1191,7 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
  */
 void pci_refresh_power_state(struct pci_dev *dev)
 {
-       if (platform_pci_power_manageable(dev))
-               platform_pci_refresh_power_state(dev);
-
+       platform_pci_refresh_power_state(dev);
        pci_update_current_state(dev, dev->current_state);
 }
 
@@ -1200,14 +1204,10 @@ 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;
-
-       if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
+       error = platform_pci_set_power_state(dev, state);
+       if (!error)
+               pci_update_current_state(dev, state);
+       else if (!dev->pm_cap) /* Fall back to PCI_D0 */
                dev->current_state = PCI_D0;
 
        return error;
@@ -1388,44 +1388,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 }
 EXPORT_SYMBOL(pci_set_power_state);
 
-/**
- * pci_choose_state - Choose the power state of a PCI device
- * @dev: PCI device to be suspended
- * @state: target sleep state for the whole system. This is the value
- *        that is passed to suspend() function.
- *
- * Returns PCI power state suitable for given device and given system
- * message.
- */
-pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
-{
-       pci_power_t ret;
-
-       if (!dev->pm_cap)
-               return PCI_D0;
-
-       ret = platform_pci_choose_state(dev);
-       if (ret != PCI_POWER_ERROR)
-               return ret;
-
-       switch (state.event) {
-       case PM_EVENT_ON:
-               return PCI_D0;
-       case PM_EVENT_FREEZE:
-       case PM_EVENT_PRETHAW:
-               /* REVISIT both freeze and pre-thaw "should" use D0 */
-       case PM_EVENT_SUSPEND:
-       case PM_EVENT_HIBERNATE:
-               return PCI_D3hot;
-       default:
-               pci_info(dev, "unrecognized suspend event %d\n",
-                        state.event);
-               BUG();
-       }
-       return PCI_D0;
-}
-EXPORT_SYMBOL(pci_choose_state);
-
 #define PCI_EXP_SAVE_REGS      7
 
 static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
@@ -1477,6 +1439,24 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        return 0;
 }
 
+void pci_bridge_reconfigure_ltr(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCIEASPM
+       struct pci_dev *bridge;
+       u32 ctl;
+
+       bridge = pci_upstream_bridge(dev);
+       if (bridge && bridge->ltr_path) {
+               pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl);
+               if (!(ctl & PCI_EXP_DEVCTL2_LTR_EN)) {
+                       pci_dbg(bridge, "re-enabling LTR\n");
+                       pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
+                                                PCI_EXP_DEVCTL2_LTR_EN);
+               }
+       }
+#endif
+}
+
 static void pci_restore_pcie_state(struct pci_dev *dev)
 {
        int i = 0;
@@ -1487,6 +1467,13 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
        if (!save_state)
                return;
 
+       /*
+        * Downstream ports reset the LTR enable bit when link goes down.
+        * Check and re-configure the bit here before restoring device.
+        * PCIe r5.0, sec 7.5.3.16.
+        */
+       pci_bridge_reconfigure_ltr(dev);
+
        cap = (u16 *)&save_state->cap.data[0];
        pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]);
        pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]);
@@ -2218,6 +2205,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
 }
 EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
 
+#ifdef CONFIG_PCIEAER
 void pcie_clear_device_status(struct pci_dev *dev)
 {
        u16 sta;
@@ -2225,6 +2213,7 @@ void pcie_clear_device_status(struct pci_dev *dev)
        pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &sta);
        pcie_capability_write_word(dev, PCI_EXP_DEVSTA, sta);
 }
+#endif
 
 /**
  * pcie_clear_root_pme_status - Clear root port PME interrupt status.
@@ -2577,8 +2566,6 @@ EXPORT_SYMBOL(pci_wake_from_d3);
  */
 static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
 {
-       pci_power_t target_state = PCI_D3hot;
-
        if (platform_pci_power_manageable(dev)) {
                /*
                 * Call the platform to find the target state for the device.
@@ -2588,32 +2575,29 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
                switch (state) {
                case PCI_POWER_ERROR:
                case PCI_UNKNOWN:
-                       break;
+                       return PCI_D3hot;
+
                case PCI_D1:
                case PCI_D2:
                        if (pci_no_d1d2(dev))
-                               break;
-                       fallthrough;
-               default:
-                       target_state = state;
+                               return PCI_D3hot;
                }
 
-               return target_state;
+               return state;
        }
 
-       if (!dev->pm_cap)
-               target_state = PCI_D0;
-
        /*
         * If the device is in D3cold even though it's not power-manageable by
         * the platform, it may have been powered down by non-standard means.
         * Best to let it slumber.
         */
        if (dev->current_state == PCI_D3cold)
-               target_state = PCI_D3cold;
+               return PCI_D3cold;
+       else if (!dev->pm_cap)
+               return PCI_D0;
 
        if (wakeup && dev->pme_support) {
-               pci_power_t state = target_state;
+               pci_power_t state = PCI_D3hot;
 
                /*
                 * Find the deepest state from which the device can generate
@@ -2628,7 +2612,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
                        return PCI_D0;
        }
 
-       return target_state;
+       return PCI_D3hot;
 }
 
 /**
@@ -2681,8 +2665,13 @@ EXPORT_SYMBOL(pci_prepare_to_sleep);
  */
 int pci_back_from_sleep(struct pci_dev *dev)
 {
+       int ret = pci_set_power_state(dev, PCI_D0);
+
+       if (ret)
+               return ret;
+
        pci_enable_wake(dev, PCI_D0, false);
-       return pci_set_power_state(dev, PCI_D0);
+       return 0;
 }
 EXPORT_SYMBOL(pci_back_from_sleep);
 
@@ -2842,6 +2831,22 @@ void pci_dev_complete_resume(struct pci_dev *pci_dev)
        spin_unlock_irq(&dev->power.lock);
 }
 
+/**
+ * pci_choose_state - Choose the power state of a PCI device.
+ * @dev: Target PCI device.
+ * @state: Target state for the whole system.
+ *
+ * Returns PCI power state suitable for @dev and @state.
+ */
+pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
+{
+       if (state.event == PM_EVENT_ON)
+               return PCI_D0;
+
+       return pci_target_state(dev, false);
+}
+EXPORT_SYMBOL(pci_choose_state);
+
 void pci_config_pm_runtime_get(struct pci_dev *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -4131,6 +4136,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
  * architectures that have memory mapped IO functions defined (and the
  * PCI_IOBASE value defined) should call this function.
  */
+#ifndef pci_remap_iospace
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 {
 #if defined(PCI_IOBASE) && defined(CONFIG_MMU)
@@ -4154,6 +4160,7 @@ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 #endif
 }
 EXPORT_SYMBOL(pci_remap_iospace);
+#endif
 
 /**
  * pci_unmap_iospace - Unmap the memory mapped I/O space
@@ -5067,12 +5074,13 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
        return pci_parent_bus_reset(dev, probe);
 }
 
-static void pci_dev_lock(struct pci_dev *dev)
+void pci_dev_lock(struct pci_dev *dev)
 {
        pci_cfg_access_lock(dev);
        /* block PM suspend, driver probe, etc. */
        device_lock(&dev->dev);
 }
+EXPORT_SYMBOL_GPL(pci_dev_lock);
 
 /* Return 1 on successful lock, 0 on contention */
 int pci_dev_trylock(struct pci_dev *dev)
@@ -5096,13 +5104,14 @@ EXPORT_SYMBOL_GPL(pci_dev_unlock);
 
 static void pci_dev_save_and_disable(struct pci_dev *dev)
 {
+       struct pci_driver *drv = to_pci_driver(dev->dev.driver);
        const struct pci_error_handlers *err_handler =
-                       dev->driver ? dev->driver->err_handler : NULL;
+                       drv ? drv->err_handler : NULL;
 
        /*
-        * dev->driver->err_handler->reset_prepare() is protected against
-        * races with ->remove() by the device lock, which must be held by
-        * the caller.
+        * drv->err_handler->reset_prepare() is protected against races
+        * with ->remove() by the device lock, which must be held by the
+        * caller.
         */
        if (err_handler && err_handler->reset_prepare)
                err_handler->reset_prepare(dev);
@@ -5127,15 +5136,15 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
 
 static void pci_dev_restore(struct pci_dev *dev)
 {
+       struct pci_driver *drv = to_pci_driver(dev->dev.driver);
        const struct pci_error_handlers *err_handler =
-                       dev->driver ? dev->driver->err_handler : NULL;
+                       drv ? drv->err_handler : NULL;
 
        pci_restore_state(dev);
 
        /*
-        * dev->driver->err_handler->reset_done() is protected against
-        * races with ->remove() by the device lock, which must be held by
-        * the caller.
+        * drv->err_handler->reset_done() is protected against races with
+        * ->remove() by the device lock, which must be held by the caller.
         */
        if (err_handler && err_handler->reset_done)
                err_handler->reset_done(dev);
@@ -5296,7 +5305,7 @@ const struct attribute_group pci_dev_reset_method_attr_group = {
  */
 int __pci_reset_function_locked(struct pci_dev *dev)
 {
-       int i, m, rc = -ENOTTY;
+       int i, m, rc;
 
        might_sleep();
 
@@ -6332,11 +6341,12 @@ EXPORT_SYMBOL_GPL(pci_pr3_present);
  * cannot be left as a userspace activity).  DMA aliases should therefore
  * be configured via quirks, such as the PCI fixup header quirk.
  */
-void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, unsigned nr_devfns)
+void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from,
+                      unsigned int nr_devfns)
 {
        int devfn_to;
 
-       nr_devfns = min(nr_devfns, (unsignedMAX_NR_DEVFNS - devfn_from);
+       nr_devfns = min(nr_devfns, (unsigned int)MAX_NR_DEVFNS - devfn_from);
        devfn_to = devfn_from + nr_devfns - 1;
 
        if (!dev->dma_alias_mask)