Merge tag 'pci-v4.18-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Jul 2018 17:55:21 +0000 (10:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Jul 2018 17:55:21 +0000 (10:55 -0700)
Pull PCI fixes from Bjorn Helgaas:

 - Fix a use-after-free in the endpoint code (Dan Carpenter)

 - Stop defaulting CONFIG_PCIE_DW_PLAT_HOST to yes (Geert Uytterhoeven)

 - Fix an nfp regression caused by a change in how we limit the number
   of VFs we can enable (Jakub Kicinski)

 - Fix failure path cleanup issues in the new R-Car gen3 PHY support
   (Marek Vasut)

 - Fix leaks of OF nodes in faraday, xilinx-nwl, xilinx (Nicholas Mc
   Guire)

* tag 'pci-v4.18-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  nfp: stop limiting VFs to 0
  PCI/IOV: Reset total_VFs limit after detaching PF driver
  PCI: faraday: Add missing of_node_put()
  PCI: xilinx-nwl: Add missing of_node_put()
  PCI: xilinx: Add missing of_node_put()
  PCI: endpoint: Use after free in pci_epf_unregister_driver()
  PCI: controller: dwc: Do not let PCIE_DW_PLAT_HOST default to yes
  PCI: rcar: Clean up PHY init on failure
  PCI: rcar: Shut the PHY down in failpath

drivers/net/ethernet/netronome/nfp/nfp_main.c
drivers/pci/controller/dwc/Kconfig
drivers/pci/controller/pci-ftpci100.c
drivers/pci/controller/pcie-rcar.c
drivers/pci/controller/pcie-xilinx-nwl.c
drivers/pci/controller/pcie-xilinx.c
drivers/pci/endpoint/pci-epf-core.c
drivers/pci/iov.c
drivers/pci/pci-driver.c
drivers/pci/pci.h

index 46b76d5a726c6ade2c48c000172a3d9ba9db7253..152283d7e59c8f4a7a69b45f520a7c9625e9ce16 100644 (file)
@@ -240,7 +240,6 @@ static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
                return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
 
        pf->limit_vfs = ~0;
-       pci_sriov_set_totalvfs(pf->pdev, 0); /* 0 is unset */
        /* Allow any setting for backwards compatibility if symbol not found */
        if (err == -ENOENT)
                return 0;
@@ -668,7 +667,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
 
        err = nfp_net_pci_probe(pf);
        if (err)
-               goto err_sriov_unlimit;
+               goto err_fw_unload;
 
        err = nfp_hwmon_register(pf);
        if (err) {
@@ -680,8 +679,6 @@ static int nfp_pci_probe(struct pci_dev *pdev,
 
 err_net_remove:
        nfp_net_pci_remove(pf);
-err_sriov_unlimit:
-       pci_sriov_set_totalvfs(pf->pdev, 0);
 err_fw_unload:
        kfree(pf->rtbl);
        nfp_mip_close(pf->mip);
@@ -715,7 +712,6 @@ static void nfp_pci_remove(struct pci_dev *pdev)
        nfp_hwmon_unregister(pf);
 
        nfp_pcie_sriov_disable(pdev);
-       pci_sriov_set_totalvfs(pf->pdev, 0);
 
        nfp_net_pci_remove(pf);
 
index 16f52c626b4bd5101afd9c517b48dc6ca014f082..91b0194240a57e8f1d1d78ab682f20135002a68d 100644 (file)
@@ -58,7 +58,6 @@ config PCIE_DW_PLAT_HOST
        depends on PCI && PCI_MSI_IRQ_DOMAIN
        select PCIE_DW_HOST
        select PCIE_DW_PLAT
-       default y
        help
          Enables support for the PCIe controller in the Designware IP to
          work in host mode. There are two instances of PCIe controller in
index a1ebe9ed441f0aef256a55393bf296b44f08c9d6..20bb2564a6b3c1a785c4e7c245a00e62e01d87ea 100644 (file)
@@ -355,11 +355,13 @@ static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
        irq = of_irq_get(intc, 0);
        if (irq <= 0) {
                dev_err(p->dev, "failed to get parent IRQ\n");
+               of_node_put(intc);
                return irq ?: -EINVAL;
        }
 
        p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX,
                                             &faraday_pci_irqdomain_ops, p);
+       of_node_put(intc);
        if (!p->irqdomain) {
                dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n");
                return -EINVAL;
index 874d75c9ee4ac44513f584267272253d4cf84e7d..c8febb009454cdcfc0ed473f4cdb9540af0de59e 100644 (file)
@@ -680,7 +680,11 @@ static int rcar_pcie_phy_init_gen3(struct rcar_pcie *pcie)
        if (err)
                return err;
 
-       return phy_power_on(pcie->phy);
+       err = phy_power_on(pcie->phy);
+       if (err)
+               phy_exit(pcie->phy);
+
+       return err;
 }
 
 static int rcar_msi_alloc(struct rcar_msi *chip)
@@ -1165,7 +1169,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
        if (rcar_pcie_hw_init(pcie)) {
                dev_info(dev, "PCIe link down\n");
                err = -ENODEV;
-               goto err_clk_disable;
+               goto err_phy_shutdown;
        }
 
        data = rcar_pci_read_reg(pcie, MACSR);
@@ -1177,7 +1181,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
                        dev_err(dev,
                                "failed to enable MSI support: %d\n",
                                err);
-                       goto err_clk_disable;
+                       goto err_phy_shutdown;
                }
        }
 
