From: Lance Richardson <lance.richard...@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: sta...@dpdk.org Reviewed-by: Ajit Khaparde <ajit.khapa...@broadcom.com> Signed-off-by: Lance Richardson <lance.richard...@broadcom.com> --- drivers/net/bnxt/bnxt_irq.c | 63 +++++++++++++++++++++++++++---------- drivers/net/bnxt/bnxt_irq.h | 2 +- 2 files changed, 48 insertions(+), 17 deletions(-) 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); -- 2.20.1 (Apple Git-117)