Skip to content

Commit 35929da

Browse files
committed
Merge tag 'dmaengine-fix-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine fixes from Vinod Koul: - email address Update for Jie Hai - fix double increment of client_count in dma_chan_get() - idxd driver fixes: use after free, probe error handling and callback on wq disable - fix for qcom gpi driver GO tre - ptdma locking fix - tegra & imx-sdma mem leak fix * tag 'dmaengine-fix-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: ptdma: pt_core_execute_cmd() should use spinlock dmaengine: tegra: Fix memory leak in terminate_all() dmaengine: xilinx_dma: call of_node_put() when breaking out of for_each_child_of_node() dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init dmaengine: Fix double increment of client_count in dma_chan_get() dmaengine: tegra210-adma: fix global intr clear Add exception protection processing for vd in axi_chan_handle_err function dmaengine: lgm: Move DT parsing after initialization MAINTAINERS: update Jie Hai's email address dmaengine: ti: k3-udma: Do conditional decrement of UDMA_CHAN_RT_PEER_BCNT_REG dmaengine: idxd: Do not call DMX TX callbacks during workqueue disable dmaengine: idxd: Prevent use after free on completion memory dmaengine: idxd: Let probe fail when workqueue cannot be enabled dmaengine: qcom: gpi: Set link_rx bit on GO TRE for rx operation
2 parents aaaf919 + 95e5fda commit 35929da

File tree

13 files changed

+46
-21
lines changed

13 files changed

+46
-21
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9298,7 +9298,7 @@ F: net/dsa/tag_hellcreek.c
92989298

92999299
HISILICON DMA DRIVER
93009300
M: Zhou Wang <[email protected]>
9301-
M: Jie Hai <haijie1@hisilicon.com>
9301+
M: Jie Hai <haijie1@huawei.com>
93029302
93039303
S: Maintained
93049304
F: drivers/dma/hisi_dma.c

drivers/dma/dmaengine.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ static int dma_chan_get(struct dma_chan *chan)
451451
/* The channel is already in use, update client count */
452452
if (chan->client_count) {
453453
__module_get(owner);
454-
goto out;
454+
chan->client_count++;
455+
return 0;
455456
}
456457

457458
if (!try_module_get(owner))
@@ -470,11 +471,11 @@ static int dma_chan_get(struct dma_chan *chan)
470471
goto err_out;
471472
}
472473

474+
chan->client_count++;
475+
473476
if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
474477
balance_ref_count(chan);
475478

476-
out:
477-
chan->client_count++;
478479
return 0;
479480

480481
err_out:

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,11 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
10181018

10191019
/* The bad descriptor currently is in the head of vc list */
10201020
vd = vchan_next_desc(&chan->vc);
1021+
if (!vd) {
1022+
dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
1023+
axi_chan_name(chan));
1024+
goto out;
1025+
}
10211026
/* Remove the completed descriptor from issued list */
10221027
list_del(&vd->node);
10231028

@@ -1032,6 +1037,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
10321037
/* Try to restart the controller */
10331038
axi_chan_start_first_queued(chan);
10341039

1040+
out:
10351041
spin_unlock_irqrestore(&chan->vc.lock, flags);
10361042
}
10371043

drivers/dma/idxd/device.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,8 +1172,19 @@ static void idxd_flush_pending_descs(struct idxd_irq_entry *ie)
11721172
spin_unlock(&ie->list_lock);
11731173

11741174
list_for_each_entry_safe(desc, itr, &flist, list) {
1175+
struct dma_async_tx_descriptor *tx;
1176+
11751177
list_del(&desc->list);
11761178
ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT;
1179+
/*
1180+
* wq is being disabled. Any remaining descriptors are
1181+
* likely to be stuck and can be dropped. callback could
1182+
* point to code that is no longer accessible, for example
1183+
* if dmatest module has been unloaded.
1184+
*/
1185+
tx = &desc->txd;
1186+
tx->callback = NULL;
1187+
tx->callback_result = NULL;
11771188
idxd_dma_complete_txd(desc, ctype, true);
11781189
}
11791190
}
@@ -1390,8 +1401,7 @@ int drv_enable_wq(struct idxd_wq *wq)
13901401
err_irq:
13911402
idxd_wq_unmap_portal(wq);
13921403
err_map_portal:
1393-
rc = idxd_wq_disable(wq, false);
1394-
if (rc < 0)
1404+
if (idxd_wq_disable(wq, false))
13951405
dev_dbg(dev, "wq %s disable failed\n", dev_name(wq_confdev(wq)));
13961406
err:
13971407
return rc;
@@ -1408,11 +1418,11 @@ void drv_disable_wq(struct idxd_wq *wq)
14081418
dev_warn(dev, "Clients has claim on wq %d: %d\n",
14091419
wq->id, idxd_wq_refcount(wq));
14101420

