Skip to content

Commit

Permalink
WIP: serial: 8250_dma: use sgl on transmit
Browse files Browse the repository at this point in the history
Signed-off-by: Ferry Toth <ftoth@exalondelft.nl>
  • Loading branch information
htot committed May 14, 2021
1 parent 200034f commit 174a779
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
3 changes: 3 additions & 0 deletions drivers/tty/serial/8250/8250.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct uart_8250_dma {
unsigned char tx_running;
unsigned char tx_err;
unsigned char rx_running;

unsigned int dma_tx_nents;
struct scatterlist tx_sgl[2];
};

struct old_serial_port {
Expand Down
34 changes: 25 additions & 9 deletions drivers/tty/serial/8250/8250_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ static void __dma_tx_complete(void *param)
{
struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma;
struct scatterlist *sgl = dma->tx_sgl;
struct circ_buf *xmit = &p->port.state->xmit;
unsigned long flags;
int ret;

dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_sync_sg_for_cpu(dma->txchan->device->dev, sgl,
dma->dma_tx_nents, DMA_TO_DEVICE);

spin_lock_irqsave(&p->port.lock, flags);

Expand Down Expand Up @@ -60,9 +61,12 @@ static void __dma_rx_complete(struct uart_8250_port *p, struct uart_8250_dma *dm
int serial8250_tx_dma(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
struct scatterlist *sgl = dma->tx_sgl;
struct circ_buf *xmit = &p->port.state->xmit;
struct dma_async_tx_descriptor *desc;
int ret;
size_t chunk1, chunk2;
int head, tail;

if (dma->tx_running)
return 0;
Expand All @@ -73,12 +77,24 @@ int serial8250_tx_dma(struct uart_8250_port *p)
return 0;
}

dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
head = xmit->head;
tail = xmit->tail;
dma->dma_tx_nents = 1;
chunk1 = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE);
chunk2 = CIRC_CNT(head, tail, UART_XMIT_SIZE) - chunk1;
if (chunk2 == 0) {
sg_init_one(sgl, xmit->buf + tail, chunk1);
} else {
dma->dma_tx_nents++;
sg_init_table(sgl, dma->dma_tx_nents);
sg_set_buf(sgl, xmit->buf + tail, chunk1);
sg_set_buf(sgl + 1, xmit->buf, chunk2);
}
dma->tx_size = chunk1 + chunk2;

desc = dmaengine_prep_slave_single(dma->txchan,
dma->tx_addr + xmit->tail,
dma->tx_size, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
desc = dmaengine_prep_slave_sg(dma->txchan, sgl, dma->dma_tx_nents,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
ret = -EBUSY;
goto err;
Expand All @@ -90,8 +106,8 @@ int serial8250_tx_dma(struct uart_8250_port *p)

dma->tx_cookie = dmaengine_submit(desc);

dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_sync_sg_for_device(dma->txchan->device->dev, sgl,
dma->dma_tx_nents, DMA_TO_DEVICE);

dma_async_issue_pending(dma->txchan);
if (dma->tx_err) {
Expand Down

0 comments on commit 174a779

Please sign in to comment.