ACPI GPE handler: mtx_lock() by idle thread
Yuri Pankov
yuripv at yuripv.net
Tue Sep 11 17:39:50 UTC 2018
Konstantin Belousov wrote:
> On Tue, Sep 11, 2018 at 08:19:26AM +0300, Yuri Pankov wrote:
>> I have the panic shown below with a simple device driver that installs
>> GPE handler in the attach routine, and does nothing else than waiting
>> for GPEs. No matter if I try to handle it sync (calling
>> SPIBUS_TRANSFER() from the handler), or async (calling
>> taskqueue_enqueue()), once one of those functions called from the
>> handler does mtx_lock(), it panics. Any hints?
> If you look at the backtrace below, you would note that ACPI GPE event
> handler is executed in the context of an interrupt. It means that it
> borrows the context of whatever thread was executed on the CPU when the
> interrupt occured. One of the consequences is that an interrupt handler
> (fast interrupt handler in the FreeBSD terminology) cannot block or
> sleep, see locking(9).
>
> There is a different way to handle interrupts in FreeBSD, by normal (not
> fast) interrupt handlers. There, the code executing in the context of
> interrupt only wakes up the interrupt thread, which executes the handler
> in its dedicated context. As the consequence, mutexes do work for such
> handlers. Still, sleep is prohibited.
>
> I briefly looked at the dev/intel/spi.c code and I see that
> intelspi_transfer() sleeps waiting for the hardware event. In other
> words, even normal interrupt handler cannot help your problem.
>
> Is it required to do the transfers in the interrupt handler code, for
> your work ? If not, then the usual solution is to delegate the work
> that requires resource acquision, to the fast taskqueue. Your code in
> GPE event handler would only schedule a task, and the running task can
> do whatever slow operations it needs. See taskqueue(9), there are
> enough examples of the fast taskqueue use in the tree.
Of course, I don't need to process the event in the GPE handler, and
just noted that I tried to compare with taskqueue_enqueue()'d async
handler, which produced the same results mainly because I was stupid and
didn't notice that there's a separate predefined taskqueue for interrupt
processing, taskqueue_fast. Now all looks good, I have the chance to do
spi transfer in async handler.
Thank you for all your help.
More information about the freebsd-hackers
mailing list