On Mon, 2010-02-08 at 08:59 +0100, Hans Verkuil wrote: > On Monday 08 February 2010 08:20:14 Dmitri Belimov wrote: > > Hi All. > > > > I wrote SPI bitbang master over GPIO of saa7134. Speed of writing is much slow then in a Windows systems. > > I make some tests: > > > > Windows, SPI bitbang 97002 bytes x 2 time of writing is around 1.2 seconds > > Linux, SPI bitbang with call saa7134_set_gpio time of writing is 18 seconds > > Linux, SPI bitbang without call saa7134_set_gpio time of writing is 0.25seconds. > > > > The overhead of SPI subsystem is 0.25 seconds. Writing speed to registers of the saa7134 > > tooooo slooooow. > > > > What you think about it? > > Internally the spi subsystem uses delays based on some nsecs parameter. I see some > interesting code in spi_bitbang.h under #ifdef EXPAND_BITBANG_TXRX. My guess is > that you use the default timings from the spi subsystem that are too high for this > card. > > Try to discover what timings are currently in use and see if they match the > hardware spec. If not, then you should figure out how to optimize that. Dmitri, When looking for timing problems in the kernel, I found the tracing facility to be very useful. Using tracing on the ivtv driver, I found that ivtv-mailbox.c:ivtv_api_get_data() is a simple function being simply inefficient. It's consuming about half the time used in the ivtv_rq_handler() mostly doing uneeded PCI MMIO. Here's a typical example where ivtv_api_get_data() takes over half of the total execution time of the ivtv_irq_handler(): 1) | ivtv_irq_handler() { 1) + 53.471 us | ivtv_api_get_data(); 1) | stream_enc_dma_append() { 1) | ivtv_queue_move() { 1) 1.064 us | ivtv_queue_move_buf(); 1) 2.943 us | } 1) 0.824 us | pci_dma_sync_single_for_device(); 1) + 15.472 us | } 1) | ivtv_dma_enc_start() { 1) | ivtv_queue_move() { 1) 0.894 us | ivtv_queue_move_buf(); 1) 2.730 us | } 1) | ivtv_dma_enc_start_xfer() { 1) 0.845 us | pci_dma_sync_single_for_device(); 1) 7.282 us | } 1) + 13.088 us | } 1) + 91.243 us | } And another example: 1) | ivtv_irq_handler() { 1) + 41.701 us | ivtv_api_get_data(); 1) 0.884 us | pci_dma_sync_single_for_cpu(); 1) | dma_post() { 1) 1.514 us | pci_dma_sync_single_for_cpu(); 1) | ivtv_queue_move() { 1) 0.881 us | ivtv_queue_move_buf(); 1) 2.879 us | } 1) + 12.360 us | } 1) + 64.144 us | } Here's how I set up this sort of tracing on my Fedora 12 machine, in case you wish to try something similar: 1. Set up access to the kernel tracer $ su - root # mount # ls -al /sys/kernel/debug/ # mount -t debugfs debug /sys/kernel/debug/ # mount # less /sys/kernel/debug/tracing/README 2. Enable dynamic function tracing # cat /proc/sys/kernel/ftrace_enabled # echo 1 > /proc/sys/kernel/ftrace_enabled # cat /sys/kernel/debug/tracing/available_filter_functions 3. Perform a function_graph trace of the ivtv.ko module functions except the I2C bus calls # echo function_graph > /sys/kernel/debug/tracing/current_tracer # echo 0 > /sys/kernel/debug/tracing/options/latency-format # echo 0 > /sys/kernel/debug/tracing/options/verbose # echo 0 > /sys/kernel/debug/tracing/tracing_max_latency # echo > /sys/kernel/debug/tracing/set_ftrace_filter # nm --defined-only /lib/modules/`uname -r`/kernel/drivers/media/video/ivtv/ivtv.ko | \ grep ' [Tt] ' | grep -v trace | grep -v 'ivtv_[sg]ets[cd][al]' | \ grep -v map_single | awk '{print $3}' > /sys/kernel/debug/tracing/set_ftrace_filter # echo 1 > /sys/kernel/debug/tracing/tracing_enabled (perform 'cat /dev/video0 > foo.mpg' in another window for a bit) # echo 0 > /sys/kernel/debug/tracing/tracing_enabled # cat /sys/kernel/debug/tracing/trace > t1.txt # less t1.txt 4. Perform a function latency trace of the ivtv.ko module functions except for I2C bus calls # echo function > /sys/kernel/debug/tracing/current_tracer # echo 1 > /sys/kernel/debug/tracing/options/latency-format # echo 1 > /sys/kernel/debug/tracing/options/verbose # echo 0 > /sys/kernel/debug/tracing/tracing_max_latency # echo > /sys/kernel/debug/tracing/set_ftrace_filter # nm --defined-only /lib/modules/`uname -r`/kernel/drivers/media/video/ivtv/ivtv.ko | \ grep ' [Tt] ' | grep -v trace | grep -v 'ivtv_[sg]ets[cd][al]' | \ grep -v map_single | awk '{print $3}' > /sys/kernel/debug/tracing/set_ftrace_filter # echo 1 > /sys/kernel/debug/tracing/tracing_enabled (perform 'cat /dev/video0 > foo.mpg' in another window for a bit) # echo 0 > /sys/kernel/debug/tracing/tracing_enabled # cat /sys/kernel/debug/tracing/trace > t2.txt # less t2.txt Hopefully that can help you set up an experiment to find your timing delays. Regards, Andy -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html