aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/coh901318.c76
-rw-r--r--drivers/dma/coh901318_lli.c13
2 files changed, 34 insertions, 55 deletions
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 12a7a151be6a..544c46278f84 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -39,7 +39,6 @@ struct coh901318_desc {
39 unsigned int sg_len; 39 unsigned int sg_len;
40 struct coh901318_lli *data; 40 struct coh901318_lli *data;
41 enum dma_data_direction dir; 41 enum dma_data_direction dir;
42 int pending_irqs;
43 unsigned long flags; 42 unsigned long flags;
44}; 43};
45 44
@@ -72,7 +71,6 @@ struct coh901318_chan {
72 71
73 unsigned long nbr_active_done; 72 unsigned long nbr_active_done;
74 unsigned long busy; 73 unsigned long busy;
75 int pending_irqs;
76 74
77 struct coh901318_base *base; 75 struct coh901318_base *base;
78}; 76};
@@ -368,10 +366,6 @@ static void
368coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc) 366coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
369{ 367{
370 list_add_tail(&desc->node, &cohc->active); 368 list_add_tail(&desc->node, &cohc->active);
371
372 BUG_ON(cohc->pending_irqs != 0);
373
374 cohc->pending_irqs = desc->pending_irqs;
375} 369}
376 370
377static struct coh901318_desc * 371static struct coh901318_desc *
@@ -617,36 +611,30 @@ static void dma_tasklet(unsigned long data)
617 /* get first active descriptor entry from list */ 611 /* get first active descriptor entry from list */
618 cohd_fin = coh901318_first_active_get(cohc); 612 cohd_fin = coh901318_first_active_get(cohc);
619 613
620 BUG_ON(cohd_fin->pending_irqs == 0);
621
622 if (cohd_fin == NULL) 614 if (cohd_fin == NULL)
623 goto err; 615 goto err;
624 616
625 cohd_fin->pending_irqs--; 617 /* locate callback to client */
626 cohc->completed = cohd_fin->desc.cookie; 618 callback = cohd_fin->desc.callback;
619 callback_param = cohd_fin->desc.callback_param;
627 620
628 if (cohc->nbr_active_done == 0) 621 /* sign this job as completed on the channel */
629 return; 622 cohc->completed = cohd_fin->desc.cookie;
630 623
631 if (!cohd_fin->pending_irqs) { 624 /* release the lli allocation and remove the descriptor */
632 /* release the lli allocation*/ 625 coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
633 coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
634 }
635 626
636 dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d pending_irqs %d" 627 /* return desc to free-list */
637 " nbr_active_done %ld\n", __func__, 628 coh901318_desc_remove(cohd_fin);
638 cohc->id, cohc->pending_irqs, cohc->nbr_active_done); 629 coh901318_desc_free(cohc, cohd_fin);
639 630
640 /* callback to client */ 631 spin_unlock_irqrestore(&cohc->lock, flags);
641 callback = cohd_fin->desc.callback;
642 callback_param = cohd_fin->desc.callback_param;
643 632
644 if (!cohd_fin->pending_irqs) { 633 /* Call the callback when we're done */
645 coh901318_desc_remove(cohd_fin); 634 if (callback)
635 callback(callback_param);
646 636
647 /* return desc to free-list */ 637 spin_lock_irqsave(&cohc->lock, flags);
648 coh901318_desc_free(cohc, cohd_fin);
649 }
650 638
651 /* 639 /*
652 * If another interrupt fired while the tasklet was scheduling, 640 * If another interrupt fired while the tasklet was scheduling,
@@ -655,9 +643,7 @@ static void dma_tasklet(unsigned long data)
655 * be handled for this channel. If there happen to be more than 643 * be handled for this channel. If there happen to be more than
656 * one IRQ to be ack:ed, we simply schedule this tasklet again. 644 * one IRQ to be ack:ed, we simply schedule this tasklet again.
657 */ 645 */
658 if (cohc->nbr_active_done) 646 cohc->nbr_active_done--;
659 cohc->nbr_active_done--;
660
661 if (cohc->nbr_active_done) { 647 if (cohc->nbr_active_done) {
662 dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs " 648 dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
663 "came in while we were scheduling this tasklet\n"); 649 "came in while we were scheduling this tasklet\n");
@@ -666,10 +652,8 @@ static void dma_tasklet(unsigned long data)
666 else 652 else
667 tasklet_schedule(&cohc->tasklet); 653 tasklet_schedule(&cohc->tasklet);
668 } 654 }
669 spin_unlock_irqrestore(&cohc->lock, flags);
670 655
671 if (callback) 656 spin_unlock_irqrestore(&cohc->lock, flags);
672 callback(callback_param);
673 657
674 return; 658 return;
675 659
@@ -688,16 +672,17 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
688 if (!cohc->allocated) 672 if (!cohc->allocated)
689 return; 673 return;
690 674
691 BUG_ON(cohc->pending_irqs == 0); 675 spin_lock(&cohc->lock);
692 676
693 cohc->pending_irqs--;
694 cohc->nbr_active_done++; 677 cohc->nbr_active_done++;
695 678
696 if (cohc->pending_irqs == 0 && coh901318_queue_start(cohc) == NULL) 679 if (coh901318_queue_start(cohc) == NULL)
697 cohc->busy = 0; 680 cohc->busy = 0;
698 681
699 BUG_ON(list_empty(&cohc->active)); 682 BUG_ON(list_empty(&cohc->active));
700 683
684 spin_unlock(&cohc->lock);
685
701 if (cohc_chan_conf(cohc)->priority_high) 686 if (cohc_chan_conf(cohc)->priority_high)
702 tasklet_hi_schedule(&cohc->tasklet); 687 tasklet_hi_schedule(&cohc->tasklet);
703 else 688 else
@@ -951,6 +936,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
951 u32 ctrl = cohc_chan_param(cohc)->ctrl_lli; 936 u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
952 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last; 937 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
953 unsigned long flg; 938 unsigned long flg;
939 int ret;
954 940
955 if (!sgl) 941 if (!sgl)
956 goto out; 942 goto out;
@@ -1010,13 +996,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1010 goto err_dma_alloc; 996 goto err_dma_alloc;
1011 997
1012 /* initiate allocated data list */ 998 /* initiate allocated data list */
1013 cohd->pending_irqs = 999 ret = coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
1014 coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len, 1000 cohc_dev_addr(cohc),
1015 cohc_dev_addr(cohc), 1001 ctrl_chained,
1016 ctrl_chained, 1002 ctrl,
1017 ctrl, 1003 ctrl_last,
1018 ctrl_last, 1004 direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
1019 direction, COH901318_CX_CTRL_TC_IRQ_ENABLE); 1005 if (ret)
1006 goto err_lli_fill;
1020 1007
1021 COH_DBG(coh901318_list_print(cohc, data)); 1008 COH_DBG(coh901318_list_print(cohc, data));
1022 1009
@@ -1030,6 +1017,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1030 spin_unlock_irqrestore(&cohc->lock, flg); 1017 spin_unlock_irqrestore(&cohc->lock, flg);
1031 1018
1032 return &cohd->desc; 1019 return &cohd->desc;
1020 err_lli_fill:
1033 err_dma_alloc: 1021 err_dma_alloc:
1034 err_direction: 1022 err_direction:
1035 spin_unlock_irqrestore(&cohc->lock, flg); 1023 spin_unlock_irqrestore(&cohc->lock, flg);
@@ -1121,7 +1109,6 @@ coh901318_terminate_all(struct dma_chan *chan)
1121 1109
1122 cohc->nbr_active_done = 0; 1110 cohc->nbr_active_done = 0;
1123 cohc->busy = 0; 1111 cohc->busy = 0;
1124 cohc->pending_irqs = 0;
1125 1112
1126 spin_unlock_irqrestore(&cohc->lock, flags); 1113 spin_unlock_irqrestore(&cohc->lock, flags);
1127} 1114}
@@ -1148,7 +1135,6 @@ void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
1148 1135
1149 spin_lock_init(&cohc->lock); 1136 spin_lock_init(&cohc->lock);
1150 1137
1151 cohc->pending_irqs = 0;
1152 cohc->nbr_active_done = 0; 1138 cohc->nbr_active_done = 0;
1153 cohc->busy = 0; 1139 cohc->busy = 0;
1154 INIT_LIST_HEAD(&cohc->free); 1140 INIT_LIST_HEAD(&cohc->free);
diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c
index f5120f238a4d..5f9af1956eab 100644
--- a/drivers/dma/coh901318_lli.c
+++ b/drivers/dma/coh901318_lli.c
@@ -166,8 +166,7 @@ coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
166 lli->src_addr = src; 166 lli->src_addr = src;
167 lli->dst_addr = dst; 167 lli->dst_addr = dst;
168 168
169 /* One irq per single transfer */ 169 return 0;
170 return 1;
171} 170}
172 171
173int 172int
@@ -223,8 +222,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
223 lli->src_addr = src; 222 lli->src_addr = src;
224 lli->dst_addr = dst; 223 lli->dst_addr = dst;
225 224
226 /* One irq per single transfer */ 225 return 0;
227 return 1;
228} 226}
229 227
230int 228int
@@ -240,7 +238,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
240 u32 ctrl_sg; 238 u32 ctrl_sg;
241 dma_addr_t src = 0; 239 dma_addr_t src = 0;
242 dma_addr_t dst = 0; 240 dma_addr_t dst = 0;
243 int nbr_of_irq = 0;
244 u32 bytes_to_transfer; 241 u32 bytes_to_transfer;
245 u32 elem_size; 242 u32 elem_size;
246 243
@@ -269,9 +266,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
269 ctrl_sg = ctrl ? ctrl : ctrl_last; 266 ctrl_sg = ctrl ? ctrl : ctrl_last;
270 267
271 268
272 if ((ctrl_sg & ctrl_irq_mask))
273 nbr_of_irq++;
274
275 if (dir == DMA_TO_DEVICE) 269 if (dir == DMA_TO_DEVICE)
276 /* increment source address */ 270 /* increment source address */
277 src = sg_dma_address(sg); 271 src = sg_dma_address(sg);
@@ -310,8 +304,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
310 } 304 }
311 spin_unlock(&pool->lock); 305 spin_unlock(&pool->lock);
312 306
313 /* There can be many IRQs per sg transfer */ 307 return 0;
314 return nbr_of_irq;
315 err: 308 err:
316 spin_unlock(&pool->lock); 309 spin_unlock(&pool->lock);
317 return -EINVAL; 310 return -EINVAL;