Commit 0b526090 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-6.7-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull serial driver fixes from Greg KH:
 "Here are some small serial driver fixes for 6.7-rc4 to resolve some
  reported issues. Included in here are:

   - pl011 dma support fix

   - sc16is7xx driver fix

   - ma35d1 console index fix

   - 8250 driver fixes for small issues

  All of these have been in linux-next with no reported issues"

* tag 'tty-6.7-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: 8250_dw: Add ACPI ID for Granite Rapids-D UART
  serial: ma35d1: Validate console index before assignment
  ARM: PL011: Fix DMA support
  serial: sc16is7xx: address RX timeout interrupt errata
  serial: 8250: 8250_omap: Clear UART_HAS_RHR_IT_DIS bit
  serial: 8250_omap: Add earlycon support for the AM654 UART controller
  serial: 8250: 8250_omap: Do not start RX DMA on THRI interrupt
parents ca20f162 e92fad02
...@@ -777,6 +777,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { ...@@ -777,6 +777,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
{ "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb },
{ "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, { "INT3434", (kernel_ulong_t)&dw8250_dw_apb },
{ "INT3435", (kernel_ulong_t)&dw8250_dw_apb }, { "INT3435", (kernel_ulong_t)&dw8250_dw_apb },
{ "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
......
...@@ -189,5 +189,6 @@ static int __init early_omap8250_setup(struct earlycon_device *device, ...@@ -189,5 +189,6 @@ static int __init early_omap8250_setup(struct earlycon_device *device,
OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup); OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup);
OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
OF_EARLYCON_DECLARE(omap8250, "ti,am654-uart", early_omap8250_setup);
#endif #endif
...@@ -933,7 +933,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) ...@@ -933,7 +933,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
if (priv->habit & UART_HAS_RHR_IT_DIS) { if (priv->habit & UART_HAS_RHR_IT_DIS) {
reg = serial_in(p, UART_OMAP_IER2); reg = serial_in(p, UART_OMAP_IER2);
reg &= ~UART_OMAP_IER2_RHR_IT_DIS; reg &= ~UART_OMAP_IER2_RHR_IT_DIS;
serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS); serial_out(p, UART_OMAP_IER2, reg);
} }
dmaengine_tx_status(rxchan, cookie, &state); dmaengine_tx_status(rxchan, cookie, &state);
...@@ -1079,7 +1079,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) ...@@ -1079,7 +1079,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
if (priv->habit & UART_HAS_RHR_IT_DIS) { if (priv->habit & UART_HAS_RHR_IT_DIS) {
reg = serial_in(p, UART_OMAP_IER2); reg = serial_in(p, UART_OMAP_IER2);
reg |= UART_OMAP_IER2_RHR_IT_DIS; reg |= UART_OMAP_IER2_RHR_IT_DIS;
serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS); serial_out(p, UART_OMAP_IER2, reg);
} }
dma_async_issue_pending(dma->rxchan); dma_async_issue_pending(dma->rxchan);
...@@ -1298,10 +1298,12 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) ...@@ -1298,10 +1298,12 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
status = serial_port_in(port, UART_LSR); status = serial_port_in(port, UART_LSR);
if (priv->habit & UART_HAS_EFR2) if ((iir & 0x3f) != UART_IIR_THRI) {
am654_8250_handle_rx_dma(up, iir, status); if (priv->habit & UART_HAS_EFR2)
else am654_8250_handle_rx_dma(up, iir, status);
status = omap_8250_handle_rx_dma(up, iir, status); else
status = omap_8250_handle_rx_dma(up, iir, status);
}
serial8250_modem_status(up); serial8250_modem_status(up);
if (status & UART_LSR_THRE && up->dma->tx_err) { if (status & UART_LSR_THRE && up->dma->tx_err) {
......
...@@ -218,17 +218,18 @@ static struct vendor_data vendor_st = { ...@@ -218,17 +218,18 @@ static struct vendor_data vendor_st = {
/* Deals with DMA transactions */ /* Deals with DMA transactions */
struct pl011_sgbuf { struct pl011_dmabuf {
struct scatterlist sg; dma_addr_t dma;
char *buf; size_t len;
char *buf;
}; };
struct pl011_dmarx_data { struct pl011_dmarx_data {
struct dma_chan *chan; struct dma_chan *chan;
struct completion complete; struct completion complete;
bool use_buf_b; bool use_buf_b;
struct pl011_sgbuf sgbuf_a; struct pl011_dmabuf dbuf_a;
struct pl011_sgbuf sgbuf_b; struct pl011_dmabuf dbuf_b;
dma_cookie_t cookie; dma_cookie_t cookie;
bool running; bool running;
struct timer_list timer; struct timer_list timer;
...@@ -241,7 +242,8 @@ struct pl011_dmarx_data { ...@@ -241,7 +242,8 @@ struct pl011_dmarx_data {
struct pl011_dmatx_data { struct pl011_dmatx_data {
struct dma_chan *chan; struct dma_chan *chan;
struct scatterlist sg; dma_addr_t dma;
size_t len;
char *buf; char *buf;
bool queued; bool queued;
}; };
...@@ -366,32 +368,24 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) ...@@ -366,32 +368,24 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
#define PL011_DMA_BUFFER_SIZE PAGE_SIZE #define PL011_DMA_BUFFER_SIZE PAGE_SIZE
static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg, static int pl011_dmabuf_init(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
dma_addr_t dma_addr; db->buf = dma_alloc_coherent(chan->device->dev, PL011_DMA_BUFFER_SIZE,
&db->dma, GFP_KERNEL);
sg->buf = dma_alloc_coherent(chan->device->dev, if (!db->buf)
PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL);
if (!sg->buf)
return -ENOMEM; return -ENOMEM;
db->len = PL011_DMA_BUFFER_SIZE;
sg_init_table(&sg->sg, 1);
sg_set_page(&sg->sg, phys_to_page(dma_addr),
PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr));
sg_dma_address(&sg->sg) = dma_addr;
sg_dma_len(&sg->sg) = PL011_DMA_BUFFER_SIZE;
return 0; return 0;
} }
static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg, static void pl011_dmabuf_free(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
if (sg->buf) { if (db->buf) {
dma_free_coherent(chan->device->dev, dma_free_coherent(chan->device->dev,
PL011_DMA_BUFFER_SIZE, sg->buf, PL011_DMA_BUFFER_SIZE, db->buf, db->dma);
sg_dma_address(&sg->sg));
} }
} }
...@@ -552,8 +546,8 @@ static void pl011_dma_tx_callback(void *data) ...@@ -552,8 +546,8 @@ static void pl011_dma_tx_callback(void *data)
uart_port_lock_irqsave(&uap->port, &flags); uart_port_lock_irqsave(&uap->port, &flags);
if (uap->dmatx.queued) if (uap->dmatx.queued)
dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1, dma_unmap_single(dmatx->chan->device->dev, dmatx->dma,
DMA_TO_DEVICE); dmatx->len, DMA_TO_DEVICE);
dmacr = uap->dmacr; dmacr = uap->dmacr;
uap->dmacr = dmacr & ~UART011_TXDMAE; uap->dmacr = dmacr & ~UART011_TXDMAE;
...@@ -639,18 +633,19 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) ...@@ -639,18 +633,19 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
memcpy(&dmatx->buf[first], &xmit->buf[0], second); memcpy(&dmatx->buf[first], &xmit->buf[0], second);
} }
dmatx->sg.length = count; dmatx->len = count;
dmatx->dma = dma_map_single(dma_dev->dev, dmatx->buf, count,
if (dma_map_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE) != 1) { DMA_TO_DEVICE);
if (dmatx->dma == DMA_MAPPING_ERROR) {
uap->dmatx.queued = false; uap->dmatx.queued = false;
dev_dbg(uap->port.dev, "unable to map TX DMA\n"); dev_dbg(uap->port.dev, "unable to map TX DMA\n");
return -EBUSY; return -EBUSY;
} }
desc = dmaengine_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV, desc = dmaengine_prep_slave_single(chan, dmatx->dma, dmatx->len, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) { if (!desc) {
dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE); dma_unmap_single(dma_dev->dev, dmatx->dma, dmatx->len, DMA_TO_DEVICE);
uap->dmatx.queued = false; uap->dmatx.queued = false;
/* /*
* If DMA cannot be used right now, we complete this * If DMA cannot be used right now, we complete this
...@@ -813,8 +808,8 @@ __acquires(&uap->port.lock) ...@@ -813,8 +808,8 @@ __acquires(&uap->port.lock)
dmaengine_terminate_async(uap->dmatx.chan); dmaengine_terminate_async(uap->dmatx.chan);
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1, dma_unmap_single(uap->dmatx.chan->device->dev, uap->dmatx.dma,
DMA_TO_DEVICE); uap->dmatx.len, DMA_TO_DEVICE);
uap->dmatx.queued = false; uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE; uap->dmacr &= ~UART011_TXDMAE;
pl011_write(uap->dmacr, uap, REG_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
...@@ -828,15 +823,15 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) ...@@ -828,15 +823,15 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
struct dma_chan *rxchan = uap->dmarx.chan; struct dma_chan *rxchan = uap->dmarx.chan;
struct pl011_dmarx_data *dmarx = &uap->dmarx; struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct pl011_sgbuf *sgbuf; struct pl011_dmabuf *dbuf;
if (!rxchan) if (!rxchan)
return -EIO; return -EIO;
/* Start the RX DMA job */ /* Start the RX DMA job */
sgbuf = uap->dmarx.use_buf_b ? dbuf = uap->dmarx.use_buf_b ?
&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
desc = dmaengine_prep_slave_sg(rxchan, &sgbuf->sg, 1, desc = dmaengine_prep_slave_single(rxchan, dbuf->dma, dbuf->len,
DMA_DEV_TO_MEM, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
/* /*
...@@ -876,8 +871,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, ...@@ -876,8 +871,8 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
bool readfifo) bool readfifo)
{ {
struct tty_port *port = &uap->port.state->port; struct tty_port *port = &uap->port.state->port;
struct pl011_sgbuf *sgbuf = use_buf_b ? struct pl011_dmabuf *dbuf = use_buf_b ?
&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
int dma_count = 0; int dma_count = 0;
u32 fifotaken = 0; /* only used for vdbg() */ u32 fifotaken = 0; /* only used for vdbg() */
...@@ -886,7 +881,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, ...@@ -886,7 +881,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
if (uap->dmarx.poll_rate) { if (uap->dmarx.poll_rate) {
/* The data can be taken by polling */ /* The data can be taken by polling */
dmataken = sgbuf->sg.length - dmarx->last_residue; dmataken = dbuf->len - dmarx->last_residue;
/* Recalculate the pending size */ /* Recalculate the pending size */
if (pending >= dmataken) if (pending >= dmataken)
pending -= dmataken; pending -= dmataken;
...@@ -900,7 +895,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, ...@@ -900,7 +895,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
* Note that tty_insert_flip_buf() tries to take as many chars * Note that tty_insert_flip_buf() tries to take as many chars
* as it can. * as it can.
*/ */
dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken, dma_count = tty_insert_flip_string(port, dbuf->buf + dmataken,
pending); pending);
uap->port.icount.rx += dma_count; uap->port.icount.rx += dma_count;
...@@ -911,7 +906,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, ...@@ -911,7 +906,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
/* Reset the last_residue for Rx DMA poll */ /* Reset the last_residue for Rx DMA poll */
if (uap->dmarx.poll_rate) if (uap->dmarx.poll_rate)
dmarx->last_residue = sgbuf->sg.length; dmarx->last_residue = dbuf->len;
/* /*
* Only continue with trying to read the FIFO if all DMA chars have * Only continue with trying to read the FIFO if all DMA chars have
...@@ -946,8 +941,8 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) ...@@ -946,8 +941,8 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
{ {
struct pl011_dmarx_data *dmarx = &uap->dmarx; struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = dmarx->chan; struct dma_chan *rxchan = dmarx->chan;
struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ? struct pl011_dmabuf *dbuf = dmarx->use_buf_b ?
&dmarx->sgbuf_b : &dmarx->sgbuf_a; &dmarx->dbuf_b : &dmarx->dbuf_a;
size_t pending; size_t pending;
struct dma_tx_state state; struct dma_tx_state state;
enum dma_status dmastat; enum dma_status dmastat;
...@@ -969,7 +964,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap) ...@@ -969,7 +964,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
pl011_write(uap->dmacr, uap, REG_DMACR); pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmarx.running = false; uap->dmarx.running = false;
pending = sgbuf->sg.length - state.residue; pending = dbuf->len - state.residue;
BUG_ON(pending > PL011_DMA_BUFFER_SIZE); BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
/* Then we terminate the transfer - we now know our residue */ /* Then we terminate the transfer - we now know our residue */
dmaengine_terminate_all(rxchan); dmaengine_terminate_all(rxchan);
...@@ -996,8 +991,8 @@ static void pl011_dma_rx_callback(void *data) ...@@ -996,8 +991,8 @@ static void pl011_dma_rx_callback(void *data)
struct pl011_dmarx_data *dmarx = &uap->dmarx; struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = dmarx->chan; struct dma_chan *rxchan = dmarx->chan;
bool lastbuf = dmarx->use_buf_b; bool lastbuf = dmarx->use_buf_b;
struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ? struct pl011_dmabuf *dbuf = dmarx->use_buf_b ?
&dmarx->sgbuf_b : &dmarx->sgbuf_a; &dmarx->dbuf_b : &dmarx->dbuf_a;
size_t pending; size_t pending;
struct dma_tx_state state; struct dma_tx_state state;
int ret; int ret;
...@@ -1015,7 +1010,7 @@ static void pl011_dma_rx_callback(void *data) ...@@ -1015,7 +1010,7 @@ static void pl011_dma_rx_callback(void *data)
* the DMA irq handler. So we check the residue here. * the DMA irq handler. So we check the residue here.
*/ */
rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state); rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
pending = sgbuf->sg.length - state.residue; pending = dbuf->len - state.residue;
BUG_ON(pending > PL011_DMA_BUFFER_SIZE); BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
/* Then we terminate the transfer - we now know our residue */ /* Then we terminate the transfer - we now know our residue */
dmaengine_terminate_all(rxchan); dmaengine_terminate_all(rxchan);
...@@ -1067,16 +1062,16 @@ static void pl011_dma_rx_poll(struct timer_list *t) ...@@ -1067,16 +1062,16 @@ static void pl011_dma_rx_poll(struct timer_list *t)
unsigned long flags; unsigned long flags;
unsigned int dmataken = 0; unsigned int dmataken = 0;
unsigned int size = 0; unsigned int size = 0;
struct pl011_sgbuf *sgbuf; struct pl011_dmabuf *dbuf;
int dma_count; int dma_count;
struct dma_tx_state state; struct dma_tx_state state;
sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; dbuf = dmarx->use_buf_b ? &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state); rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
if (likely(state.residue < dmarx->last_residue)) { if (likely(state.residue < dmarx->last_residue)) {
dmataken = sgbuf->sg.length - dmarx->last_residue; dmataken = dbuf->len - dmarx->last_residue;
size = dmarx->last_residue - state.residue; size = dmarx->last_residue - state.residue;
dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken, dma_count = tty_insert_flip_string(port, dbuf->buf + dmataken,
size); size);
if (dma_count == size) if (dma_count == size)
dmarx->last_residue = state.residue; dmarx->last_residue = state.residue;
...@@ -1123,7 +1118,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) ...@@ -1123,7 +1118,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
return; return;
} }
sg_init_one(&uap->dmatx.sg, uap->dmatx.buf, PL011_DMA_BUFFER_SIZE); uap->dmatx.len = PL011_DMA_BUFFER_SIZE;
/* The DMA buffer is now the FIFO the TTY subsystem can use */ /* The DMA buffer is now the FIFO the TTY subsystem can use */
uap->port.fifosize = PL011_DMA_BUFFER_SIZE; uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
...@@ -1133,7 +1128,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap) ...@@ -1133,7 +1128,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
goto skip_rx; goto skip_rx;
/* Allocate and map DMA RX buffers */ /* Allocate and map DMA RX buffers */
ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_a, ret = pl011_dmabuf_init(uap->dmarx.chan, &uap->dmarx.dbuf_a,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
if (ret) { if (ret) {
dev_err(uap->port.dev, "failed to init DMA %s: %d\n", dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
...@@ -1141,12 +1136,12 @@ static void pl011_dma_startup(struct uart_amba_port *uap) ...@@ -1141,12 +1136,12 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
goto skip_rx; goto skip_rx;
} }
ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_b, ret = pl011_dmabuf_init(uap->dmarx.chan, &uap->dmarx.dbuf_b,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
if (ret) { if (ret) {
dev_err(uap->port.dev, "failed to init DMA %s: %d\n", dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
"RX buffer B", ret); "RX buffer B", ret);
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
goto skip_rx; goto skip_rx;
} }
...@@ -1200,8 +1195,9 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) ...@@ -1200,8 +1195,9 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
/* In theory, this should already be done by pl011_dma_flush_buffer */ /* In theory, this should already be done by pl011_dma_flush_buffer */
dmaengine_terminate_all(uap->dmatx.chan); dmaengine_terminate_all(uap->dmatx.chan);
if (uap->dmatx.queued) { if (uap->dmatx.queued) {
dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1, dma_unmap_single(uap->dmatx.chan->device->dev,
DMA_TO_DEVICE); uap->dmatx.dma, uap->dmatx.len,
DMA_TO_DEVICE);
uap->dmatx.queued = false; uap->dmatx.queued = false;
} }
...@@ -1212,8 +1208,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) ...@@ -1212,8 +1208,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
if (uap->using_rx_dma) { if (uap->using_rx_dma) {
dmaengine_terminate_all(uap->dmarx.chan); dmaengine_terminate_all(uap->dmarx.chan);
/* Clean up the RX DMA */ /* Clean up the RX DMA */
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE); pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a, DMA_FROM_DEVICE);
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE); pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_b, DMA_FROM_DEVICE);
if (uap->dmarx.poll_rate) if (uap->dmarx.poll_rate)
del_timer_sync(&uap->dmarx.timer); del_timer_sync(&uap->dmarx.timer);
uap->using_rx_dma = false; uap->using_rx_dma = false;
......
...@@ -552,11 +552,19 @@ static void ma35d1serial_console_putchar(struct uart_port *port, unsigned char c ...@@ -552,11 +552,19 @@ static void ma35d1serial_console_putchar(struct uart_port *port, unsigned char c
*/ */
static void ma35d1serial_console_write(struct console *co, const char *s, u32 count) static void ma35d1serial_console_write(struct console *co, const char *s, u32 count)
{ {
struct uart_ma35d1_port *up = &ma35d1serial_ports[co->index]; struct uart_ma35d1_port *up;
unsigned long flags; unsigned long flags;
int locked = 1; int locked = 1;
u32 ier; u32 ier;
if ((co->index < 0) || (co->index >= MA35_UART_NR)) {
pr_warn("Failed to write on ononsole port %x, out of range\n",
co->index);
return;
}
up = &ma35d1serial_ports[co->index];
if (up->port.sysrq) if (up->port.sysrq)
locked = 0; locked = 0;
else if (oops_in_progress) else if (oops_in_progress)
......
...@@ -766,6 +766,18 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) ...@@ -766,6 +766,18 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
case SC16IS7XX_IIR_RTOI_SRC: case SC16IS7XX_IIR_RTOI_SRC:
case SC16IS7XX_IIR_XOFFI_SRC: case SC16IS7XX_IIR_XOFFI_SRC:
rxlen = sc16is7xx_port_read(port, SC16IS7XX_RXLVL_REG); rxlen = sc16is7xx_port_read(port, SC16IS7XX_RXLVL_REG);
/*
* There is a silicon bug that makes the chip report a
* time-out interrupt but no data in the FIFO. This is
* described in errata section 18.1.4.
*
* When this happens, read one byte from the FIFO to
* clear the interrupt.
*/
if (iir == SC16IS7XX_IIR_RTOI_SRC && !rxlen)
rxlen = 1;
if (rxlen) if (rxlen)
sc16is7xx_handle_rx(port, rxlen, iir); sc16is7xx_handle_rx(port, rxlen, iir);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment