Skip to contentSkip to conversation

spi: bcm2835: can_dma and scatter/gather question

DISCUSSION Martin Sperl 2 participants 2 messages Apr 30, 2015 1 message not in the archive SPI

lore
Share & tools
lore
#0 lore raw

I am trying to implement dma now for the spi-bcm2835 driver and I have come accross a few implementation details for border cases that make things "complicated"...

Things are fine and simple as long as transfers-length of an individual entry in the scatter-gather-list is a multiple of 4 bytes.

Otherwise the bcm2835-SPI-HW requires that we reset(empty) the FIFO as the DMA is pushing 32 bits with every transfer - even if we are only interrested in 2 bytes.

If this "reset" is not done then when the HW is enabled the next time those remaining bit will get shifted out automatically.

On top of that this also means that in case we have multiple entries in the scatter/gather list we have to have RX and TX scater-gathers with identical length to make things work propperly.

Here one of those complex examples for 6kb tx and rx, where the buffers are adjacent to each other and are NOT aligned on 32 bit boundries.

TX-scatter-gather list:
Page=0 start=0x001 end=0xfff lenfth=0xfff
Page=2 start=0x000 end=0x800 length=0x801
RX-scatter-gather list:
Page=2 start=0x801 end=0xfff length=0x7ff
Page=4 start=0x000 end=0xfff length=0x1000
Page=6 start=0x000 end=0x001 length=0x001

(page is the phyical/dma_address page, [start,end] are (inclusive) offsets inside the page)

For something like this to work we would need to split it like this:
TX-scatter-gather list:
Page=0 start=0x001 end=0x7ff lenfth=0x7ff
Page=0 start=0x800 end=0xfff lenfth=0x800
Page=2 start=0x000 end=0x7ff length=0x800
Page=2 start=0x800 end=0x800 length=0x001 RX-scatter-gather list:
Page=2 start=0x801 end=0xfff length=0x7ff
Page=4 start=0x000 end=0x7ff length=0x800
Page=4 start=0x800 end=0xfff length=0x800
Page=6 start=0x000 end=0x001 length=0x001

note that this would require a FIFO reset after the first and last transfer...

The question is: can the spi-framework fullfill those requirements as well? Otherwise there would be the need to add an additional translation step inside the driver to translate those...

Maybe we need to make the use of the mapping code configurable as well, or should such "custom" things go into prepare_message instead without implementing can_dma?

One more thing: is there a helper to create a sg_table for spi_message.is_dma_mapped==1?

Thanks, Martin
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw
Quoted 3 lines · Martin Sperl

The question is: can the spi-framework fullfill those requirements as well? Otherwise there would be the need to add an additional translation step inside the driver to translate those...

You can see the code for yourself... we're mostly not doing anything in the SPI code, we just throw a list of pages into a scatterlist but the actual mapping is done by the DMA mapping code which is free to do things like coalesce adjacent blocks. If the hardware genuinely requires that the Tx and Rx scatterlists have entries of exactly the same length I'm not sure that's going to be reliably satisfied if memory gets fragmented.

Quoted 3 lines

Maybe we need to make the use of the mapping code configurable as well, or should such "custom" things go into prepare_message instead without implementing can_dma?

It sounds like the driver should just not DMA anything that isn't page aligned and 32 bit multiple, or special case the first non-aligned bits. I'd expect anything doing large DMAs to be trying to make them page aligned anyway. A facility to provide an interface for cutting off the start and end of transfers for separate handling as PIO seems like a reasonable idea but I'm not immediately seeing a straightforward way to implement it, it seems like it might require most of the infrastructure we'd need in order to coalesce adjacent transfers in a message (which would be really nice to have).

Quoted 2 lines

One more thing: is there a helper to create a sg_table for spi_message.is_dma_mapped==1?

is_dma_mapped is legacy and should be going away rather than used in new code since just providing a single physical address really isn't enough, if we need something in future it'll be done with the scatterlist.