Blob Blame History Raw
From 0b030f54f094fcd42f4a607a675c1851129a58c8 Mon Sep 17 00:00:00 2001
From: Dave Jiang <dave.jiang@intel.com>
Date: Fri, 6 Aug 2021 10:37:40 -0700
Subject: [PATCH] dmaengine: idxd: make submit failure path consistent on desc freeing
Git-commit: 0b030f54f094fcd42f4a607a675c1851129a58c8
Patch-mainline: v5.15-rc1
References: git-fixes

The submission path for dmaengine API does not do descriptor freeing on
failure. Also, with the abort mechanism, the freeing of descriptor happens
when the abort callback is completed. Therefore free descriptor on all
error paths for submission call to make things consistent. Also remove the
double free that would happen on abort in idxd_dma_tx_submit() call.

Fixes: 6b4b87f2c31a ("dmaengine: idxd: fix submission race window")
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/162827146072.3459011.10255348500504659810.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/dma/idxd/dma.c    |    4 +---
 drivers/dma/idxd/submit.c |   11 +++++++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

--- a/drivers/dma/idxd/dma.c
+++ b/drivers/dma/idxd/dma.c
@@ -149,10 +149,8 @@ static dma_cookie_t idxd_dma_tx_submit(s
 	cookie = dma_cookie_assign(tx);
 
 	rc = idxd_submit_desc(wq, desc);
-	if (rc < 0) {
-		idxd_free_desc(wq, desc);
+	if (rc < 0)
 		return rc;
-	}
 
 	return cookie;
 }
--- a/drivers/dma/idxd/submit.c
+++ b/drivers/dma/idxd/submit.c
@@ -140,11 +140,15 @@ int idxd_submit_desc(struct idxd_wq *wq,
 	void __iomem *portal;
 	int rc;
 
-	if (idxd->state != IDXD_DEV_ENABLED)
+	if (idxd->state != IDXD_DEV_ENABLED) {
+		idxd_free_desc(wq, desc);
 		return -EIO;
+	}
 
-	if (!percpu_ref_tryget_live(&wq->wq_active))
+	if (!percpu_ref_tryget_live(&wq->wq_active)) {
+		idxd_free_desc(wq, desc);
 		return -ENXIO;
+	}
 
 	portal = idxd_wq_portal_addr(wq);
 
@@ -176,8 +180,11 @@ int idxd_submit_desc(struct idxd_wq *wq,
 		rc = enqcmds(portal, desc->hw);
 		if (rc < 0) {
 			percpu_ref_put(&wq->wq_active);
+			/* abort operation frees the descriptor */
 			if (ie)
 				llist_abort_desc(wq, ie, desc);
+			else
+				idxd_free_desc(wq, desc);
 			return rc;
 		}
 	}