Skip to content

Commit bf04dcc

Browse files
authored
Merge pull request #35 from htot/hsu_dma_optimize
Hsu dma optimize
2 parents 8d4b6bf + e12d3f2 commit bf04dcc

File tree

4 files changed

+61
-5
lines changed

4 files changed

+61
-5
lines changed

drivers/tty/serial/8250/8250.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ struct uart_8250_dma {
4949
unsigned char tx_running;
5050
unsigned char tx_err;
5151
unsigned char rx_running;
52+
53+
unsigned int dma_tx_nents;
54+
struct scatterlist tx_sgl[2];
5255
};
5356

5457
struct old_serial_port {

drivers/tty/serial/8250/8250_dma.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ static void __dma_rx_complete(void *param)
6262
int serial8250_tx_dma(struct uart_8250_port *p)
6363
{
6464
struct uart_8250_dma *dma = p->dma;
65+
struct scatterlist *sgl = dma->tx_sgl;
6566
struct circ_buf *xmit = &p->port.state->xmit;
6667
struct dma_async_tx_descriptor *desc;
6768
int ret;
69+
size_t chunk1, chunk2;
70+
int head, tail;
6871

6972
if (dma->tx_running)
7073
return 0;
@@ -75,12 +78,28 @@ int serial8250_tx_dma(struct uart_8250_port *p)
7578
return 0;
7679
}
7780

78-
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
81+
head = READ_ONCE(xmit->head);
82+
tail = READ_ONCE(xmit->tail);
83+
dma->dma_tx_nents = 1;
84+
chunk1 = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE);
85+
chunk2 = CIRC_CNT(head, tail, UART_XMIT_SIZE) - chunk1;
86+
if (chunk2 == 0) {
87+
sg_init_one(sgl, xmit->buf + tail, chunk1);
88+
} else {
89+
dma->dma_tx_nents++;
90+
sg_init_table(sgl, dma->dma_tx_nents);
91+
sg_set_buf(&sgl[0], xmit->buf + tail, chunk1);
92+
sg_set_buf(&sgl[1], xmit->buf, chunk2);
93+
sg_dma_address(&sgl[1]) = dma->tx_addr;
94+
sg_dma_len(&sgl[1]) = chunk2;
95+
}
96+
sg_dma_address(&sgl[0]) = dma->tx_addr + tail;
97+
sg_dma_len(&sgl[0]) = chunk1;
98+
dma->tx_size = chunk1 + chunk2;
7999

80-
desc = dmaengine_prep_slave_single(dma->txchan,
81-
dma->tx_addr + xmit->tail,
82-
dma->tx_size, DMA_MEM_TO_DEV,
83-
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
100+
desc = dmaengine_prep_slave_sg(dma->txchan, sgl, dma->dma_tx_nents,
101+
DMA_MEM_TO_DEV,
102+
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
84103
if (!desc) {
85104
ret = -EBUSY;
86105
goto err;

drivers/tty/serial/8250/8250_mid.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ static int tng_handle_irq(struct uart_port *p)
8888
err = hsu_dma_get_status(chip, mid->dma_index * 2 + 1, &status);
8989
if (err > 0) {
9090
serial8250_rx_dma_flush(up);
91+
/* Immediately after flushing arm DMA again */
92+
if (up->dma) up->dma->rx_dma(up);
9193
ret |= 1;
9294
} else if (err == 0)
9395
ret |= hsu_dma_do_irq(chip, mid->dma_index * 2 + 1, status);
@@ -232,6 +234,29 @@ static void mid8250_set_termios(struct uart_port *p,
232234
serial8250_do_set_termios(p, termios, old);
233235
}
234236

237+
static int mid8250_startup(struct uart_port *port)
238+
{
239+
struct uart_8250_port *up = up_to_u8250p(port);
240+
int ret;
241+
242+
ret = serial8250_do_startup(port);
243+
244+
/* Arm Rx DMA at ->startup() time */
245+
246+
if (up->dma) up->dma->rx_dma(up);
247+
248+
return ret;
249+
}
250+
251+
static void mid8250_shutdown(struct uart_port *port)
252+
{
253+
struct uart_8250_port *up = up_to_u8250p(port);
254+
255+
if (up->dma) serial8250_rx_dma_flush(up);
256+
257+
serial8250_do_shutdown(port);
258+
}
259+
235260
static bool mid8250_dma_filter(struct dma_chan *chan, void *param)
236261
{
237262
struct hsu_dma_slave *s = param;
@@ -306,6 +331,8 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
306331
uart.port.uartclk = mid->board->base_baud * 16;
307332
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
308333
uart.port.set_termios = mid8250_set_termios;
334+
uart.port.startup = mid8250_startup;
335+
uart.port.shutdown = mid8250_shutdown;
309336

310337
uart.port.mapbase = pci_resource_start(pdev, bar);
311338
uart.port.membase = pcim_iomap(pdev, bar, 0);

drivers/tty/serial/8250/8250_port.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,6 +2404,13 @@ int serial8250_do_startup(struct uart_port *port)
24042404
if (msg) {
24052405
dev_warn_ratelimited(port->dev, "%s\n", msg);
24062406
up->dma = NULL;
2407+
} else {
2408+
/*
2409+
* change tty_io write() to not split
2410+
* large writes into 2K chunks
2411+
*/
2412+
set_bit(TTY_NO_WRITE_SPLIT,
2413+
&port->state->port.tty->flags);
24072414
}
24082415
}
24092416

0 commit comments

Comments
 (0)