Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Vinicius Costa Gomes and committed by
Vinod Koul
f019d781 d6077df7

+39
+22
drivers/dma/idxd/device.c
··· 1339 1339 1340 1340 free_irq(ie->vector, ie); 1341 1341 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 + 1342 1347 if (idxd->request_int_handles) 1343 1348 idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX); 1344 1349 idxd_device_clear_perm_entry(idxd, ie); 1345 1350 ie->vector = -1; 1346 1351 ie->int_handle = INVALID_INT_HANDLE; 1347 1352 ie->pasid = IOMMU_PASID_INVALID; 1353 + } 1354 + 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; 1348 1370 } 1349 1371 1350 1372 int idxd_wq_request_irq(struct idxd_wq *wq)
+1
drivers/dma/idxd/idxd.h
··· 803 803 int idxd_wq_init_percpu_ref(struct idxd_wq *wq); 804 804 void idxd_wq_free_irq(struct idxd_wq *wq); 805 805 int idxd_wq_request_irq(struct idxd_wq *wq); 806 + void idxd_wq_flush_descs(struct idxd_wq *wq); 806 807 807 808 /* submission */ 808 809 int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
+16
drivers/dma/idxd/irq.c
··· 397 397 dev_err(&idxd->pdev->dev, "FLR failed\n"); 398 398 } 399 399 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 + 400 411 static irqreturn_t idxd_halt(struct idxd_device *idxd) 401 412 { 402 413 union gensts_reg gensts; ··· 426 415 } else if (gensts.reset_type == IDXD_DEVICE_RESET_FLR) { 427 416 idxd->state = IDXD_DEV_HALTED; 428 417 idxd_mask_error_interrupts(idxd); 418 + /* Flush all pending descriptors, and disable 419 + * interrupts, they will be re-enabled when FLR 420 + * concludes. 421 + */ 422 + idxd_wqs_flush_descs(idxd); 429 423 dev_dbg(&idxd->pdev->dev, 430 424 "idxd halted, doing FLR. After FLR, configs are restored\n"); 431 425 INIT_WORK(&idxd->work, idxd_device_flr);