Re: [SAA7134, REQUEST] slow register writing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux