All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources()
@ 2018-05-24  7:23 Marek Vasut
  2018-05-24  7:23 ` [PATCH 2/6] PCI: rcar: Add missing irq_dispose_mapping() into failpath Marek Vasut
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

The rcar_pcie_get_resources() is another misnomer with a side effect.
The function does not only get resources, but also enables/disables bus
clock. This is forgotten in the probe() function though and if anything
in probe() fails after rcar_pcie_get_resources() is called, the bus
clock are never disabled.

This patch pulls the clock handling out of the rcar_pcie_get_resources()
and enables clock after all the resources were requested. Moreover, this
patch also always disables the clock in case of failure.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
 drivers/pci/host/pcie-rcar.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 8d161563bce8..0879880f7975 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -946,32 +946,22 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 		dev_err(dev, "cannot get pcie bus clock\n");
 		return PTR_ERR(pcie->bus_clk);
 	}
-	err = clk_prepare_enable(pcie->bus_clk);
-	if (err)
-		return err;
 
 	i = irq_of_parse_and_map(dev->of_node, 0);
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
-		err = -ENOENT;
-		goto err_map_reg;
+		return -ENOENT;
 	}
 	pcie->msi.irq1 = i;
 
 	i = irq_of_parse_and_map(dev->of_node, 1);
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
-		err = -ENOENT;
-		goto err_map_reg;
+		return -ENOENT;
 	}
 	pcie->msi.irq2 = i;
 
 	return 0;
-
-err_map_reg:
-	clk_disable_unprepare(pcie->bus_clk);
-
-	return err;
 }
 
 static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
@@ -1115,22 +1105,28 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 		goto err_pm_put;
 	}
 
+	err = clk_prepare_enable(pcie->bus_clk);
+	if (err) {
+		dev_err(dev, "failed to enable bus clock: %d\n", err);
+		goto err_pm_put;
+	}
+
 	err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
 	if (err)
-		goto err_pm_put;
+		goto err_clk_disable;
 
 	phy_init_fn = of_device_get_match_data(dev);
 	err = phy_init_fn(pcie);
 	if (err) {
 		dev_err(dev, "failed to init PCIe PHY\n");
-		goto err_pm_put;
+		goto err_clk_disable;
 	}
 
 	/* Failure to get a link might just be that no cards are inserted */
 	if (rcar_pcie_hw_init(pcie)) {
 		dev_info(dev, "PCIe link down\n");
 		err = -ENODEV;
-		goto err_pm_put;
+		goto err_clk_disable;
 	}
 
 	data = rcar_pci_read_reg(pcie, MACSR);
@@ -1142,16 +1138,19 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 			dev_err(dev,
 				"failed to enable MSI support: %d\n",
 				err);
-			goto err_pm_put;
+			goto err_clk_disable;
 		}
 	}
 
 	err = rcar_pcie_enable(pcie);
 	if (err)
-		goto err_pm_put;
+		goto err_clk_disable;
 
 	return 0;
 
+err_clk_disable:
+	clk_disable_unprepare(pcie->bus_clk);
+
 err_pm_put:
 	pm_runtime_put(dev);
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/6] PCI: rcar: Add missing irq_dispose_mapping() into failpath
  2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
@ 2018-05-24  7:23 ` Marek Vasut
  2018-05-24  7:23 ` [PATCH 3/6] PCI: rcar: Teardown MSI setup if rcar_pcie_enable() fails Marek Vasut
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

The rcar_pcie_get_resources() is another misnomer with a side effect.
The function does not only get resources, but also maps MSI IRQs via
irq_of_parse_and_map(). In case anything fails afterward, the IRQ
mapping must be disposed through irq_dispose_mapping() which is not
done.

This patch handles irq_of_parse_and_map() failures in by disposing
of the mapping in rcar_pcie_get_resources() as well as in probe.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
 drivers/pci/host/pcie-rcar.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 0879880f7975..6bb1cdec26be 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -950,18 +950,25 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 	i = irq_of_parse_and_map(dev->of_node, 0);
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
-		return -ENOENT;
+		err = -ENOENT;
+		goto err_irq1;
 	}
 	pcie->msi.irq1 = i;
 
 	i = irq_of_parse_and_map(dev->of_node, 1);
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
-		return -ENOENT;
+		err = -ENOENT;
+		goto err_irq2;
 	}
 	pcie->msi.irq2 = i;
 
 	return 0;
+
+err_irq2:
+	irq_dispose_mapping(pcie->msi.irq1);
+err_irq1:
+	return err;
 }
 
 static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
@@ -1108,7 +1115,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	err = clk_prepare_enable(pcie->bus_clk);
 	if (err) {
 		dev_err(dev, "failed to enable bus clock: %d\n", err);
-		goto err_pm_put;
+		goto err_unmap_msi_irqs;
 	}
 
 	err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
@@ -1151,6 +1158,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 err_clk_disable:
 	clk_disable_unprepare(pcie->bus_clk);
 
+err_unmap_msi_irqs:
+	irq_dispose_mapping(pcie->msi.irq2);
+	irq_dispose_mapping(pcie->msi.irq1);
+
 err_pm_put:
 	pm_runtime_put(dev);
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/6] PCI: rcar: Teardown MSI setup if rcar_pcie_enable() fails
  2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
  2018-05-24  7:23 ` [PATCH 2/6] PCI: rcar: Add missing irq_dispose_mapping() into failpath Marek Vasut
