]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PCI: OF: Add generic function to parse and allocate PCI resources
authorCyrille Pitchen <cyrille.pitchen@free-electrons.com>
Tue, 30 Jan 2018 20:56:50 +0000 (21:56 +0100)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Wed, 31 Jan 2018 11:09:32 +0000 (11:09 +0000)
The patch moves the gen_pci_parse_request_of_pci_ranges() function from
drivers/pci/host/pci-host-common.c into drivers/pci/of.c to easily share
common source code between PCI host drivers.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
drivers/pci/host/pci-host-common.c
drivers/pci/of.c
include/linux/pci.h

index 44a47d4f0b8f294fef5c2b2482b0a16856849f01..efd904d93562abef741da4785c09aab19400908f 100644 (file)
 #include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
-static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
-                      struct list_head *resources, struct resource **bus_range)
-{
-       int err, res_valid = 0;
-       struct device_node *np = dev->of_node;
-       resource_size_t iobase;
-       struct resource_entry *win, *tmp;
-
-       err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
-       if (err)
-               return err;
-
-       err = devm_request_pci_bus_resources(dev, resources);
-       if (err)
-               return err;
-
-       resource_list_for_each_entry_safe(win, tmp, resources) {
-               struct resource *res = win->res;
-
-               switch (resource_type(res)) {
-               case IORESOURCE_IO:
-                       err = pci_remap_iospace(res, iobase);
-                       if (err) {
-                               dev_warn(dev, "error %d: failed to map resource %pR\n",
-                                        err, res);
-                               resource_list_destroy_entry(win);
-                       }
-                       break;
-               case IORESOURCE_MEM:
-                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
-                       break;
-               case IORESOURCE_BUS:
-                       *bus_range = res;
-                       break;
-               }
-       }
-
-       if (res_valid)
-               return 0;
-
-       dev_err(dev, "non-prefetchable memory resource required\n");
-       return -EINVAL;
-}
-
 static void gen_pci_unmap_cfg(void *ptr)
 {
        pci_ecam_free((struct pci_config_window *)ptr);
@@ -82,9 +38,9 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
        struct pci_config_window *cfg;
 
        /* Parse our PCI ranges and request their resources */
-       err = gen_pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
+       err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
        if (err)
-               goto err_out;
+               return ERR_PTR(err);
 
        err = of_address_to_resource(dev->of_node, 0, &cfgres);
        if (err) {
@@ -135,7 +91,6 @@ int pci_host_common_probe(struct platform_device *pdev,
        of_pci_check_probe_only();
 
        /* Parse and map our Configuration Space windows */
-       INIT_LIST_HEAD(&resources);
        cfg = gen_pci_init(dev, &resources, ops);
        if (IS_ERR(cfg))
                return PTR_ERR(cfg);
index e112da11630ee46803fc14d02f979c079c70ba79..54e210501b73a179d2ee25714621ccfacb9ab876 100644 (file)
@@ -88,3 +88,54 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
        return NULL;
 #endif
 }
+
+int pci_parse_request_of_pci_ranges(struct device *dev,
+                                   struct list_head *resources,
+                                   struct resource **bus_range)
+{
+       int err, res_valid = 0;
+       struct device_node *np = dev->of_node;
+       resource_size_t iobase;
+       struct resource_entry *win, *tmp;
+
+       INIT_LIST_HEAD(resources);
+       err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
+       if (err)
+               return err;
+
+       err = devm_request_pci_bus_resources(dev, resources);
+       if (err)
+               goto out_release_res;
+
+       resource_list_for_each_entry_safe(win, tmp, resources) {
+               struct resource *res = win->res;
+
+               switch (resource_type(res)) {
+               case IORESOURCE_IO:
+                       err = pci_remap_iospace(res, iobase);
+                       if (err) {
+                               dev_warn(dev, "error %d: failed to map resource %pR\n",
+                                        err, res);
+                               resource_list_destroy_entry(win);
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+                       break;
+               case IORESOURCE_BUS:
+                       if (bus_range)
+                               *bus_range = res;
+                       break;
+               }
+       }
+
+       if (res_valid)
+               return 0;
+
+       dev_err(dev, "non-prefetchable memory resource required\n");
+       err = -EINVAL;
+
+ out_release_res:
+       pci_free_resource_list(resources);
+       return err;
+}
index c170c9250c8b706e62e00f4b6a26149735bacba5..c7a701abbf179609c3da0773543b7a57a4b87dda 100644 (file)
@@ -2182,6 +2182,9 @@ void pci_release_of_node(struct pci_dev *dev);
 void pci_set_bus_of_node(struct pci_bus *bus);
 void pci_release_bus_of_node(struct pci_bus *bus);
 struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
+int pci_parse_request_of_pci_ranges(struct device *dev,
+                                   struct list_head *resources,
+                                   struct resource **bus_range);
 
 /* Arch may override this (weak) */
 struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
@@ -2206,6 +2209,12 @@ static inline struct device_node *
 pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; }
 static inline struct irq_domain *
 pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
+static inline int pci_parse_request_of_pci_ranges(struct device *dev,
+                                                 struct list_head *resources,
+                                                 struct resource **bus_range)
+{
+       return -EINVAL;
+}
 #endif  /* CONFIG_OF */
 
 #ifdef CONFIG_ACPI