[10/22] net/bnxt: retry irq callback deregistration
Checks
Commit Message
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(-)
@@ -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;
}
@@ -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);