DMAENGINE: COH 901 318 remove irq counting
authorLinus Walleij <linus.walleij@stericsson.com>
Tue, 2 Mar 2010 21:17:44 +0000 (14:17 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 2 Mar 2010 21:17:44 +0000 (14:17 -0700)
This removes the pointless irq counting for the COH 901 318, as
it turns out the hardware will only ever fire one IRQ for a linked
list anyway. In the process also a missing spinlock was introduced.

Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/dma/coh901318.c
drivers/dma/coh901318_lli.c

index 12a7a15..544c462 100644 (file)
@@ -39,7 +39,6 @@ struct coh901318_desc {
        unsigned int sg_len;
        struct coh901318_lli *data;
        enum dma_data_direction dir;
-       int pending_irqs;
        unsigned long flags;
 };
 
@@ -72,7 +71,6 @@ struct coh901318_chan {
 
        unsigned long nbr_active_done;
        unsigned long busy;
-       int pending_irqs;
 
        struct coh901318_base *base;
 };
@@ -368,10 +366,6 @@ static void
 coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
 {
        list_add_tail(&desc->node, &cohc->active);
-
-       BUG_ON(cohc->pending_irqs != 0);
-
-       cohc->pending_irqs = desc->pending_irqs;
 }
 
 static struct coh901318_desc *
@@ -617,36 +611,30 @@ static void dma_tasklet(unsigned long data)
        /* get first active descriptor entry from list */
        cohd_fin = coh901318_first_active_get(cohc);
 
-       BUG_ON(cohd_fin->pending_irqs == 0);
-
        if (cohd_fin == NULL)
                goto err;
 
-       cohd_fin->pending_irqs--;
-       cohc->completed = cohd_fin->desc.cookie;
+       /* locate callback to client */
+       callback = cohd_fin->desc.callback;
+       callback_param = cohd_fin->desc.callback_param;
 
-       if (cohc->nbr_active_done == 0)
-               return;
+       /* sign this job as completed on the channel */
+       cohc->completed = cohd_fin->desc.cookie;
 
-       if (!cohd_fin->pending_irqs) {
-               /* release the lli allocation*/
-               coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
-       }
+       /* release the lli allocation and remove the descriptor */
+       coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
 
-       dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d pending_irqs %d"
-                " nbr_active_done %ld\n", __func__,
-                cohc->id, cohc->pending_irqs, cohc->nbr_active_done);
+       /* return desc to free-list */
+       coh901318_desc_remove(cohd_fin);
+       coh901318_desc_free(cohc, cohd_fin);
 
-       /* callback to client */
-       callback = cohd_fin->desc.callback;
-       callback_param = cohd_fin->desc.callback_param;
+       spin_unlock_irqrestore(&cohc->lock, flags);
 
-       if (!cohd_fin->pending_irqs) {
-               coh901318_desc_remove(cohd_fin);
+       /* Call the callback when we're done */
+       if (callback)
+               callback(callback_param);
 
-               /* return desc to free-list */
-               coh901318_desc_free(cohc, cohd_fin);
-       }
+       spin_lock_irqsave(&cohc->lock, flags);
 
        /*
         * If another interrupt fired while the tasklet was scheduling,
@@ -655,9 +643,7 @@ static void dma_tasklet(unsigned long data)
         * be handled for this channel. If there happen to be more than
         * one IRQ to be ack:ed, we simply schedule this tasklet again.
         */
-       if (cohc->nbr_active_done)
-               cohc->nbr_active_done--;
-
+       cohc->nbr_active_done--;
        if (cohc->nbr_active_done) {
                dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
                        "came in while we were scheduling this tasklet\n");
@@ -666,10 +652,8 @@ static void dma_tasklet(unsigned long data)
                else
                        tasklet_schedule(&cohc->tasklet);
        }
-       spin_unlock_irqrestore(&cohc->lock, flags);
 
-       if (callback)
-               callback(callback_param);
+       spin_unlock_irqrestore(&cohc->lock, flags);
 
        return;
 
@@ -688,16 +672,17 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
        if (!cohc->allocated)
                return;
 
-       BUG_ON(cohc->pending_irqs == 0);
+       spin_lock(&cohc->lock);
 
-       cohc->pending_irqs--;
        cohc->nbr_active_done++;
 
-       if (cohc->pending_irqs == 0 && coh901318_queue_start(cohc) == NULL)
+       if (coh901318_queue_start(cohc) == NULL)
                cohc->busy = 0;
 
        BUG_ON(list_empty(&cohc->active));
 
+       spin_unlock(&cohc->lock);
+
        if (cohc_chan_conf(cohc)->priority_high)
                tasklet_hi_schedule(&cohc->tasklet);
        else
@@ -951,6 +936,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
        u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
        unsigned long flg;
+       int ret;
 
        if (!sgl)
                goto out;
@@ -1010,13 +996,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                goto err_dma_alloc;
 
        /* initiate allocated data list */
-       cohd->pending_irqs =
-               coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
-                                     cohc_dev_addr(cohc),
-                                     ctrl_chained,
-                                     ctrl,
-                                     ctrl_last,
-                                     direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
+       ret = coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
+                                   cohc_dev_addr(cohc),
+                                   ctrl_chained,
+                                   ctrl,
+                                   ctrl_last,
+                                   direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
+       if (ret)
+               goto err_lli_fill;
 
        COH_DBG(coh901318_list_print(cohc, data));
 
@@ -1030,6 +1017,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        spin_unlock_irqrestore(&cohc->lock, flg);
 
        return &cohd->desc;
+ err_lli_fill:
  err_dma_alloc:
  err_direction:
        spin_unlock_irqrestore(&cohc->lock, flg);
@@ -1121,7 +1109,6 @@ coh901318_terminate_all(struct dma_chan *chan)
 
        cohc->nbr_active_done = 0;
        cohc->busy = 0;
-       cohc->pending_irqs = 0;
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 }
@@ -1148,7 +1135,6 @@ void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
 
                        spin_lock_init(&cohc->lock);
 
-                       cohc->pending_irqs = 0;
                        cohc->nbr_active_done = 0;
                        cohc->busy = 0;
                        INIT_LIST_HEAD(&cohc->free);
index f5120f2..5f9af19 100644 (file)
@@ -166,8 +166,7 @@ coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
        lli->src_addr = src;
        lli->dst_addr = dst;
 
-       /* One irq per single transfer */
-       return 1;
+       return 0;
 }
 
 int
@@ -223,8 +222,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
        lli->src_addr = src;
        lli->dst_addr = dst;
 
-       /* One irq per single transfer */
-       return 1;
+       return 0;
 }
 
 int
@@ -240,7 +238,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
        u32 ctrl_sg;
        dma_addr_t src = 0;
        dma_addr_t dst = 0;
-       int nbr_of_irq = 0;
        u32 bytes_to_transfer;
        u32 elem_size;
 
@@ -269,9 +266,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
                        ctrl_sg = ctrl ? ctrl : ctrl_last;
 
 
-               if ((ctrl_sg & ctrl_irq_mask))
-                       nbr_of_irq++;
-
                if (dir == DMA_TO_DEVICE)
                        /* increment source address */
                        src = sg_dma_address(sg);
@@ -310,8 +304,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
        }
        spin_unlock(&pool->lock);
 
-       /* There can be many IRQs per sg transfer */
-       return nbr_of_irq;
+       return 0;
  err:
        spin_unlock(&pool->lock);
        return -EINVAL;