lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241030194920.3202282-1-chris.packham@alliedtelesis.co.nz>
Date: Thu, 31 Oct 2024 08:49:20 +1300
From: Chris Packham <chris.packham@...iedtelesis.co.nz>
To: broonie@...nel.org,
	miquel.raynal@...tlin.com
Cc: linux-spi@...r.kernel.org,
	linux-mtd@...ts.infradead.org,
	linux-kernel@...r.kernel.org,
	Chris Packham <chris.packham@...iedtelesis.co.nz>
Subject: [PATCH v2] spi: spi-mem: rtl-snand: Correctly handle DMA transfers

The RTL9300 has some limitations on the maximum DMA transfers possible.
For reads this is 2080 bytes (520*4) for writes this is 520 bytes. Deal
with this by splitting transfers into appropriately sized parts.

Fixes: 42d20a6a61b8 ("spi: spi-mem: Add Realtek SPI-NAND controller")
Signed-off-by: Chris Packham <chris.packham@...iedtelesis.co.nz>
---

Notes:
    Changes in v2:
    - Drop unecessary "also" change. data.in and data.out point to the same
      memory but the latter is marked as const which causes some compiler
      warnings when we're trying to get a dma mapping for it.

 drivers/spi/spi-realtek-rtl-snand.c | 46 +++++++++++++++++++----------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-realtek-rtl-snand.c b/drivers/spi/spi-realtek-rtl-snand.c
index 23c42c8469e4..cd0484041147 100644
--- a/drivers/spi/spi-realtek-rtl-snand.c
+++ b/drivers/spi/spi-realtek-rtl-snand.c
@@ -231,19 +231,22 @@ static int rtl_snand_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_
 
 static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_op *op)
 {
+	unsigned int pos, nbytes;
 	int ret;
 	dma_addr_t buf_dma;
 	enum dma_data_direction dir;
-	u32 trig;
+	u32 trig, len, maxlen;
 
 	ret = rtl_snand_xfer_head(snand, cs, op);
 	if (ret)
 		goto out_deselect;
 
 	if (op->data.dir == SPI_MEM_DATA_IN) {
+		maxlen = 2080;
 		dir = DMA_FROM_DEVICE;
 		trig = 0;
 	} else if (op->data.dir == SPI_MEM_DATA_OUT) {
+		maxlen = 520;
 		dir = DMA_TO_DEVICE;
 		trig = 1;
 	} else {
@@ -264,26 +267,37 @@ static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_
 	if (ret)
 		goto out_unmap;
 
-	reinit_completion(&snand->comp);
+	pos = 0;
+	len = op->data.nbytes;
 
-	ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma);
-	if (ret)
-		goto out_disable_int;
+	while (pos < len) {
+		nbytes = len - pos;
+		if (nbytes > maxlen)
+			nbytes = maxlen;
 
-	ret = regmap_write(snand->regmap, SNAFDLR,
-			   CMR_WID(op->data.buswidth) | (op->data.nbytes & 0xffff));
-	if (ret)
-		goto out_disable_int;
+		reinit_completion(&snand->comp);
 
-	ret = regmap_write(snand->regmap, SNAFDTR, trig);
-	if (ret)
-		goto out_disable_int;
+		ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma + pos);
+		if (ret)
+			goto out_disable_int;
 
-	if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
-		ret = -ETIMEDOUT;
+		pos += nbytes;
 
-	if (ret)
-		goto out_disable_int;
+		ret = regmap_write(snand->regmap, SNAFDLR,
+				CMR_WID(op->data.buswidth) | nbytes);
+		if (ret)
+			goto out_disable_int;
+
+		ret = regmap_write(snand->regmap, SNAFDTR, trig);
+		if (ret)
+			goto out_disable_int;
+
+		if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
+			ret = -ETIMEDOUT;
+
+		if (ret)
+			goto out_disable_int;
+	}
 
 out_disable_int:
 	regmap_update_bits(snand->regmap, SNAFCFR, SNAFCFR_DMA_IE, 0);
-- 
2.47.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