mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/5] spi: dw: use threaded interrupt
@ 2026-09-09 14:36 Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 1/5] spi: dw: use DW_SPI_ISR directly Jisheng Zhang
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

To avoid blocking for an excessive amount of time, eventually impacting
on system responsiveness, hard interrupt handlers should finish
executing in as little time as possible.

Use threaded interrupt and move the SPI transfer handling to an
interrupt thread.

After that, since the dw_reader() and dw_writer() are called in
threaded ISR now, so we can delay the unmasking interrupts until no
rx and tx action is taken, thus reduce the interrupt numbers further.

Tested with below two cmds
./spidev_test -D /dev/spidev1.3 -s 30000000 -S 327680 -I 1

./spidev_test -D /dev/spidev1.3 -s 30000000 -S 327680 -I 1000
./rtla timerlat top -q -k -P f:95

The first cmd is to check the interrupt numbers optmizaion result, the
2nd cmd group is to check the threaded interrupt improvement.

Before the patch:
each 320KB spi spidev_test transfer triggers 33118 interrupts

spidev_test reports ~22090 kbps
and rtla reports:
                                     Timer Latency
  0 00:00:37   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #9958      |        1         0        67    103394 |        6         4      2198    105031
  1 #36902     |        1         0         1        18 |        5         4         5        29

After the patch:
each 320KB spi spidev_test transfer only triggers 1 interrupts
spidev_test reports ~23520 kbps
and now rtla reports:
                                    Timer Latency
  0 00:00:58   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #58362     |        1         0         0        29 |        6         3         4        56
  1 #58363     |        1         0         1        23 |        6         4         5        68

In summary:
before the patch	after the patch
33118 interrutps	1 interrupts		reduced by 33117 times!
103394 us max latency	29 us max latency	reduced by 3564 times!
22090 kbps rate		23520 kbps rate		improved by 6.5%

Since v2:
  - rebase against latest version
  - remove the "spi: dw: use DW_SPI_INT_MASK instead of hardcoded 0xff"
  - add three more patches to clean up irq code introduced by recent "enhanced
    spi" support
  - Don't use threaded interrupt for target mode and the enhanced spi

Since v1:
  - rebase against latest version
  - drop two patches which have been merged
  - correct some performance numbers
  - don't move request irq code block so no changes for err handling code path
  - move spi_finalize_current_transfer to the end of threaded irq fn
  - don't rely on irq status in threaded fn, but try rx and tx as much
    as possible in the loop

Jisheng Zhang (5):
  spi: dw: use DW_SPI_ISR directly
  spi: dw: remove useless dws->transfer_handler check
  spi: dw: remove duplicated "!rx_len && !tx_len" handling from
    dw_spi_irq
  spi: dw: restore previous irq handling behavior when !ctlr->cur_msg
  spi: dw: use threaded interrupt and optimize the threaded ISR

 drivers/spi/spi-dw-core.c | 86 ++++++++++++++++++++++++++++++++-------
 1 file changed, 72 insertions(+), 14 deletions(-)

-- 
2.53.0


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

* [PATCH v3 1/5] spi: dw: use DW_SPI_ISR directly
  2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
@ 2026-09-09 14:36 ` Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 2/5] spi: dw: remove useless dws->transfer_handler check Jisheng Zhang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

The DW_SPI_ISR register reports the masked interrupts, no need to mask
again.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/spi/spi-dw-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 206d3f9dd83d..1c060f0ec50c 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -275,7 +275,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
 	struct spi_controller *ctlr = dev_id;
 	struct dw_spi *dws = spi_controller_get_devdata(ctlr);
-	u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK;
+	u16 irq_status = dw_readl(dws, DW_SPI_ISR);
 
 	if (!irq_status)
 		return IRQ_NONE;
-- 
2.53.0


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

* [PATCH v3 2/5] spi: dw: remove useless dws->transfer_handler check
  2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 1/5] spi: dw: use DW_SPI_ISR directly Jisheng Zhang
@ 2026-09-09 14:36 ` Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 3/5] spi: dw: remove duplicated "!rx_len && !tx_len" handling from dw_spi_irq Jisheng Zhang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

