diff mbox series

[04/32] spi: dw: Introduce polling device tree property

Message ID 20201107081420.60325-5-damien.lemoal@wdc.com
State New
Headers show
Series RISC-V Kendryte K210 support improvments | expand

Commit Message

Damien Le Moal Nov. 7, 2020, 8:13 a.m. UTC
With boards that have slow interrupts context switch, and a fast device
connected to a spi master, e.g. an SD card through mmc-spi, using
dw_spi_poll_transfer() intead of the regular interrupt based
dw_spi_transfer_handler() function is more efficient and can avoid a lot
of RX FIFO overflow errors while keeping the device SPI frequency
reasonnably high (for speed). Introduce the "polling" device tree
property to allow requesting polled processing of transfer depending on
the connected device while keeping the spi master interrupts property
unschanged. E.g. device trees such as:

Generic soc.dtsi dts:

spi0: spi@53000000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "snps,dw-apb-ssi";
	reg = <0x53000000 0x100>;
	interrupts = <2>;
	...
}

Board specific dts:

...
&spi0 {
	polling;
	status = "okay";

	slot@0 {
		compatible = "mmc-spi-slot";
		reg = <0>;
		voltage-ranges = <3300 3300>;
		spi-max-frequency = <4000000>;
	};
}

will result in using polled transfers for the SD card while other boards
using spi0 for different peripherals can use interrupt based transfers
without needing to change the generic base soc dts.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-mmio.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Comments

Mark Brown Nov. 9, 2020, 4:04 p.m. UTC | #1
On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:

> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi, using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed). Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:

This isn't something that looks like it should be configured via DT as a
separate property, this is more of a tuning property as far as I can see
- even on the same hardware there might be cases where people prefer to
keep using interrupts but for example allow transfers to stall while
waiting for the interrupt controller giving lower throughput but more
CPU cycles available for other things.

Unfortunately we don't have any information about how much interrupt
latency we should expect which makes this a bit annoying.  I do see that
there's already some existing attempt in the DMA code to tune burst
sizes to avoid FIFO overflows - it looks like the hardware is doing
something unusual and possibly unfortunate here though I've never
looked at it so I'm not sure exactly what is going on there but perhaps
ther's some tuning that can be done in there?  TBH I'm not clear what
the failure mode is where we need software to service interrupts
promptly in the middle of a DMA transfer in the first place, that seems
really strange.
Serge Semin Nov. 9, 2020, 7:59 p.m. UTC | #2
On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi,

> using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and

I can believe in that. But the next part seems questionable:

> can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed).

No matter whether it's an IRQ-based or poll-based transfer, as long as a
client SPI-device is connected with a GPIO-based chip-select (or the
DW APB SSI-controller feature of the automatic chip-select toggling is
fixed), the Rx FIFO should never overrun. It's ensured by the transfer
algorithm design by calculating the rxtx_gap in the dw_writer()
method. If the error still happens then there must be some bug in
the code.

It's also strange to hear that the polling-based transfer helps
to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
causes them. Both of those methods are based on the same dw_writer()
and dw_reader() methods. So basically they both should either work
well or cause the errors at same time.

So to speak could you more through debug your case?

On the other hand the errors (but not the Rx FIFO overflow) might be
caused by the DW APB SSI nasty feature of the native chip-select
automatic assertion/de-assertion. So if your MMC-spi port is handled
by the native DW APB SSI CS lane, then it won't work well for sure.
No matter whether you use the poll- or IRQ-based transfers.

-Sergey


> Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:
> 
> Generic soc.dtsi dts:
> 
> spi0: spi@53000000 {
> 	#address-cells = <1>;
> 	#size-cells = <0>;
> 	compatible = "snps,dw-apb-ssi";
> 	reg = <0x53000000 0x100>;
> 	interrupts = <2>;
> 	...
> }
> 
> Board specific dts:
> 
> ...
> &spi0 {
> 	polling;
> 	status = "okay";
> 
> 	slot@0 {
> 		compatible = "mmc-spi-slot";
> 		reg = <0>;
> 		voltage-ranges = <3300 3300>;
> 		spi-max-frequency = <4000000>;
> 	};
> }
> 
> will result in using polled transfers for the SD card while other boards
> using spi0 for different peripherals can use interrupt based transfers
> without needing to change the generic base soc dts.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index d0cc5bf4fa4e..3f1bc384cb45 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -20,6 +20,7 @@
>  #include <linux/property.h>
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
> +#include <linux/interrupt.h>
>  
>  #include "spi-dw.h"
>  
> @@ -246,9 +247,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
>  
>  	dws->paddr = mem->start;
>  
> -	dws->irq = platform_get_irq(pdev, 0);
> -	if (dws->irq < 0)
> -		return dws->irq; /* -ENXIO */
> +	if (device_property_read_bool(&pdev->dev, "polling")) {
> +		dws->irq = IRQ_NOTCONNECTED;
> +	} else {
> +		dws->irq = platform_get_irq(pdev, 0);
> +		if (dws->irq < 0)
> +			return dws->irq; /* -ENXIO */
> +	}
>  
>  	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
>  	if (IS_ERR(dwsmmio->clk))
> -- 
> 2.28.0
>
diff mbox series

Patch

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..3f1bc384cb45 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -20,6 +20,7 @@ 
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
+#include <linux/interrupt.h>
 
 #include "spi-dw.h"
 
@@ -246,9 +247,13 @@  static int dw_spi_mmio_probe(struct platform_device *pdev)
 
 	dws->paddr = mem->start;
 
-	dws->irq = platform_get_irq(pdev, 0);
-	if (dws->irq < 0)
-		return dws->irq; /* -ENXIO */
+	if (device_property_read_bool(&pdev->dev, "polling")) {
+		dws->irq = IRQ_NOTCONNECTED;
+	} else {
+		dws->irq = platform_get_irq(pdev, 0);
+		if (dws->irq < 0)
+			return dws->irq; /* -ENXIO */
+	}
 
 	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dwsmmio->clk))