1411-
idxd_wq_free_resources(wq);
14121421
idxd_wq_unmap_portal(wq);
14131422
idxd_wq_drain(wq);
14141423
idxd_wq_free_irq(wq);
14151424
idxd_wq_reset(wq);
1425+
idxd_wq_free_resources(wq);
14161426
percpu_ref_exit(&wq->wq_active);
14171427
wq->type = IDXD_WQT_NONE;
14181428
wq->client_count = 0;

drivers/dma/imx-sdma.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1521,10 +1521,12 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
15211521
sdma_config_ownership(sdmac, false, true, false);
15221522

15231523
if (sdma_load_context(sdmac))
1524-
goto err_desc_out;
1524+
goto err_bd_out;
15251525

15261526
return desc;
15271527

1528+
err_bd_out:
1529+
sdma_free_bd(desc);
15281530
err_desc_out:
15291531
kfree(desc);
15301532
err_out:

drivers/dma/lgm/lgm-dma.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ static void ldma_dev_init(struct ldma_dev *d)
914914
}
915915
}
916916

917-
static int ldma_cfg_init(struct ldma_dev *d)
917+
static int ldma_parse_dt(struct ldma_dev *d)
918918
{
919919
struct fwnode_handle *fwnode = dev_fwnode(d->dev);
920920
struct ldma_port *p;
@@ -1661,10 +1661,6 @@ static int intel_ldma_probe(struct platform_device *pdev)
16611661
p->ldev = d;
16621662
}
16631663

1664-
ret = ldma_cfg_init(d);
1665-
if (ret)
1666-
return ret;
1667-
16681664
dma_dev->dev = &pdev->dev;
16691665

16701666
ch_mask = (unsigned long)d->channels_mask;
@@ -1675,6 +1671,10 @@ static int intel_ldma_probe(struct platform_device *pdev)
16751671
ldma_dma_init_v3X(j, d);
16761672
}
16771673

1674+
ret = ldma_parse_dt(d);
1675+
if (ret)
1676+
return ret;
1677+
16781678
dma_dev->device_alloc_chan_resources = ldma_alloc_chan_resources;
16791679
dma_dev->device_free_chan_resources = ldma_free_chan_resources;
16801680
dma_dev->device_terminate_all = ldma_terminate_all;

drivers/dma/ptdma/ptdma-dev.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
7171
bool soc = FIELD_GET(DWORD0_SOC, desc->dw0);
7272
u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx];
7373
u32 tail;
74+
unsigned long flags;
7475

7576
if (soc) {
7677
desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0);
7778
desc->dw0 &= ~DWORD0_SOC;
7879
}
79-
mutex_lock(&cmd_q->q_mutex);
80+
spin_lock_irqsave(&cmd_q->q_lock, flags);
8081

8182
/* Copy 32-byte command descriptor to hw queue. */
8283
memcpy(q_desc, desc, 32);
@@ -91,7 +92,7 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
9192

9293
/* Turn the queue back on using our cached control register */
9394
pt_start_queue(cmd_q);
94-
mutex_unlock(&cmd_q->q_mutex);
95+
spin_unlock_irqrestore(&cmd_q->q_lock, flags);
9596

9697
return 0;
9798
}
@@ -199,7 +200,7 @@ int pt_core_init(struct pt_device *pt)
199200

200201
cmd_q->pt = pt;
201202
cmd_q->dma_pool = dma_pool;
202-
mutex_init(&cmd_q->q_mutex);
203+
spin_lock_init(&cmd_q->q_lock);
203204

204205
/* Page alignment satisfies our needs for N <= 128 */
205206
cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);

drivers/dma/ptdma/ptdma.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ struct pt_cmd_queue {
196196
struct ptdma_desc *qbase;
197197

198198
/* Aligned queue start address (per requirement) */
199-
struct mutex q_mutex ____cacheline_aligned;
199+
spinlock_t q_lock ____cacheline_aligned;
200200
unsigned int qidx;
201201

202202
unsigned int qsize;

drivers/dma/qcom/gpi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,7 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc,
17561756
tre->dword[3] = u32_encode_bits(TRE_TYPE_GO, TRE_FLAGS_TYPE);
17571757
if (spi->cmd == SPI_RX) {
17581758
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
1759+
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_LINK);
17591760
} else if (spi->cmd == SPI_TX) {
17601761
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN);
17611762
} else { /* SPI_DUPLEX */

drivers/dma/tegra186-gpc-dma.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
711711
return err;
712712
}
713713

714+
vchan_terminate_vdesc(&tdc->dma_desc->vd);
714715
tegra_dma_disable(tdc);
715716
tdc->dma_desc = NULL;
716717
}

0 commit comments

Comments
 (0)