WLAN Horrible Roaming Performance (N800, OS2008), Software or Hardware Problem ?

Kalle Valo kalle.valo at nokia.com
Fri Feb 22 14:30:11 EET 2008


"ext Frantisek Dufka" <dufkaf at seznam.cz> writes:

> Kalle Valo wrote:
>
>> Nope, on N800 cx3110x and omap2_mcspi do not busyloop during the DMA
>> transfer. They use workqueues to allow sleeping, and completions for
>> signalling.
>>
>
> How is it so when you cannot sleep inside cx3110x_spi_dma_read and
> cx3110x_spi_dma_write?

I don't have the 770 sources here right now, but I'll try explain this
still. Basically the difference is the context where the functions are
called. Here's a simplified interrupt flow for 770:

interrupt handler -> tasklet -> cx3110x_spi_dma_read()

and here's the N800/N810 version:

interrupt handler -> workqueue -> cx3110x_spi_dma_read()

Because dma_read() is called from a workqueue (basically a dedicated
kernel process) it can sleep. In other words, dma_read() is called
from a process context. 

In 770 the call to dma_read() is issued from a tasklet instead. And
you cannot sleep in a tasklet (because it's in interrupt context,
meaning not a process, and cannot be rescheduled).

> There appears to be same code for N800 too just
> the body of those functions does not use McBSP but SPI API:
>
> spi_message_add_tail(&t[1], &m); 
>
> spi_sync(lp->spi_device, &m); 
>
>
> Does it mean we can wrap McBSP usage into similar api and leave
> cx3110x otherwise alone without restructuring it?

Yes, you could do something like that. Of course you cannot use SPI
framework, but similar wait_for_completion()/complete() pairs for
waiting McBSP DMA to finish.

> But still I don't get it, either spi_sync bysyloops or the semantics
> of cx3110x_spi_dma_write changed and it can return when the transfer
> is not yet done (??).

spi_sync() will return only after the transmission has finished. What
you are missing that in N800 there are two extra kernel processes
running. 770 version does not use any kernel processes (a tasklet is
not a process, basically).

Here's the spi_sync() function:

http://lxr.linux.no/linux/drivers/spi/spi.c#L526

Do you see that wait_for_completion()? It means that the process
calling this function is put to sleep and the scheduler will wake it
up only after someone calls complete() for the 'done' completion
structure. That someone is spi_complete() few lines above, which will
be called from omap_mcspi2 process after the transfer has completed.

Do I make any sense?

If you are interested more, LDD3 is a good read:

http://lwn.net/Kernel/LDD3/

> BTW, let's remove maemo-developers at maemo.org and move just to
> cx3110x-devel at garage.maemo.org

I agree.

-- 
Kalle Valo



More information about the cx3110x-devel mailing list