Yuji Sasaki

Kernel dump with mxs-auart.c in DMA mode

Discussion created by Yuji Sasaki on Aug 7, 2012
Latest reply on Oct 22, 2013 by Guillaume Lecocq

I experienced "BUG: scheduling while atomic:" Kernel dump with mxs-auart.c (after Freescale patch applied) in DMA mode. I tracked down the cause - in DMA mode, mxs-auart.c sets ASYNC_LOW_LATENCY flags on uart_port structure which eventually turn tty->low_latency flag in serial_core.c.

The patched mxs-auart.c uses tasklet to process bottom-half of DMA interrupt. In the end the tasklet callses tty_flip_buffer_push() to pass received data to user process. However tty_flip_buffer_push() is strictly prohibited to be called from IRQ hander with low_latency flag=1, since it will directly calls flush_to_ldisc() API, which includes mutex lock to tty->termios_mutex. Interrupt could happen any time, even when application access to the /dev/ttySPx and locks the mutex. If this happens, Linux kernel dumps with "BUG: scheduling while atomic" error.

 

I'm not sure if I should eliminate ASYNC_LOW_LATENCY flag completely. At this point I'm testing mxs-auart.c driver with my patch to temporally disable low_latency flag while calling tty_flip_buffer_push() from dma_rx_do_tasklet.

 

static void dma_rx_do_tasklet(unsigned long arg)
{
        .
        .
        .
        int low_latency_backup;
        .
        .
        .
        /* tty_flip_buffer_push strictly prohibits to be called
         * from IRQ handler with low_latency=1 to avoid
         * task scheduling (mutex lock) */
        low_latency_backup = tty->low_latency;
        tty->low_latency = 0;
        tty_flip_buffer_push(tty);
        tty->low_latency = low_latency_backup;
}

Outcomes