From: Sonic Zhang Date: Thu, 11 Jun 2009 12:42:57 +0000 (+0100) Subject: Blackfin Serial Driver: handle irregular DMA register status in auto start mode X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=35ff69357949cfff5c3d8e3038b77146872e3bd3;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git Blackfin Serial Driver: handle irregular DMA register status in auto start mode This bug is caused by irregular behavior of DMA register CURR_X_COUNT and CURR_Y_COUNT when an auto restart uart rx DMA run to last byte in DMA buffer, trigger the interrupt and stay at this possiton. The status of current x and y is 0:7 instead of 512:8 or 0:8. The driver doesn't take care of this case when calculating the position. URL: http://blackfin.uclinux.org/gf/tracker/5063 Reported-by: Tomasz Motylewski Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 676efdad3712..854e96dfb070 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -490,7 +490,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) 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; - if (uart->rx_dma_nrows == DMA_RX_YCOUNT) + if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) uart->rx_dma_nrows = 0; x_pos = DMA_RX_XCOUNT - x_pos; if (x_pos == DMA_RX_XCOUNT) @@ -546,15 +546,16 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; unsigned short irqstat; - int pos; + int x_pos, pos; spin_lock(&uart->port.lock); irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); clear_dma_irqstat(uart->rx_dma_channel); 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; - if (uart->rx_dma_nrows == DMA_RX_YCOUNT) + if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) uart->rx_dma_nrows = 0; pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;