struct scatterlist              sg_rx;
        struct tasklet_struct   tasklet_rx;
        struct tasklet_struct   tasklet_tx;
+       atomic_t                tasklet_shutdown;
        unsigned int            irq_status_prev;
        unsigned int            tx_len;
 
        return atmel_port->fifo_size;
 }
 
+static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port,
+                                  struct tasklet_struct *t)
+{
+       if (!atomic_read(&atmel_port->tasklet_shutdown))
+               tasklet_schedule(t);
+}
+
 static unsigned int atmel_get_lines_status(struct uart_port *port)
 {
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
                status = atmel_uart_readl(port, ATMEL_US_CSR);
        }
 
-       tasklet_schedule(&atmel_port->tasklet_rx);
+       atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
 }
 
 /*
         * remaining data from the beginning of xmit->buf to xmit->head.
         */
        if (!uart_circ_empty(xmit))
-               tasklet_schedule(&atmel_port->tasklet_tx);
+               atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
        struct uart_port *port = arg;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-       tasklet_schedule(&atmel_port->tasklet_rx);
+       atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
 }
 
 static void atmel_release_rx_dma(struct uart_port *port)
        if (dmastat == DMA_ERROR) {
                dev_dbg(port->dev, "Get residue error, restart tasklet\n");
                atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
-               tasklet_schedule(&atmel_port->tasklet_rx);
+               atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
                return;
        }
 
        struct uart_port *port = (void *)data;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-       tasklet_schedule(&atmel_port->tasklet_rx);
-       mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
+       if (!atomic_read(&atmel_port->tasklet_shutdown)) {
+               tasklet_schedule(&atmel_port->tasklet_rx);
+               mod_timer(&atmel_port->uart_timer,
+                         jiffies + uart_poll_timeout(port));
+       }
 }
 
 /*
                if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
                        atmel_uart_writel(port, ATMEL_US_IDR,
                                          (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
-                       tasklet_schedule(&atmel_port->tasklet_rx);
+                       atmel_tasklet_schedule(atmel_port,
+                                              &atmel_port->tasklet_rx);
                }
 
                if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
                if (pending & ATMEL_US_TIMEOUT) {
                        atmel_uart_writel(port, ATMEL_US_IDR,
                                          ATMEL_US_TIMEOUT);
-                       tasklet_schedule(&atmel_port->tasklet_rx);
+                       atmel_tasklet_schedule(atmel_port,
+                                              &atmel_port->tasklet_rx);
                }
        }
 
                /* Either PDC or interrupt transmission */
                atmel_uart_writel(port, ATMEL_US_IDR,
                                  atmel_port->tx_done_mask);
-               tasklet_schedule(&atmel_port->tasklet_tx);
+               atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
        }
 }
 
                return retval;
        }
 
-       tasklet_enable(&atmel_port->tasklet_rx);
-       tasklet_enable(&atmel_port->tasklet_tx);
+       atomic_set(&atmel_port->tasklet_shutdown, 0);
+       tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func,
+                       (unsigned long)port);
+       tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func,
+                       (unsigned long)port);
 
        /*
         * Initialize DMA (if necessary)
 {
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
+       /* Disable interrupts at device level */
+       atmel_uart_writel(port, ATMEL_US_IDR, -1);
+
+       /* Prevent spurious interrupts from scheduling the tasklet */
+       atomic_inc(&atmel_port->tasklet_shutdown);
+
        /*
         * Prevent any tasklets being scheduled during
         * cleanup
         */
        del_timer_sync(&atmel_port->uart_timer);
 
+       /* Make sure that no interrupt is on the fly */
+       synchronize_irq(port->irq);
+
        /*
         * Clear out any scheduled tasklets before
         * we destroy the buffers
         */
-       tasklet_disable(&atmel_port->tasklet_rx);
-       tasklet_disable(&atmel_port->tasklet_tx);
        tasklet_kill(&atmel_port->tasklet_rx);
        tasklet_kill(&atmel_port->tasklet_tx);
 
        /*
         * Ensure everything is stopped and
-        * disable all interrupts, port and break condition.
+        * disable port and break condition.
         */
        atmel_stop_rx(port);
        atmel_stop_tx(port);
 
        atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
-       atmel_uart_writel(port, ATMEL_US_IDR, -1);
-
 
        /*
         * Shut-down the DMA.
        port->irq       = pdev->resource[1].start;
        port->rs485_config      = atmel_config_rs485;
 
-       tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func,
-                       (unsigned long)port);
-       tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func,
-                       (unsigned long)port);
-       tasklet_disable(&atmel_port->tasklet_rx);
-       tasklet_disable(&atmel_port->tasklet_tx);
-
        memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
        if (pdata && pdata->regs) {
        atmel_port->uart.line = ret;
        atmel_serial_probe_fifos(atmel_port, pdev);
 
+       atomic_set(&atmel_port->tasklet_shutdown, 0);
        spin_lock_init(&atmel_port->lock_suspended);
 
        ret = atmel_init_port(atmel_port, pdev);