aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/fsldma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/fsldma.c')
-rw-r--r--drivers/dma/fsldma.c197
1 files changed, 144 insertions, 53 deletions
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 465f16dd78e5..d5d6885ab341 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -466,6 +466,88 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
466} 466}
467 467
468/** 468/**
469 * fsldma_clean_completed_descriptor - free all descriptors which
470 * has been completed and acked
471 * @chan: Freescale DMA channel
472 *
473 * This function is used on all completed and acked descriptors.
474 * All descriptors should only be freed in this function.
475 */
476static void fsldma_clean_completed_descriptor(struct fsldma_chan *chan)
477{
478 struct fsl_desc_sw *desc, *_desc;
479
480 /* Run the callback for each descriptor, in order */
481 list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node)
482 if (async_tx_test_ack(&desc->async_tx))
483 fsl_dma_free_descriptor(chan, desc);
484}
485
486/**
487 * fsldma_run_tx_complete_actions - cleanup a single link descriptor
488 * @chan: Freescale DMA channel
489 * @desc: descriptor to cleanup and free
490 * @cookie: Freescale DMA transaction identifier
491 *
492 * This function is used on a descriptor which has been executed by the DMA
493 * controller. It will run any callbacks, submit any dependencies.
494 */
495static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
496 struct fsl_desc_sw *desc, dma_cookie_t cookie)
497{
498 struct dma_async_tx_descriptor *txd = &desc->async_tx;
499 dma_cookie_t ret = cookie;
500
501 BUG_ON(txd->cookie < 0);
502
503 if (txd->cookie > 0) {
504 ret = txd->cookie;
505
506 /* Run the link descriptor callback function */
507 if (txd->callback) {
508 chan_dbg(chan, "LD %p callback\n", desc);
509 txd->callback(txd->callback_param);
510 }
511 }
512
513 /* Run any dependencies */
514 dma_run_dependencies(txd);
515
516 return ret;
517}
518
519/**
520 * fsldma_clean_running_descriptor - move the completed descriptor from
521 * ld_running to ld_completed
522 * @chan: Freescale DMA channel
523 * @desc: the descriptor which is completed
524 *
525 * Free the descriptor directly if acked by async_tx api, or move it to
526 * queue ld_completed.
527 */
528static void fsldma_clean_running_descriptor(struct fsldma_chan *chan,
529 struct fsl_desc_sw *desc)
530{
531 /* Remove from the list of transactions */
532 list_del(&desc->node);
533
534 /*
535 * the client is allowed to attach dependent operations
536 * until 'ack' is set
537 */
538 if (!async_tx_test_ack(&desc->async_tx)) {
539 /*
540 * Move this descriptor to the list of descriptors which is
541 * completed, but still awaiting the 'ack' bit to be set.
542 */
543 list_add_tail(&desc->node, &chan->ld_completed);
544 return;
545 }
546
547 dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
548}
549
550/**
469 * fsl_chan_xfer_ld_queue - transfer any pending transactions 551 * fsl_chan_xfer_ld_queue - transfer any pending transactions
470 * @chan : Freescale DMA channel 552 * @chan : Freescale DMA channel
471 * 553 *
@@ -533,31 +615,58 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
533} 615}
534 616
535/** 617/**
536 * fsldma_cleanup_descriptor - cleanup and free a single link descriptor 618 * fsldma_cleanup_descriptors - cleanup link descriptors which are completed
619 * and move them to ld_completed to free until flag 'ack' is set
537 * @chan: Freescale DMA channel 620 * @chan: Freescale DMA channel
538 * @desc: descriptor to cleanup and free
539 * 621 *
540 * This function is used on a descriptor which has been executed by the DMA 622 * This function is used on descriptors which have been executed by the DMA
541 * controller. It will run any callbacks, submit any dependencies, and then 623 * controller. It will run any callbacks, submit any dependencies, then
542 * free the descriptor. 624 * free these descriptors if flag 'ack' is set.
543 */ 625 */
544static void fsldma_cleanup_descriptor(struct fsldma_chan *chan, 626static void fsldma_cleanup_descriptors(struct fsldma_chan *chan)
545 struct fsl_desc_sw *desc)
546{ 627{
547 struct dma_async_tx_descriptor *txd = &desc->async_tx; 628 struct fsl_desc_sw *desc, *_desc;
629 dma_cookie_t cookie = 0;
630 dma_addr_t curr_phys = get_cdar(chan);
631 int seen_current = 0;
548 632
549 /* Run the link descriptor callback function */ 633 fsldma_clean_completed_descriptor(chan);
550 if (txd->callback) { 634
551 chan_dbg(chan, "LD %p callback\n", desc); 635 /* Run the callback for each descriptor, in order */
552 txd->callback(txd->callback_param); 636 list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
637 /*
638 * do not advance past the current descriptor loaded into the
639 * hardware channel, subsequent descriptors are either in
640 * process or have not been submitted
641 */
642 if (seen_current)
643 break;
644
645 /*
646 * stop the search if we reach the current descriptor and the
647 * channel is busy
648 */
649 if (desc->async_tx.phys == curr_phys) {
650 seen_current = 1;
651 if (!dma_is_idle(chan))
652 break;
653 }
654
655 cookie = fsldma_run_tx_complete_actions(chan, desc, cookie);
656
657 fsldma_clean_running_descriptor(chan, desc);
553 } 658 }
554 659
555 /* Run any dependencies */ 660 /*
556 dma_run_dependencies(txd); 661 * Start any pending transactions automatically
662 *
663 * In the ideal case, we keep the DMA controller busy while we go
664 * ahead and free the descriptors below.
665 */
666 fsl_chan_xfer_ld_queue(chan);
557 667
558 dma_descriptor_unmap(txd); 668 if (cookie > 0)
559 chan_dbg(chan, "LD %p free\n", desc); 669 chan->common.completed_cookie = cookie;
560 dma_pool_free(chan->desc_pool, desc, txd->phys);
561} 670}
562 671
563/** 672/**
@@ -627,8 +736,10 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
627 736
628 chan_dbg(chan, "free all channel resources\n"); 737 chan_dbg(chan, "free all channel resources\n");
629 spin_lock_bh(&chan->desc_lock); 738 spin_lock_bh(&chan->desc_lock);
739 fsldma_cleanup_descriptors(chan);
630 fsldma_free_desc_list(chan, &chan->ld_pending); 740 fsldma_free_desc_list(chan, &chan->ld_pending);
631 fsldma_free_desc_list(chan, &chan->ld_running); 741 fsldma_free_desc_list(chan, &chan->ld_running);
742 fsldma_free_desc_list(chan, &chan->ld_completed);
632 spin_unlock_bh(&chan->desc_lock); 743 spin_unlock_bh(&chan->desc_lock);
633 744
634 dma_pool_destroy(chan->desc_pool); 745 dma_pool_destroy(chan->desc_pool);
@@ -865,6 +976,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
865 /* Remove and free all of the descriptors in the LD queue */ 976 /* Remove and free all of the descriptors in the LD queue */
866 fsldma_free_desc_list(chan, &chan->ld_pending); 977 fsldma_free_desc_list(chan, &chan->ld_pending);
867 fsldma_free_desc_list(chan, &chan->ld_running); 978 fsldma_free_desc_list(chan, &chan->ld_running);
979 fsldma_free_desc_list(chan, &chan->ld_completed);
868 chan->idle = true; 980 chan->idle = true;
869 981
870 spin_unlock_bh(&chan->desc_lock); 982 spin_unlock_bh(&chan->desc_lock);
@@ -923,6 +1035,17 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
923 dma_cookie_t cookie, 1035 dma_cookie_t cookie,
924 struct dma_tx_state *txstate) 1036 struct dma_tx_state *txstate)
925{ 1037{
1038 struct fsldma_chan *chan = to_fsl_chan(dchan);
1039 enum dma_status ret;
1040
1041 ret = dma_cookie_status(dchan, cookie, txstate);
1042 if (ret == DMA_COMPLETE)
1043 return ret;
1044
1045 spin_lock_bh(&chan->desc_lock);
1046 fsldma_cleanup_descriptors(chan);
1047 spin_unlock_bh(&chan->desc_lock);
1048
926 return dma_cookie_status(dchan, cookie, txstate); 1049 return dma_cookie_status(dchan, cookie, txstate);
927} 1050}
928 1051
@@ -1000,51 +1123,18 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
1000static void dma_do_tasklet(unsigned long data) 1123static void dma_do_tasklet(unsigned long data)
1001{ 1124{
1002 struct fsldma_chan *chan = (struct fsldma_chan *)data; 1125 struct fsldma_chan *chan = (struct fsldma_chan *)data;
1003 struct fsl_desc_sw *desc, *_desc;
1004 LIST_HEAD(ld_cleanup);
1005 1126
1006 chan_dbg(chan, "tasklet entry\n"); 1127 chan_dbg(chan, "tasklet entry\n");
1007 1128
1008 spin_lock_bh(&chan->desc_lock); 1129 spin_lock_bh(&chan->desc_lock);
1009 1130
1010 /* update the cookie if we have some descriptors to cleanup */
1011 if (!list_empty(&chan->ld_running)) {
1012 dma_cookie_t cookie;
1013
1014 desc = to_fsl_desc(chan->ld_running.prev);
1015 cookie = desc->async_tx.cookie;
1016 dma_cookie_complete(&desc->async_tx);
1017
1018 chan_dbg(chan, "completed_cookie=%d\n", cookie);
1019 }
1020
1021 /*
1022 * move the descriptors to a temporary list so we can drop the lock
1023 * during the entire cleanup operation
1024 */
1025 list_splice_tail_init(&chan->ld_running, &ld_cleanup);
1026
1027 /* the hardware is now idle and ready for more */ 1131 /* the hardware is now idle and ready for more */
1028 chan->idle = true; 1132 chan->idle = true;
1029 1133
1030 /* 1134 /* Run all cleanup for descriptors which have been completed */
1031 * Start any pending transactions automatically 1135 fsldma_cleanup_descriptors(chan);
1032 *
1033 * In the ideal case, we keep the DMA controller busy while we go
1034 * ahead and free the descriptors below.
1035 */
1036 fsl_chan_xfer_ld_queue(chan);
1037 spin_unlock_bh(&chan->desc_lock);
1038
1039 /* Run the callback for each descriptor, in order */
1040 list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
1041
1042 /* Remove from the list of transactions */
1043 list_del(&desc->node);
1044 1136
1045 /* Run all cleanup for this descriptor */ 1137 spin_unlock_bh(&chan->desc_lock);
1046 fsldma_cleanup_descriptor(chan, desc);
1047 }
1048 1138
1049 chan_dbg(chan, "tasklet exit\n"); 1139 chan_dbg(chan, "tasklet exit\n");
1050} 1140}
@@ -1228,6 +1318,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
1228 spin_lock_init(&chan->desc_lock); 1318 spin_lock_init(&chan->desc_lock);
1229 INIT_LIST_HEAD(&chan->ld_pending); 1319 INIT_LIST_HEAD(&chan->ld_pending);
1230 INIT_LIST_HEAD(&chan->ld_running); 1320 INIT_LIST_HEAD(&chan->ld_running);
1321 INIT_LIST_HEAD(&chan->ld_completed);
1231 chan->idle = true; 1322 chan->idle = true;
1232#ifdef CONFIG_PM 1323#ifdef CONFIG_PM
1233 chan->pm_state = RUNNING; 1324 chan->pm_state = RUNNING;