PCI: mvebu: Fix PCI I/O mapping creation sequence
Subsystems (3)
Thomas Petazzoni
maintainerPATCH 1/1 PCI: mvebu: Fix PCI I/O mapping creation sequence
Commit ee1604381a371 ("PCI: mvebu: Only remap I/O space if configured") had the side effect that the PCI I/O mapping was created much earlier than before, at a point where the probe() of the driver could still fail. This is for example a problem if one gets an -EPROBE_DEFER at some point during probe(), after pci_ioremap_io() has been called.
Indeed, there is currently no function to undo what pci_ioremap_io() did, and switching to pci_remap_iospace() is not an option in pci-mvebu due to the need for special memory attributes on Armada 38x.
Reverting ee1604381a371 ("PCI: mvebu: Only remap I/O space if configured") would be a possibility, but it would require also reverting 42342073e38b5 ("PCI: mvebu: Convert to use pci_host_bridge directly"). So instead, we use an open-coded version of pci_host_probe() that creates the PCI I/O mapping at a point where we are guaranteed not to fail anymore.
--- drivers/pci/controller/pci-mvebu.c | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)
drivers/pci/controller/pci-mvebu.c +48 -4
@@ -1145,7 +1145,6 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) {struct device *dev = &pcie->pdev->dev;struct device_node *np = dev->of_node; -unsigned int i;int ret;INIT_LIST_HEAD (&pcie->resources);
@@ -1179,13 +1178,58 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) resource_size(&pcie->io) - 1); pcie->realio.name ="PCI I/O" ; +pci_add_resource (&pcie->resources, &pcie->realio); + } + +return devm_request_pci_bus_resources (dev, &pcie->resources); +} + +/* +* This is a copy of pci_host_probe(), except that it does the I/O +* remap as the last step, once we are sure we won't fail. +* +* It should be removed once the I/O remap error handling issue has +* been sorted out. +*/ +static int mvebu_pci_host_probe (struct pci_host_bridge *bridge) +{ +struct mvebu_pcie *pcie; +struct pci_bus *bus, *child; +int ret; + + ret =pci_scan_root_bus_bridge (bridge); +if (ret <0 ) { +dev_err (bridge->dev.parent,"Scanning root bridge failed" ); +return ret; + } + + pcie =pci_host_bridge_priv (bridge); +if (resource_size (&pcie->io) !=0 ) { +unsigned int i; +for (i =0 ; i <resource_size (&pcie->realio); i +=SZ_64K )pci_ioremap_io (i, pcie->io.start + i); + } -pci_add_resource (&pcie->resources, &pcie->realio); + bus = bridge->bus; + +/* +* We insert PCI resources into the iomem_resource and +* ioport_resource trees in either pci_bus_claim_resources() +* or pci_bus_assign_resources(). +*/ +if (pci_has_flag (PCI_PROBE_ONLY )) { +pci_bus_claim_resources (bus); + }else { +pci_bus_size_bridges (bus); +pci_bus_assign_resources (bus); + +list_for_each_entry (child, &bus->children, node) +pcie_bus_configure_settings (child); } -return devm_request_pci_bus_resources (dev, &pcie->resources); +pci_bus_add_devices (bus); +return 0 ; }static int mvebu_pcie_probe (struct platform_device *pdev)
@@ -1268,7 +1312,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) bridge->align_resource = mvebu_pcie_align_resource; bridge->msi = pcie->msi; -return pci_host_probe (bridge); +return mvebu_pci_host_probe (bridge); }static const struct of_device_id mvebu_pcie_of_match_table[] = {
Signature · 1 line
2.14.4
PATCH 1/1 PCI: mvebu: Fix PCI I/O mapping creation sequence
Quoted 18 lines · Thomas Petazzoni
Commit
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") had the side effect that the PCI I/O mapping was created much earlier than before, at a point where theprobe()of the driver could still fail. This is for example a problem if one gets an -EPROBE_DEFER at some point duringprobe(), afterpci_ioremap_io()has been called.Indeed, there is currently no function to undo what
pci_ioremap_io()did, and switching topci_remap_iospace()is not an option in pci-mvebu due to the need for special memory attributes on Armada 38x.Reverting
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") would be a possibility, but it would require also reverting42342073e38b5("PCI: mvebu: Convert to usepci_host_bridgedirectly"). So instead, we use an open-coded version ofpci_host_probe()that creates the PCI I/O mapping at a point where we are guaranteed not to fail anymore.
Quoted 6 lines
Reported-by Jan Kundrát <[email protected]>Fixes ee1604381a371 ("PCI: mvebu: Only remap I/O space if configured")Signed-off-by Thomas Petazzoni <[email protected]>--- drivers/pci/controller/pci-mvebu.c | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)
Thank you Thomas.
Bjorn, is it possible please to send this patch for -rc7 ? It is a regression we introduced in the last cycle.
Thanks,
Lorenzo
Quoted 85 lines
drivers/pci/controller/pci-mvebu.c +48
-4@@ -1145,7 +1145,6 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) {struct device *dev = &pcie->pdev->dev;struct device_node *np = dev->of_node; -unsigned int i;int ret;INIT_LIST_HEAD (&pcie->resources);@@ -1179,13 +1178,58 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) resource_size(&pcie->io) - 1); pcie->realio.name ="PCI I/O" ; +pci_add_resource (&pcie->resources, &pcie->realio); + } + +return devm_request_pci_bus_resources (dev, &pcie->resources); +} + +/* +* This is a copy of pci_host_probe(), except that it does the I/O +* remap as the last step, once we are sure we won't fail. +* +* It should be removed once the I/O remap error handling issue has +* been sorted out. +*/ +static int mvebu_pci_host_probe (struct pci_host_bridge *bridge) +{ +struct mvebu_pcie *pcie; +struct pci_bus *bus, *child; +int ret; + + ret =pci_scan_root_bus_bridge (bridge); +if (ret <0 ) { +dev_err (bridge->dev.parent,"Scanning root bridge failed" ); +return ret; + } + + pcie =pci_host_bridge_priv (bridge); +if (resource_size (&pcie->io) !=0 ) { +unsigned int i; +for (i =0 ; i <resource_size (&pcie->realio); i +=SZ_64K )pci_ioremap_io (i, pcie->io.start + i); + } -pci_add_resource (&pcie->resources, &pcie->realio); + bus = bridge->bus; + +/* +* We insert PCI resources into the iomem_resource and +* ioport_resource trees in either pci_bus_claim_resources() +* or pci_bus_assign_resources(). +*/ +if (pci_has_flag (PCI_PROBE_ONLY )) { +pci_bus_claim_resources (bus); + }else { +pci_bus_size_bridges (bus); +pci_bus_assign_resources (bus); + +list_for_each_entry (child, &bus->children, node) +pcie_bus_configure_settings (child); } -return devm_request_pci_bus_resources (dev, &pcie->resources); +pci_bus_add_devices (bus); +return 0 ; }static int mvebu_pcie_probe (struct platform_device *pdev)@@ -1268,7 +1312,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) bridge->align_resource = mvebu_pcie_align_resource; bridge->msi = pcie->msi; -return pci_host_probe (bridge); +return mvebu_pci_host_probe (bridge); }static const struct of_device_id mvebu_pcie_of_match_table[] = {Signature · 1 line
2.14.4
PATCH 1/1 PCI: mvebu: Fix PCI I/O mapping creation sequence
In reply to Thomas PetazzoniQuoted 18 lines · Thomas Petazzoni
Commit
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") had the side effect that the PCI I/O mapping was created much earlier than before, at a point where theprobe()of the driver could still fail. This is for example a problem if one gets an -EPROBE_DEFER at some point duringprobe(), afterpci_ioremap_io()has been called.Indeed, there is currently no function to undo what
pci_ioremap_io()did, and switching topci_remap_iospace()is not an option in pci-mvebu due to the need for special memory attributes on Armada 38x.Reverting
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") would be a possibility, but it would require also reverting42342073e38b5("PCI: mvebu: Convert to usepci_host_bridgedirectly"). So instead, we use an open-coded version ofpci_host_probe()that creates the PCI I/O mapping at a point where we are guaranteed not to fail anymore.
Quoted 3 lines
Reported-by Jan Kundr?t <[email protected]>Fixes ee1604381a371 ("PCI: mvebu: Only remap I/O space if configured")Signed-off-by Thomas Petazzoni <[email protected]>
Just a rebuild-and-boot test. We don't use any PCIe devices yet, but I'll grab an ugly eBay converter and try this patch with a normal PCIe card later.
Thanks!
Jan
PATCH 1/1 PCI: mvebu: Fix PCI I/O mapping creation sequence
Quoted 3 lines
Just a rebuild-and-boot test. We don't use any PCIe devices yet, but I'll grab an ugly eBay converter and try this patch with a normal PCIe card later.
The patch works. I can access an i210 over a miniPCIe -> PCIe adapter.
With kind regards,
Jan
PATCH 1/1 PCI: mvebu: Fix PCI I/O mapping creation sequence
In reply to Thomas PetazzoniQuoted 18 lines · Thomas Petazzoni
Commit
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") had the side effect that the PCI I/O mapping was created much earlier than before, at a point where theprobe()of the driver could still fail. This is for example a problem if one gets an -EPROBE_DEFER at some point duringprobe(), afterpci_ioremap_io()has been called.Indeed, there is currently no function to undo what
pci_ioremap_io()did, and switching topci_remap_iospace()is not an option in pci-mvebu due to the need for special memory attributes on Armada 38x.Reverting
ee1604381a371("PCI: mvebu: Only remap I/O space if configured") would be a possibility, but it would require also reverting42342073e38b5("PCI: mvebu: Convert to usepci_host_bridgedirectly"). So instead, we use an open-coded version ofpci_host_probe()that creates the PCI I/O mapping at a point where we are guaranteed not to fail anymore.
Quoted 3 lines
Reported-by Jan Kundr?t <[email protected]>Fixes ee1604381a371 ("PCI: mvebu: Only remap I/O space if configured")Signed-off-by Thomas Petazzoni <[email protected]>
Applied with Lorenzo's ack and Jan's tested-by to for-linux for v4.19, thanks!
Quoted 89 lines
--- drivers/pci/controller/pci-mvebu.c | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)drivers/pci/controller/pci-mvebu.c +48
-4@@ -1145,7 +1145,6 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) {struct device *dev = &pcie->pdev->dev;struct device_node *np = dev->of_node; -unsigned int i;int ret;INIT_LIST_HEAD (&pcie->resources);@@ -1179,13 +1178,58 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) resource_size(&pcie->io) - 1); pcie->realio.name ="PCI I/O" ; +pci_add_resource (&pcie->resources, &pcie->realio); + } + +return devm_request_pci_bus_resources (dev, &pcie->resources); +} + +/* +* This is a copy of pci_host_probe(), except that it does the I/O +* remap as the last step, once we are sure we won't fail. +* +* It should be removed once the I/O remap error handling issue has +* been sorted out. +*/ +static int mvebu_pci_host_probe (struct pci_host_bridge *bridge) +{ +struct mvebu_pcie *pcie; +struct pci_bus *bus, *child; +int ret; + + ret =pci_scan_root_bus_bridge (bridge); +if (ret <0 ) { +dev_err (bridge->dev.parent,"Scanning root bridge failed" ); +return ret; + } + + pcie =pci_host_bridge_priv (bridge); +if (resource_size (&pcie->io) !=0 ) { +unsigned int i; +for (i =0 ; i <resource_size (&pcie->realio); i +=SZ_64K )pci_ioremap_io (i, pcie->io.start + i); + } -pci_add_resource (&pcie->resources, &pcie->realio); + bus = bridge->bus; + +/* +* We insert PCI resources into the iomem_resource and +* ioport_resource trees in either pci_bus_claim_resources() +* or pci_bus_assign_resources(). +*/ +if (pci_has_flag (PCI_PROBE_ONLY )) { +pci_bus_claim_resources (bus); + }else { +pci_bus_size_bridges (bus); +pci_bus_assign_resources (bus); + +list_for_each_entry (child, &bus->children, node) +pcie_bus_configure_settings (child); } -return devm_request_pci_bus_resources (dev, &pcie->resources); +pci_bus_add_devices (bus); +return 0 ; }static int mvebu_pcie_probe (struct platform_device *pdev)@@ -1268,7 +1312,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) bridge->align_resource = mvebu_pcie_align_resource; bridge->msi = pcie->msi; -return pci_host_probe (bridge); +return mvebu_pci_host_probe (bridge); }static const struct of_device_id mvebu_pcie_of_match_table[] = {Signature · 1 line
2.14.4