Skip to content

Commit a516c61

Browse files
committed
Merge tag 'dmaengine-fix-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine fixes from Vinod Koul: "A bunch of driver fixes with idxd ones being the biggest: - Xilinx regmap init error handling, dma_device directions, residue calculation, and reset related timeout fixes - Renesas CHCTRL updates and driver list fixes - DW HDMA cycle bits and MSI data programming fix - IDXD pile of fixes for memeory leak and FLR fixes" * tag 'dmaengine-fix-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (21 commits) dmaengine: xilinx_dma: Fix reset related timeout with two-channel AXIDMA dmaengine: xilinx: xilinx_dma: Fix unmasked residue subtraction dmaengine: xilinx: xilinx_dma: Fix residue calculation for cyclic DMA dmaengine: xilinx: xilinx_dma: Fix dma_device directions dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock dmaengine: sh: rz-dmac: Protect the driver specific lists dmaengine: idxd: fix possible wrong descriptor completion in llist_abort_desc() dmaengine: xilinx: xdma: Fix regmap init error handling dmaengine: dw-edma: Fix multiple times setting of the CYCLE_STATE and CYCLE_BIT bits for HDMA. dmaengine: idxd: Fix leaking event log memory dmaengine: idxd: Fix freeing the allocated ida too late dmaengine: idxd: Fix memory leak when a wq is reset dmaengine: idxd: Fix not releasing workqueue on .release() dmaengine: idxd: Wait for submitted operations on .device_synchronize() dmaengine: idxd: Flush all pending descriptors dmaengine: idxd: Flush kernel workqueues on Function Level Reset dmaengine: idxd: Fix possible invalid memory access after FLR dmaengine: idxd: Fix crash when the event log is disabled dmaengine: idxd: Fix lockdep warnings when calling idxd_device_config() dmaengine: dw-edma: fix MSI data programming for multi-IRQ case ...
2 parents 32ee88d + a17ce4b commit a516c61

14 files changed

Lines changed: 167 additions & 94 deletions

File tree

drivers/dma/dw-edma/dw-edma-core.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ static int dw_edma_irq_request(struct dw_edma *dw,
844844
{
845845
struct dw_edma_chip *chip = dw->chip;
846846
struct device *dev = dw->chip->dev;
847+
struct msi_desc *msi_desc;
847848
u32 wr_mask = 1;
848849
u32 rd_mask = 1;
849850
int i, err = 0;
@@ -895,9 +896,12 @@ static int dw_edma_irq_request(struct dw_edma *dw,
895896
&dw->irq[i]);
896897
if (err)
897898
goto err_irq_free;
898-
899-
if (irq_get_msi_desc(irq))
899+
msi_desc = irq_get_msi_desc(irq);
900+
if (msi_desc) {
900901
get_cached_msi_msg(irq, &dw->irq[i].msi);
902+
if (!msi_desc->pci.msi_attrib.is_msix)
903+
dw->irq[i].msi.data = dw->irq[0].msi.data + i;
904+
}
901905
}
902906

903907
dw->nr_irqs = i;

drivers/dma/dw-edma/dw-hdma-v0-core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,10 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
252252
lower_32_bits(chunk->ll_region.paddr));
253253
SET_CH_32(dw, chan->dir, chan->id, llp.msb,
254254
upper_32_bits(chunk->ll_region.paddr));
255+
/* Set consumer cycle */
256+
SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
257+
HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
255258
}
256-
/* Set consumer cycle */
257-
SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
258-
HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
259259

260260
dw_hdma_v0_sync_ll_data(chunk);
261261

drivers/dma/fsl-edma-main.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -317,28 +317,24 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
317317
return NULL;
318318
i = fsl_chan - fsl_edma->chans;
319319

320-
fsl_chan->priority = dma_spec->args[1];
321-
fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
322-
fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
323-
fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
320+
if (!b_chmux && i != dma_spec->args[0])
321+
continue;
324322

