PCI: Export pci_dev_lock()
[platform/kernel/linux-starfive.git] / drivers / pci / pci.c
index 39c65b5..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;
 
@@ -1439,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;
@@ -1449,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++]);
@@ -2053,14 +2078,14 @@ void pcim_pin_device(struct pci_dev *pdev)
 EXPORT_SYMBOL(pcim_pin_device);
 
 /*
- * pcibios_add_device - provide arch specific hooks when adding device dev
+ * pcibios_device_add - provide arch specific hooks when adding device dev
  * @dev: the PCI device being added
  *
  * Permits the platform to provide architecture specific functionality when
  * devices are added. This is the default implementation. Architecture
  * implementations can override this.
  */
-int __weak pcibios_add_device(struct pci_dev *dev)
+int __weak pcibios_device_add(struct pci_dev *dev)
 {
        return 0;
 }
@@ -2180,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;
@@ -2187,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.
@@ -3697,6 +3724,14 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
        struct pci_dev *bridge;
        u32 cap, ctl2;
 
+       /*
+        * Per PCIe r5.0, sec 9.3.5.10, the AtomicOp Requester Enable bit
+        * in Device Control 2 is reserved in VFs and the PF value applies
+        * to all associated VFs.
+        */
+       if (dev->is_virtfn)
+               return -EINVAL;
+
        if (!pci_is_pcie(dev))
                return -EINVAL;
 
@@ -5039,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)
@@ -5068,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);
@@ -5099,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);
@@ -5268,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();
 
@@ -6304,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)