[10/22] net/bnxt: retry irq callback deregistration

Message ID 20190718033616.37605-11-ajit.khaparde@broadcom.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series bnxt patchset |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Ajit Khaparde July 18, 2019, 3:36 a.m. UTC
  From: Lance Richardson <lance.richardson@broadcom.com>

rte_intr_callback_unregister() can fail if the handler happens to
be active at the time of the call. Add logic to retry a reasonable
number of times to help ensure that the callback is unregistered
on uninit.

Fixes: 7bc8e9a227cc ("net/bnxt: support async link notification")
Cc: stable@dpdk.org

Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Signed-off-by: Lance Richardson <lance.richardson@broadcom.com>
---
 drivers/net/bnxt/bnxt_irq.c | 63 +++++++++++++++++++++++++++----------
 drivers/net/bnxt/bnxt_irq.h |  2 +-
 2 files changed, 48 insertions(+), 17 deletions(-)
  

Patch

diff --git a/drivers/net/bnxt/bnxt_irq.c b/drivers/net/bnxt/bnxt_irq.c
index 9ff16ddd8..42a2ff2a3 100644
--- a/drivers/net/bnxt/bnxt_irq.c
+++ b/drivers/net/bnxt/bnxt_irq.c
@@ -51,21 +51,45 @@  static void bnxt_int_handler(void *param)
 		B_CP_DB_REARM(cpr, cpr->cp_raw_cons);
 }
 
-void bnxt_free_int(struct bnxt *bp)
+int bnxt_free_int(struct bnxt *bp)
 {
-	struct bnxt_irq *irq;
-
-	irq = bp->irq_tbl;
-	if (irq) {
-		if (irq->requested) {
-			rte_intr_callback_unregister(&bp->pdev->intr_handle,
-						     irq->handler,
-						     (void *)bp->eth_dev);
-			irq->requested = 0;
+	struct rte_intr_handle *intr_handle = &bp->pdev->intr_handle;
+	struct bnxt_irq *irq = bp->irq_tbl;
+	int rc = 0;
+
+	if (!irq)
+		return 0;
+
+	if (irq->requested) {
+		int count = 0;
+
+		/*
+		 * Callback deregistration will fail with rc -EAGAIN if the
+		 * callback is currently active. Retry every 50 ms until
+		 * successful or 500 ms has elapsed.
+		 */
+		do {
+			rc = rte_intr_callback_unregister(intr_handle,
+							  irq->handler,
+							  bp->eth_dev);
+			if (rc >= 0) {
+				irq->requested = 0;
+				break;
+			}
+			rte_delay_ms(50);
+		} while (count++ < 10);
+
+		if (rc < 0) {
+			PMD_DRV_LOG(ERR, "irq cb unregister failed rc: %d\n",
+				    rc);
+			return rc;
 		}
-		rte_free((void *)bp->irq_tbl);
-		bp->irq_tbl = NULL;
 	}
+
+	rte_free(bp->irq_tbl);
+	bp->irq_tbl = NULL;
+
+	return 0;
 }
 
 void bnxt_disable_int(struct bnxt *bp)
@@ -129,13 +153,20 @@  int bnxt_setup_int(struct bnxt *bp)
 
 int bnxt_request_int(struct bnxt *bp)
 {
+	struct rte_intr_handle *intr_handle = &bp->pdev->intr_handle;
+	struct bnxt_irq *irq = bp->irq_tbl;
 	int rc = 0;
 
-	struct bnxt_irq *irq = bp->irq_tbl;
+	if (!irq)
+		return 0;
 
-	rte_intr_callback_register(&bp->pdev->intr_handle, irq->handler,
-				   (void *)bp->eth_dev);
+	if (!irq->requested) {
+		rc = rte_intr_callback_register(intr_handle,
+						irq->handler,
+						bp->eth_dev);
+		if (!rc)
+			irq->requested = 1;
+	}
 
-	irq->requested = 1;
 	return rc;
 }
diff --git a/drivers/net/bnxt/bnxt_irq.h b/drivers/net/bnxt/bnxt_irq.h
index 75ba2135b..460a97a09 100644
--- a/drivers/net/bnxt/bnxt_irq.h
+++ b/drivers/net/bnxt/bnxt_irq.h
@@ -17,7 +17,7 @@  struct bnxt_irq {
 };
 
 struct bnxt;
-void bnxt_free_int(struct bnxt *bp);
+int bnxt_free_int(struct bnxt *bp);
 void bnxt_disable_int(struct bnxt *bp);
 void bnxt_enable_int(struct bnxt *bp);
 int bnxt_setup_int(struct bnxt *bp);