Skip to content

Commit b334b77

Browse files
committed
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
2 parents e900f2c + 72586c6 commit b334b77

File tree

4 files changed

+105
-22
lines changed

4 files changed

+105
-22
lines changed

drivers/tty/n_tty.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,17 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
162162
return put_user(x, ptr);
163163
}
164164

165+
static inline int tty_copy_to_user(struct tty_struct *tty,
166+
void __user *to,
167+
const void *from,
168+
unsigned long n)
169+
{
170+
struct n_tty_data *ldata = tty->disc_data;
171+
172+
tty_audit_add_data(tty, to, n, ldata->icanon);
173+
return copy_to_user(to, from, n);
174+
}
175+
165176
/**
166177
* n_tty_kick_worker - start input worker (if required)
167178
* @tty: terminal
@@ -2070,8 +2081,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
20702081

20712082
size = N_TTY_BUF_SIZE - tail;
20722083
n = eol - tail;
2073-
if (n > 4096)
2074-
n += 4096;
2084+
if (n > N_TTY_BUF_SIZE)
2085+
n += N_TTY_BUF_SIZE;
20752086
n += found;
20762087
c = n;
20772088

@@ -2084,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
20842095
__func__, eol, found, n, c, size, more);
20852096

20862097
if (n > size) {
2087-
ret = copy_to_user(*b, read_buf_addr(ldata, tail), size);
2098+
ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size);
20882099
if (ret)
20892100
return -EFAULT;
2090-
ret = copy_to_user(*b + size, ldata->read_buf, n - size);
2101+
ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size);
20912102
} else
2092-
ret = copy_to_user(*b, read_buf_addr(ldata, tail), n);
2103+
ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n);
20932104

20942105
if (ret)
20952106
return -EFAULT;

drivers/tty/serial/8250/8250_omap.c

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -562,12 +562,36 @@ static irqreturn_t omap_wake_irq(int irq, void *dev_id)
562562
return IRQ_NONE;
563563
}
564564

565+
#ifdef CONFIG_SERIAL_8250_DMA
566+
static int omap_8250_dma_handle_irq(struct uart_port *port);
567+
#endif
568+
569+
static irqreturn_t omap8250_irq(int irq, void *dev_id)
570+
{
571+
struct uart_port *port = dev_id;
572+
struct uart_8250_port *up = up_to_u8250p(port);
573+
unsigned int iir;
574+
int ret;
575+
576+
#ifdef CONFIG_SERIAL_8250_DMA
577+
if (up->dma) {
578+
ret = omap_8250_dma_handle_irq(port);
579+
return IRQ_RETVAL(ret);
580+
}
581+
#endif
582+
583+
serial8250_rpm_get(up);
584+
iir = serial_port_in(port, UART_IIR);
585+
ret = serial8250_handle_irq(port, iir);
586+
serial8250_rpm_put(up);
587+
588+
return IRQ_RETVAL(ret);
589+
}
590+
565591
static int omap_8250_startup(struct uart_port *port)
566592
{
567-
struct uart_8250_port *up =
568-
container_of(port, struct uart_8250_port, port);
593+
struct uart_8250_port *up = up_to_u8250p(port);
569594
struct omap8250_priv *priv = port->private_data;
570-
571595
int ret;
572596

573597
if (priv->wakeirq) {
@@ -580,10 +604,31 @@ static int omap_8250_startup(struct uart_port *port)
580604

581605
pm_runtime_get_sync(port->dev);
582606

583-
ret = serial8250_do_startup(port);
584-
if (ret)
607+
up->mcr = 0;
608+
serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
609+
610+
serial_out(up, UART_LCR, UART_LCR_WLEN8);
611+
612+
up->lsr_saved_flags = 0;
613+
up->msr_saved_flags = 0;
614+
615+
if (up->dma) {
616+
ret = serial8250_request_dma(up);
617+
if (ret) {
618+
dev_warn_ratelimited(port->dev,
619+
"failed to request DMA\n");
620+
up->dma = NULL;
621+
}
622+
}
623+
624+
ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED,
625+
dev_name(port->dev), port);
626+
if (ret < 0)
585627
goto err;
586628

629+
up->ier = UART_IER_RLSI | UART_IER_RDI;
630+
serial_out(up, UART_IER, up->ier);
631+
587632
#ifdef CONFIG_PM
588633
up->capabilities |= UART_CAP_RPM;
589634
#endif
@@ -610,8 +655,7 @@ static int omap_8250_startup(struct uart_port *port)
610655

611656
static void omap_8250_shutdown(struct uart_port *port)
612657
{
613-
struct uart_8250_port *up =
614-
container_of(port, struct uart_8250_port, port);
658+
struct uart_8250_port *up = up_to_u8250p(port);
615659
struct omap8250_priv *priv = port->private_data;
616660

617661
flush_work(&priv->qos_work);
@@ -621,11 +665,24 @@ static void omap_8250_shutdown(struct uart_port *port)
621665
pm_runtime_get_sync(port->dev);
622666

623667
serial_out(up, UART_OMAP_WER, 0);
624-
serial8250_do_shutdown(port);
668+
669+
up->ier = 0;
670+
serial_out(up, UART_IER, 0);
671+
672+
if (up->dma)
673+
serial8250_release_dma(up);
674+
675+
/*
676+
* Disable break condition and FIFOs
677+
*/
678+
if (up->lcr & UART_LCR_SBC)
679+
serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC);
680+
serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
625681

