SPI operations on interrupt context!?

Daniel. danielhilst at gmail.com
Tue Sep 8 17:23:31 EDT 2015


Even spi_async sleeps? I thought that spi_async wouldn't sleep :/

I have a board with an MCP23S17 gpio expander that is used as an
digital input. I need to notify my application every time that any
input status changes. The MCP triggers an interrupt every time that an
input changes, but, the application may not be able to poll the MCP at
the same rate that the input changes, so I used a circular queue at
MCP driver. I need to add input changes (readed from INTCAP) as soon
as they came, to be free to get new input changes as soon as possible.
I'm looking for 1ms resolution here, so, summarizing, I want to be
able to enqueue input changes at each 1ms.

The MCP works like this.

1 - Input changes (set IRQ flags)
2 - Raise IRQ
3 - IRS reads INTCAP (this clears IRQ flags)

Okay, ... I was enqueing on the threaded IRQ, but was losing events.
The "losing events" here means that I got two interrupts in a row,
with same INTCAP values, so I got input changes notification (IRS
called) with no input changes. I think that a new interrupt is being
raised before I read INTCAP so it got masked. The big question is: How
to read INTCAP as fast as possible?

This is why I tried spi_async in interrupt context. (mcp_hard_irq),
but I'm still losing events at 1ms resolution.

So, explaning the mess I did in the code :), first of all I've updated
the code, is still in the same link:
https://gist.github.com/gkos/4cce494e90518077084a

I've decided to use a producing/consuming aproach, since application
will never be abble to poll input status at same rate that it changes
I need to enqueue it. To do this I've created a new function inside
this module. mcp_getlast() should take the last element in queue, or
wait for next event if is empty, is my consumer, here it is:
https://gist.github.com/gkos/4cce494e90518077084a#file-gpio-mcp23s08-c-L182

The procucer is the mcp23s17_produce_complete handler, it should
enqueue INTCAP and return. This is it!
https://gist.github.com/gkos/4cce494e90518077084a#file-gpio-mcp23s08-c-L346

I've enabled tracing on my kernel (3.10.53 running on an i.MX6 quad).
At the trace file I got this lines:
        spi32766-72    [000] d...  2589.220910:
mcp23s17_produce_complete: mcp23s08: produced ffffff01
        spi32766-72    [000] d...  2589.222973:
mcp23s17_produce_complete: mcp23s08: produced ffffff00
        spi32766-72    [000] d...  2589.223235:
mcp23s17_produce_complete: mcp23s08: produced ffffff01
        spi32766-72    [000] d...  2589.226119:
mcp23s17_produce_complete: mcp23s08: produced ffffff00
        spi32766-72    [000] d...  2589.227631:
mcp23s17_produce_complete: mcp23s08: produced ffffff00
        spi32766-72    [000] d...  2589.227898:
mcp23s17_produce_complete: mcp23s08: produced ffffff01

There is possible see that INTCAP repeated (..ff00). This my problem!

Well, thanks anybody that readed that long, any ideia would be helpful

Best regards,


2015-09-08 16:30 GMT-03:00 anish singh <anish198519851985 at gmail.com>:
>
>
> On Tue, Sep 8, 2015 at 10:19 AM, Daniel. <danielhilst at gmail.com> wrote:
>>
>> Hi all,
>>
>> I'm dealing with a SPI driver and I have a doubt. I need to read and write
>> data to spi (registers and values) inside interrupt handler. I want to know
>> if this pattern is safe or if I'll face problems with it.
>
>
> AFAIK the spi calls sleep, so it is not safe.
>>
>>
>> This code is being added to gpio-mcp23s08.c driver to handle IRQ and save
>> INTCAP at interruption time. INTCAP register keeps the input port status at
>> interruption time. I want to capture this as fast as possible and put it at
>> a circular queue. I write this code inspired by spi_sync function, but using
>> spinlocks so it doesn't sleeps. But, these spin_(un)lock calls seems a bad
>> ideia to me. Any better idea or guidelines?
>>
>> Here is the code.
>>
>> https://gist.github.com/gkos/4cce494e90518077084a#file-gpio-mcp23s08-c-L440
>>
>> The functions are mcp23s17_read_irqsafe and mcp23s17_read_irqsafe_complete
>>
>> PS: The code is a little messed up (because I've been trying to optimize
>> this INTCAP capturing by many means)
>>
>  What exactly you are trying to optimize you have not mentioned. I looked at
> the driver code
> you pointed out in your mail and looks like they are using threaded irq and
> I am sure that you
> understand that threaded irq can perform sleeping operations as it is
> basically a kthread.
>
> http://lxr.free-electrons.com/source/drivers/gpio/gpio-mcp23s08.c#L494 so
> you can easily use
> spinlock here. It is not interrupt context.
>
> Generally if you are trying to optimize something in linux kernel you should
> be very clear about your goal.
>
>> Cheers
>> - dhs
>>
>> --
>> "Do or do not. There is no try"
>>   Yoda Master
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>



-- 
"Do or do not. There is no try"
  Yoda Master



More information about the Kernelnewbies mailing list