serial: bfin-uart: avoid dead lock in rx irq handler in smp kernel
authorSteven Miao <realmz6@gmail.com>
Wed, 7 Nov 2012 05:27:56 +0000 (13:27 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Nov 2012 00:59:58 +0000 (16:59 -0800)
Disabing dma irq and lock bottom half in smp kernel doesn't ensure exclusive
uart access. Call spin_lock_irqsave() instead.

Signed-off-by: Steven Miao <realmz6@gmail.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/bfin_uart.c

index 9242d56ba2670d4aebc21749d9003c4d42986a35..ca64c4a83ce05ff05dc34d9d512a48f992d397fc 100644 (file)
@@ -477,9 +477,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
 void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
 {
        int x_pos, pos;
+       unsigned long flags;
 
-       dma_disable_irq_nosync(uart->rx_dma_channel);
-       spin_lock_bh(&uart->rx_lock);
+       spin_lock_irqsave(&uart->rx_lock, flags);
 
        /* 2D DMA RX buffer ring is used. Because curr_y_count and
         * curr_x_count can't be read as an atomic operation,
@@ -510,8 +510,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
                uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
        }
 
-       spin_unlock_bh(&uart->rx_lock);
-       dma_enable_irq(uart->rx_dma_channel);
+       spin_unlock_irqrestore(&uart->rx_lock, flags);
 
        mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
 }