325323
if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1))
326324
continue;
327325

328326
if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1))
329327
continue;
330328

331-
if (!b_chmux && i == dma_spec->args[0]) {
332-
chan = dma_get_slave_channel(chan);
333-
chan->device->privatecnt++;
334-
return chan;
335-
} else if (b_chmux && !fsl_chan->srcid) {
336-
/* if controller support channel mux, choose a free channel */
337-
chan = dma_get_slave_channel(chan);
338-
chan->device->privatecnt++;
339-
fsl_chan->srcid = dma_spec->args[0];
340-
return chan;
341-
}
329+
fsl_chan->srcid = dma_spec->args[0];
330+
fsl_chan->priority = dma_spec->args[1];
331+
fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
332+
fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
333+
fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
334+
335+
chan = dma_get_slave_channel(chan);
336+
chan->device->privatecnt++;
337+
return chan;
342338
}
343339
return NULL;
344340
}

drivers/dma/idxd/cdev.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,7 @@ static const struct device_type idxd_cdev_file_type = {
158158
static void idxd_cdev_dev_release(struct device *dev)
159159
{
160160
struct idxd_cdev *idxd_cdev = dev_to_cdev(dev);
161-
struct idxd_cdev_context *cdev_ctx;
162-
struct idxd_wq *wq = idxd_cdev->wq;
163161

164-
cdev_ctx = &ictx[wq->idxd->data->type];
165-
ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
166162
kfree(idxd_cdev);
167163
}
168164

@@ -582,11 +578,15 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)
582578

583579
void idxd_wq_del_cdev(struct idxd_wq *wq)
584580
{
581+
struct idxd_cdev_context *cdev_ctx;
585582
struct idxd_cdev *idxd_cdev;
586583

587584
idxd_cdev = wq->idxd_cdev;
588585
wq->idxd_cdev = NULL;
589586
cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
587+
588+
cdev_ctx = &ictx[wq->idxd->data->type];
589+
ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
590590
put_device(cdev_dev(idxd_cdev));
591591
}
592592

drivers/dma/idxd/device.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
175175
free_descs(wq);
176176
dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
177177
sbitmap_queue_free(&wq->sbq);
178+
wq->type = IDXD_WQT_NONE;
178179
}
179180
EXPORT_SYMBOL_NS_GPL(idxd_wq_free_resources, "IDXD");
180181

@@ -382,7 +383,6 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
382383
lockdep_assert_held(&wq->wq_lock);
383384
wq->state = IDXD_WQ_DISABLED;
384385
memset(wq->wqcfg, 0, idxd->wqcfg_size);
385-
wq->type = IDXD_WQT_NONE;
386386
wq->threshold = 0;
387387
wq->priority = 0;
388388
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
@@ -831,8 +831,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
831831
struct device *dev = &idxd->pdev->dev;
832832
struct idxd_evl *evl = idxd->evl;
833833

834-
gencfg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
835-
if (!gencfg.evl_en)
834+
if (!evl)
836835
return;
837836

838837
mutex_lock(&evl->lock);
@@ -1125,7 +1124,11 @@ int idxd_device_config(struct idxd_device *idxd)
11251124
{
11261125
int rc;
11271126

1128-
lockdep_assert_held(&idxd->dev_lock);
1127+
guard(spinlock)(&idxd->dev_lock);
1128+
1129+
if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1130+
return 0;
1131+
11291132
rc = idxd_wqs_setup(idxd);
11301133
if (rc < 0)
11311134
return rc;
@@ -1332,6 +1335,11 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
13321335

13331336
free_irq(ie->vector, ie);
13341337
idxd_flush_pending_descs(ie);
1338+
1339+
/* The interrupt might have been already released by FLR */
1340+
if (ie->int_handle == INVALID_INT_HANDLE)
1341+
return;
1342+
13351343
if (idxd->request_int_handles)
13361344
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
13371345
idxd_device_clear_perm_entry(idxd, ie);
@@ -1340,6 +1348,23 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
13401348
ie->pasid = IOMMU_PASID_INVALID;
13411349
}
13421350