@@ -1191,6 +1195,12 @@ err_msi_teardown:
        if (IS_ENABLED(CONFIG_PCI_MSI))
                rcar_pcie_teardown_msi(pcie);
 
+err_phy_shutdown:
+       if (pcie->phy) {
+               phy_power_off(pcie->phy);
+               phy_exit(pcie->phy);
+       }
+
 err_clk_disable:
        clk_disable_unprepare(pcie->bus_clk);
 
index 6a4bbb5b3de006f37f005bf0f198b28de16c7619..fb32840ce8e66ac75f7c164a402ac9a0e0ae094b 100644 (file)
@@ -559,7 +559,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
                                                        PCI_NUM_INTX,
                                                        &legacy_domain_ops,
                                                        pcie);
-
+       of_node_put(legacy_intc_node);
        if (!pcie->legacy_irq_domain) {
                dev_err(dev, "failed to create IRQ domain\n");
                return -ENOMEM;
index b110a3a814e35e3bbd7839e68994cef56f19ed43..7b1389d8e2a5711383a4e8d8a6a424a4a33448f4 100644 (file)
@@ -509,6 +509,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
        port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
                                                 &intx_domain_ops,
                                                 port);
+       of_node_put(pcie_intc_node);
        if (!port->leg_domain) {
                dev_err(dev, "Failed to get a INTx IRQ domain\n");
                return -ENODEV;
index 523a8cab3bfba16613a03d13916aef3b223ef2cb..bf53fad636a5076dca0c5b564085a53621d37a9b 100644 (file)
@@ -145,10 +145,10 @@ EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
  */
 void pci_epf_unregister_driver(struct pci_epf_driver *driver)
 {
-       struct config_group *group;
+       struct config_group *group, *tmp;
 
        mutex_lock(&pci_epf_mutex);
-       list_for_each_entry(group, &driver->epf_group, group_entry)
+       list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry)
                pci_ep_cfs_remove_epf_group(group);
        list_del(&driver->epf_group);
        mutex_unlock(&pci_epf_mutex);
index d0d73dbbd5ca4123fce20254a0bf6495dcbe1d9e..0f04ae648cf14bcc590ce55b5b91a5635b02c500 100644 (file)
@@ -574,6 +574,22 @@ void pci_iov_release(struct pci_dev *dev)
                sriov_release(dev);
 }
 
+/**
+ * pci_iov_remove - clean up SR-IOV state after PF driver is detached
+ * @dev: the PCI device
+ */
+void pci_iov_remove(struct pci_dev *dev)
+{
+       struct pci_sriov *iov = dev->sriov;
+
+       if (!dev->is_physfn)
+               return;
+
+       iov->driver_max_VFs = iov->total_VFs;
+       if (iov->num_VFs)
+               pci_warn(dev, "driver left SR-IOV enabled after remove\n");
+}
+
 /**
  * pci_iov_update_resource - update a VF BAR
  * @dev: the PCI device
index c125d53033c69cafe42734c32935561547abbdba..6792292b5fc7055ab145703a3e718e50d0d4751c 100644 (file)
@@ -445,6 +445,7 @@ static int pci_device_remove(struct device *dev)
                }
                pcibios_free_irq(pci_dev);
                pci_dev->driver = NULL;
+               pci_iov_remove(pci_dev);
        }
 
        /* Undo the runtime PM settings in local_pci_probe() */
index c358e7a07f3faf2abbfff9de4b9e219ae6558e58..882f1f9596dfffa644e624b3a42a120999f06581 100644 (file)
@@ -311,6 +311,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
 #ifdef CONFIG_PCI_IOV
 int pci_iov_init(struct pci_dev *dev);
 void pci_iov_release(struct pci_dev *dev);
+void pci_iov_remove(struct pci_dev *dev);
 void pci_iov_update_resource(struct pci_dev *dev, int resno);
 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 void pci_restore_iov_state(struct pci_dev *dev);
@@ -323,6 +324,9 @@ static inline int pci_iov_init(struct pci_dev *dev)
 }
 static inline void pci_iov_release(struct pci_dev *dev)
 
+{
+}
+static inline void pci_iov_remove(struct pci_dev *dev)
 {
 }
 static inline void pci_restore_iov_state(struct pci_dev *dev)