[PATCH] spi: rockchip: Disable local irq when pio write out of interrupt service

Jon Lin posted 1 patch 3 years, 10 months ago
drivers/spi/spi-rockchip.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
[PATCH] spi: rockchip: Disable local irq when pio write out of interrupt service
Posted by Jon Lin 3 years, 10 months ago
Avoid interrupt come and interrupt the pio_writer.

Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
Signed-off-by: Jon <jon.lin@rock-chips.com>
---

 drivers/spi/spi-rockchip.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index a08215eb9e14..2184de146928 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -199,6 +199,7 @@ struct rockchip_spi {
 	bool cs_high_supported; /* native CS supports active-high polarity */
 
 	struct spi_transfer *xfer; /* Store xfer temporarily */
+	spinlock_t lock; /* prevent I/O concurrent access */
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
@@ -293,9 +294,13 @@ static void rockchip_spi_handle_err(struct spi_controller *ctlr,
 
 static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
 {
-	u32 tx_free = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
-	u32 words = min(rs->tx_left, tx_free);
+	u32 tx_free;
+	u32 words;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rs->lock, flags);
+	tx_free = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
+	words = min(rs->tx_left, tx_free);
 	rs->tx_left -= words;
 	for (; words; words--) {
 		u32 txw;
@@ -308,6 +313,7 @@ static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
 		writel_relaxed(txw, rs->regs + ROCKCHIP_SPI_TXDR);
 		rs->tx += rs->n_bytes;
 	}
+	spin_unlock_irqrestore(&rs->lock, flags);
 }
 
 static void rockchip_spi_pio_reader(struct rockchip_spi *rs)
@@ -779,6 +785,8 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 		goto err_put_ctlr;
 	}
 
+	spin_lock_init(&rs->lock);
+
 	rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk");
 	if (IS_ERR(rs->apb_pclk)) {
 		dev_err(&pdev->dev, "Failed to get apb_pclk\n");
-- 
2.17.1
Re: [PATCH] spi: rockchip: Disable local irq when pio write out of interrupt service
Posted by Mark Brown 3 years, 10 months ago
On Mon, Jun 13, 2022 at 05:27:44PM +0800, Jon Lin wrote:
> Avoid interrupt come and interrupt the pio_writer.
> 
> +	spin_lock_irqsave(&rs->lock, flags);
> +	tx_free = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
> +	words = min(rs->tx_left, tx_free);
>  	rs->tx_left -= words;
>  	for (; words; words--) {
>  		u32 txw;
> @@ -308,6 +313,7 @@ static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
>  		writel_relaxed(txw, rs->regs + ROCKCHIP_SPI_TXDR);
>  		rs->tx += rs->n_bytes;
>  	}
> +	spin_unlock_irqrestore(&rs->lock, flags);

So this is effectively just disabling interrupts during PIO, there's no
other users of the lock which is rather heavyweight.  What's the actual
issue here?  We should also have something saying what's going on in the
code since right now the lock just looks redundant.