transfer_handler is initialized before any DW SPI interrupt is
unmasked. While the IRQ is registered but the handler is NULL,
dw_spi_hw_init() has all DW SPI interrupts disabled. Therefore
dw_spi_irq() cannot observe a DW SPI interrupt with a NULL
transfer_handler.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/spi/spi-dw-core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 1c060f0ec50c..f4c4e9dae25e 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -280,8 +280,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 	if (!irq_status)
 		return IRQ_NONE;
 
-	if (!dws->transfer_handler ||
-	    (!ctlr->cur_msg && dws->transfer_handler == dw_spi_transfer_handler)) {
+	if (!ctlr->cur_msg && dws->transfer_handler == dw_spi_transfer_handler) {
 		dw_spi_mask_intr(dws, 0xff);
 		return IRQ_HANDLED;
 	}
-- 
2.53.0


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

* [PATCH v3 3/5] spi: dw: remove duplicated "!rx_len && !tx_len" handling from dw_spi_irq
  2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 1/5] spi: dw: use DW_SPI_ISR directly Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 2/5] spi: dw: remove useless dws->transfer_handler check Jisheng Zhang
@ 2026-09-09 14:36 ` Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 4/5] spi: dw: restore previous irq handling behavior when !ctlr->cur_msg Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR Jisheng Zhang
  4 siblings, 0 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

dw_spi_irq() need not handle enhanced-transfer's "!rx_len && !tx_len"
case as that state is already handled by dw_spi_enh_handler()

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/spi/spi-dw-core.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index f4c4e9dae25e..91de357f97f3 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -284,12 +284,6 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 		dw_spi_mask_intr(dws, 0xff);
 		return IRQ_HANDLED;
 	}
-	if (dws->transfer_handler == dw_spi_enh_handler &&
-	    !dws->rx_len && !dws->tx_len) {
-		dw_spi_mask_intr(dws, 0xff);
-		spi_finalize_current_transfer(ctlr);
-		return IRQ_HANDLED;
-	}
 
 	return dws->transfer_handler(dws);
 }
-- 
2.53.0


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

* [PATCH v3 4/5] spi: dw: restore previous irq handling behavior when !ctlr->cur_msg
  2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
                   ` (2 preceding siblings ...)
  2026-09-09 14:36 ` [PATCH v3 3/5] spi: dw: remove duplicated "!rx_len && !tx_len" handling from dw_spi_irq Jisheng Zhang
@ 2026-09-09 14:36 ` Jisheng Zhang
  2026-09-09 14:36 ` [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR Jisheng Zhang
  4 siblings, 0 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

Recent "enhanced" support changes the dw_spi_irq() behavior a bit
when !!ctlr->cur_msg:

    if (!ctlr->cur_msg && dws->transfer_handler == dw_spi_transfer_handler) {
            dw_spi_mask_intr(dws, 0xff);
            return IRQ_HANDLED;
    }

But it misses the dma case, where the transfer_handler ==
dw_spi_dma_transfer_handler, so this changes the previous long time
working behavior, let's restore the previous handling by only filtering
out the dw_spi_enh_handler.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/spi/spi-dw-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 91de357f97f3..da7d4872e513 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -280,7 +280,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 	if (!irq_status)
 		return IRQ_NONE;
 
-	if (!ctlr->cur_msg && dws->transfer_handler == dw_spi_transfer_handler) {
+	if (!ctlr->cur_msg && dws->transfer_handler != dw_spi_enh_handler) {
 		dw_spi_mask_intr(dws, 0xff);
 		return IRQ_HANDLED;
 	}
-- 
2.53.0


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

* [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR
  2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
                   ` (3 preceding siblings ...)
  2026-09-09 14:36 ` [PATCH v3 4/5] spi: dw: restore previous irq handling behavior when !ctlr->cur_msg Jisheng Zhang
@ 2026-09-09 14:36 ` Jisheng Zhang
  2026-09-10 22:17   ` Mark Brown
  2026-09-11 14:22   ` Joseph Steel
  4 siblings, 2 replies; 8+ messages in thread
