Commit b334b773 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty/serial driver fixes from Greg KH:
 "Here are a few TTY and Serial driver fixes for reported regressions
  and crashes.

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

* tag 'tty-4.1-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  n_tty: Fix auditing support for cannonical mode
  serial: 8250_omap: provide complete custom startup & shutdown callbacks
  n_tty: Fix calculation of size in canon_copy_from_read_buf
  serial: imx: Fix DMA handling for IDLE condition aborts
  serial/amba-pl011: Unconditionally poll for FIFO space before each TX char
parents e900f2c0 72586c60
...@@ -162,6 +162,17 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, ...@@ -162,6 +162,17 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
return put_user(x, ptr); return put_user(x, ptr);
} }
static inline int tty_copy_to_user(struct tty_struct *tty,
void __user *to,
const void *from,
unsigned long n)
{
struct n_tty_data *ldata = tty->disc_data;
tty_audit_add_data(tty, to, n, ldata->icanon);
return copy_to_user(to, from, n);
}
/** /**
* n_tty_kick_worker - start input worker (if required) * n_tty_kick_worker - start input worker (if required)
* @tty: terminal * @tty: terminal
...@@ -2070,8 +2081,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, ...@@ -2070,8 +2081,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
size = N_TTY_BUF_SIZE - tail; size = N_TTY_BUF_SIZE - tail;
n = eol - tail; n = eol - tail;
if (n > 4096) if (n > N_TTY_BUF_SIZE)
n += 4096; n += N_TTY_BUF_SIZE;
n += found; n += found;
c = n; c = n;
...@@ -2084,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, ...@@ -2084,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
__func__, eol, found, n, c, size, more); __func__, eol, found, n, c, size, more);
if (n > size) { if (n > size) {
ret = copy_to_user(*b, read_buf_addr(ldata, tail), size); ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size);
if (ret) if (ret)
return -EFAULT; return -EFAULT;
ret = copy_to_user(*b + size, ldata->read_buf, n - size); ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size);
} else } else
ret = copy_to_user(*b, read_buf_addr(ldata, tail), n); ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n);
if (ret) if (ret)
return -EFAULT; return -EFAULT;
......
...@@ -562,12 +562,36 @@ static irqreturn_t omap_wake_irq(int irq, void *dev_id) ...@@ -562,12 +562,36 @@ static irqreturn_t omap_wake_irq(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
} }
#ifdef CONFIG_SERIAL_8250_DMA
static int omap_8250_dma_handle_irq(struct uart_port *port);
#endif
static irqreturn_t omap8250_irq(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir;
int ret;
#ifdef CONFIG_SERIAL_8250_DMA
if (up->dma) {
ret = omap_8250_dma_handle_irq(port);
return IRQ_RETVAL(ret);
}
#endif
serial8250_rpm_get(up);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
serial8250_rpm_put(up);
return IRQ_RETVAL(ret);
}
static int omap_8250_startup(struct uart_port *port) static int omap_8250_startup(struct uart_port *port)
{ {
struct uart_8250_port *up = struct uart_8250_port *up = up_to_u8250p(port);
container_of(port, struct uart_8250_port, port);
struct omap8250_priv *priv = port->private_data; struct omap8250_priv *priv = port->private_data;
int ret; int ret;
if (priv->wakeirq) { if (priv->wakeirq) {
...@@ -580,10 +604,31 @@ static int omap_8250_startup(struct uart_port *port) ...@@ -580,10 +604,31 @@ static int omap_8250_startup(struct uart_port *port)
pm_runtime_get_sync(port->dev); pm_runtime_get_sync(port->dev);
ret = serial8250_do_startup(port); up->mcr = 0;
if (ret) serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_out(up, UART_LCR, UART_LCR_WLEN8);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
if (up->dma) {
ret = serial8250_request_dma(up);
if (ret) {
dev_warn_ratelimited(port->dev,
"failed to request DMA\n");
up->dma = NULL;
}
}
ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED,
dev_name(port->dev), port);
if (ret < 0)
goto err; goto err;
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
#ifdef CONFIG_PM #ifdef CONFIG_PM
up->capabilities |= UART_CAP_RPM; up->capabilities |= UART_CAP_RPM;
#endif #endif
...@@ -610,8 +655,7 @@ static int omap_8250_startup(struct uart_port *port) ...@@ -610,8 +655,7 @@ static int omap_8250_startup(struct uart_port *port)
static void omap_8250_shutdown(struct uart_port *port) static void omap_8250_shutdown(struct uart_port *port)
{ {
struct uart_8250_port *up = struct uart_8250_port *up = up_to_u8250p(port);
container_of(port, struct uart_8250_port, port);
struct omap8250_priv *priv = port->private_data; struct omap8250_priv *priv = port->private_data;
flush_work(&priv->qos_work); flush_work(&priv->qos_work);
...@@ -621,11 +665,24 @@ static void omap_8250_shutdown(struct uart_port *port) ...@@ -621,11 +665,24 @@ static void omap_8250_shutdown(struct uart_port *port)
pm_runtime_get_sync(port->dev); pm_runtime_get_sync(port->dev);
serial_out(up, UART_OMAP_WER, 0); serial_out(up, UART_OMAP_WER, 0);
serial8250_do_shutdown(port);
up->ier = 0;
serial_out(up, UART_IER, 0);
if (up->dma)
serial8250_release_dma(up);
/*
* Disable break condition and FIFOs
*/
if (up->lcr & UART_LCR_SBC)
serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC);
serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
pm_runtime_mark_last_busy(port->dev); pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev); pm_runtime_put_autosuspend(port->dev);
free_irq(port->irq, port);
if (priv->wakeirq) if (priv->wakeirq)
free_irq(priv->wakeirq, port); free_irq(priv->wakeirq, port);
} }
...@@ -974,6 +1031,13 @@ static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) ...@@ -974,6 +1031,13 @@ static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
} }
#endif #endif
static int omap8250_no_handle_irq(struct uart_port *port)
{
/* IRQ has not been requested but handling irq? */
WARN_ONCE(1, "Unexpected irq handling before port startup\n");
return 0;
}
static int omap8250_probe(struct platform_device *pdev) static int omap8250_probe(struct platform_device *pdev)
{ {
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -1075,6 +1139,7 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1075,6 +1139,7 @@ static int omap8250_probe(struct platform_device *pdev)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(&up, priv); omap_serial_fill_features_erratas(&up, priv);
up.port.handle_irq = omap8250_no_handle_irq;
#ifdef CONFIG_SERIAL_8250_DMA #ifdef CONFIG_SERIAL_8250_DMA
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
/* /*
...@@ -1088,7 +1153,6 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1088,7 +1153,6 @@ static int omap8250_probe(struct platform_device *pdev)
ret = of_property_count_strings(pdev->dev.of_node, "dma-names"); ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
if (ret == 2) { if (ret == 2) {
up.dma = &priv->omap8250_dma; up.dma = &priv->omap8250_dma;
up.port.handle_irq = omap_8250_dma_handle_irq;
priv->omap8250_dma.fn = the_no_dma_filter_fn; priv->omap8250_dma.fn = the_no_dma_filter_fn;
priv->omap8250_dma.tx_dma = omap_8250_tx_dma; priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
priv->omap8250_dma.rx_dma = omap_8250_rx_dma; priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
......
...@@ -1249,20 +1249,19 @@ __acquires(&uap->port.lock) ...@@ -1249,20 +1249,19 @@ __acquires(&uap->port.lock)
/* /*
* Transmit a character * Transmit a character
* There must be at least one free entry in the TX FIFO to accept the char.
* *
* Returns true if the FIFO might have space in it afterwards; * Returns true if the character was successfully queued to the FIFO.
* returns false if the FIFO definitely became full. * Returns false otherwise.
*/ */
static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c) static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
{ {
if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
return false; /* unable to transmit character */
writew(c, uap->port.membase + UART01x_DR); writew(c, uap->port.membase + UART01x_DR);
uap->port.icount.tx++; uap->port.icount.tx++;
if (likely(uap->tx_irq_seen > 1))
return true; return true;
return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
} }
static bool pl011_tx_chars(struct uart_amba_port *uap) static bool pl011_tx_chars(struct uart_amba_port *uap)
...@@ -1296,7 +1295,8 @@ static bool pl011_tx_chars(struct uart_amba_port *uap) ...@@ -1296,7 +1295,8 @@ static bool pl011_tx_chars(struct uart_amba_port *uap)
return false; return false;
if (uap->port.x_char) { if (uap->port.x_char) {
pl011_tx_char(uap, uap->port.x_char); if (!pl011_tx_char(uap, uap->port.x_char))
goto done;
uap->port.x_char = 0; uap->port.x_char = 0;
--count; --count;
} }
......
...@@ -911,6 +911,14 @@ static void dma_rx_callback(void *data) ...@@ -911,6 +911,14 @@ static void dma_rx_callback(void *data)
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue; count = RX_BUF_SIZE - state.residue;
if (readl(sport->port.membase + USR2) & USR2_IDLE) {
/* In condition [3] the SDMA counted up too early */
count--;
writel(USR2_IDLE, sport->port.membase + USR2);
}
dev_dbg(sport->port.dev, "We get %d bytes.\n", count); dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) { if (count) {
......
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