mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
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 <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Acked-by: Linus Walleij <[email protected]> CC: Grant Likely <[email protected]> CC: Rob Herring <[email protected]> CC: Arnd Bergmann <[email protected]> CC: Thierry Reding <[email protected]> CC: Simon Horman <[email protected]> CC: Catalin Marinas <[email protected]>
This commit is contained in:
parent
83bbde1cc0
commit
0b0b0893d4
5 changed files with 80 additions and 30 deletions
|
|
@ -295,14 +295,50 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
|
||||
|
||||
void of_pci_range_to_resource(struct of_pci_range *range,
|
||||
struct device_node *np, struct resource *res)
|
||||
/*
|
||||
* of_pci_range_to_resource - Create a resource from an of_pci_range
|
||||
* @range: the PCI range that describes the resource
|
||||
* @np: device node where the range belongs to
|
||||
* @res: pointer to a valid resource that will be updated to
|
||||
* reflect the values contained in the range.
|
||||
*
|
||||
* Returns EINVAL if the range cannot be converted to resource.
|
||||
*
|
||||
* Note that if the range is an IO range, the resource will be converted
|
||||
* using pci_address_to_pio() which can fail if it is called too early or
|
||||
* if the range cannot be matched to any host bridge IO space (our case here).
|
||||
* To guard against that we try to register the IO range first.
|
||||
* If that fails we know that pci_address_to_pio() will do too.
|
||||
*/
|
||||
int of_pci_range_to_resource(struct of_pci_range *range,
|
||||
struct device_node *np, struct resource *res)
|
||||
{
|
||||
int err;
|
||||
res->flags = range->flags;
|
||||
res->start = range->cpu_addr;
|
||||
res->end = range->cpu_addr + range->size - 1;
|
||||
res->parent = res->child = res->sibling = NULL;
|
||||
res->name = np->full_name;
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
unsigned long port;
|
||||
err = pci_register_io_range(range->cpu_addr, range->size);
|
||||
if (err)
|
||||
goto invalid_range;
|
||||
port = pci_address_to_pio(range->cpu_addr);
|
||||
if (port == (unsigned long)-1) {
|
||||
err = -EINVAL;
|
||||
goto invalid_range;
|
||||
}
|
||||
res->start = port;
|
||||
} else {
|
||||
res->start = range->cpu_addr;
|
||||
}
|
||||
res->end = res->start + range->size - 1;
|
||||
return 0;
|
||||
|
||||
invalid_range:
|
||||
res->start = (resource_size_t)OF_BAD_ADDR;
|
||||
res->end = (resource_size_t)OF_BAD_ADDR;
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue