spi_async inside IRQ handler and spin_(un)lock_irq* doubt.

Daniel. danielhilst at gmail.com
Wed Nov 11 13:56:53 EST 2015

Hi everybody!

I'm using an gpio expansion called MCP23s17 from Microchip as a
digital input device. There are 6 input ports at my device. The MCP is
configured to generate an interrupt at input state change (from 0 to
1, or 1 to 0, what ever), the interrupts are disabled on MCP until the
INTCAP register is readed. This register holds a byte where each bit
represent the input port state at interrupt time. So my code does like

#1 An interrupt ocurred
#2 I initialize a spi_message to get INTCAP and fires a spi_async_locked.
#3 The SPI core do its stuff
#4 The complete callback is called. It gets the INTCAP value
     and put it on a circular queue to be read after by the user application.

So basicaly I enqueue INTCAP values to be consumed by user's
application. So far not so good. I'm facing problems of NULL pointers
at kernel after sometime when high throughput happens and/or when
multiple inputs changes at same time. The spi_message used at #2 is
always in the same memory area, allocated at probe time. What I'm
think is happening is that a new interrupt is happening while step #3
is running, so spi_message_init() is called on a message about to be
transferred, and when is transferred I got the NULL pointer handling
error. So I put a spin_lockirqsave() at step #2 before messing up with
the spi_message buffer and spin_unlock_irqrestore() at step #4. If
spi_async_locked() fails I unlock it too. But this make a big doubt
arises in my head.

Since interrupts are disabled at the chip (this is farly common) until
I read some register, should still I use spin_lock_irqsave()/restore()
routines or I'm safe to keep with normal spin_lock() ones? What
happens if an interrupt (from other hardware for example) happens
while a spin lock is held?

Here is the code: http://pastebin.com/JTubAHuz

Thanks in advance,

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

More information about the Kernelnewbies mailing list