diff options
| -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; |
