diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/coh901318.c | 76 | ||||
-rw-r--r-- | drivers/dma/coh901318_lli.c | 13 |
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 | |||
368 | coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc) | 366 | coh901318_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 | ||
377 | static struct coh901318_desc * | 371 | static 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 | ||
173 | int | 172 | int |
@@ -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 | ||
230 | int | 228 | int |
@@ -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; |