OSDN Git Service

Merge tag 'pci-v4.18-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Jul 2018 18:54:04 +0000 (11:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Jul 2018 18:54:04 +0000 (11:54 -0700)
Pull PCI fixes from Bjorn Helgaas:

 - Fix crashes that happen when PHY drivers are left disabled in the V3
   Semiconductor, MediaTek, Faraday, Aardvark, DesignWare, Versatile,
   and X-Gene host controller drivers (Sergei Shtylyov)

 - Fix a NULL pointer dereference in the endpoint library configfs
   support (Kishon Vijay Abraham I)

 - Fix a race condition in Hyper-V IRQ handling (Dexuan Cui)

* tag 'pci-v4.18-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  PCI: v3-semi: Fix I/O space page leak
  PCI: mediatek: Fix I/O space page leak
  PCI: faraday: Fix I/O space page leak
  PCI: aardvark: Fix I/O space page leak
  PCI: designware: Fix I/O space page leak
  PCI: versatile: Fix I/O space page leak
  PCI: xgene: Fix I/O space page leak
  PCI: OF: Fix I/O space page leak
  PCI: endpoint: Fix NULL pointer dereference error when CONFIGFS is disabled
  PCI: hv: Disable/enable IRQs rather than BH in hv_compose_msi_msg()

12 files changed:
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/pci-aardvark.c
drivers/pci/controller/pci-ftpci100.c
drivers/pci/controller/pci-hyperv.c
drivers/pci/controller/pci-v3-semi.c
drivers/pci/controller/pci-versatile.c
drivers/pci/controller/pci-xgene.c
drivers/pci/controller/pcie-mediatek.c
drivers/pci/endpoint/pci-epf-core.c
drivers/pci/of.c
drivers/pci/pci.c
include/linux/pci.h

index 781aa03..29a0575 100644 (file)
@@ -363,7 +363,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
        resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
                switch (resource_type(win->res)) {
                case IORESOURCE_IO:
-                       ret = pci_remap_iospace(win->res, pp->io_base);
+                       ret = devm_pci_remap_iospace(dev, win->res,
+                                                    pp->io_base);
                        if (ret) {
                                dev_warn(dev, "Error %d: failed to map resource %pR\n",
                                         ret, win->res);
index d3172d5..0fae816 100644 (file)
@@ -849,7 +849,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie)
                                             0, 0xF8000000, 0,
                                             lower_32_bits(res->start),
                                             OB_PCIE_IO);
-                       err = pci_remap_iospace(res, iobase);
+                       err = devm_pci_remap_iospace(dev, res, iobase);
                        if (err) {
                                dev_warn(dev, "error %d: failed to map resource %pR\n",
                                         err, res);
index 20bb256..bf5ece5 100644 (file)
@@ -503,7 +503,7 @@ static int faraday_pci_probe(struct platform_device *pdev)
                                dev_err(dev, "illegal IO mem size\n");
                                return -EINVAL;
                        }