@ 2018-05-24  7:23 ` Marek Vasut
  2018-05-24  7:23 ` [PATCH 4/6] PCI: rcar: Poll more often in rcar_pcie_wait_for_dl() Marek Vasut
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

If the rcar_pcie_enable() fails and MSIs are enabled, the setup done in
rcar_pcie_enable_msi() is never undone. Add a function to tear down the
MSI setup by disabling the MSI handling in the PCIe block, deallocating
the pages requested for the MSIs and zapping the IRQ mapping.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
 drivers/pci/host/pcie-rcar.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 6bb1cdec26be..d6a7e8482dcf 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -923,6 +923,28 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 	return err;
 }
 
+static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
+{
+	struct rcar_msi *msi = &pcie->msi;
+	int irq, i;
+
+	/* Disable all MSI interrupts */
+	rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
+
+	/* Disable address decoding of the MSI interrupt, MSIFE */
+	rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
+
+	free_pages(msi->pages, 0);
+
+	for (i = 0; i < INT_PCI_MSI_NR; i++) {
+		irq = irq_find_mapping(msi->domain, i);
+		if (irq > 0)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(msi->domain);
+}
+
 static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
@@ -1151,10 +1173,14 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 
 	err = rcar_pcie_enable(pcie);
 	if (err)
-		goto err_clk_disable;
+		goto err_msi_teardown;
 
 	return 0;
 
+err_msi_teardown:
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		rcar_pcie_teardown_msi(pcie);
+
 err_clk_disable:
 	clk_disable_unprepare(pcie->bus_clk);
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/6] PCI: rcar: Poll more often in rcar_pcie_wait_for_dl()
  2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
  2018-05-24  7:23 ` [PATCH 2/6] PCI: rcar: Add missing irq_dispose_mapping() into failpath Marek Vasut
  2018-05-24  7:23 ` [PATCH 3/6] PCI: rcar: Teardown MSI setup if rcar_pcie_enable() fails Marek Vasut