1351+
void idxd_wq_flush_descs(struct idxd_wq *wq)
1352+
{
1353+
struct idxd_irq_entry *ie = &wq->ie;
1354+
struct idxd_device *idxd = wq->idxd;
1355+
1356+
guard(mutex)(&wq->wq_lock);
1357+
1358+
if (wq->state != IDXD_WQ_ENABLED || wq->type != IDXD_WQT_KERNEL)
1359+
return;
1360+
1361+
idxd_flush_pending_descs(ie);
1362+
if (idxd->request_int_handles)
1363+
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
1364+
idxd_device_clear_perm_entry(idxd, ie);
1365+
ie->int_handle = INVALID_INT_HANDLE;
1366+
}
1367+
13431368
int idxd_wq_request_irq(struct idxd_wq *wq)
13441369
{
13451370
struct idxd_device *idxd = wq->idxd;
@@ -1454,11 +1479,7 @@ int idxd_drv_enable_wq(struct idxd_wq *wq)
14541479
}
14551480
}
14561481

1457-
rc = 0;
1458-
spin_lock(&idxd->dev_lock);
1459-
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1460-
rc = idxd_device_config(idxd);
1461-
spin_unlock(&idxd->dev_lock);
1482+
rc = idxd_device_config(idxd);
14621483
if (rc < 0) {
14631484
dev_dbg(dev, "Writing wq %d config failed: %d\n", wq->id, rc);
14641485
goto err;
@@ -1533,7 +1554,6 @@ void idxd_drv_disable_wq(struct idxd_wq *wq)
15331554
idxd_wq_reset(wq);
15341555
idxd_wq_free_resources(wq);
15351556
percpu_ref_exit(&wq->wq_active);
1536-
wq->type = IDXD_WQT_NONE;
15371557
wq->client_count = 0;
15381558
}
15391559
EXPORT_SYMBOL_NS_GPL(idxd_drv_disable_wq, "IDXD");
@@ -1554,10 +1574,7 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
15541574
}
15551575

15561576
/* Device configuration */
1557-
spin_lock(&idxd->dev_lock);
1558-
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
1559-
rc = idxd_device_config(idxd);
1560-
spin_unlock(&idxd->dev_lock);
1577+
rc = idxd_device_config(idxd);
15611578
if (rc < 0)
15621579
return -ENXIO;
15631580

drivers/dma/idxd/dma.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,22 @@ static void idxd_dma_release(struct dma_device *device)
194194
kfree(idxd_dma);
195195
}
196196

