[PATCH v3 1/2] spi: Split spi message into chunks of <65535 in the spi subsystem

Meghana Madhyastha meghana.madhyastha at gmail.com
Mon Mar 12 09:54:30 UTC 2018


Split spi messages into chunks of <65535 in the spi subsystem and remove the message
length warning in bcm2835_spi_can_dma. This is so that the messages can be transferred
via dma and that the tinydrm drivers need not split it. The current chunk size is 65532.
This is because the scatter gather segment is required to be multiple of 4. The size
has to be <65535 due to hardware limitations.

Signed-off-by: Meghana Madhyastha <meghana.madhyastha at gmail.com>
---
 drivers/spi/spi-bcm2835.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index f35cc10772f6..280ffa5aef7e 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -365,19 +365,6 @@ static bool bcm2835_spi_can_dma(struct spi_master *master,
 	if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH)
 		return false;
 
-	/* BCM2835_SPI_DLEN has defined a max transfer size as
-	 * 16 bit, so max is 65535
-	 * we can revisit this by using an alternative transfer
-	 * method - ideally this would get done without any more
-	 * interaction...
-	 */
-	if (tfr->len > 65535) {
-		dev_warn_once(&spi->dev,
-			      "transfer size of %d too big for dma-transfer\n",
-			      tfr->len);
-		return false;
-	}
-
 	/* if we run rx/tx_buf with word aligned addresses then we are OK */
 	if ((((size_t)tfr->rx_buf & 3) == 0) &&
 	    (((size_t)tfr->tx_buf & 3) == 0))
@@ -461,7 +448,7 @@ static void bcm2835_dma_init(struct spi_master *master, struct device *dev)
 
 	/* all went well, so set can_dma */
 	master->can_dma = bcm2835_spi_can_dma;
-	master->max_dma_len = 65535; /* limitation by BCM2835_SPI_DLEN */
+	master->max_dma_len = 65532; /* limitation by BCM2835_SPI_DLEN */
 	/* need to do TX AND RX DMA, so we need dummy buffers */
 	master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
 
@@ -597,7 +584,14 @@ static int bcm2835_spi_prepare_message(struct spi_master *master,
 {
 	struct spi_device *spi = msg->spi;
 	struct bcm2835_spi *bs = spi_master_get_devdata(master);
+	gfp_t gfp_flags = GFP_KERNEL | GFP_DMA;
 	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+	size_t max_transfer_size = 65532;
+	int ret;
+
+	ret = spi_split_transfers_maxsize(master, msg, max_transfer_size, gfp_flags);
+	if (ret)
+	       return ret;
 
 	cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
 
-- 
2.11.0



More information about the dri-devel mailing list