ARM: PL08x: fix atomic_t usage and tx_submit() return value range
authorRussell King - ARM Linux <linux@arm.linux.org.uk>
Mon, 3 Jan 2011 22:31:04 +0000 (22:31 +0000)
committerDan Williams <dan.j.williams@intel.com>
Wed, 5 Jan 2011 03:16:10 +0000 (19:16 -0800)
The last_issued variable uses an atomic type, which is only
incremented inside a protected region, and then read.  Everywhere else
only reads the value, so it isn't using atomic_t correctly, and it
doesn't even need to.  Moreover, the DMA engine code provides us with
a variable for this already - chan.cookie.  Use chan.cookie instead.

Also, avoid negative dma_cookie_t values - negative returns from
tx_submit() mean failure, yet in reality we always succeed.  Restart
from cookie 1, just like other DMA engine drivers do.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/dma/amba-pl08x.c
include/linux/amba/pl08x.h

index 0809810f9e7a5e95e02c1d2839b192fe668e69bc..5d9a15652dba8846eba33447c5b5c1abcb61bf54 100644 (file)
@@ -74,7 +74,6 @@
 #include <asm/hardware/pl080.h>
 #include <asm/dma.h>
 #include <asm/mach/dma.h>
-#include <asm/atomic.h>
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
 
@@ -1082,8 +1081,10 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
 
-       atomic_inc(&plchan->last_issued);
-       tx->cookie = atomic_read(&plchan->last_issued);
+       plchan->chan.cookie += 1;
+       if (plchan->chan.cookie < 0)
+               plchan->chan.cookie = 1;
+       tx->cookie = plchan->chan.cookie;
        /* This unlock follows the lock in the prep() function */
        spin_unlock_irqrestore(&plchan->lock, plchan->lockflags);
 
@@ -1115,7 +1116,7 @@ pl08x_dma_tx_status(struct dma_chan *chan,
        enum dma_status ret;
        u32 bytesleft = 0;
 
-       last_used = atomic_read(&plchan->last_issued);
+       last_used = plchan->chan.cookie;
        last_complete = plchan->lc;
 
        ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -1131,7 +1132,7 @@ pl08x_dma_tx_status(struct dma_chan *chan,
        /*
         * This cookie not complete yet
         */
-       last_used = atomic_read(&plchan->last_issued);
+       last_used = plchan->chan.cookie;
        last_complete = plchan->lc;
 
        /* Get number of bytes left in the active transactions and queue */
@@ -1641,8 +1642,7 @@ static void pl08x_tasklet(unsigned long data)
                /*
                 * Update last completed
                 */
-               plchan->lc =
-                       (plchan->at->tx.cookie);
+               plchan->lc = plchan->at->tx.cookie;
 
                /*
                 * Callback to signal completion
@@ -1820,8 +1820,8 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                         chan->name);
 
                chan->chan.device = dmadev;
-               atomic_set(&chan->last_issued, 0);
-               chan->lc = atomic_read(&chan->last_issued);
+               chan->chan.cookie = 0;
+               chan->lc = 0;
 
                spin_lock_init(&chan->lock);
                INIT_LIST_HEAD(&chan->desc_list);
index 521a0f8974ac688b20c083e1e71c410b2f26252a..4ae62b4684f96e89e2113685c4991270913f0287 100644 (file)
@@ -174,7 +174,6 @@ struct pl08x_dma_chan {
        struct pl08x_channel_data *cd;
        dma_addr_t runtime_addr;
        enum dma_data_direction runtime_direction;
-       atomic_t last_issued;
        dma_cookie_t lc;
        struct list_head desc_list;
        struct pl08x_txd *at;