-
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: Lukas 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: Mark Brown <broonie@kernel.org>
3bd7f658