History

Merge branch 'fixes' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine fixes from Vinod Koul: "Here are hopefully last set of fixes for 4.1. This time we have: - fixing pause capability reporting on both dmaengine pause & resume support by Krzysztof - locking fix fir at_xdmac by Ludovic - slave configuration fix for at_xdmac by Ludovic" * 'fixes' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: Fix choppy sound because of unimplemented resume dmaengine: at_xdmac: rework slave configuration part dmaengine: at_xdmac: lock fixes

Linus Torvalds committed 11 years ago

Commit b86a7562 parents dc75117 88d04642 files · +144 −93Browse files

Unified · Split

2 files
  1. drivers/dma/at_xdmac.c +139 −92
  2. drivers/dma/dmaengine.c +5 −1
drivers/dma/at_xdmac.c+139−92
@@ -174,6 +174,8 @@ · 173 unmodified lines
174174 #define AT_XDMAC_MBR_UBC_NDV3 (0x3 << 27) /* Next Descriptor View 3 */
175175
176176 #define AT_XDMAC_MAX_CHAN 0x20
177+#define AT_XDMAC_MAX_CSIZE 16 /* 16 data */
178+#define AT_XDMAC_MAX_DWIDTH 8 /* 64 bits */
177179
178180 #define AT_XDMAC_DMA_BUSWIDTHS\
179181 (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
@@ -192,20 +194,17 @@ struct at_xdmac_chan { · 12 unmodified lines
192194 struct dma_chan chan;
193195 void __iomem *ch_regs;
194196 u32 mask; /* Channel Mask */
195− u32 cfg[2]; /* Channel Configuration Register */
196− #define AT_XDMAC_DEV_TO_MEM_CFG 0 /* Predifined dev to mem channel conf */
197− #define AT_XDMAC_MEM_TO_DEV_CFG 1 /* Predifined mem to dev channel conf */
197+ u32 cfg; /* Channel Configuration Register */
198198 u8 perid; /* Peripheral ID */
199199 u8 perif; /* Peripheral Interface */
200200 u8 memif; /* Memory Interface */
201− u32 per_src_addr;
202− u32 per_dst_addr;
203201 u32 save_cc;
204202 u32 save_cim;
205203 u32 save_cnda;
206204 u32 save_cndc;
207205 unsigned long status;
208206 struct tasklet_struct tasklet;
207+ struct dma_slave_config sconfig;
209208
210209 spinlock_t lock;
211210
@@ -415,8 +414,9 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx) · 203 unmodified lines
415414 struct at_xdmac_desc *desc = txd_to_at_desc(tx);
416415 struct at_xdmac_chan *atchan = to_at_xdmac_chan(tx->chan);
417416 dma_cookie_t cookie;
417+ unsigned long irqflags;
418418
419− spin_lock_bh(&atchan->lock);
419+ spin_lock_irqsave(&atchan->lock, irqflags);
420420 cookie = dma_cookie_assign(tx);
421421
422422 dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n",
@@ -425,7 +425,7 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx) · 2 unmodified lines
425425 if (list_is_singular(&atchan->xfers_list))
426426 at_xdmac_start_xfer(atchan, desc);
427427
428− spin_unlock_bh(&atchan->lock);
428+ spin_unlock_irqrestore(&atchan->lock, irqflags);
429429 return cookie;
430430 }
431431
@@ -494,61 +494,94 @@ static struct dma_chan *at_xdmac_xlate(struct of_phandle_args *dma_spec, · 62 unmodified lines
494494 return chan;
495495 }
496496
497+static int at_xdmac_compute_chan_conf(struct dma_chan *chan,
498+ enum dma_transfer_direction direction)
499+{
500+ struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
501+ int csize, dwidth;
502+
503+ if (direction == DMA_DEV_TO_MEM) {
504+ atchan->cfg =
505+ AT91_XDMAC_DT_PERID(atchan->perid)
506+ | AT_XDMAC_CC_DAM_INCREMENTED_AM
507+ | AT_XDMAC_CC_SAM_FIXED_AM
508+ | AT_XDMAC_CC_DIF(atchan->memif)
509+ | AT_XDMAC_CC_SIF(atchan->perif)
510+ | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
511+ | AT_XDMAC_CC_DSYNC_PER2MEM
512+ | AT_XDMAC_CC_MBSIZE_SIXTEEN
513+ | AT_XDMAC_CC_TYPE_PER_TRAN;
514+ csize = ffs(atchan->sconfig.src_maxburst) - 1;
515+ if (csize < 0) {
516+ dev_err(chan2dev(chan), "invalid src maxburst value\n");
517+ return -EINVAL;
518+ }
519+ atchan->cfg |= AT_XDMAC_CC_CSIZE(csize);
520+ dwidth = ffs(atchan->sconfig.src_addr_width) - 1;
521+ if (dwidth < 0) {
522+ dev_err(chan2dev(chan), "invalid src addr width value\n");
523+ return -EINVAL;
524+ }
525+ atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth);
526+ } else if (direction == DMA_MEM_TO_DEV) {
527+ atchan->cfg =
528+ AT91_XDMAC_DT_PERID(atchan->perid)
529+ | AT_XDMAC_CC_DAM_FIXED_AM
530+ | AT_XDMAC_CC_SAM_INCREMENTED_AM
531+ | AT_XDMAC_CC_DIF(atchan->perif)
532+ | AT_XDMAC_CC_SIF(atchan->memif)
533+ | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
534+ | AT_XDMAC_CC_DSYNC_MEM2PER
535+ | AT_XDMAC_CC_MBSIZE_SIXTEEN
536+ | AT_XDMAC_CC_TYPE_PER_TRAN;
537+ csize = ffs(atchan->sconfig.dst_maxburst) - 1;
538+ if (csize < 0) {
539+ dev_err(chan2dev(chan), "invalid src maxburst value\n");
540+ return -EINVAL;
541+ }
542+ atchan->cfg |= AT_XDMAC_CC_CSIZE(csize);
543+ dwidth = ffs(atchan->sconfig.dst_addr_width) - 1;
544+ if (dwidth < 0) {
545+ dev_err(chan2dev(chan), "invalid dst addr width value\n");
546+ return -EINVAL;
547+ }
548+ atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth);
549+ }
550+
551+ dev_dbg(chan2dev(chan), "%s: cfg=0x%08x\n", __func__, atchan->cfg);
552+
553+ return 0;
554+}
555+
556+/*
557+ * Only check that maxburst and addr width values are supported by the
558+ * the controller but not that the configuration is good to perform the
559+ * transfer since we don't know the direction at this stage.
560+ */
561+static int at_xdmac_check_slave_config(struct dma_slave_config *sconfig)
562+{
563+ if ((sconfig->src_maxburst > AT_XDMAC_MAX_CSIZE)
564+ || (sconfig->dst_maxburst > AT_XDMAC_MAX_CSIZE))
565+ return -EINVAL;
566+
567+ if ((sconfig->src_addr_width > AT_XDMAC_MAX_DWIDTH)
568+ || (sconfig->dst_addr_width > AT_XDMAC_MAX_DWIDTH))
569+ return -EINVAL;
570+
571+ return 0;
572+}
573+
497574 static int at_xdmac_set_slave_config(struct dma_chan *chan,
498575 struct dma_slave_config *sconfig)
499576 {
500577 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
501− u8 dwidth;
502− int csize;
503578
504− atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] =
505− AT91_XDMAC_DT_PERID(atchan->perid)
506− | AT_XDMAC_CC_DAM_INCREMENTED_AM
507− | AT_XDMAC_CC_SAM_FIXED_AM
508− | AT_XDMAC_CC_DIF(atchan->memif)
509− | AT_XDMAC_CC_SIF(atchan->perif)
510− | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
511− | AT_XDMAC_CC_DSYNC_PER2MEM
512− | AT_XDMAC_CC_MBSIZE_SIXTEEN
513− | AT_XDMAC_CC_TYPE_PER_TRAN;
514− csize = at_xdmac_csize(sconfig->src_maxburst);
515− if (csize < 0) {
516− dev_err(chan2dev(chan), "invalid src maxburst value\n");
579+ if (at_xdmac_check_slave_config(sconfig)) {
580+ dev_err(chan2dev(chan), "invalid slave configuration\n");
517581 return -EINVAL;
518582 }
519− atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_CSIZE(csize);
520− dwidth = ffs(sconfig->src_addr_width) - 1;
521− atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
522−
523−
524− atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] =
525− AT91_XDMAC_DT_PERID(atchan->perid)
526− | AT_XDMAC_CC_DAM_FIXED_AM
527− | AT_XDMAC_CC_SAM_INCREMENTED_AM
528− | AT_XDMAC_CC_DIF(atchan->perif)
529− | AT_XDMAC_CC_SIF(atchan->memif)
530− | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
531− | AT_XDMAC_CC_DSYNC_MEM2PER
532− | AT_XDMAC_CC_MBSIZE_SIXTEEN
533− | AT_XDMAC_CC_TYPE_PER_TRAN;
534− csize = at_xdmac_csize(sconfig->dst_maxburst);
535− if (csize < 0) {
536− dev_err(chan2dev(chan), "invalid src maxburst value\n");
537− return -EINVAL;
538− }
539− atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_CSIZE(csize);
540− dwidth = ffs(sconfig->dst_addr_width) - 1;
541− atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
542−
543− /* Src and dst addr are needed to configure the link list descriptor. */
544− atchan->per_src_addr = sconfig->src_addr;
545− atchan->per_dst_addr = sconfig->dst_addr;
546583
547− dev_dbg(chan2dev(chan),
548− "%s: cfg[dev2mem]=0x%08x, cfg[mem2dev]=0x%08x, per_src_addr=0x%08x, per_dst_addr=0x%08x\n",
549− __func__, atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG],
550− atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG],
551− atchan->per_src_addr, atchan->per_dst_addr);
584+ memcpy(&atchan->sconfig, sconfig, sizeof(atchan->sconfig));
552585
553586 return 0;
554587 }
@@ -563,6 +596,8 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, · 8 unmodified lines
563596 struct scatterlist *sg;
564597 int i;
565598 unsigned int xfer_size = 0;
599+ unsigned long irqflags;
600+ struct dma_async_tx_descriptor *ret = NULL;
566601
567602 if (!sgl)
568603 return NULL;
@@ -578,7 +613,10 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, · 9 unmodified lines
578613 flags);
579614
580615 /* Protect dma_sconfig field that can be modified by set_slave_conf. */
581− spin_lock_bh(&atchan->lock);
616+ spin_lock_irqsave(&atchan->lock, irqflags);
617+
618+ if (at_xdmac_compute_chan_conf(chan, direction))
619+ goto spin_unlock;
582620
583621 /* Prepare descriptors. */
584622 for_each_sg(sgl, sg, sg_len, i) {
@@ -589,8 +627,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, · 4 unmodified lines
589627 mem = sg_dma_address(sg);
590628 if (unlikely(!len)) {
591629 dev_err(chan2dev(chan), "sg data length is zero\n");
592− spin_unlock_bh(&atchan->lock);
593− return NULL;
630+ goto spin_unlock;
594631 }
595632 dev_dbg(chan2dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n",
596633 __func__, i, len, mem);
@@ -600,20 +637,18 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, · 3 unmodified lines
600637 dev_err(chan2dev(chan), "can't get descriptor\n");
601638 if (first)
602639 list_splice_init(&first->descs_list, &atchan->free_descs_list);
603− spin_unlock_bh(&atchan->lock);
604− return NULL;
640+ goto spin_unlock;
605641 }
606642
607643 /* Linked list descriptor setup. */
608644 if (direction == DMA_DEV_TO_MEM) {
609− desc->lld.mbr_sa = atchan->per_src_addr;
645+ desc->lld.mbr_sa = atchan->sconfig.src_addr;
610646 desc->lld.mbr_da = mem;
611− desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
612647 } else {
613648 desc->lld.mbr_sa = mem;
614− desc->lld.mbr_da = atchan->per_dst_addr;
615− desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
649+ desc->lld.mbr_da = atchan->sconfig.dst_addr;
616650 }
651+ desc->lld.mbr_cfg = atchan->cfg;
617652 dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
618653 fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
619654 ? at_xdmac_get_dwidth(desc->lld.mbr_cfg)
@@ -645,13 +680,15 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, · 25 unmodified lines
645680 xfer_size += len;
646681 }
647682
648− spin_unlock_bh(&atchan->lock);
649683
650684 first->tx_dma_desc.flags = flags;
651685 first->xfer_size = xfer_size;
652686 first->direction = direction;
687+ ret = &first->tx_dma_desc;
653688
654− return &first->tx_dma_desc;
689+spin_unlock:
690+ spin_unlock_irqrestore(&atchan->lock, irqflags);
691+ return ret;
655692 }
656693
657694 static struct dma_async_tx_descriptor *
@@ -664,6 +701,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, · 6 unmodified lines
664701 struct at_xdmac_desc *first = NULL, *prev = NULL;
665702 unsigned int periods = buf_len / period_len;
666703 int i;
704+ unsigned long irqflags;
667705
668706 dev_dbg(chan2dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n",
669707 __func__, &buf_addr, buf_len, period_len,
@@ -679,32 +717,34 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, · 9 unmodified lines
679717 return NULL;
680718 }
681719
720+ if (at_xdmac_compute_chan_conf(chan, direction))
721+ return NULL;
722+
682723 for (i = 0; i < periods; i++) {
683724 struct at_xdmac_desc *desc = NULL;
684725
685− spin_lock_bh(&atchan->lock);
726+ spin_lock_irqsave(&atchan->lock, irqflags);
686727 desc = at_xdmac_get_desc(atchan);
687728 if (!desc) {
688729 dev_err(chan2dev(chan), "can't get descriptor\n");
689730 if (first)
690731 list_splice_init(&first->descs_list, &atchan->free_descs_list);
691− spin_unlock_bh(&atchan->lock);
732+ spin_unlock_irqrestore(&atchan->lock, irqflags);
692733 return NULL;
693734 }
694− spin_unlock_bh(&atchan->lock);
735+ spin_unlock_irqrestore(&atchan->lock, irqflags);
695736 dev_dbg(chan2dev(chan),
696737 "%s: desc=0x%p, tx_dma_desc.phys=%pad\n",
697738 __func__, desc, &desc->tx_dma_desc.phys);
698739
699740 if (direction == DMA_DEV_TO_MEM) {
700− desc->lld.mbr_sa = atchan->per_src_addr;
741+ desc->lld.mbr_sa = atchan->sconfig.src_addr;
701742 desc->lld.mbr_da = buf_addr + i * period_len;
702− desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
703743 } else {
704744 desc->lld.mbr_sa = buf_addr + i * period_len;
705− desc->lld.mbr_da = atchan->per_dst_addr;
706− desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
745+ desc->lld.mbr_da = atchan->sconfig.dst_addr;
707746 }
747+ desc->lld.mbr_cfg = atchan->cfg;
708748 desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1
709749 | AT_XDMAC_MBR_UBC_NDEN
710750 | AT_XDMAC_MBR_UBC_NSEN
@@ -766,6 +806,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, · 55 unmodified lines
766806 | AT_XDMAC_CC_SIF(0)
767807 | AT_XDMAC_CC_MBSIZE_SIXTEEN
768808 | AT_XDMAC_CC_TYPE_MEM_TRAN;
809+ unsigned long irqflags;
769810
770811 dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, len=%zd, flags=0x%lx\n",
771812 __func__, &src, &dest, len, flags);
@@ -798,9 +839,9 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, · 26 unmodified lines
798839
799840 dev_dbg(chan2dev(chan), "%s: remaining_size=%zu\n", __func__, remaining_size);
800841
801− spin_lock_bh(&atchan->lock);
842+ spin_lock_irqsave(&atchan->lock, irqflags);
802843 desc = at_xdmac_get_desc(atchan);
803− spin_unlock_bh(&atchan->lock);
844+ spin_unlock_irqrestore(&atchan->lock, irqflags);
804845 if (!desc) {
805846 dev_err(chan2dev(chan), "can't get descriptor\n");
806847 if (first)
@@ -886,6 +927,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 79 unmodified lines
886927 int residue;
887928 u32 cur_nda, mask, value;
888929 u8 dwidth = 0;
930+ unsigned long flags;
889931
890932 ret = dma_cookie_status(chan, cookie, txstate);
891933 if (ret == DMA_COMPLETE)
@@ -894,7 +936,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 2 unmodified lines
894936 if (!txstate)
895937 return ret;
896938
897− spin_lock_bh(&atchan->lock);
939+ spin_lock_irqsave(&atchan->lock, flags);
898940
899941 desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
900942
@@ -904,8 +946,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 3 unmodified lines
904946 */
905947 if (!desc->active_xfer) {
906948 dma_set_residue(txstate, desc->xfer_size);
907− spin_unlock_bh(&atchan->lock);
908− return ret;
949+ goto spin_unlock;
909950 }
910951
911952 residue = desc->xfer_size;
@@ -936,14 +977,14 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 24 unmodified lines
936977 }
937978 residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth;
938979
939− spin_unlock_bh(&atchan->lock);
940−
941980 dma_set_residue(txstate, residue);
942981
943982 dev_dbg(chan2dev(chan),
944983 "%s: desc=0x%p, tx_dma_desc.phys=%pad, tx_status=%d, cookie=%d, residue=%d\n",
945984 __func__, desc, &desc->tx_dma_desc.phys, ret, cookie, residue);
946985
986+spin_unlock:
987+ spin_unlock_irqrestore(&atchan->lock, flags);
947988 return ret;
948989 }
949990
@@ -964,8 +1005,9 @@ static void at_xdmac_remove_xfer(struct at_xdmac_chan *atchan, · 14 unmodified lines
9641005 static void at_xdmac_advance_work(struct at_xdmac_chan *atchan)
9651006 {
9661007 struct at_xdmac_desc *desc;
1008+ unsigned long flags;
9671009
968− spin_lock_bh(&atchan->lock);
1010+ spin_lock_irqsave(&atchan->lock, flags);
9691011
9701012 /*
9711013 * If channel is enabled, do nothing, advance_work will be triggered
@@ -980,7 +1022,7 @@ static void at_xdmac_advance_work(struct at_xdmac_chan *atchan) · 8 unmodified lines
9801022 at_xdmac_start_xfer(atchan, desc);
9811023 }
9821024
983− spin_unlock_bh(&atchan->lock);
1025+ spin_unlock_irqrestore(&atchan->lock, flags);
9841026 }
9851027
9861028 static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
@@ -1116,12 +1158,13 @@ static int at_xdmac_device_config(struct dma_chan *chan, · 129 unmodified lines
11161158 {
11171159 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
11181160 int ret;
1161+ unsigned long flags;
11191162
11201163 dev_dbg(chan2dev(chan), "%s\n", __func__);
11211164
1122− spin_lock_bh(&atchan->lock);
1165+ spin_lock_irqsave(&atchan->lock, flags);
11231166 ret = at_xdmac_set_slave_config(chan, config);
1124− spin_unlock_bh(&atchan->lock);
1167+ spin_unlock_irqrestore(&atchan->lock, flags);
11251168
11261169 return ret;
11271170 }
@@ -1130,18 +1173,19 @@ static int at_xdmac_device_pause(struct dma_chan *chan) · 2 unmodified lines
11301173 {
11311174 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
11321175 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
1176+ unsigned long flags;
11331177
11341178 dev_dbg(chan2dev(chan), "%s\n", __func__);
11351179
11361180 if (test_and_set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status))
11371181 return 0;
11381182
1139− spin_lock_bh(&atchan->lock);
1183+ spin_lock_irqsave(&atchan->lock, flags);
11401184 at_xdmac_write(atxdmac, AT_XDMAC_GRWS, atchan->mask);
11411185 while (at_xdmac_chan_read(atchan, AT_XDMAC_CC)
11421186 & (AT_XDMAC_CC_WRIP | AT_XDMAC_CC_RDIP))
11431187 cpu_relax();
1144− spin_unlock_bh(&atchan->lock);
1188+ spin_unlock_irqrestore(&atchan->lock, flags);
11451189
11461190 return 0;
11471191 }
@@ -1150,18 +1194,19 @@ static int at_xdmac_device_resume(struct dma_chan *chan) · 2 unmodified lines
11501194 {
11511195 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
11521196 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
1197+ unsigned long flags;
11531198
11541199 dev_dbg(chan2dev(chan), "%s\n", __func__);
11551200
1156− spin_lock_bh(&atchan->lock);
1201+ spin_lock_irqsave(&atchan->lock, flags);
11571202 if (!at_xdmac_chan_is_paused(atchan)) {
1158− spin_unlock_bh(&atchan->lock);
1203+ spin_unlock_irqrestore(&atchan->lock, flags);
11591204 return 0;
11601205 }
11611206
11621207 at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask);
11631208 clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
1164− spin_unlock_bh(&atchan->lock);
1209+ spin_unlock_irqrestore(&atchan->lock, flags);
11651210
11661211 return 0;
11671212 }
@@ -1171,10 +1216,11 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan) · 3 unmodified lines
11711216 struct at_xdmac_desc *desc, *_desc;
11721217 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
11731218 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
1219+ unsigned long flags;
11741220
11751221 dev_dbg(chan2dev(chan), "%s\n", __func__);
11761222
1177− spin_lock_bh(&atchan->lock);
1223+ spin_lock_irqsave(&atchan->lock, flags);
11781224 at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
11791225 while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask)
11801226 cpu_relax();
@@ -1184,7 +1230,7 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan) · 3 unmodified lines
11841230 at_xdmac_remove_xfer(atchan, desc);
11851231
11861232 clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status);
1187− spin_unlock_bh(&atchan->lock);
1233+ spin_unlock_irqrestore(&atchan->lock, flags);
11881234
11891235 return 0;
11901236 }
@@ -1194,8 +1240,9 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) · 3 unmodified lines
11941240 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
11951241 struct at_xdmac_desc *desc;
11961242 int i;
1243+ unsigned long flags;
11971244
1198− spin_lock_bh(&atchan->lock);
1245+ spin_lock_irqsave(&atchan->lock, flags);
11991246
12001247 if (at_xdmac_chan_is_enabled(atchan)) {
12011248 dev_err(chan2dev(chan),
@@ -1226,7 +1273,7 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) · 24 unmodified lines
12261273 dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i);
12271274
12281275 spin_unlock:
1229− spin_unlock_bh(&atchan->lock);
1276+ spin_unlock_irqrestore(&atchan->lock, flags);
12301277 return i;
12311278 }
12321279
drivers/dma/dmaengine.c+5−1
@@ -487,7 +487,11 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps) · 486 unmodified lines
487487 caps->directions = device->directions;
488488 caps->residue_granularity = device->residue_granularity;
489489
490− caps->cmd_pause = !!device->device_pause;
490+ /*
491+ * Some devices implement only pause (e.g. to get residuum) but no
492+ * resume. However cmd_pause is advertised as pause AND resume.
493+ */
494+ caps->cmd_pause = !!(device->device_pause && device->device_resume);
491495 caps->cmd_terminate = !!device->device_terminate_all;
492496
493497 return 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t