I'm using kernel 3.14.52 and I found the source code kernel/driver/tty/serial/imx.c will got the DMA transmit status but do not deal with it.
Imx.c (drivers\tty\serial)
static void dma_rx_callback(void *data)
{
struct imx_port *sport = data;
struct dma_chan *chan = sport->dma_chan_rx;
struct tty_struct *tty = sport->port.state->port.tty;
struct dma_tx_state state;
enum dma_status status;
unsigned int count;
/* If we have finish the reading. we will not accept any more data. */
if (tty->closing) {
imx_rx_dma_done(sport);
return;
}
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); // to get DMA status but not care this return value "status"?
+ if(DMA_ERROR == status){
+ dmaengine_terminate_all(chan);
+ dmaengine_resume(chan);
+ }
count = RX_BUF_SIZE - state.residue;
sport->rx_buf.buf_info[sport->rx_buf.cur_idx].filled = true;
sport->rx_buf.buf_info[sport->rx_buf.cur_idx].rx_bytes = count;
sport->rx_buf.cur_idx++;
sport->rx_buf.cur_idx %= IMX_RXBD_NUM;
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (sport->rx_buf.cur_idx == sport->rx_buf.last_completed_idx)
dev_err(sport->port.dev, "overwrite!\n");
if (count)
dma_rx_work(sport);
}
The DMA status defined
Dmaengine.h (include\linux)
enum dma_status {
DMA_COMPLETE,
DMA_IN_PROGRESS,
DMA_PAUSED,
DMA_ERROR,
};