linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated
@ 2021-06-07 21:33 Javier Martinez Canillas
  2021-06-08  6:48 ` [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated【请注意,邮件由linux-rockchip-bounces+shawn.lin=rock-chips.com@lists.infradead.org代发】 Shawn Lin
  0 siblings, 1 reply; 3+ messages in thread
From: Javier Martinez Canillas @ 2021-06-07 21:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Javier Martinez Canillas, Peter Robinson, Bjorn Helgaas,
	Heiko Stuebner, Lorenzo Pieralisi, Rob Herring, Shawn Lin,
	linux-arm-kernel, linux-pci, linux-rockchip

IRQ handlers that are registered for shared interrupts can be called at
any time after have been registered using the request_irq() function.

It's up to drivers to ensure that's always safe for these to be called.

Both the "pcie-sys" and "pcie-client" interrupts are shared, but since
their handlers are registered very early in the probe function, an error
later can lead to these handlers being executed before all the required
have been properly setup.

For example, the rockchip_pcie_read() function used by these IRQ handlers
expects that some PCIe clocks will already be enabled, otherwise trying
to access the PCIe registers causes the read to hang and never return.

The CONFIG_DEBUG_SHIRQ option tests if drivers are able to cope with their
shared interrupt handlers being called, by generating a spurious interrupt
just before a shared interrupt handler is unregistered.

But this means that if the option is enabled, any error in the probe path
of this driver could lead to one of the IRQ handlers to be executed.

In a rockpro64 board, the following sequence of events happens:

  1) "pcie-sys" IRQ is requested and its handler registered.
  2) "pcie-client" IRQ is requested and its handler registered.
  3) probe later fails due readl_poll_timeout() returning a timeout.
  4) the "pcie-sys" IRQ is unregistered.
  5) CONFIG_DEBUG_SHIRQ triggers a spurious interrupt.
  6) "pcie-client" IRQ handler is called for this spurious interrupt.
  7) IRQ handler tries to read PCIE_CLIENT_INT_STATUS with clocks gated.
  8) the machine hangs because rockchip_pcie_read() call never returns.

To avoid cases like this, the handlers don't have to be registered until
very late in the probe function, once all the resources have been setup.

So let's just move all the IRQ init before the pci_host_probe() call, that
will prevent issues like this and seems to be the correct thing to do too.

Reported-by: Peter Robinson <pbrobinson@gmail.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

 drivers/pci/controller/pcie-rockchip-host.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index f1d08a1b159..78d04ac29cd 100644
--- a/drivers/pci/controller/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
@@ -592,10 +592,6 @@ static int rockchip_pcie_parse_host_dt(struct rockchip_pcie *rockchip)
 	if (err)
 		return err;
 
-	err = rockchip_pcie_setup_irq(rockchip);
-	if (err)
-		return err;
-
 	rockchip->vpcie12v = devm_regulator_get_optional(dev, "vpcie12v");
 	if (IS_ERR(rockchip->vpcie12v)) {
 		if (PTR_ERR(rockchip->vpcie12v) != -ENODEV)
@@ -973,8 +969,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
 	if (err)
 		goto err_vpcie;
 
-	rockchip_pcie_enable_interrupts(rockchip);
-
 	err = rockchip_pcie_init_irq_domain(rockchip);
 	if (err < 0)
 		goto err_deinit_port;
@@ -992,6 +986,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
 	bridge->sysdata = rockchip;
 	bridge->ops = &rockchip_pcie_ops;
 
+	err = rockchip_pcie_setup_irq(rockchip);
+	if (err)
+		goto err_remove_irq_domain;
+
+	rockchip_pcie_enable_interrupts(rockchip);
+
 	err = pci_host_probe(bridge);
 	if (err < 0)
 		goto err_remove_irq_domain;
-- 
2.31.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated【请注意,邮件由linux-rockchip-bounces+shawn.lin=rock-chips.com@lists.infradead.org代发】
  2021-06-07 21:33 [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated Javier Martinez Canillas
@ 2021-06-08  6:48 ` Shawn Lin
  2021-06-08  8:02   ` Javier Martinez Canillas
  0 siblings, 1 reply; 3+ messages in thread
From: Shawn Lin @ 2021-06-08  6:48 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: shawn.lin, Peter Robinson, Bjorn Helgaas, Heiko Stuebner,
	Lorenzo Pieralisi, Rob Herring, linux-arm-kernel, linux-pci,
	linux-rockchip, linux-kernel

On 2021/6/8 5:33, Javier Martinez Canillas wrote:
> IRQ handlers that are registered for shared interrupts can be called at
> any time after have been registered using the request_irq() function.
> 
> It's up to drivers to ensure that's always safe for these to be called.
> 
> Both the "pcie-sys" and "pcie-client" interrupts are shared, but since
> their handlers are registered very early in the probe function, an error
> later can lead to these handlers being executed before all the required
> have been properly setup.
> 
> For example, the rockchip_pcie_read() function used by these IRQ handlers
> expects that some PCIe clocks will already be enabled, otherwise trying
> to access the PCIe registers causes the read to hang and never return.
> 
> The CONFIG_DEBUG_SHIRQ option tests if drivers are able to cope with their
> shared interrupt handlers being called, by generating a spurious interrupt
> just before a shared interrupt handler is unregistered.
> 
> But this means that if the option is enabled, any error in the probe path
> of this driver could lead to one of the IRQ handlers to be executed.
> 
> In a rockpro64 board, the following sequence of events happens:
> 
>    1) "pcie-sys" IRQ is requested and its handler registered.
>    2) "pcie-client" IRQ is requested and its handler registered.
>    3) probe later fails due readl_poll_timeout() returning a timeout.
>    4) the "pcie-sys" IRQ is unregistered.
>    5) CONFIG_DEBUG_SHIRQ triggers a spurious interrupt.
>    6) "pcie-client" IRQ handler is called for this spurious interrupt.
>    7) IRQ handler tries to read PCIE_CLIENT_INT_STATUS with clocks gated.
>    8) the machine hangs because rockchip_pcie_read() call never returns.
> 
> To avoid cases like this, the handlers don't have to be registered until
> very late in the probe function, once all the resources have been setup.
> 
> So let's just move all the IRQ init before the pci_host_probe() call, that
> will prevent issues like this and seems to be the correct thing to do too.
> 

Acked-by: Shawn Lin <shawn.lin@rock-chips.com>

Thanks.

> Reported-by: Peter Robinson <pbrobinson@gmail.com>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> ---
> 
>   drivers/pci/controller/pcie-rockchip-host.c | 12 ++++++------
>   1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
> index f1d08a1b159..78d04ac29cd 100644
> --- a/drivers/pci/controller/pcie-rockchip-host.c
> +++ b/drivers/pci/controller/pcie-rockchip-host.c
> @@ -592,10 +592,6 @@ static int rockchip_pcie_parse_host_dt(struct rockchip_pcie *rockchip)
>   	if (err)
>   		return err;
>   
> -	err = rockchip_pcie_setup_irq(rockchip);
> -	if (err)
> -		return err;
> -
>   	rockchip->vpcie12v = devm_regulator_get_optional(dev, "vpcie12v");
>   	if (IS_ERR(rockchip->vpcie12v)) {
>   		if (PTR_ERR(rockchip->vpcie12v) != -ENODEV)
> @@ -973,8 +969,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
>   	if (err)
>   		goto err_vpcie;
>   
> -	rockchip_pcie_enable_interrupts(rockchip);
> -
>   	err = rockchip_pcie_init_irq_domain(rockchip);
>   	if (err < 0)
>   		goto err_deinit_port;
> @@ -992,6 +986,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
>   	bridge->sysdata = rockchip;
>   	bridge->ops = &rockchip_pcie_ops;
>   
> +	err = rockchip_pcie_setup_irq(rockchip);
> +	if (err)
> +		goto err_remove_irq_domain;
> +
> +	rockchip_pcie_enable_interrupts(rockchip);
> +
>   	err = pci_host_probe(bridge);
>   	if (err < 0)
>   		goto err_remove_irq_domain;
> 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated【请注意,邮件由linux-rockchip-bounces+shawn.lin=rock-chips.com@lists.infradead.org代发】
  2021-06-08  6:48 ` [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated【请注意,邮件由linux-rockchip-bounces+shawn.lin=rock-chips.com@lists.infradead.org代发】 Shawn Lin
@ 2021-06-08  8:02   ` Javier Martinez Canillas
  0 siblings, 0 replies; 3+ messages in thread
From: Javier Martinez Canillas @ 2021-06-08  8:02 UTC (permalink / raw)
  To: Shawn Lin
  Cc: Peter Robinson, Bjorn Helgaas, Heiko Stuebner, Lorenzo Pieralisi,
	Rob Herring, linux-arm-kernel, linux-pci, linux-rockchip,
	linux-kernel

On 6/8/21 8:48 AM, Shawn Lin wrote:
> On 2021/6/8 5:33, Javier Martinez Canillas wrote:

[snip]

>>
>> So let's just move all the IRQ init before the pci_host_probe() call, that
>> will prevent issues like this and seems to be the correct thing to do too.
>>
> 
> Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
>

Thanks a lot for the ack!

Peter Robinson noticed a missing word in the changelog, I'll send a v2 now.
 Best regards,
-- 
Javier Martinez Canillas
Software Engineer
New Platform Technologies Enablement team
RHEL Engineering


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2021-06-08  8:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-07 21:33 [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated Javier Martinez Canillas
2021-06-08  6:48 ` [PATCH] PCI: rockchip: Avoid accessing PCIe registers with clocks gated【请注意,邮件由linux-rockchip-bounces+shawn.lin=rock-chips.com@lists.infradead.org代发】 Shawn Lin
2021-06-08  8:02   ` Javier Martinez Canillas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).