aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/atmel_serial.c
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2016-06-17 06:05:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-25 16:38:37 -0400
commit9205218e491d70bf45f4527cd3bcb5cd3734ae17 (patch)
tree4c6542027d07066134e1392eba69fcf78ffe6314 /drivers/tty/serial/atmel_serial.c
parent9b6519009dbe2b361a73284ea0fd2e9b86aeef4d (diff)
tty/serial: atmel: re-integrate status check in irq handler
The IRQ status check and related actions was done in the tasklet without benefit. So, move it back to the IRQ context to simplify IRQ handling and having the possibility to split the tasklet in two separated ones for receive and transmit actions. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/atmel_serial.c')
-rw-r--r--drivers/tty/serial/atmel_serial.c43
1 files changed, 17 insertions, 26 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 954941dd8124..8854ac6f383d 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -146,9 +146,7 @@ struct atmel_uart_port {
146 struct scatterlist sg_tx; 146 struct scatterlist sg_tx;
147 struct scatterlist sg_rx; 147 struct scatterlist sg_rx;
148 struct tasklet_struct tasklet; 148 struct tasklet_struct tasklet;
149 unsigned int irq_status;
150 unsigned int irq_status_prev; 149 unsigned int irq_status_prev;
151 unsigned int status_change;
152 unsigned int tx_len; 150 unsigned int tx_len;
153 151
154 struct circ_buf rx_ring; 152 struct circ_buf rx_ring;
@@ -1237,14 +1235,27 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
1237 unsigned int status) 1235 unsigned int status)
1238{ 1236{
1239 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 1237 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1238 unsigned int status_change;
1240 1239
1241 if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC 1240 if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
1242 | ATMEL_US_CTSIC)) { 1241 | ATMEL_US_CTSIC)) {
1243 atmel_port->irq_status = status; 1242 status_change = status ^ atmel_port->irq_status_prev;
1244 atmel_port->status_change = atmel_port->irq_status ^
1245 atmel_port->irq_status_prev;
1246 atmel_port->irq_status_prev = status; 1243 atmel_port->irq_status_prev = status;
1247 tasklet_schedule(&atmel_port->tasklet); 1244
1245 if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
1246 | ATMEL_US_DCD | ATMEL_US_CTS)) {
1247 /* TODO: All reads to CSR will clear these interrupts! */
1248 if (status_change & ATMEL_US_RI)
1249 port->icount.rng++;
1250 if (status_change & ATMEL_US_DSR)
1251 port->icount.dsr++;
1252 if (status_change & ATMEL_US_DCD)
1253 uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
1254 if (status_change & ATMEL_US_CTS)
1255 uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
1256
1257 wake_up_interruptible(&port->state->port.delta_msr_wait);
1258 }
1248 } 1259 }
1249} 1260}
1250 1261
@@ -1575,31 +1586,12 @@ static void atmel_tasklet_func(unsigned long data)
1575{ 1586{
1576 struct uart_port *port = (struct uart_port *)data; 1587 struct uart_port *port = (struct uart_port *)data;
1577 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 1588 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1578 unsigned int status = atmel_port->irq_status;
1579 unsigned int status_change = atmel_port->status_change;
1580 1589
1581 /* The interrupt handler does not take the lock */ 1590 /* The interrupt handler does not take the lock */
1582 spin_lock(&port->lock); 1591 spin_lock(&port->lock);
1583 1592
1584 atmel_port->schedule_tx(port); 1593 atmel_port->schedule_tx(port);
1585 1594
1586 if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
1587 | ATMEL_US_DCD | ATMEL_US_CTS)) {
1588 /* TODO: All reads to CSR will clear these interrupts! */
1589 if (status_change & ATMEL_US_RI)
1590 port->icount.rng++;
1591 if (status_change & ATMEL_US_DSR)
1592 port->icount.dsr++;
1593 if (status_change & ATMEL_US_DCD)
1594 uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
1595 if (status_change & ATMEL_US_CTS)
1596 uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
1597
1598 wake_up_interruptible(&port->state->port.delta_msr_wait);
1599
1600 atmel_port->status_change = 0;
1601 }
1602
1603 atmel_port->schedule_rx(port); 1595 atmel_port->schedule_rx(port);
1604 1596
1605 spin_unlock(&port->lock); 1597 spin_unlock(&port->lock);
@@ -1833,7 +1825,6 @@ static int atmel_startup(struct uart_port *port)
1833 1825
1834 /* Save current CSR for comparison in atmel_tasklet_func() */ 1826 /* Save current CSR for comparison in atmel_tasklet_func() */
1835 atmel_port->irq_status_prev = atmel_get_lines_status(port); 1827 atmel_port->irq_status_prev = atmel_get_lines_status(port);
1836 atmel_port->irq_status = atmel_port->irq_status_prev;
1837 1828
1838 /* 1829 /*
1839 * Finally, enable the serial port 1830 * Finally, enable the serial port