• Lukas Wunner's avatar
    spi: bcm2835: Overcome sglist entry length limitation · 3bd7f658
    Lukas Wunner authored
    When in DMA mode, the BCM2835 SPI controller requires that the FIFO is
    accessed in 4 byte chunks.  This rule is not fulfilled if a transfer
    consists of multiple sglist entries, one per page, and the first entry
    starts in the middle of a page with an offset not a multiple of 4.
    
    The driver currently falls back to programmed I/O for such transfers,
    incurring a significant performance penalty.
    
    Overcome this hardware limitation by transferring the first few bytes of
    a transfer without DMA such that the remainder of the first sglist entry
    becomes a multiple of 4.  Specifics are provided in kerneldoc comments.
    
    An alternative approach would have been to split transfers in the
    ->prepare_message hook, but this may necessitate two transfers per page,
    defeating the goal of clustering multiple pages together in a single
    transfer for efficiency.  E.g. if the first TX sglist entry's length is
    23 and the first RX's is 40, the first transfer would send and receive
    23 bytes, the second 40 - 23 = 17 bytes, the third 4096 - 17 = 4079
    bytes, the fourth 4096 - 4079 = 17 bytes and so on.  In other words,
    O(n) transfers are necessary (n = number of sglist entries), whereas
    the algorithm implemented herein only requires O(1) additional work.
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Cc: Mathias Duckeck <m.duckeck@kunbus.de>
    Cc: Frank Pavlic <f.pavlic@kunbus.de>
    Cc: Martin Sperl <kernel@martin.sperl.org>
    Cc: Noralf Trønnes <noralf@tronnes.org>
    Signed-off-by: default avatarMark Brown <broonie@kernel.org>
    3bd7f658
spi-bcm2835.c 27.4 KB