Skip to content

Commit f019d78

Browse files
vcgomesvinodkoul
authored andcommitted
dmaengine: idxd: Flush kernel workqueues on Function Level Reset
When a Function Level Reset (FLR) happens, terminate the pending descriptors that were issued by in-kernel users and disable the interrupts associated with those. They will be re-enabled after FLR finishes. idxd_wq_flush_desc() is declared on idxd.h because it's going to be used in by the DMA backend in a future patch. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://patch.msgid.link/20260121-idxd-fix-flr-on-kernel-queues-v3-v3-4-7ed70658a9d1@intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent d6077df commit f019d78

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

drivers/dma/idxd/device.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,11 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
13391339

13401340
free_irq(ie->vector, ie);
13411341
idxd_flush_pending_descs(ie);
1342+
1343+
/* The interrupt might have been already released by FLR */
1344+
if (ie->int_handle == INVALID_INT_HANDLE)
1345+
return;
1346+
13421347
if (idxd->request_int_handles)
13431348
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
13441349
idxd_device_clear_perm_entry(idxd, ie);
@@ -1347,6 +1352,23 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
13471352
ie->pasid = IOMMU_PASID_INVALID;
13481353
}
13491354

1355+
void idxd_wq_flush_descs(struct idxd_wq *wq)
1356+
{
1357+
struct idxd_irq_entry *ie = &wq->ie;
1358+
struct idxd_device *idxd = wq->idxd;
1359+
1360+
guard(mutex)(&wq->wq_lock);
1361+
1362+
if (wq->state != IDXD_WQ_ENABLED || wq->type != IDXD_WQT_KERNEL)
1363+
return;
1364+
1365+
idxd_flush_pending_descs(ie);
1366+
if (idxd->request_int_handles)
1367+
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
1368+
idxd_device_clear_perm_entry(idxd, ie);
1369+
ie->int_handle = INVALID_INT_HANDLE;
1370+
}
1371+
13501372
int idxd_wq_request_irq(struct idxd_wq *wq)
13511373
{
13521374
struct idxd_device *idxd = wq->idxd;

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/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);

0 commit comments

Comments
 (0)