2008-05-05 04:28:22 SPI transfer NOW (if possible)
Hans Eklund (SWEDEN)
Message: 55483
Ive been around this issue before, at moderate load of the system we see a heavy spread in the time it takes to execute a single and short spi_sync() with only a few bytes to transfer, sometimes not returning after 10-20ms or worse.
Im in need of making sure a short spi message to an FPGA unit get sent just within a few milliseconds, hardly a real-time problem, i just need to reconfiugure a camera running at 20-30 fps now and then. So in between the frames i need to some SPI. Raising FPS to 50-60 would require the SPI part of the code to execute(and return with success) even faster. There is an algorithm that need to be run on each frame also. But with the spi framework it can fail at times. I believe this is the source of the problem:
1) compose a message of two transfers, say 3 bytes TX and 3 byte RX.
2) call spi_sync which in turn cann spi_async and the thread will wait for completion.
3) spi_async will call spi->master->transfer that do queue_work on the pump_message() function.
4) once the message is processed, the message pump schedules the first transfer...
5) once the transfer is scheduled, the data is sent over the SPI bus and the next transfer is tasklet_schedules once again(either from dma interrupt or end of pio).
All the tasklet scheduling is really taking a toll here. Who knows what house keeping business would take place between each transfer. I would like to skip the tasklet_schedule latencies here and get to the fun part which is in 5) and also skipping the scheduling the next transfers and just call the transfer part directly(if possible). Im imagining this function could be allow to execute if
- there is only once spi protocol driver loded
- or the message queue is emtpy.
If a DMA transfer was intended we cant cut the DMA complete to workqueue latency, we will have to live with that, but the tasklet_schedule()'s could be cut if the circumstances are right. A short PIO transfer could be executed right away and return.
Im scetching on combining the transfer() and pump_messages() function (all found in spi_bfin5xx.c) into a single function call chain and add an option at the end of pump_transfers() to run it again directly recursiveley and not schedule it self as a tasklet.
Is this stupid? Could it be done? Would there be an easier way to make this happen? I would really like to see a function very soon that could send 10 bytes of SPI data at 20Mhz in < 1ms if the bus is idle!
/Hans
(edit: clarify, formatting)
QuoteReplyEditDelete
2008-05-05 07:30:31 Re: SPI transfer NOW (if possible)
Hans Eklund (SWEDEN)
Message: 55496
Done and... well half way done..
Implemented bfin_direct_transfer in the blackfin spi master.. a small hack of copy-pasted code to avoid tasklets and workqueues.
Test module uses it and do a 4 byte TX transfer only, compared to spi_sync(), No other busy threads on the system:
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 806 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 698 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 643 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 642 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 679 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 686 us
root:~> direl.sh
tic-toc[4]: do_transfer (bfin_direct_transfer) = 28 us
tic-toc[4]: do_transfer (spi_sync) = 643 us
root:~>
So we can cut the corners on small transfers. Ok, the excess ~600us is not dead CPU time of course.. but it feels somwhat unnecesary. One byte takes around 22us due to overhead of sending a message. (600/120 Mhz system, bf537).
Maybe not the best long term solution; but if there is only one spi protocol driver loaded in the system, this function could be made callable from interrupt context and force direct PIO transfers, a functionality requested now and then.
It remains to make it work with other drivers as well. If similar work has been done, feel free to say so
/H
QuoteReplyEditDelete
2008-06-18 02:55:50 Re: SPI transfer NOW (if possible)
Bryan Wu (CHINA)
Message: 57456
Hi Hans,
Sorry for jumping so later. I maybe missed your message in my Gmail.
I also thought about this long delay and long message travell problem before. Basically, your idea is correct to me. We can delete the tasklet_schedule() and transfer the message at once.
Could you please send us your patch? We intend to test it on our test machine. if it is ok, I'd like to merge it to our spi driver, because some customers complained the performance drop after we change spi from our own implementation to generic spi framework.
Thanks
-Bryan
QuoteReplyEditDelete
2011-04-25 15:45:27 Re: SPI transfer NOW (if possible)
Lars Weber Rasmussen (DENMARK)
Message: 100149
Having a similar issue with 'long' setup time. Once the transfer is running everything is fine, but .....
Does Hans Eklunds patch excist?
br
lars