From: Jisheng Zhang @ 2026-09-09 14:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel

To avoid blocking for an excessive amount of time, eventually impacting
on system responsiveness, hard interrupt handlers should finish
executing in as little time as possible.

Use threaded interrupt and move the SPI transfer handling to an
interrupt thread for host mode and non enhanced spi for two reasons:

"while the performance improvement will apply for both target mode
has no control over the clocking of data by the host so is much more
vulnerable to dropping data in a threaded interrupt if the system is
loaded.  In host mode this isn't an issue since we'll simply stop
clocking data while waiting for the scheduler to get round to the
interrupt thread."

In theory, we could do this for enhanced spi too, but I don't have the
HW to test, so I leave enhanced spi interrupt routine as is, anyone
has the HW can implement similar optimization in the future.

After that, since the dw_reader() and dw_writer() are called in
threaded ISR now, so we can delay the unmasking interrupts until no
rx and tx action is taken, thus reduce the interrupt numbers further.

Tested with below two cmds
./spidev_test -D /dev/spidev1.3 -s 30000000 -S 327680 -I 1

./spidev_test -D /dev/spidev1.3 -s 30000000 -S 327680 -I 1000
./rtla timerlat top -q -k -P f:95

The first cmd is to check the interrupt numbers optmizaion result, the
2nd cmd group is to check the threaded interrupt improvement.

Before the patch:
each 320KB spi spidev_test transfer triggers 33118 interrupts

spidev_test reports ~22090 kbps
and rtla reports:
                                     Timer Latency
  0 00:00:37   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #9958      |        1         0        67    103394 |        6         4      2198    105031
  1 #36902     |        1         0         1        18 |        5         4         5        29

After the patch:
each 320KB spi spidev_test transfer only triggers 1 interrupts
spidev_test reports ~23520 kbps
and now rtla reports:
                                    Timer Latency
  0 00:00:58   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #58362     |        1         0         0        29 |        6         3         4        56
  1 #58363     |        1         0         1        23 |        6         4         5        68

In summary:
before the patch	after the patch
33118 interrutps	1 interrupts		reduced by 33117 times!
103394 us max latency	29 us max latency	reduced by 3564 times!
22090 kbps rate		23520 kbps rate		improved by 6.5%

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/spi/spi-dw-core.c | 75 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index da7d4872e513..c1f24f263488 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -132,10 +132,11 @@ static inline u32 dw_spi_rx_max(struct dw_spi *dws)
 	return min_t(u32, dws->rx_len, dw_readl(dws, DW_SPI_RXFLR));
 }
 
-static void dw_writer(struct dw_spi *dws)
+static u32 dw_writer(struct dw_spi *dws)
 {
 	u32 max = dw_spi_tx_max(dws);
 	u32 txw = 0;
+	u32 tx = 0;
 
 	while (max--) {
 		if (dws->tx) {
@@ -150,13 +151,16 @@ static void dw_writer(struct dw_spi *dws)
 		}
 		dw_write_io_reg(dws, DW_SPI_DR, txw);
 		--dws->tx_len;
+		++tx;
 	}
+	return tx;
 }
 
-static void dw_reader(struct dw_spi *dws)
+static u32 dw_reader(struct dw_spi *dws)
 {
 	u32 max = dw_spi_rx_max(dws);
 	u32 rxw;
+	u32 rx = 0;
 
 	while (max--) {
 		rxw = dw_read_io_reg(dws, DW_SPI_DR);
@@ -171,7 +175,9 @@ static void dw_reader(struct dw_spi *dws)
 			dws->rx += dws->n_bytes;
 		}
 		--dws->rx_len;
+		++rx;
 	}
+	return rx;
 }
 
 int dw_spi_check_status(struct dw_spi *dws, bool raw)
@@ -210,6 +216,62 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw)
 }
 EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, "SPI_DW_CORE");
 