@ 2018-05-24  7:23 ` Marek Vasut
  2018-05-24  7:23 ` [PATCH 5/6] PCI: rcar: Remove IRQ mappings in rcar_pcie_enable_msi failpath Marek Vasut
  2018-05-24  7:23 ` [PATCH 6/6] PCI: rcar: Shut the PHY down in failpath Marek Vasut
  4 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

The data link active signal usually takes ~20 uSec to be asserted,
poll the bit more often to avoid useless delays in this function.
Use udelay() instead of usleep() for such a small delay as suggested
by the timer documentation and because this will be used in atomic
context later on when the suspend/resume patches land.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
V2: s/content/context in commit message
V3: Add cpu_relax()
---
 drivers/pci/host/pcie-rcar.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index d6a7e8482dcf..4843a4dc6059 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -546,13 +546,14 @@ static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
 
 static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
 {
-	unsigned int timeout = 10;
+	unsigned int timeout = 10000;
 
 	while (timeout--) {
 		if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
 			return 0;
 
-		msleep(5);
+		udelay(5);
+		cpu_relax();
 	}
 
 	return -ETIMEDOUT;
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/6] PCI: rcar: Remove IRQ mappings in rcar_pcie_enable_msi failpath
  2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
                   ` (2 preceding siblings ...)
  2018-05-24  7:23 ` [PATCH 4/6] PCI: rcar: Poll more often in rcar_pcie_wait_for_dl() Marek Vasut
@ 2018-05-24  7:23 ` Marek Vasut
  2018-05-24  7:23 ` [PATCH 6/6] PCI: rcar: Shut the PHY down in failpath Marek Vasut
  4 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

The rcar_pcie_enable_msi() creates IRQ mappings using irq_create_mapping()
before requesting the IRQs using devm_request_irq(). If devm_request_irq()
fails for some reason, rcar_pcie_enable_msi() does not remove the mapping.

Pull out the code for disposing IRQ mappings from rcar_pcie_teardown_msi()
into a separate function and call it from both rcar_pcie_teardown_msi()
and rcar_pcie_enable_msi() failpath to remove the mappings correctly.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
 drivers/pci/host/pcie-rcar.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4843a4dc6059..636c3c5095d2 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -866,6 +866,20 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = rcar_msi_map,
 };
 
+static void rcar_pcie_unmap_msi(struct rcar_pcie *pcie)
+{
+	struct rcar_msi *msi = &pcie->msi;
+	int i, irq;
+
+	for (i = 0; i < INT_PCI_MSI_NR; i++) {
+		irq = irq_find_mapping(msi->domain, i);
+		if (irq > 0)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(msi->domain);
+}
+
 static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
@@ -920,14 +934,13 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 	return 0;
 
 err:
-	irq_domain_remove(msi->domain);
+	rcar_pcie_unmap_msi(pcie);
 	return err;
 }
 
 static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
 {
 	struct rcar_msi *msi = &pcie->msi;
-	int irq, i;
 
 	/* Disable all MSI interrupts */
 	rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
@@ -937,13 +950,7 @@ static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
 
 	free_pages(msi->pages, 0);
 
-	for (i = 0; i < INT_PCI_MSI_NR; i++) {
-		irq = irq_find_mapping(msi->domain, i);
-		if (irq > 0)
-			irq_dispose_mapping(irq);
-	}
-
-	irq_domain_remove(msi->domain);
+	rcar_pcie_unmap_msi(pcie);
 }
 
 static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] PCI: rcar: Shut the PHY down in failpath
  2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
                   ` (3 preceding siblings ...)
  2018-05-24  7:23 ` [PATCH 5/6] PCI: rcar: Remove IRQ mappings in rcar_pcie_enable_msi failpath Marek Vasut
@ 2018-05-24  7:23 ` Marek Vasut
  4 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2018-05-24  7:23 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Geert Uytterhoeven, Phil Edworthy, Simon Horman,
	Wolfram Sang, linux-renesas-soc

If anything fails past phy_init_fn() and the system is a Gen3 with
a PHY, the PHY will be left on and inited. This is caused by the
phy_init_fn, which is in fact a pointer to rcar_pcie_phy_init_gen3()
function, which starts the PHY, yet has no counterpart in the failpath.
Add that counterpart.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
Fixes: 517ca93a7159 ("PCI: rcar: Add R-Car gen3 PHY support")
---
 drivers/pci/host/pcie-rcar.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 636c3c5095d2..695781934f0a 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -1163,7 +1163,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	if (rcar_pcie_hw_init(pcie)) {
 		dev_info(dev, "PCIe link down\n");
 		err = -ENODEV;
-		goto err_clk_disable;
+		goto err_phy_shutdown;
 	}
 
 	data = rcar_pci_read_reg(pcie, MACSR);
@@ -1175,7 +1175,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 			dev_err(dev,
 				"failed to enable MSI support: %d\n",
 				err);
-			goto err_clk_disable;
+			goto err_phy_shutdown;
 		}
 	}
 
@@ -1189,6 +1189,12 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		rcar_pcie_teardown_msi(pcie);
 
+err_phy_shutdown:
+	if (pcie->phy) {
+		phy_power_off(pcie->phy);
+		phy_exit(pcie->phy);
+	}
+
 err_clk_disable:
 	clk_disable_unprepare(pcie->bus_clk);
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-05-24  7:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-24  7:23 [PATCH 1/6] PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources() Marek Vasut
2018-05-24  7:23 ` [PATCH 2/6] PCI: rcar: Add missing irq_dispose_mapping() into failpath Marek Vasut
2018-05-24  7:23 ` [PATCH 3/6] PCI: rcar: Teardown MSI setup if rcar_pcie_enable() fails Marek Vasut
2018-05-24  7:23 ` [PATCH 4/6] PCI: rcar: Poll more often in rcar_pcie_wait_for_dl() Marek Vasut
2018-05-24  7:23 ` [PATCH 5/6] PCI: rcar: Remove IRQ mappings in rcar_pcie_enable_msi failpath Marek Vasut
2018-05-24  7:23 ` [PATCH 6/6] PCI: rcar: Shut the PHY down in failpath Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.