Skip to content

Commit

Permalink
DMAENGINE: COH 901 318 remove irq counting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Linus Walleij authored and Dan Williams committed Mar 2, 2010
1 parent b87108a commit 0b58828
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 55 deletions.
76 changes: 31 additions & 45 deletions drivers/dma/coh901318.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down Expand Up @@ -72,7 +71,6 @@ struct coh901318_chan {

unsigned long nbr_active_done;
unsigned long busy;
int pending_irqs;

struct coh901318_base *base;
};
Expand Down Expand Up @@ -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 *
Expand Down Expand Up @@ -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,
Expand All @@ -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");
Expand All @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));

Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
Expand Down
13 changes: 3 additions & 10 deletions drivers/dma/coh901318_lli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 0b58828

Please sign in to comment.