Merge tag 'dmaengine-fix-5.5-rc5' of git://git.infradead.org/users/vkoul/slave-dma
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 4 Jan 2020 18:49:15 +0000 (10:49 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 4 Jan 2020 18:49:15 +0000 (10:49 -0800)
Pull dmaengine fixes from Vinod Koul:
 "A bunch of fixes for:

   - uninitialized dma_slave_caps access

   - virt-dma use after free in vchan_complete()

   - driver fixes for ioat, k3dma and jz4780"

* tag 'dmaengine-fix-5.5-rc5' of git://git.infradead.org/users/vkoul/slave-dma:
  ioat: ioat_alloc_ring() failure handling.
  dmaengine: virt-dma: Fix access after free in vchan_complete()
  dmaengine: k3dma: Avoid null pointer traversal
  dmaengine: dma-jz4780: Also break descriptor chains on JZ4725B
  dmaengine: Fix access to uninitialized dma_slave_caps

drivers/dma/dma-jz4780.c
drivers/dma/ioat/dma.c
drivers/dma/k3dma.c
drivers/dma/virt-dma.c
include/linux/dmaengine.h

index fa626ac..44af435 100644 (file)
@@ -999,7 +999,8 @@ static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
        .nb_channels = 6,
        .transfer_ord_max = 5,
-       .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC,
+       .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
+                JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4770_dma_soc_data = {
index 1a422a8..18c011e 100644 (file)
@@ -377,10 +377,11 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
 
                descs->virt = dma_alloc_coherent(to_dev(ioat_chan),
                                                 SZ_2M, &descs->hw, flags);
-               if (!descs->virt && (i > 0)) {
+               if (!descs->virt) {
                        int idx;
 
                        for (idx = 0; idx < i; idx++) {
+                               descs = &ioat_chan->descs[idx];
                                dma_free_coherent(to_dev(ioat_chan), SZ_2M,
                                                  descs->virt, descs->hw);
                                descs->virt = NULL;
index adecea5..c5c1aa0 100644 (file)
@@ -229,9 +229,11 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
                        c = p->vchan;
                        if (c && (tc1 & BIT(i))) {
                                spin_lock_irqsave(&c->vc.lock, flags);
-                               vchan_cookie_complete(&p->ds_run->vd);
-                               p->ds_done = p->ds_run;
-                               p->ds_run = NULL;
+                               if (p->ds_run != NULL) {
+                                       vchan_cookie_complete(&p->ds_run->vd);
+                                       p->ds_done = p->ds_run;
+                                       p->ds_run = NULL;
+                               }
                                spin_unlock_irqrestore(&c->vc.lock, flags);
                        }
                        if (c && (tc2 & BIT(i))) {
@@ -271,6 +273,10 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
        if (BIT(c->phy->idx) & k3_dma_get_chan_stat(d))
                return -EAGAIN;
 
+       /* Avoid losing track of  ds_run if a transaction is in flight */
+       if (c->phy->ds_run)
+               return -EAGAIN;
+
        if (vd) {
                struct k3_dma_desc_sw *ds =
                        container_of(vd, struct k3_dma_desc_sw, vd);
index ec4adf4..256fc66 100644 (file)
@@ -104,9 +104,8 @@ static void vchan_complete(unsigned long arg)
                dmaengine_desc_get_callback(&vd->tx, &cb);
 
                list_del(&vd->node);
-               vchan_vdesc_fini(vd);
-
                dmaengine_desc_callback_invoke(&cb, &vd->tx_result);
+               vchan_vdesc_fini(vd);
        }
 }
 
index 8fcdee1..dad4a68 100644 (file)
@@ -1364,8 +1364,11 @@ static inline int dma_get_slave_caps(struct dma_chan *chan,
 static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx)
 {
        struct dma_slave_caps caps;
+       int ret;
 
-       dma_get_slave_caps(tx->chan, &caps);
+       ret = dma_get_slave_caps(tx->chan, &caps);
+       if (ret)
+               return ret;
 
        if (caps.descriptor_reuse) {
                tx->flags |= DMA_CTRL_REUSE;