diff options
author | Cyrille Pitchen <cyrille.pitchen@free-electrons.com> | 2018-01-30 15:56:50 -0500 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2018-01-31 06:09:32 -0500 |
commit | 3a8f77e48666a39adb3ac4d5ce8261563e039e31 (patch) | |
tree | b5146ef9b6734451c1c246871d63d30808199658 | |
parent | 9de0eec29c07a65c21323f934d84ce164b0d9205 (diff) |
PCI: OF: Add generic function to parse and allocate PCI resources
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>
-rw-r--r-- | drivers/pci/host/pci-host-common.c | 49 | ||||
-rw-r--r-- | drivers/pci/of.c | 51 | ||||
-rw-r--r-- | include/linux/pci.h | 9 |
3 files changed, 62 insertions, 47 deletions
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 44a47d4f0b8f..efd904d93562 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c | |||
@@ -24,50 +24,6 @@ | |||
24 | #include <linux/pci-ecam.h> | 24 | #include <linux/pci-ecam.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | 26 | ||
27 | static int gen_pci_parse_request_of_pci_ranges(struct device *dev, | ||
28 | struct list_head *resources, struct resource **bus_range) | ||
29 | { | ||
30 | int err, res_valid = 0; | ||
31 | struct device_node *np = dev->of_node; | ||
32 | resource_size_t iobase; | ||
33 | struct resource_entry *win, *tmp; | ||
34 | |||
35 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); | ||
36 | if (err) | ||
37 | return err; | ||
38 | |||
39 | err = devm_request_pci_bus_resources(dev, resources); | ||
40 | if (err) | ||
41 | return err; | ||
42 | |||
43 | resource_list_for_each_entry_safe(win, tmp, resources) { | ||
44 | struct resource *res = win->res; | ||
45 | |||
46 | switch (resource_type(res)) { | ||
47 | case IORESOURCE_IO: | ||
48 | err = pci_remap_iospace(res, iobase); | ||
49 | if (err) { | ||
50 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
51 | err, res); | ||
52 | resource_list_destroy_entry(win); | ||
53 | } | ||
54 | break; | ||
55 | case IORESOURCE_MEM: | ||
56 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | ||
57 | break; | ||
58 | case IORESOURCE_BUS: | ||
59 | *bus_range = res; | ||
60 | break; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | if (res_valid) | ||
65 | return 0; | ||
66 | |||
67 | dev_err(dev, "non-prefetchable memory resource required\n"); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | static void gen_pci_unmap_cfg(void *ptr) | 27 | static void gen_pci_unmap_cfg(void *ptr) |
72 | { | 28 | { |
73 | pci_ecam_free((struct pci_config_window *)ptr); | 29 | pci_ecam_free((struct pci_config_window *)ptr); |
@@ -82,9 +38,9 @@ static struct pci_config_window *gen_pci_init(struct device *dev, | |||
82 | struct pci_config_window *cfg; | 38 | struct pci_config_window *cfg; |
83 | 39 | ||
84 | /* Parse our PCI ranges and request their resources */ | 40 | /* Parse our PCI ranges and request their resources */ |
85 | err = gen_pci_parse_request_of_pci_ranges(dev, resources, &bus_range); | 41 | err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range); |
86 | if (err) | 42 | if (err) |
87 | goto err_out; | 43 | return ERR_PTR(err); |
88 | 44 | ||
89 | err = of_address_to_resource(dev->of_node, 0, &cfgres); | 45 | err = of_address_to_resource(dev->of_node, 0, &cfgres); |
90 | if (err) { | 46 | if (err) { |
@@ -135,7 +91,6 @@ int pci_host_common_probe(struct platform_device *pdev, | |||
135 | of_pci_check_probe_only(); | 91 | of_pci_check_probe_only(); |
136 | 92 | ||
137 | /* Parse and map our Configuration Space windows */ | 93 | /* Parse and map our Configuration Space windows */ |
138 | INIT_LIST_HEAD(&resources); | ||
139 | cfg = gen_pci_init(dev, &resources, ops); | 94 | cfg = gen_pci_init(dev, &resources, ops); |
140 | if (IS_ERR(cfg)) | 95 | if (IS_ERR(cfg)) |
141 | return PTR_ERR(cfg); | 96 | return PTR_ERR(cfg); |
diff --git a/drivers/pci/of.c b/drivers/pci/of.c index e112da11630e..54e210501b73 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c | |||
@@ -88,3 +88,54 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus) | |||
88 | return NULL; | 88 | return NULL; |
89 | #endif | 89 | #endif |
90 | } | 90 | } |
91 | |||
92 | int pci_parse_request_of_pci_ranges(struct device *dev, | ||
93 | struct list_head *resources, | ||
94 | struct resource **bus_range) | ||
95 | { | ||
96 | int err, res_valid = 0; | ||
97 | struct device_node *np = dev->of_node; | ||
98 | resource_size_t iobase; | ||
99 | struct resource_entry *win, *tmp; | ||
100 | |||
101 | INIT_LIST_HEAD(resources); | ||
102 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); | ||
103 | if (err) | ||
104 | return err; | ||
105 | |||
106 | err = devm_request_pci_bus_resources(dev, resources); | ||
107 | if (err) | ||
108 | goto out_release_res; | ||
109 | |||
110 | resource_list_for_each_entry_safe(win, tmp, resources) { | ||
111 | struct resource *res = win->res; | ||
112 | |||
113 | switch (resource_type(res)) { | ||
114 | case IORESOURCE_IO: | ||
115 | err = pci_remap_iospace(res, iobase); | ||
116 | if (err) { | ||
117 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
118 | err, res); | ||
119 | resource_list_destroy_entry(win); | ||
120 | } | ||
121 | break; | ||
122 | case IORESOURCE_MEM: | ||
123 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | ||
124 | break; | ||
125 | case IORESOURCE_BUS: | ||
126 | if (bus_range) | ||
127 | *bus_range = res; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | if (res_valid) | ||
133 | return 0; | ||
134 | |||
135 | dev_err(dev, "non-prefetchable memory resource required\n"); | ||
136 | err = -EINVAL; | ||
137 | |||
138 | out_release_res: | ||
139 | pci_free_resource_list(resources); | ||
140 | return err; | ||
141 | } | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index c170c9250c8b..c7a701abbf17 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -2182,6 +2182,9 @@ void pci_release_of_node(struct pci_dev *dev); | |||
2182 | void pci_set_bus_of_node(struct pci_bus *bus); | 2182 | void pci_set_bus_of_node(struct pci_bus *bus); |
2183 | void pci_release_bus_of_node(struct pci_bus *bus); | 2183 | void pci_release_bus_of_node(struct pci_bus *bus); |
2184 | struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus); | 2184 | struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus); |
2185 | int pci_parse_request_of_pci_ranges(struct device *dev, | ||
2186 | struct list_head *resources, | ||
2187 | struct resource **bus_range); | ||
2185 | 2188 | ||
2186 | /* Arch may override this (weak) */ | 2189 | /* Arch may override this (weak) */ |
2187 | struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); | 2190 | struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); |
@@ -2206,6 +2209,12 @@ static inline struct device_node * | |||
2206 | pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; } | 2209 | pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; } |
2207 | static inline struct irq_domain * | 2210 | static inline struct irq_domain * |
2208 | pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; } | 2211 | pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; } |
2212 | static inline int pci_parse_request_of_pci_ranges(struct device *dev, | ||
2213 | struct list_head *resources, | ||
2214 | struct resource **bus_range) | ||
2215 | { | ||
2216 | return -EINVAL; | ||
2217 | } | ||
2209 | #endif /* CONFIG_OF */ | 2218 | #endif /* CONFIG_OF */ |
2210 | 2219 | ||
2211 | #ifdef CONFIG_ACPI | 2220 | #ifdef CONFIG_ACPI |