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