diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 12:16:17 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 12:16:17 -0700 |
commit | 507ffe4f3840ac24890a8123c702cf1b7fe4d33c (patch) | |
tree | 1046888f9db00f268a0056d7f6e427e21502f84c /drivers/tty/serial/8250/8250_dma.c | |
parent | fdc719b63ae35d6a2d8a2a2c76eed813294664bf (diff) | |
parent | 45efcb2d32d35f6509543e477568842d8467035d (diff) |
Merge tag 'tty-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver update from Greg Kroah-Hartman:
"Here's the big tty/serial driver merge request for 3.10-rc1
Once again, Jiri has a number of TTY driver fixes and cleanups, and
Peter Hurley came through with a bunch of ldisc fixes that resolve a
number of reported issues. There are some other serial driver
cleanups as well.
All of these have been in the linux-next tree for a while"
* tag 'tty-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (117 commits)
tty/serial/sirf: fix MODULE_DEVICE_TABLE
serial: mxs: drop superfluous {get|put}_device
serial: mxs: fix buffer overflow
ARM: PL011: add support for extended FIFO-size of PL011-r1p5
serial_core.c: add put_device() after device_find_child()
tty: Fix unsafe bit ops in tty_throttle_safe/unthrottle_safe
serial: sccnxp: Replace pdata.init/exit with regulator API
serial: sccnxp: Do not override device name
TTY: pty, fix compilation warning
TTY: rocket, fix compilation warning
TTY: ircomm: fix DTR being raised on hang up
TTY: synclinkmp: fix DTR being raised on hang up
TTY: synclink_gt: fix DTR being raised on hang up
TTY: synclink: fix DTR being raised on hang up
serial: 8250_dw: Fix the stub for dw8250_probe_acpi()
serial: 8250_dw: Convert to devm_ioremap()
serial: 8250_dw: Set port capabilities based on CPR register
serial: 8250_dw: Let ACPI code extract the DMA client info
serial: 8250_dw: Support clk framework also with ACPI
serial: 8250_dw: Enable runtime PM
...
Diffstat (limited to 'drivers/tty/serial/8250/8250_dma.c')
-rw-r--r-- | drivers/tty/serial/8250/8250_dma.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index b9f7fd28112..7046769608d 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -33,10 +33,8 @@ static void __dma_tx_complete(void *param) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&p->port); - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { + if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) serial8250_tx_dma(p); - uart_write_wakeup(&p->port); - } } static void __dma_rx_complete(void *param) @@ -67,12 +65,11 @@ int serial8250_tx_dma(struct uart_8250_port *p) struct circ_buf *xmit = &p->port.state->xmit; struct dma_async_tx_descriptor *desc; - if (dma->tx_running) - return -EBUSY; + if (uart_tx_stopped(&p->port) || dma->tx_running || + uart_circ_empty(xmit)) + return 0; dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - if (!dma->tx_size) - return -EINVAL; desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, @@ -104,20 +101,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) struct dma_tx_state state; int dma_status; - /* - * If RCVR FIFO trigger level was not reached, complete the transfer and - * let 8250.c copy the remaining data. - */ - if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { - dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, - &state); + dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + + switch (iir & 0x3f) { + case UART_IIR_RLSI: + /* 8250_core handles errors and break interrupts */ + return -EIO; + case UART_IIR_RX_TIMEOUT: + /* + * If RCVR FIFO trigger level was not reached, complete the + * transfer and let 8250_core copy the remaining data. + */ if (dma_status == DMA_IN_PROGRESS) { dmaengine_pause(dma->rxchan); __dma_rx_complete(p); } return -ETIMEDOUT; + default: + break; } + if (dma_status) + return 0; + desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); @@ -143,21 +149,31 @@ int serial8250_request_dma(struct uart_8250_port *p) struct uart_8250_dma *dma = p->dma; dma_cap_mask_t mask; - dma->rxconf.src_addr = p->port.mapbase + UART_RX; - dma->txconf.dst_addr = p->port.mapbase + UART_TX; + /* Default slave configuration parameters */ + 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->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_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); /* Get a channel for RX */ - dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param); + dma->rxchan = dma_request_slave_channel_compat(mask, + dma->fn, dma->rx_param, + p->port.dev, "rx"); if (!dma->rxchan) return -ENODEV; dmaengine_slave_config(dma->rxchan, &dma->rxconf); /* Get a channel for TX */ - dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param); + dma->txchan = dma_request_slave_channel_compat(mask, + dma->fn, dma->tx_param, + p->port.dev, "tx"); if (!dma->txchan) { dma_release_channel(dma->rxchan); return -ENODEV; |