diff options
Diffstat (limited to 'drivers/pci/of_property.c')
-rw-r--r-- | drivers/pci/of_property.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c index c2c7334152bc..58fbafac7c6a 100644 --- a/drivers/pci/of_property.c +++ b/drivers/pci/of_property.c @@ -26,7 +26,7 @@ struct of_pci_addr_pair { * side and the child address is the corresponding address on the secondary * side. */ -struct of_pci_range { +struct of_pci_range_entry { u32 child_addr[OF_PCI_ADDRESS_CELLS]; u32 parent_addr[OF_PCI_ADDRESS_CELLS]; u32 size[OF_PCI_SIZE_CELLS]; @@ -101,7 +101,7 @@ static int of_pci_prop_bus_range(struct pci_dev *pdev, static int of_pci_prop_ranges(struct pci_dev *pdev, struct of_changeset *ocs, struct device_node *np) { - struct of_pci_range *rp; + struct of_pci_range_entry *rp; struct resource *res; int i, j, ret; u32 flags, num; @@ -126,7 +126,7 @@ static int of_pci_prop_ranges(struct pci_dev *pdev, struct of_changeset *ocs, if (of_pci_get_addr_flags(&res[j], &flags)) continue; - val64 = res[j].start; + val64 = pci_bus_address(pdev, &res[j] - pdev->resource); of_pci_set_address(pdev, rp[i].parent_addr, val64, 0, flags, false); if (pci_is_bridge(pdev)) { @@ -183,6 +183,26 @@ static int of_pci_prop_interrupts(struct pci_dev *pdev, return of_changeset_add_prop_u32(ocs, np, "interrupts", (u32)pin); } +static int of_pci_prop_intr_ctrl(struct pci_dev *pdev, struct of_changeset *ocs, + struct device_node *np) +{ + int ret; + u8 pin; + + ret = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (ret != 0) + return ret; + + if (!pin) + return 0; + + ret = of_changeset_add_prop_u32(ocs, np, "#interrupt-cells", 1); + if (ret) + return ret; + + return of_changeset_add_prop_bool(ocs, np, "interrupt-controller"); +} + static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, struct device_node *np) { @@ -238,6 +258,8 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, return 0; int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL); + if (!int_map) + return -ENOMEM; mapp = int_map; list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { @@ -334,6 +356,10 @@ int of_pci_add_properties(struct pci_dev *pdev, struct of_changeset *ocs, ret = of_pci_prop_intr_map(pdev, ocs, np); if (ret) return ret; + } else { + ret = of_pci_prop_intr_ctrl(pdev, ocs, np); + if (ret) + return ret; } ret = of_pci_prop_ranges(pdev, ocs, np); |