Hi, Sonic,

This spin_lock may cause dead lock in SMP.

Because uart_start(), which in drivers/serial/serial_core.c, will spin
lock and irqsave this lock then call port->ops->start_tx(port).

BRs,
Graf

在 2008-09-25四的 01:08 [EMAIL PROTECTED]
> Revision
>         5334
> Author
>         sonicz
> Date
>         2008-09-25 01:08:29 -0500 (Thu, 25 Sep 2008)
> Log Message
> Fix bug[#4436] Add spin_lock_irqsave() when receive and transfer data.
> Modified Paths
>       * trunk/drivers/serial/bfin_5xx.c
> Diff
> Modified: trunk/drivers/serial/bfin_5xx.c (5333 => 5334)
> 
> --- trunk/drivers/serial/bfin_5xx.c   2008-09-24 11:08:54 UTC (rev 5333)
> +++ trunk/drivers/serial/bfin_5xx.c   2008-09-25 06:08:29 UTC (rev 5334)
> @@ -82,7 +82,9 @@
>  static void bfin_serial_stop_tx(struct uart_port *port)
>  {
>       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
> +#ifdef CONFIG_SERIAL_BFIN_DMA
>       struct circ_buf *xmit = &uart->port.info->xmit;
> +#endif
>  
>       while (!(UART_GET_LSR(uart) & TEMT))
>               cpu_relax();
> @@ -108,6 +110,7 @@
>  static void bfin_serial_start_tx(struct uart_port *port)
>  {
>       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
> +     int flags;
>  
>       /*
>        * To avoid losting RX interrupt, we reset IR function
> @@ -116,6 +119,7 @@
>       if (port->info->tty->ldisc.num == N_IRDA)
>               bfin_serial_reset_irda(port);
>  
> +     spin_lock_irqsave(&uart->port.lock, flags);
>  #ifdef CONFIG_SERIAL_BFIN_DMA
>       if (uart->tx_done)
>               bfin_serial_dma_tx_chars(uart);
> @@ -123,6 +127,7 @@
>       UART_SET_IER(uart, ETBEI);
>       bfin_serial_tx_chars(uart);
>  #endif
> +     spin_unlock_irqrestore(&uart->port.lock, flags);
>  }
>  
>  /*
> @@ -412,8 +417,10 @@
>  
>  void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
>  {
> -     int x_pos, pos;
> +     int x_pos, pos, flags;
>  
> +     spin_lock_irqsave(&uart->port.lock, flags);
> +
>       uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
>       x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
>       uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
> @@ -430,6 +437,8 @@
>               uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
>       }
>  
> +     spin_unlock_irqrestore(&uart->port.lock, flags);
> +
>       mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
>  }
>  
> @@ -464,10 +473,9 @@
>       spin_lock(&uart->port.lock);
>       irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
>       clear_dma_irqstat(uart->rx_dma_channel);
> +     bfin_serial_dma_rx_chars(uart);
>       spin_unlock(&uart->port.lock);
>  
> -     mod_timer(&(uart->rx_dma_timer), jiffies);
> -
>       return IRQ_HANDLED;
>  }
>  #endif
> _______________________________________________
> Linux-kernel-commits mailing list
> [email protected]
> http://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

_______________________________________________
Linux-kernel-commits mailing list
[email protected]
http://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to