197+
static int idxd_dma_terminate_all(struct dma_chan *c)
198+
{
199+
struct idxd_wq *wq = to_idxd_wq(c);
200+
201+
idxd_wq_flush_descs(wq);
202+
203+
return 0;
204+
}
205+
206+
static void idxd_dma_synchronize(struct dma_chan *c)
207+
{
208+
struct idxd_wq *wq = to_idxd_wq(c);
209+
210+
idxd_wq_drain(wq);
211+
}
212+
197213
int idxd_register_dma_device(struct idxd_device *idxd)
198214
{
199215
struct idxd_dma_dev *idxd_dma;
@@ -224,6 +240,8 @@ int idxd_register_dma_device(struct idxd_device *idxd)
224240
dma->device_issue_pending = idxd_dma_issue_pending;
225241
dma->device_alloc_chan_resources = idxd_dma_alloc_chan_resources;
226242
dma->device_free_chan_resources = idxd_dma_free_chan_resources;
243+
dma->device_terminate_all = idxd_dma_terminate_all;
244+
dma->device_synchronize = idxd_dma_synchronize;
227245

228246
rc = dma_async_device_register(dma);
229247
if (rc < 0) {

drivers/dma/idxd/idxd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,7 @@ void idxd_wq_quiesce(struct idxd_wq *wq);
803803
int idxd_wq_init_percpu_ref(struct idxd_wq *wq);
804804
void idxd_wq_free_irq(struct idxd_wq *wq);
805805
int idxd_wq_request_irq(struct idxd_wq *wq);
806+
void idxd_wq_flush_descs(struct idxd_wq *wq);
806807

807808
/* submission */
808809
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);

drivers/dma/idxd/init.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,8 @@ static void idxd_device_config_restore(struct idxd_device *idxd,
973973

974974
idxd->rdbuf_limit = idxd_saved->saved_idxd.rdbuf_limit;
975975

976-
idxd->evl->size = saved_evl->size;
976+
if (idxd->evl)
977+
idxd->evl->size = saved_evl->size;
977978

978979
for (i = 0; i < idxd->max_groups; i++) {
979980
struct idxd_group *saved_group, *group;
@@ -1104,12 +1105,10 @@ static void idxd_reset_done(struct pci_dev *pdev)
11041105
idxd_device_config_restore(idxd, idxd->idxd_saved);
11051106

11061107
/* Re-configure IDXD device if allowed. */
1107-
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) {
1108-
rc = idxd_device_config(idxd);
1109-
if (rc < 0) {
1110-
dev_err(dev, "HALT: %s config fails\n", idxd_name);
1111-
goto out;
1112-
}
1108+
rc = idxd_device_config(idxd);
1109+
if (rc < 0) {
1110+
dev_err(dev, "HALT: %s config fails\n", idxd_name);
1111+
goto out;
11131112
}
11141113

11151114
/* Bind IDXD device to driver. */
@@ -1147,6 +1146,7 @@ static void idxd_reset_done(struct pci_dev *pdev)
11471146
}
11481147
out:
11491148
kfree(idxd->idxd_saved);
1149+
idxd->idxd_saved = NULL;
11501150
}
11511151

11521152
static const struct pci_error_handlers idxd_error_handler = {

drivers/dma/idxd/irq.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,17 @@ static void idxd_device_flr(struct work_struct *work)
397397
dev_err(&idxd->pdev->dev, "FLR failed\n");
398398
}
399399

400+
static void idxd_wqs_flush_descs(struct idxd_device *idxd)
401+
{
402+
int i;
403+
404+
for (i = 0; i < idxd->max_wqs; i++) {
405+
struct idxd_wq *wq = idxd->wqs[i];
406+
407+
idxd_wq_flush_descs(wq);
408+
}
409+
}
410+
400411
static irqreturn_t idxd_halt(struct idxd_device *idxd)
401412
{
402413
union gensts_reg gensts;
@@ -415,6 +426,11 @@ static irqreturn_t idxd_halt(struct idxd_device *idxd)
415426
} else if (gensts.reset_type == IDXD_DEVICE_RESET_FLR) {
416427
idxd->state = IDXD_DEV_HALTED;
417428
idxd_mask_error_interrupts(idxd);
429+
/* Flush all pending descriptors, and disable
430+
* interrupts, they will be re-enabled when FLR
431+
* concludes.
432+
*/
433+
idxd_wqs_flush_descs(idxd);
418434
dev_dbg(&idxd->pdev->dev,
419435
"idxd halted, doing FLR. After FLR, configs are restored\n");
420436
INIT_WORK(&idxd->work, idxd_device_flr);

drivers/dma/idxd/submit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
138138
*/
139139
list_for_each_entry_safe(d, t, &flist, list) {
140140
list_del_init(&d->list);
141-
idxd_dma_complete_txd(found, IDXD_COMPLETE_ABORT, true,
141+
idxd_dma_complete_txd(d, IDXD_COMPLETE_ABORT, true,
142142
NULL, NULL);
143143
}
144144
}

0 commit comments

Comments
 (0)