struct tty_port *tty_port = &p->port.state->port;
struct dma_tx_state state;
int count;
+ unsigned long flags;
+ spin_lock_irqsave(&p->port.lock, flags);
+ del_timer(&dma->dma_rx_timer);
dma->rx_running = 0;
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
- count = dma->rx_size - state.residue;
+ count = dma->rx_size - state.residue - dma->rx_index;
+ tty_insert_flip_string(tty_port, dma->rx_buf + dma->rx_index, count);
+ p->port.icount.rx += count;
+ dma->rx_index = dma->rx_size - state.residue;
+
+ tty_flip_buffer_push(tty_port);
+
+ /* RDI can be enable again, so that dma transfer can be restarted */
+ p->ier |= (UART_IER_RLSI | UART_IER_RDI);
+ p->port.read_status_mask |= UART_LSR_DR;
+ serial_port_out(&p->port, UART_IER, p->ier);
+
+ spin_unlock_irqrestore(&p->port.lock, flags);
+}
+
+void __dma_rx_timer_callback(unsigned long param)
+{
+ struct uart_8250_port *p = (struct uart_8250_port *)param;
+ struct uart_8250_dma *dma = p->dma;
+ struct tty_port *tty_port = &p->port.state->port;
+ struct dma_tx_state state;
+ int count;
+ unsigned long flags;
+
+ if (dma->rx_running == 0)
+ return;
+
+ spin_lock_irqsave(&p->port.lock, flags);
+ dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
- tty_insert_flip_string(tty_port, dma->rx_buf, count);
+ count = dma->rx_size - state.residue - dma->rx_index;
+ tty_insert_flip_string(tty_port, dma->rx_buf + dma->rx_index, count);
p->port.icount.rx += count;
+ dma->rx_index = dma->rx_size - state.residue;
tty_flip_buffer_push(tty_port);
+ spin_unlock_irqrestore(&p->port.lock, flags);
+
+ mod_timer(&dma->dma_rx_timer, jiffies + msecs_to_jiffies(10));
}
int serial8250_tx_dma(struct uart_8250_port *p)
dma->rx_cookie = dmaengine_submit(desc);
dma_async_issue_pending(dma->rxchan);
+ dma->rx_index = 0;
+
+ mod_timer(&dma->dma_rx_timer, jiffies + msecs_to_jiffies(10));
return 0;
}
dma->rxconf.direction = DMA_DEV_TO_MEM;
dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->rxconf.src_addr = p->port.mapbase + UART_RX;
+ dma->rxconf.src_maxburst = 1;
dma->txconf.direction = DMA_MEM_TO_DEV;
dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->txconf.dst_addr = p->port.mapbase + UART_TX;
+ dma->txconf.dst_maxburst = 1;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dev_dbg_ratelimited(p->port.dev, "got both dma channels\n");
+ /* init rx timer */
+ dma->dma_rx_timer.function = __dma_rx_timer_callback;
+ dma->dma_rx_timer.data = (unsigned long)p;
+ dma->dma_rx_timer.expires = jiffies + msecs_to_jiffies(10);
+ init_timer(&dma->dma_rx_timer);
+
return 0;
err:
dma_release_channel(dma->rxchan);
if (!dma)
return;
+ del_timer_sync(&dma->dma_rx_timer);
+
/* Release RX resources */
dmaengine_terminate_all(dma->rxchan);
dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,