626682
pm_runtime_mark_last_busy(port->dev);
627683
pm_runtime_put_autosuspend(port->dev);
628684

685+
free_irq(port->irq, port);
629686
if (priv->wakeirq)
630687
free_irq(priv->wakeirq, port);
631688
}
@@ -974,6 +1031,13 @@ static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
9741031
}
9751032
#endif
9761033

1034+
static int omap8250_no_handle_irq(struct uart_port *port)
1035+
{
1036+
/* IRQ has not been requested but handling irq? */
1037+
WARN_ONCE(1, "Unexpected irq handling before port startup\n");
1038+
return 0;
1039+
}
1040+
9771041
static int omap8250_probe(struct platform_device *pdev)
9781042
{
9791043
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1075,6 +1139,7 @@ static int omap8250_probe(struct platform_device *pdev)
10751139
pm_runtime_get_sync(&pdev->dev);
10761140

10771141
omap_serial_fill_features_erratas(&up, priv);
1142+
up.port.handle_irq = omap8250_no_handle_irq;
10781143
#ifdef CONFIG_SERIAL_8250_DMA
10791144
if (pdev->dev.of_node) {
10801145
/*
@@ -1088,7 +1153,6 @@ static int omap8250_probe(struct platform_device *pdev)
10881153
ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
10891154
if (ret == 2) {
10901155
up.dma = &priv->omap8250_dma;
1091-
up.port.handle_irq = omap_8250_dma_handle_irq;
10921156
priv->omap8250_dma.fn = the_no_dma_filter_fn;
10931157
priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
10941158
priv->omap8250_dma.rx_dma = omap_8250_rx_dma;

drivers/tty/serial/amba-pl011.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,20 +1249,19 @@ __acquires(&uap->port.lock)
12491249

12501250
/*
12511251
* Transmit a character
1252-
* There must be at least one free entry in the TX FIFO to accept the char.
12531252
*
1254-
* Returns true if the FIFO might have space in it afterwards;
1255-
* returns false if the FIFO definitely became full.
1253+
* Returns true if the character was successfully queued to the FIFO.
1254+
* Returns false otherwise.
12561255
*/
12571256
static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
12581257
{
1258+
if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
1259+
return false; /* unable to transmit character */
1260+
12591261
writew(c, uap->port.membase + UART01x_DR);
12601262
uap->port.icount.tx++;
12611263

1262-
if (likely(uap->tx_irq_seen > 1))
1263-
return true;
1264-
1265-
return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
1264+
return true;
12661265
}
12671266

12681267
static bool pl011_tx_chars(struct uart_amba_port *uap)
@@ -1296,7 +1295,8 @@ static bool pl011_tx_chars(struct uart_amba_port *uap)
12961295
return false;
12971296

12981297
if (uap->port.x_char) {
1299-
pl011_tx_char(uap, uap->port.x_char);
1298+
if (!pl011_tx_char(uap, uap->port.x_char))
1299+
goto done;
13001300
uap->port.x_char = 0;
13011301
--count;
13021302
}

drivers/tty/serial/imx.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,14 @@ static void dma_rx_callback(void *data)
911911

912912
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
913913
count = RX_BUF_SIZE - state.residue;
914+
915+
if (readl(sport->port.membase + USR2) & USR2_IDLE) {
916+
/* In condition [3] the SDMA counted up too early */
917+
count--;
918+
919+
writel(USR2_IDLE, sport->port.membase + USR2);
920+
}
921+
914922
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
915923

916924
if (count) {

0 commit comments

Comments
 (0)