OSDN Git Service

Merge tag 'dropmachtimexh-v2' of git://git.pengutronix.de/git/ukl/linux
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / tty / serial / atmel_serial.c
index 40d6c9b..91c0d88 100644 (file)
@@ -819,9 +819,6 @@ static void atmel_release_rx_dma(struct uart_port *port)
        atmel_port->desc_rx = NULL;
        atmel_port->chan_rx = NULL;
        atmel_port->cookie_rx = -EINVAL;
-
-       if (!atmel_port->is_usart)
-               del_timer_sync(&atmel_port->uart_timer);
 }
 
 static void atmel_rx_from_dma(struct uart_port *port)
@@ -1223,9 +1220,6 @@ static void atmel_release_rx_pdc(struct uart_port *port)
                                 DMA_FROM_DEVICE);
                kfree(pdc->buf);
        }
-
-       if (!atmel_port->is_usart)
-               del_timer_sync(&atmel_port->uart_timer);
 }
 
 static void atmel_rx_from_pdc(struct uart_port *port)
@@ -1598,12 +1592,13 @@ static int atmel_startup(struct uart_port *port)
        /* enable xmit & rcvr */
        UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
+       setup_timer(&atmel_port->uart_timer,
+                       atmel_uart_timer_callback,
+                       (unsigned long)port);
+
        if (atmel_use_pdc_rx(port)) {
                /* set UART timeout */
                if (!atmel_port->is_usart) {
-                       setup_timer(&atmel_port->uart_timer,
-                                       atmel_uart_timer_callback,
-                                       (unsigned long)port);
                        mod_timer(&atmel_port->uart_timer,
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
@@ -1618,9 +1613,6 @@ static int atmel_startup(struct uart_port *port)
        } else if (atmel_use_dma_rx(port)) {
                /* set UART timeout */
                if (!atmel_port->is_usart) {
-                       setup_timer(&atmel_port->uart_timer,
-                                       atmel_uart_timer_callback,
-                                       (unsigned long)port);
                        mod_timer(&atmel_port->uart_timer,
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
@@ -1644,12 +1636,30 @@ static int atmel_startup(struct uart_port *port)
 static void atmel_shutdown(struct uart_port *port)
 {
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
        /*
-        * Ensure everything is stopped.
+        * Prevent any tasklets being scheduled during
+        * cleanup
+        */
+       del_timer_sync(&atmel_port->uart_timer);
+
+       /*
+        * Clear out any scheduled tasklets before
+        * we destroy the buffers
+        */
+       tasklet_kill(&atmel_port->tasklet);
+
+       /*
+        * Ensure everything is stopped and
+        * disable all interrupts, port and break condition.
         */
        atmel_stop_rx(port);
        atmel_stop_tx(port);
 
+       UART_PUT_CR(port, ATMEL_US_RSTSTA);
+       UART_PUT_IDR(port, -1);
+
+
        /*
         * Shut-down the DMA.
         */
@@ -1659,10 +1669,10 @@ static void atmel_shutdown(struct uart_port *port)
                atmel_port->release_tx(port);
 
        /*
-        * Disable all interrupts, port and break condition.
+        * Reset ring buffer pointers
         */
-       UART_PUT_CR(port, ATMEL_US_RSTSTA);
-       UART_PUT_IDR(port, -1);
+       atmel_port->rx_ring.head = 0;
+       atmel_port->rx_ring.tail = 0;
 
        /*
         * Free the interrupt
@@ -2454,11 +2464,12 @@ static int atmel_serial_remove(struct platform_device *pdev)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
        int ret = 0;
 
+       tasklet_kill(&atmel_port->tasklet);
+
        device_init_wakeup(&pdev->dev, 0);
 
        ret = uart_remove_one_port(&atmel_uart, port);
 
-       tasklet_kill(&atmel_port->tasklet);
        kfree(atmel_port->rx_ring.buf);
 
        /* "port" is allocated statically, so we shouldn't free it */