diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-03 21:16:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-03 21:16:48 -0500 |
commit | 71a83a6db6138b9d41d8a0b6b91cb59f6dc4742c (patch) | |
tree | f74b6e4e48257ec6ce40b95645ecb8533b9cc1f8 /drivers/dma/sun6i-dma.c | |
parent | b97526f3ff95f92b107f0fb52cbb8627e395429b (diff) | |
parent | a6c5170d1edea97c538c81e377e56c7b5c5b7e63 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/ethernet/rocker/rocker.c
The rocker commit was two overlapping changes, one to rename
the ->vport member to ->pport, and another making the bitmask
expression use '1ULL' instead of plain '1'.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/dma/sun6i-dma.c')
-rw-r--r-- | drivers/dma/sun6i-dma.c | 160 |
1 files changed, 87 insertions, 73 deletions
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 159f1736a16f..7ebcf9bec698 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c | |||
@@ -355,38 +355,6 @@ static void sun6i_dma_free_desc(struct virt_dma_desc *vd) | |||
355 | kfree(txd); | 355 | kfree(txd); |
356 | } | 356 | } |
357 | 357 | ||
358 | static int sun6i_dma_terminate_all(struct sun6i_vchan *vchan) | ||
359 | { | ||
360 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device); | ||
361 | struct sun6i_pchan *pchan = vchan->phy; | ||
362 | unsigned long flags; | ||
363 | LIST_HEAD(head); | ||
364 | |||
365 | spin_lock(&sdev->lock); | ||
366 | list_del_init(&vchan->node); | ||
367 | spin_unlock(&sdev->lock); | ||
368 | |||
369 | spin_lock_irqsave(&vchan->vc.lock, flags); | ||
370 | |||
371 | vchan_get_all_descriptors(&vchan->vc, &head); | ||
372 | |||
373 | if (pchan) { | ||
374 | writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE); | ||
375 | writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE); | ||
376 | |||
377 | vchan->phy = NULL; | ||
378 | pchan->vchan = NULL; | ||
379 | pchan->desc = NULL; | ||
380 | pchan->done = NULL; | ||
381 | } | ||
382 | |||
383 | spin_unlock_irqrestore(&vchan->vc.lock, flags); | ||
384 | |||
385 | vchan_dma_desc_free_list(&vchan->vc, &head); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) | 358 | static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) |
391 | { | 359 | { |
392 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device); | 360 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device); |
@@ -675,57 +643,92 @@ err_lli_free: | |||
675 | return NULL; | 643 | return NULL; |
676 | } | 644 | } |
677 | 645 | ||
678 | static int sun6i_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 646 | static int sun6i_dma_config(struct dma_chan *chan, |
679 | unsigned long arg) | 647 | struct dma_slave_config *config) |
648 | { | ||
649 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); | ||
650 | |||
651 | memcpy(&vchan->cfg, config, sizeof(*config)); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static int sun6i_dma_pause(struct dma_chan *chan) | ||
657 | { | ||
658 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); | ||
659 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); | ||
660 | struct sun6i_pchan *pchan = vchan->phy; | ||
661 | |||
662 | dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc); | ||
663 | |||
664 | if (pchan) { | ||
665 | writel(DMA_CHAN_PAUSE_PAUSE, | ||
666 | pchan->base + DMA_CHAN_PAUSE); | ||
667 | } else { | ||
668 | spin_lock(&sdev->lock); | ||
669 | list_del_init(&vchan->node); | ||
670 | spin_unlock(&sdev->lock); | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static int sun6i_dma_resume(struct dma_chan *chan) | ||
680 | { | 677 | { |
681 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); | 678 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); |
682 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); | 679 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); |
683 | struct sun6i_pchan *pchan = vchan->phy; | 680 | struct sun6i_pchan *pchan = vchan->phy; |
684 | unsigned long flags; | 681 | unsigned long flags; |
685 | int ret = 0; | ||
686 | 682 | ||
687 | switch (cmd) { | 683 | dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc); |
688 | case DMA_RESUME: | ||
689 | dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc); | ||
690 | 684 | ||
691 | spin_lock_irqsave(&vchan->vc.lock, flags); | 685 | spin_lock_irqsave(&vchan->vc.lock, flags); |
692 | 686 | ||
693 | if (pchan) { | 687 | if (pchan) { |
694 | writel(DMA_CHAN_PAUSE_RESUME, | 688 | writel(DMA_CHAN_PAUSE_RESUME, |
695 | pchan->base + DMA_CHAN_PAUSE); | 689 | pchan->base + DMA_CHAN_PAUSE); |
696 | } else if (!list_empty(&vchan->vc.desc_issued)) { | 690 | } else if (!list_empty(&vchan->vc.desc_issued)) { |
697 | spin_lock(&sdev->lock); | 691 | spin_lock(&sdev->lock); |
698 | list_add_tail(&vchan->node, &sdev->pending); | 692 | list_add_tail(&vchan->node, &sdev->pending); |
699 | spin_unlock(&sdev->lock); | 693 | spin_unlock(&sdev->lock); |
700 | } | 694 | } |
701 | 695 | ||
702 | spin_unlock_irqrestore(&vchan->vc.lock, flags); | 696 | spin_unlock_irqrestore(&vchan->vc.lock, flags); |
703 | break; | ||
704 | 697 | ||
705 | case DMA_PAUSE: | 698 | return 0; |
706 | dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc); | 699 | } |
707 | 700 | ||
708 | if (pchan) { | 701 | static int sun6i_dma_terminate_all(struct dma_chan *chan) |
709 | writel(DMA_CHAN_PAUSE_PAUSE, | 702 | { |
710 | pchan->base + DMA_CHAN_PAUSE); | 703 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); |
711 | } else { | 704 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); |
712 | spin_lock(&sdev->lock); | 705 | struct sun6i_pchan *pchan = vchan->phy; |
713 | list_del_init(&vchan->node); | 706 | unsigned long flags; |
714 | spin_unlock(&sdev->lock); | 707 | LIST_HEAD(head); |
715 | } | 708 | |
716 | break; | 709 | spin_lock(&sdev->lock); |
717 | 710 | list_del_init(&vchan->node); | |
718 | case DMA_TERMINATE_ALL: | 711 | spin_unlock(&sdev->lock); |
719 | ret = sun6i_dma_terminate_all(vchan); | 712 | |
720 | break; | 713 | spin_lock_irqsave(&vchan->vc.lock, flags); |
721 | case DMA_SLAVE_CONFIG: | 714 | |
722 | memcpy(&vchan->cfg, (void *)arg, sizeof(struct dma_slave_config)); | 715 | vchan_get_all_descriptors(&vchan->vc, &head); |
723 | break; | 716 | |
724 | default: | 717 | if (pchan) { |
725 | ret = -ENXIO; | 718 | writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE); |
726 | break; | 719 | writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE); |
720 | |||
721 | vchan->phy = NULL; | ||
722 | pchan->vchan = NULL; | ||
723 | pchan->desc = NULL; | ||
724 | pchan->done = NULL; | ||
727 | } | 725 | } |
728 | return ret; | 726 | |
727 | spin_unlock_irqrestore(&vchan->vc.lock, flags); | ||
728 | |||
729 | vchan_dma_desc_free_list(&vchan->vc, &head); | ||
730 | |||
731 | return 0; | ||
729 | } | 732 | } |
730 | 733 | ||
731 | static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, | 734 | static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, |
@@ -960,9 +963,20 @@ static int sun6i_dma_probe(struct platform_device *pdev) | |||
960 | sdc->slave.device_issue_pending = sun6i_dma_issue_pending; | 963 | sdc->slave.device_issue_pending = sun6i_dma_issue_pending; |
961 | sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg; | 964 | sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg; |
962 | sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy; | 965 | sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy; |
963 | sdc->slave.device_control = sun6i_dma_control; | ||
964 | sdc->slave.copy_align = 4; | 966 | sdc->slave.copy_align = 4; |
965 | 967 | sdc->slave.device_config = sun6i_dma_config; | |
968 | sdc->slave.device_pause = sun6i_dma_pause; | ||
969 | sdc->slave.device_resume = sun6i_dma_resume; | ||
970 | sdc->slave.device_terminate_all = sun6i_dma_terminate_all; | ||
971 | sdc->slave.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
972 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
973 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
974 | sdc->slave.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
975 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
976 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
977 | sdc->slave.directions = BIT(DMA_DEV_TO_MEM) | | ||
978 | BIT(DMA_MEM_TO_DEV); | ||
979 | sdc->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | ||
966 | sdc->slave.dev = &pdev->dev; | 980 | sdc->slave.dev = &pdev->dev; |
967 | 981 | ||
968 | sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels, | 982 | sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels, |