diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index 8797b032ee..040cae3b19 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -370,6 +370,8 @@ struct bnxt { #define BNXT_FLAG_STINGRAY (1 << 14) #define BNXT_FLAG_FW_RESET (1 << 15) #define BNXT_FLAG_FATAL_ERROR (1 << 16) +#define BNXT_FLAG_FW_CAP_IF_CHANGE (1 << 17) +#define BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE (1 << 18) #define BNXT_FLAG_EXT_STATS_SUPPORTED (1 << 29) #define BNXT_FLAG_NEW_RM (1 << 30) #define BNXT_FLAG_INIT_DONE (1U << 31) diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index 6bc006a719..1bb84eacd9 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -794,6 +794,25 @@ bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev) return bnxt_xmit_pkts; } +static int bnxt_handle_if_change_status(struct bnxt *bp) +{ + int rc; + + /* Since fw has undergone a reset and lost all contexts, + * set fatal flag to not issue hwrm during cleanup + */ + bp->flags |= BNXT_FLAG_FATAL_ERROR; + bnxt_uninit_resources(bp, true); + + /* clear fatal flag so that re-init happens */ + bp->flags &= ~BNXT_FLAG_FATAL_ERROR; + rc = bnxt_init_resources(bp, true); + + bp->flags &= ~BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE; + + return rc; +} + static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev) { struct bnxt *bp = eth_dev->data->dev_private; @@ -807,6 +826,15 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev) bp->rx_cp_nr_rings, RTE_ETHDEV_QUEUE_STAT_CNTRS); } + rc = bnxt_hwrm_if_change(bp, 1); + if (!rc) { + if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) { + rc = bnxt_handle_if_change_status(bp); + if (rc) + return rc; + } + } + rc = bnxt_init_chip(bp); if (rc) goto error; @@ -833,6 +861,7 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev) return 0; error: + bnxt_hwrm_if_change(bp, 0); bnxt_shutdown_nic(bp); bnxt_free_tx_mbufs(bp); bnxt_free_rx_mbufs(bp); @@ -899,6 +928,7 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev) bnxt_free_tx_mbufs(bp); bnxt_free_rx_mbufs(bp); bnxt_shutdown_nic(bp); + bnxt_hwrm_if_change(bp, 0); bp->dev_stopped = 1; } diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c index abbad0152c..1bdbb1433d 100644 --- a/drivers/net/bnxt/bnxt_hwrm.c +++ b/drivers/net/bnxt/bnxt_hwrm.c @@ -726,6 +726,11 @@ int bnxt_hwrm_func_driver_register(struct bnxt *bp) rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB); HWRM_CHECK_RESULT(); + + flags = rte_le_to_cpu_32(resp->flags); + if (flags & HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED) + bp->flags |= BNXT_FLAG_FW_CAP_IF_CHANGE; + HWRM_UNLOCK(); bp->flags |= BNXT_FLAG_REGISTERED; @@ -4659,3 +4664,40 @@ int bnxt_hwrm_set_mac(struct bnxt *bp) return rc; } + +int bnxt_hwrm_if_change(struct bnxt *bp, bool up) +{ + struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr; + struct hwrm_func_drv_if_change_input req = {0}; + uint32_t flags; + int rc; + + if (!(bp->flags & BNXT_FLAG_FW_CAP_IF_CHANGE)) + return 0; + + /* Do not issue FUNC_DRV_IF_CHANGE during reset recovery. + * If we issue FUNC_DRV_IF_CHANGE with flags down before + * FUNC_DRV_UNRGTR, FW resets before FUNC_DRV_UNRGTR + */ + if (!up && (bp->flags & BNXT_FLAG_FW_RESET)) + return 0; + + HWRM_PREP(req, FUNC_DRV_IF_CHANGE, BNXT_USE_CHIMP_MB); + + if (up) + req.flags = + rte_cpu_to_le_32(HWRM_FUNC_DRV_IF_CHANGE_INPUT_FLAGS_UP); + + rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB); + + HWRM_CHECK_RESULT(); + flags = rte_le_to_cpu_32(resp->flags); + HWRM_UNLOCK(); + + if (flags & HWRM_FUNC_DRV_IF_CHANGE_OUTPUT_FLAGS_HOT_FW_RESET_DONE) { + PMD_DRV_LOG(INFO, "FW reset happened while port was down\n"); + bp->flags |= BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE; + } + + return 0; +} diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h index a036205329..2f57e950bb 100644 --- a/drivers/net/bnxt/bnxt_hwrm.h +++ b/drivers/net/bnxt/bnxt_hwrm.h @@ -201,4 +201,5 @@ int bnxt_hwrm_tunnel_redirect_query(struct bnxt *bp, uint32_t *type); int bnxt_hwrm_tunnel_redirect_info(struct bnxt *bp, uint8_t tun_type, uint16_t *dst_fid); int bnxt_hwrm_set_mac(struct bnxt *bp); +int bnxt_hwrm_if_change(struct bnxt *bp, bool state); #endif