aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/host/pci-host-generic.c120
1 files changed, 27 insertions, 93 deletions
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 1e1a80fc6faa..18959075d164 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops {
32 32
33struct gen_pci_cfg_windows { 33struct gen_pci_cfg_windows {
34 struct resource res; 34 struct resource res;
35 struct resource bus_range; 35 struct resource *bus_range;
36 void __iomem **win; 36 void __iomem **win;
37 37
38 const struct gen_pci_cfg_bus_ops *ops; 38 const struct gen_pci_cfg_bus_ops *ops;
@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
50{ 50{
51 struct pci_sys_data *sys = bus->sysdata; 51 struct pci_sys_data *sys = bus->sysdata;
52 struct gen_pci *pci = sys->private_data; 52 struct gen_pci *pci = sys->private_data;
53 resource_size_t idx = bus->number - pci->cfg.bus_range.start; 53 resource_size_t idx = bus->number - pci->cfg.bus_range->start;
54 54
55 return pci->cfg.win[idx] + ((devfn << 8) | where); 55 return pci->cfg.win[idx] + ((devfn << 8) | where);
56} 56}
@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
66{ 66{
67 struct pci_sys_data *sys = bus->sysdata; 67 struct pci_sys_data *sys = bus->sysdata;
68 struct gen_pci *pci = sys->private_data; 68 struct gen_pci *pci = sys->private_data;
69 resource_size_t idx = bus->number - pci->cfg.bus_range.start; 69 resource_size_t idx = bus->number - pci->cfg.bus_range->start;
70 70
71 return pci->cfg.win[idx] + ((devfn << 12) | where); 71 return pci->cfg.win[idx] + ((devfn << 12) | where);
72} 72}
@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = {
138}; 138};
139MODULE_DEVICE_TABLE(of, gen_pci_of_match); 139MODULE_DEVICE_TABLE(of, gen_pci_of_match);
140 140
141static int gen_pci_calc_io_offset(struct device *dev,
142 struct of_pci_range *range,
143 struct resource *res,
144 resource_size_t *offset)
145{
146 static atomic_t wins = ATOMIC_INIT(0);
147 int err, idx, max_win;
148 unsigned int window;
149
150 if (!PAGE_ALIGNED(range->cpu_addr))
151 return -EINVAL;
152
153 max_win = (IO_SPACE_LIMIT + 1) / SZ_64K;
154 idx = atomic_inc_return(&wins);
155 if (idx > max_win)
156 return -ENOSPC;
157
158 window = (idx - 1) * SZ_64K;
159 err = pci_ioremap_io(window, range->cpu_addr);
160 if (err)
161 return err;
162
163 of_pci_range_to_resource(range, dev->of_node, res);
164 res->start = window;
165 res->end = res->start + range->size - 1;
166 *offset = window - range->pci_addr;
167 return 0;
168}
169
170static int gen_pci_calc_mem_offset(struct device *dev,
171 struct of_pci_range *range,
172 struct resource *res,
173 resource_size_t *offset)
174{
175 of_pci_range_to_resource(range, dev->of_node, res);
176 *offset = range->cpu_addr - range->pci_addr;
177 return 0;
178}
179
180static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) 141static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
181{ 142{
182 struct pci_host_bridge_window *win;
183
184 list_for_each_entry(win, &pci->resources, list)
185 release_resource(win->res);
186
187 pci_free_resource_list(&pci->resources); 143 pci_free_resource_list(&pci->resources);
188} 144}
189 145
190static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) 146static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
191{ 147{
192 struct of_pci_range range;
193 struct of_pci_range_parser parser;
194 int err, res_valid = 0; 148 int err, res_valid = 0;
195 struct device *dev = pci->host.dev.parent; 149 struct device *dev = pci->host.dev.parent;
196 struct device_node *np = dev->of_node; 150 struct device_node *np = dev->of_node;
151 resource_size_t iobase;
152 struct pci_host_bridge_window *win;
197 153
198 if (of_pci_range_parser_init(&parser, np)) { 154 err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
199 dev_err(dev, "missing \"ranges\" property\n"); 155 &iobase);
200 return -EINVAL; 156 if (err)
201 } 157 return err;
202 158
203 for_each_of_pci_range(&parser, &range) { 159 list_for_each_entry(win, &pci->resources, list) {
204 struct resource *parent, *res; 160 struct resource *parent, *res = win->res;
205 resource_size_t offset;
206 u32 restype = range.flags & IORESOURCE_TYPE_BITS;
207 161
208 res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); 162 switch (resource_type(res)) {
209 if (!res) {
210 err = -ENOMEM;
211 goto out_release_res;
212 }
213
214 switch (restype) {
215 case IORESOURCE_IO: 163 case IORESOURCE_IO:
216 parent = &ioport_resource; 164 parent = &ioport_resource;
217 err = gen_pci_calc_io_offset(dev, &range, res, &offset); 165 err = pci_remap_iospace(res, iobase);
166 if (err) {
167 dev_warn(dev, "error %d: failed to map resource %pR\n",
168 err, res);
169 continue;
170 }
218 break; 171 break;
219 case IORESOURCE_MEM: 172 case IORESOURCE_MEM:
220 parent = &iomem_resource; 173 parent = &iomem_resource;
221 err = gen_pci_calc_mem_offset(dev, &range, res, &offset); 174 res_valid |= !(res->flags & IORESOURCE_PREFETCH);
222 res_valid |= !(res->flags & IORESOURCE_PREFETCH || err);
223 break; 175 break;
176 case IORESOURCE_BUS:
177 pci->cfg.bus_range = res;
224 default: 178 default:
225 err = -EINVAL;
226 continue; 179 continue;
227 } 180 }
228 181
229 if (err) { 182 err = devm_request_resource(dev, parent, res);
230 dev_warn(dev,
231 "error %d: failed to add resource [type 0x%x, %lld bytes]\n",
232 err, restype, range.size);
233 continue;
234 }
235
236 err = request_resource(parent, res);
237 if (err) 183 if (err)
238 goto out_release_res; 184 goto out_release_res;
239
240 pci_add_resource_offset(&pci->resources, res, offset);
241 } 185 }
242 186
243 if (!res_valid) { 187 if (!res_valid) {
@@ -262,14 +206,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
262 struct device *dev = pci->host.dev.parent; 206 struct device *dev = pci->host.dev.parent;
263 struct device_node *np = dev->of_node; 207 struct device_node *np = dev->of_node;
264 208
265 if (of_pci_parse_bus_range(np, &pci->cfg.bus_range))
266 pci->cfg.bus_range = (struct resource) {
267 .name = np->name,
268 .start = 0,
269 .end = 0xff,
270 .flags = IORESOURCE_BUS,
271 };
272
273 err = of_address_to_resource(np, 0, &pci->cfg.res); 209 err = of_address_to_resource(np, 0, &pci->cfg.res);
274 if (err) { 210 if (err) {
275 dev_err(dev, "missing \"reg\" property\n"); 211 dev_err(dev, "missing \"reg\" property\n");
@@ -277,12 +213,12 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
277 } 213 }
278 214
279 /* Limit the bus-range to fit within reg */ 215 /* Limit the bus-range to fit within reg */
280 bus_max = pci->cfg.bus_range.start + 216 bus_max = pci->cfg.bus_range->start +
281 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; 217 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
282 pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, 218 pci->cfg.bus_range->end = min_t(resource_size_t,
283 bus_max); 219 pci->cfg.bus_range->end, bus_max);
284 220
285 pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), 221 pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
286 sizeof(*pci->cfg.win), GFP_KERNEL); 222 sizeof(*pci->cfg.win), GFP_KERNEL);
287 if (!pci->cfg.win) 223 if (!pci->cfg.win)
288 return -ENOMEM; 224 return -ENOMEM;
@@ -293,7 +229,7 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
293 "Configuration Space")) 229 "Configuration Space"))
294 return -ENOMEM; 230 return -ENOMEM;
295 231
296 bus_range = &pci->cfg.bus_range; 232 bus_range = pci->cfg.bus_range;
297 for (busn = bus_range->start; busn <= bus_range->end; ++busn) { 233 for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
298 u32 idx = busn - bus_range->start; 234 u32 idx = busn - bus_range->start;
299 u32 sz = 1 << pci->cfg.ops->bus_shift; 235 u32 sz = 1 << pci->cfg.ops->bus_shift;
@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
305 return -ENOMEM; 241 return -ENOMEM;
306 } 242 }
307 243
308 /* Register bus resource */
309 pci_add_resource(&pci->resources, bus_range);
310 return 0; 244 return 0;
311} 245}
312 246