|
@@ -165,6 +165,7 @@ struct atmel_uart_port {
|
|
|
struct tasklet_struct tasklet;
|
|
|
unsigned int irq_status;
|
|
|
unsigned int irq_status_prev;
|
|
|
+ unsigned int status_change;
|
|
|
|
|
|
struct circ_buf rx_ring;
|
|
|
|
|
@@ -1177,6 +1178,9 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
|
|
|
if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
|
|
|
| ATMEL_US_CTSIC)) {
|
|
|
atmel_port->irq_status = status;
|
|
|
+ atmel_port->status_change = atmel_port->irq_status ^
|
|
|
+ atmel_port->irq_status_prev;
|
|
|
+ atmel_port->irq_status_prev = status;
|
|
|
tasklet_schedule(&atmel_port->tasklet);
|
|
|
}
|
|
|
}
|
|
@@ -1523,17 +1527,14 @@ static void atmel_tasklet_func(unsigned long data)
|
|
|
{
|
|
|
struct uart_port *port = (struct uart_port *)data;
|
|
|
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
|
|
- unsigned int status;
|
|
|
- unsigned int status_change;
|
|
|
+ unsigned int status = atmel_port->irq_status;
|
|
|
+ unsigned int status_change = atmel_port->status_change;
|
|
|
|
|
|
/* The interrupt handler does not take the lock */
|
|
|
spin_lock(&port->lock);
|
|
|
|
|
|
atmel_port->schedule_tx(port);
|
|
|
|
|
|
- status = atmel_port->irq_status;
|
|
|
- status_change = status ^ atmel_port->irq_status_prev;
|
|
|
-
|
|
|
if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
|
|
|
| ATMEL_US_DCD | ATMEL_US_CTS)) {
|
|
|
/* TODO: All reads to CSR will clear these interrupts! */
|
|
@@ -1548,7 +1549,7 @@ static void atmel_tasklet_func(unsigned long data)
|
|
|
|
|
|
wake_up_interruptible(&port->state->port.delta_msr_wait);
|
|
|
|
|
|
- atmel_port->irq_status_prev = status;
|
|
|
+ atmel_port->status_change = 0;
|
|
|
}
|
|
|
|
|
|
atmel_port->schedule_rx(port);
|