ath9k: fix dma sync in rx path
authorMing Lei <tom.leiming@gmail.com>
Sat, 15 May 2010 10:25:40 +0000 (18:25 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 4 Jun 2010 18:55:09 +0000 (14:55 -0400)
If buffer is to be accessed by cpu after dma is over, but
between dma mapping and dma unmapping, we should use
dma_sync_single_for_cpu to sync the buffer between cpu with
device. And dma_sync_single_for_device is used to let
device gain the buffer again.

v2: Felix pointed out dma_sync_single_for_device is needed to return
buffer to device if an unsuccessful status bit check is found.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Acked-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/recv.c

index 1618f8fe195db4ad783e117baad6b15d4f4bae83..d373364ef8a928f6c35934652f787f8f548a70f8 100644 (file)
@@ -700,12 +700,16 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
        bf = SKB_CB_ATHBUF(skb);
        BUG_ON(!bf);
 
-       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+       dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
                                common->rx_bufsize, DMA_FROM_DEVICE);
 
        ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
-       if (ret == -EINPROGRESS)
+       if (ret == -EINPROGRESS) {
+               /*let device gain the buffer again*/
+               dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+                               common->rx_bufsize, DMA_FROM_DEVICE);
                return false;
+       }
 
        __skb_unlink(skb, &rx_edma->rx_fifo);
        if (ret == -EINVAL) {
@@ -814,7 +818,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
         * 1. accessing the frame
         * 2. requeueing the same buffer to h/w
         */
-       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+       dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
                        common->rx_bufsize,
                        DMA_FROM_DEVICE);