0405-dmaengine-bcm2835-Avoid-splitting-periods-into-very-.patch 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. From 1b57eb7cd54e31f84df2378c3858a4ad2d3ab8a1 Mon Sep 17 00:00:00 2001
  2. From: Matthias Reichl <hias@horus.com>
  3. Date: Wed, 8 Jun 2016 13:09:56 +0200
  4. Subject: [PATCH] dmaengine: bcm2835: Avoid splitting periods into very small
  5. chunks
  6. The current cyclic DMA period splitting implementation can generate
  7. very small chunks at the end of each period. For example a 65536 byte
  8. period will be split into a 65532 byte chunk and a 4 byte chunk on
  9. the "lite" DMA channels.
  10. This increases pressure on the RAM controller as the DMA controller
  11. needs to fetch two control blocks from RAM in quick succession and
  12. could potentially cause latency issues if the RAM is tied up by other
  13. devices.
  14. We can easily avoid these situations by distributing the remaining
  15. length evenly between the last-but-one and the last chunk, making
  16. sure that split chunks will be at least half the maximum length the
  17. DMA controller can handle.
  18. This patch checks if the last chunk would be less than half of
  19. the maximum DMA length and if yes distributes the max len+4...max_len*1.5
  20. bytes evenly between the last 2 chunks. This results in chunk sizes
  21. between max_len/2 and max_len*0.75 bytes.
  22. Signed-off-by: Matthias Reichl <hias@horus.com>
  23. Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
  24. Tested-by: Clive Messer <clive.messer@digitaldreamtime.co.uk>
  25. ---
  26. drivers/dma/bcm2835-dma.c | 14 ++++++++++++++
  27. 1 file changed, 14 insertions(+)
  28. --- a/drivers/dma/bcm2835-dma.c
  29. +++ b/drivers/dma/bcm2835-dma.c
  30. @@ -253,6 +253,20 @@ static void bcm2835_dma_create_cb_set_le
  31. /* have we filled in period_length yet? */
  32. if (*total_len + control_block->length < period_len) {
  33. + /*
  34. + * If the next control block is the last in the period
  35. + * and it's length would be less than half of max_len
  36. + * change it so that both control blocks are (almost)
  37. + * equally long. This avoids generating very short
  38. + * control blocks (worst case would be 4 bytes) which
  39. + * might be problematic. We also have to make sure the
  40. + * new length is a multiple of 4 bytes.
  41. + */
  42. + if (*total_len + control_block->length + max_len / 2 >
  43. + period_len) {
  44. + control_block->length =
  45. + DIV_ROUND_UP(period_len - *total_len, 8) * 4;
  46. + }
  47. /* update number of bytes in this period so far */
  48. *total_len += control_block->length;
  49. return;