+static irqreturn_t dw_spi_irq_thread_fn(int irq, void *dev_id)
+{
+	struct spi_controller *ctlr = dev_id;
+	struct dw_spi *dws = spi_controller_get_devdata(ctlr);
+	u32 rx, tx, imask, mask = 0;
+	bool finalize = false;
+
+	do {
+		/*
+		 * Read data from the Rx FIFO every time we've got a chance executing
+		 * this method. If there is nothing left to receive, terminate the
+		 * procedure. Otherwise adjust the Rx FIFO Threshold level if it's a
+		 * final stage of the transfer. By doing so we'll get the next IRQ
+		 * right when the leftover incoming data is received.
+		 */
+		rx = dw_reader(dws);
+		if (!dws->rx_len) {
+			mask |= 0xff;
+			finalize = true;
+		} else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
+			dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
+		}
+
+		/*
+		 * Send data out as much as possible. The Tx FIFO Empty IRQ will be
+		 * disabled after the data transmission is finished so not to
+		 * have the TXE IRQ flood at the final stage of the transfer.
+		 */
+		tx = dw_writer(dws);
+		if (!dws->tx_len)
+			mask |= DW_SPI_INT_TXEI;
+	} while (rx != 0 || tx != 0);
+
+	imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI |
+		DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
+	imask &= ~mask;
+	dw_spi_umask_intr(dws, imask);
+
+	if (finalize)
+		spi_finalize_current_transfer(dws->ctlr);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_spi_host_handler(struct dw_spi *dws)
+{
+	if (dw_spi_check_status(dws, false)) {
+		spi_finalize_current_transfer(dws->ctlr);
+		return IRQ_HANDLED;
+	}
+
+	dw_spi_mask_intr(dws, 0xff);
+
+	return IRQ_WAKE_THREAD;
+}
+
 static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
 {
 	u16 irq_status = dw_readl(dws, DW_SPI_ISR);
@@ -415,7 +477,10 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
 	dw_writel(dws, DW_SPI_TXFTLR, level);
 	dw_writel(dws, DW_SPI_RXFTLR, level - 1);
 
-	dws->transfer_handler = dw_spi_transfer_handler;
+	if (spi_controller_is_target(dws->ctlr))
+		dws->transfer_handler = dw_spi_transfer_handler;
+	else
+		dws->transfer_handler = dw_spi_host_handler;
 
 	imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI |
 		DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
@@ -1305,8 +1370,8 @@ int dw_spi_add_controller(struct device *dev, struct dw_spi *dws)
 	/* Basic HW init */
 	dw_spi_hw_init(dev, dws);
 
-	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
-			  ctlr);
+	ret = request_threaded_irq(dws->irq, dw_spi_irq, dw_spi_irq_thread_fn,
+				   IRQF_SHARED, dev_name(dev), ctlr);
 	if (ret < 0 && ret != -ENOTCONN) {
 		dev_err(dev, "can not request IRQ\n");
 		goto err_free_ctlr;
-- 
2.53.0


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

* Re: [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR
  2026-09-09 14:36 ` [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR Jisheng Zhang
@ 2026-09-10 22:17   ` Mark Brown
  2026-09-11 14:22   ` Joseph Steel
  1 sibling, 0 replies; 8+ messages in thread
From: Mark Brown @ 2026-09-10 22:17 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2244 bytes --]

On Wed, Sep 09, 2026 at 10:36:52PM +0800, Jisheng Zhang wrote:
> To avoid blocking for an excessive amount of time, eventually impacting
> on system responsiveness, hard interrupt handlers should finish
> executing in as little time as possible.

> +static irqreturn_t dw_spi_irq_thread_fn(int irq, void *dev_id)
> +{
> +	struct spi_controller *ctlr = dev_id;
> +	struct dw_spi *dws = spi_controller_get_devdata(ctlr);
> +	u32 rx, tx, imask, mask = 0;
> +	bool finalize = false;
> +
> +	do {

...

> +	} while (rx != 0 || tx != 0);

This will sit and drive the FIFOs for as long as we manage to push data
through them.  Usually we should have DMA so any long transfers wouldn't
be here but if there's systems with this controller wired up without DMA
we could potentially end up doing very large transfers, that can trigger
the hung task detector.  The simplistic solution is to use cond_resched()
to give other things a chance to run.

The hardirq handler would just do one round of FIFO operations and
return, allowing other things to happen until the device interrupts
again.

> +static irqreturn_t dw_spi_host_handler(struct dw_spi *dws)
> +{
> +	if (dw_spi_check_status(dws, false)) {
> +		spi_finalize_current_transfer(dws->ctlr);
> +		return IRQ_HANDLED;
> +	}
> +
> +	dw_spi_mask_intr(dws, 0xff);
> +
> +	return IRQ_WAKE_THREAD;
> +}

It feels like it might be good to do one round of FIFO in the hardirq
handler before deferring for a longer transfer, that would avoid needing
to schedule for very short transfers.  Essentially a copybreak like we'd
use for choosing between PIO and DMA.  This is entirely based on vibes
rather than having benchmarked anything, but all your numbers seem to be
for larger transfers rather than a continual stream of short transfers.
The people doing stuff like running CAN buses often run into trying to
saturate the bus which means they are very concerned with the latency
from transaction initiation to completion, and from completion to
initiating the next transfer.

TBH along those lines with really short transfers (eg, read/write 16 bit
registers) we might not want to bother with the interrupt at all and
poll but that's a separate thing.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR
  2026-09-09 14:36 ` [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR Jisheng Zhang
  2026-09-10 22:17   ` Mark Brown
@ 2026-09-11 14:22   ` Joseph Steel
  1 sibling, 0 replies; 8+ messages in thread
From: Joseph Steel @ 2026-09-11 14:22 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: Mark Brown, linux-spi, linux-kernel

Hi

On Wed, Sep 09, 2026 at 10:36:52PM +0800, Jisheng Zhang wrote:
> To avoid blocking for an excessive amount of time, eventually impacting
> on system responsiveness, hard interrupt handlers should finish
> executing in as little time as possible.
> 
> Use threaded interrupt and move the SPI transfer handling to an
> interrupt thread for host mode and non enhanced spi for two reasons:
> 
> "while the performance improvement will apply for both target mode
> has no control over the clocking of data by the host so is much more
> vulnerable to dropping data in a threaded interrupt if the system is
> loaded.  In host mode this isn't an issue since we'll simply stop
> clocking data while waiting for the scheduler to get round to the
> interrupt thread."

This isn't correct. FYI the IRQ-based Tx/Rx has been implemented in
the driver for a reason. The reason is - "damn automatic chip-select
toggling if there is no data to transmit in Tx FIFO." That is if a
platform uses the native controller chip-selects and the driver can't
feed the Tx FIFO fast enough so one wouldn't get empty for the entire
SPI-message handling, then the native CS will be automatically
de-asserted on the Tx FIFO emptying event which will effectively break
the message transfer.

So if you still wish the threaded IRQ handling, then it must be
utilized only for the non-native CS (like GPIO) or if the platform has
a custom native chip-select override.

-Joseph

> 

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

end of thread, other threads:[~2026-09-11 14:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-09 14:36 [PATCH v3 0/5] spi: dw: use threaded interrupt Jisheng Zhang
2026-09-09 14:36 ` [PATCH v3 1/5] spi: dw: use DW_SPI_ISR directly Jisheng Zhang
2026-09-09 14:36 ` [PATCH v3 2/5] spi: dw: remove useless dws->transfer_handler check Jisheng Zhang
2026-09-09 14:36 ` [PATCH v3 3/5] spi: dw: remove duplicated "!rx_len && !tx_len" handling from dw_spi_irq Jisheng Zhang
2026-09-09 14:36 ` [PATCH v3 4/5] spi: dw: restore previous irq handling behavior when !ctlr->cur_msg Jisheng Zhang
2026-09-09 14:36 ` [PATCH v3 5/5] spi: dw: use threaded interrupt and optimize the threaded ISR Jisheng Zhang
2026-09-10 22:17   ` Mark Brown
2026-09-11 14:22   ` Joseph Steel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®