diff options
author | Liviu Dudau <Liviu.Dudau@arm.com> | 2014-09-29 10:29:25 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-30 19:08:40 -0400 |
commit | 0b0b0893d49b34201a6c4416b1a707b580b91e3d (patch) | |
tree | 6705257f35735ce6bc8c85a760d49227905d6b13 /drivers/of/address.c | |
parent | 83bbde1cc0ec9d156b9271e29ffe0dc89c687feb (diff) |
of/pci: Fix the conversion of IO ranges into IO resources
The ranges property for a host bridge controller in DT describes the
mapping between the PCI bus address and the CPU physical address. The
resources framework however expects that the IO resources start at a pseudo
"port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT. The
conversion from PCI ranges to resources failed to take that into account,
returning a CPU physical address instead of a port number.
Also fix all the drivers that depend on the old behaviour by fetching the
CPU physical address based on the port number where it is being needed.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
CC: Grant Likely <grant.likely@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Simon Horman <horms@verge.net.au>
CC: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r-- | drivers/of/address.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 327a57410797..afdb78299f61 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -295,14 +295,50 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, | |||
295 | } | 295 | } |
296 | EXPORT_SYMBOL_GPL(of_pci_range_parser_one); | 296 | EXPORT_SYMBOL_GPL(of_pci_range_parser_one); |
297 | 297 | ||
298 | void of_pci_range_to_resource(struct of_pci_range *range, | 298 | /* |
299 | struct device_node *np, struct resource *res) | 299 | * of_pci_range_to_resource - Create a resource from an of_pci_range |
300 | * @range: the PCI range that describes the resource | ||
301 | * @np: device node where the range belongs to | ||
302 | * @res: pointer to a valid resource that will be updated to | ||
303 | * reflect the values contained in the range. | ||
304 | * | ||
305 | * Returns EINVAL if the range cannot be converted to resource. | ||
306 | * | ||
307 | * Note that if the range is an IO range, the resource will be converted | ||
308 | * using pci_address_to_pio() which can fail if it is called too early or | ||
309 | * if the range cannot be matched to any host bridge IO space (our case here). | ||
310 | * To guard against that we try to register the IO range first. | ||
311 | * If that fails we know that pci_address_to_pio() will do too. | ||
312 | */ | ||
313 | int of_pci_range_to_resource(struct of_pci_range *range, | ||
314 | struct device_node *np, struct resource *res) | ||
300 | { | 315 | { |
316 | int err; | ||
301 | res->flags = range->flags; | 317 | res->flags = range->flags; |
302 | res->start = range->cpu_addr; | ||
303 | res->end = range->cpu_addr + range->size - 1; | ||
304 | res->parent = res->child = res->sibling = NULL; | 318 | res->parent = res->child = res->sibling = NULL; |
305 | res->name = np->full_name; | 319 | res->name = np->full_name; |
320 | |||
321 | if (res->flags & IORESOURCE_IO) { | ||
322 | unsigned long port; | ||
323 | err = pci_register_io_range(range->cpu_addr, range->size); | ||
324 | if (err) | ||
325 | goto invalid_range; | ||
326 | port = pci_address_to_pio(range->cpu_addr); | ||
327 | if (port == (unsigned long)-1) { | ||
328 | err = -EINVAL; | ||
329 | goto invalid_range; | ||
330 | } | ||
331 | res->start = port; | ||
332 | } else { | ||
333 | res->start = range->cpu_addr; | ||
334 | } | ||
335 | res->end = res->start + range->size - 1; | ||
336 | return 0; | ||
337 | |||
338 | invalid_range: | ||
339 | res->start = (resource_size_t)OF_BAD_ADDR; | ||
340 | res->end = (resource_size_t)OF_BAD_ADDR; | ||
341 | return err; | ||
306 | } | 342 | } |
307 | #endif /* CONFIG_PCI */ | 343 | #endif /* CONFIG_PCI */ |
308 | 344 | ||