Patch "spi: atmel-qspi: Memory barriers after memory-mapped I/O" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    spi: atmel-qspi: Memory barriers after memory-mapped I/O

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     spi-atmel-qspi-memory-barriers-after-memory-mapped-i.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f94dafce8b288f1ee2fe8a321205cc2abc210ede
Author: Bence Csókás <csokas.bence@xxxxxxxxx>
Date:   Thu Dec 19 10:12:58 2024 +0100

    spi: atmel-qspi: Memory barriers after memory-mapped I/O
    
    [ Upstream commit be92ab2de0ee1a13291c3b47b2d7eb24d80c0a2c ]
    
    The QSPI peripheral control and status registers are
    accessible via the SoC's APB bus, whereas MMIO transactions'
    data travels on the AHB bus.
    
    Microchip documentation and even sample code from Atmel
    emphasises the need for a memory barrier before the first
    MMIO transaction to the AHB-connected QSPI, and before the
    last write to its registers via APB. This is achieved by
    the following lines in `atmel_qspi_transfer()`:
    
            /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
            (void)atmel_qspi_read(aq, QSPI_IFR);
    
    However, the current documentation makes no mention to
    synchronization requirements in the other direction, i.e.
    after the last data written via AHB, and before the first
    register access on APB.
    
    In our case, we were facing an issue where the QSPI peripheral
    would cease to send any new CSR (nCS Rise) interrupts,
    leading to a timeout in `atmel_qspi_wait_for_completion()`
    and ultimately this panic in higher levels:
    
            ubi0 error: ubi_io_write: error -110 while writing 63108 bytes
     to PEB 491:128, written 63104 bytes
    
    After months of extensive research of the codebase, fiddling
    around the debugger with kgdb, and back-and-forth with
    Microchip, we came to the conclusion that the issue is
    probably that the peripheral is still busy receiving on AHB
    when the LASTXFER bit is written to its Control Register
    on APB, therefore this write gets lost, and the peripheral
    still thinks there is more data to come in the MMIO transfer.
    This was first formulated when we noticed that doubling the
    write() of QSPI_CR_LASTXFER seemed to solve the problem.
    
    Ultimately, the solution is to introduce memory barriers
    after the AHB-mapped MMIO transfers, to ensure ordering.
    
    Fixes: d5433def3153 ("mtd: spi-nor: atmel-quadspi: Add spi-mem support to atmel-quadspi")
    Cc: Hari.PrasathGE@xxxxxxxxxxxxx
    Cc: Mahesh.Abotula@xxxxxxxxxxxxx
    Cc: Marco.Cardellini@xxxxxxxxxxxxx
    Cc: stable@xxxxxxxxxxxxxxx # c0a0203cf579: ("spi: atmel-quadspi: Create `atmel_qspi_ops`"...)
    Cc: stable@xxxxxxxxxxxxxxx # 6.x.y
    Signed-off-by: Bence Csókás <csokas.bence@xxxxxxxxx>
    Link: https://patch.msgid.link/20241219091258.395187-1-csokas.bence@xxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 32fcab2a11885..a62baef08e6a8 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -454,13 +454,20 @@ static int atmel_qspi_transfer(struct spi_mem *mem,
 	(void)atmel_qspi_read(aq, QSPI_IFR);
 
 	/* Send/Receive data */
-	if (op->data.dir == SPI_MEM_DATA_IN)
+	if (op->data.dir == SPI_MEM_DATA_IN) {
 		memcpy_fromio(op->data.buf.in, aq->mem + offset,
 			      op->data.nbytes);
-	else
+
+		/* Synchronize AHB and APB accesses again */
+		rmb();
+	} else {
 		memcpy_toio(aq->mem + offset, op->data.buf.out,
 			    op->data.nbytes);
 
+		/* Synchronize AHB and APB accesses again */
+		wmb();
+	}
+
 	/* Release the chip-select */
 	atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux