Kernel dump with mxs-auart.c in DMA mode

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Kernel dump with mxs-auart.c in DMA mode

1,453件の閲覧回数
YS
Contributor IV

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;
}

ラベル(1)
0 件の賞賛
返信
2 返答(返信)

935件の閲覧回数
YS
Contributor IV

Okay, my patch seems like working. AUART can now handle up to 2Mbps throughput (not bitrate) with DMA mode. No kernel dump observed so far.

0 件の賞賛
返信

935件の閲覧回数
guillaume_lecoc
Contributor I

Hi,

I think your patch is not complete, because you did not correct the normal mode. Shouldn't you do the same at the end of mxs_auart_rx_chars(struct mxs_auart_port *s), because it is also called in irq context.

Also, after reading tty_flip_buffer() from atomic context when low_latency==1 (Linux Serial), it seems to me that the flag ASYNC_LOW_LATENCY has to be removed. After some investigation, its seems to be used in different context.

It is mostly (and commonly) set by userland software which want to reduce the latency when receiving characters. In this case, it is used by driver to change the way they drive the hardware depending on what the user want.

It is only set by some few driver (like CDC-ACM for example). In this case, not that the userland have no way to disable this flag.

Imho (but correct me if I'm wrong), it should never be set by the driver directly but the driver should take care of it (like your patch did), and not throw an ugly exception if this flag is requested by the user.

By the way, I was going here because I saw some latency problem, and that flag felt really strange to me and caught my attention.

I figure out that my problem was related to the "really high" value of the rxtimeout flag which is configured to 0x80 in DMA mode (1031 bits), whereas the reference manual wrote that the default value is 0x03 (31 bits).

0 件の賞賛
返信