Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi/spi-bcm2835: Split transfers that exceed DLEN

Split spi transfers into chunks of <=65532 to enable the driver to
perform DMA transfer on big buffers. The DLEN register specifies the
number of bytes to transfer in DMA mode. It is 16-bit wide and thus the
maximum DMA transfer is 65535 bytes. Set the maximum to 65532 (4 byte
aligned) since the FIFO in DMA mode is accessed in 4 byte chunks.

->max_dma_len is the value the spi core uses when splitting the buffer
into scatter gather entries.
The BCM2835 DMA block has 2 types of channels/engines:
- Normal: Max length: 1G
- Lite: Max length: 65535

Even when using a Lite channel we will not exceed the max length, so
let's drop setting ->max_dma_len.

Signed-off-by: Meghana Madhyastha <meghana.madhyastha@gmail.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Meghana Madhyastha and committed by
Mark Brown
8b7bd10e 937e6d75

+11 -28
+11 -28
drivers/spi/spi-bcm2835.c
··· 335 335 return 1; 336 336 } 337 337 338 - /* 339 - * DMA support 340 - * 341 - * this implementation has currently a few issues in so far as it does 342 - * not work arrount limitations of the HW. 343 - * 344 - * the main one being that DMA transfers are limited to 16 bit 345 - * (so 0 to 65535 bytes) by the SPI HW due to BCM2835_SPI_DLEN 346 - * 347 - * there may be a few more border-cases we may need to address as well 348 - * but unfortunately this would mean splitting up the scatter-gather 349 - * list making it slightly unpractical... 350 - */ 351 - 352 338 /** 353 339 * bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA 354 340 * @master: SPI master ··· 616 630 if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH) 617 631 return false; 618 632 619 - /* BCM2835_SPI_DLEN has defined a max transfer size as 620 - * 16 bit, so max is 65535 621 - * we can revisit this by using an alternative transfer 622 - * method - ideally this would get done without any more 623 - * interaction... 624 - */ 625 - if (tfr->len > 65535) { 626 - dev_warn_once(&spi->dev, 627 - "transfer size of %d too big for dma-transfer\n", 628 - tfr->len); 629 - return false; 630 - } 631 - 632 633 /* return OK */ 633 634 return true; 634 635 } ··· 680 707 681 708 /* all went well, so set can_dma */ 682 709 master->can_dma = bcm2835_spi_can_dma; 683 - master->max_dma_len = 65535; /* limitation by BCM2835_SPI_DLEN */ 684 710 /* need to do TX AND RX DMA, so we need dummy buffers */ 685 711 master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; 686 712 ··· 816 844 struct spi_device *spi = msg->spi; 817 845 struct bcm2835_spi *bs = spi_master_get_devdata(master); 818 846 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 847 + int ret; 848 + 849 + /* 850 + * DMA transfers are limited to 16 bit (0 to 65535 bytes) by the SPI HW 851 + * due to DLEN. Split up transfers (32-bit FIFO aligned) if the limit is 852 + * exceeded. 853 + */ 854 + ret = spi_split_transfers_maxsize(master, msg, 65532, 855 + GFP_KERNEL | GFP_DMA); 856 + if (ret) 857 + return ret; 819 858 820 859 cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); 821 860