-                       ret = pci_remap_iospace(io, io_base);
+                       ret = devm_pci_remap_iospace(dev, io, io_base);
                        if (ret) {
                                dev_warn(dev, "error %d: failed to map resource %pR\n",
                                         ret, io);
index 6cc5036..f6325f1 100644 (file)
@@ -1073,6 +1073,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
        struct pci_bus *pbus;
        struct pci_dev *pdev;
        struct cpumask *dest;
+       unsigned long flags;
        struct compose_comp_ctxt comp;
        struct tran_int_desc *int_desc;
        struct {
@@ -1164,14 +1165,15 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
                 * the channel callback directly when channel->target_cpu is
                 * the current CPU. When the higher level interrupt code
                 * calls us with interrupt enabled, let's add the
-                * local_bh_disable()/enable() to avoid race.
+                * local_irq_save()/restore() to avoid race:
+                * hv_pci_onchannelcallback() can also run in tasklet.
                 */
-               local_bh_disable();
+               local_irq_save(flags);
 
                if (hbus->hdev->channel->target_cpu == smp_processor_id())
                        hv_pci_onchannelcallback(hbus);
 
-               local_bh_enable();
+               local_irq_restore(flags);
 
                if (hpdev->state == hv_pcichild_ejecting) {
                        dev_err_once(&hbus->hdev->device,
index 68b8bfb..d219404 100644 (file)
@@ -537,7 +537,7 @@ static int v3_pci_setup_resource(struct v3_pci *v3,
                v3->io_bus_addr = io->start - win->offset;
                dev_dbg(dev, "I/O window %pR, bus addr %pap\n",
                        io, &v3->io_bus_addr);
-               ret = pci_remap_iospace(io, io_base);
+               ret = devm_pci_remap_iospace(dev, io, io_base);
                if (ret) {
                        dev_warn(dev,
                                 "error %d: failed to map resource %pR\n",
index 994f320..f59ad27 100644 (file)
@@ -82,7 +82,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
 
                switch (resource_type(res)) {
                case IORESOURCE_IO:
-                       err = pci_remap_iospace(res, iobase);
+                       err = devm_pci_remap_iospace(dev, res, iobase);
                        if (err) {
                                dev_warn(dev, "error %d: failed to map resource %pR\n",
                                         err, res);
index d854d67..ffda3e8 100644 (file)
@@ -423,7 +423,7 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
                case IORESOURCE_IO:
                        xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base,
                                                res->start - window->offset);
-                       ret = pci_remap_iospace(res, io_base);
+                       ret = devm_pci_remap_iospace(dev, res, io_base);
                        if (ret < 0)
                                return ret;
                        break;
index 0baabe3..861dda6 100644 (file)
@@ -1109,7 +1109,7 @@ static int mtk_pcie_request_resources(struct mtk_pcie *pcie)
        if (err < 0)
                return err;
 
-       pci_remap_iospace(&pcie->pio, pcie->io.start);
+       devm_pci_remap_iospace(dev, &pcie->pio, pcie->io.start);
 
        return 0;
 }
index bf53fad..825fa24 100644 (file)
@@ -137,25 +137,60 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
 }
 EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
 
-/**
- * pci_epf_unregister_driver() - unregister the PCI EPF driver
- * @driver: the PCI EPF driver that has to be unregistered
- *
- * Invoke to unregister the PCI EPF driver.
- */
-void pci_epf_unregister_driver(struct pci_epf_driver *driver)
+static void pci_epf_remove_cfs(struct pci_epf_driver *driver)
 {
        struct config_group *group, *tmp;
 
+       if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS))
+               return;
+
        mutex_lock(&pci_epf_mutex);
        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);
+}
+
+/**
+ * pci_epf_unregister_driver() - unregister the PCI EPF driver
+ * @driver: the PCI EPF driver that has to be unregistered
+ *
+ * Invoke to unregister the PCI EPF driver.
+ */
+void pci_epf_unregister_driver(struct pci_epf_driver *driver)
+{
+       pci_epf_remove_cfs(driver);
        driver_unregister(&driver->driver);
 }
 EXPORT_SYMBOL_GPL(pci_epf_unregister_driver);
 
+static int pci_epf_add_cfs(struct pci_epf_driver *driver)
+{
+       struct config_group *group;
+       const struct pci_epf_device_id *id;
+
+       if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS))
+               return 0;
+
+       INIT_LIST_HEAD(&driver->epf_group);
+
+       id = driver->id_table;
+       while (id->name[0]) {
+               group = pci_ep_cfs_add_epf_group(id->name);
+               if (IS_ERR(group)) {
+                       pci_epf_remove_cfs(driver);
+                       return PTR_ERR(group);
+               }
+
+               mutex_lock(&pci_epf_mutex);
+               list_add_tail(&group->group_entry, &driver->epf_group);
+               mutex_unlock(&pci_epf_mutex);
+               id++;
+       }
+
+       return 0;
+}
+
 /**
  * __pci_epf_register_driver() - register a new PCI EPF driver
  * @driver: structure representing PCI EPF driver
@@ -167,8 +202,6 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver,
                              struct module *owner)
 {
        int ret;
-       struct config_group *group;
-       const struct pci_epf_device_id *id;
 
        if (!driver->ops)
                return -EINVAL;
@@ -183,16 +216,7 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver,
        if (ret)
                return ret;
 
-       INIT_LIST_HEAD(&driver->epf_group);
-
-       id = driver->id_table;
-       while (id->name[0]) {
-               group = pci_ep_cfs_add_epf_group(id->name);
-               mutex_lock(&pci_epf_mutex);
-               list_add_tail(&group->group_entry, &driver->epf_group);
-               mutex_unlock(&pci_epf_mutex);
-               id++;
-       }
+       pci_epf_add_cfs(driver);
 
        return 0;
 }
index d088c91..69a60d6 100644 (file)
@@ -612,7 +612,7 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
 
                switch (resource_type(res)) {
                case IORESOURCE_IO:
-                       err = pci_remap_iospace(res, iobase);
+                       err = devm_pci_remap_iospace(dev, res, iobase);
                        if (err) {
                                dev_warn(dev, "error %d: failed to map resource %pR\n",
                                         err, res);
index 97acba7..316496e 100644 (file)
@@ -3579,6 +3579,44 @@ void pci_unmap_iospace(struct resource *res)
 }
 EXPORT_SYMBOL(pci_unmap_iospace);
 
+static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
+{
+       struct resource **res = ptr;
+
+       pci_unmap_iospace(*res);
+}
+
+/**
+ * devm_pci_remap_iospace - Managed pci_remap_iospace()
+ * @dev: Generic device to remap IO address for
+ * @res: Resource describing the I/O space
+ * @phys_addr: physical address of range to be mapped
+ *
+ * Managed pci_remap_iospace().  Map is automatically unmapped on driver
+ * detach.
+ */
+int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
+                          phys_addr_t phys_addr)
+{
+       const struct resource **ptr;
+       int error;
+
+       ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       error = pci_remap_iospace(res, phys_addr);
+       if (error) {
+               devres_free(ptr);
+       } else  {
+               *ptr = res;
+               devres_add(dev, ptr);
+       }
+
+       return error;
+}
+EXPORT_SYMBOL(devm_pci_remap_iospace);
+
 /**
  * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
  * @dev: Generic device to remap IO address for
index 340029b..abd5d5e 100644 (file)
@@ -1240,6 +1240,8 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
+                          phys_addr_t phys_addr);
 void pci_unmap_iospace(struct resource *res);
 void __iomem *devm_pci_remap_cfgspace(struct device *dev,
                                      resource_size_t offset,