net/bnxt: query firmware error recovery capabilities
authorKalesh AP <kalesh-anakkur.purayil@broadcom.com>
Wed, 2 Oct 2019 01:23:26 +0000 (18:23 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 8 Oct 2019 10:14:30 +0000 (12:14 +0200)
In Driver initiated error recovery process, driver has to know about
the registers offset and values to initiate FW reset. The HWRM command
HWRM_ERROR_RECOVERY_QCFG is used to obtain all the registers and values
required to initiate FW reset. This command response includes
FW heart_beat register, health status register, Error counter register,
register offsets and values to do chip reset if firmware crashes and
becomes unresponsive.

Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
drivers/net/bnxt/bnxt.h
drivers/net/bnxt/bnxt_ethdev.c
drivers/net/bnxt/bnxt_hwrm.c
drivers/net/bnxt/bnxt_hwrm.h

index 040cae3..bfe5cb0 100644 (file)
@@ -343,6 +343,29 @@ struct bnxt_ctx_mem_info {
 #define US_PER_MS                      1000
 #define NS_PER_US                      1000
 
+struct bnxt_error_recovery_info {
+       /* All units in milliseconds */
+       uint32_t        driver_polling_freq;
+       uint32_t        master_func_wait_period;
+       uint32_t        normal_func_wait_period;
+       uint32_t        master_func_wait_period_after_reset;
+       uint32_t        max_bailout_time_after_reset;
+#define BNXT_FW_STATUS_REG             0
+#define BNXT_FW_HEARTBEAT_CNT_REG      1
+#define BNXT_FW_RECOVERY_CNT_REG       2
+#define BNXT_FW_RESET_INPROG_REG       3
+       uint32_t        status_regs[4];
+       uint32_t        reset_inprogress_reg_mask;
+#define BNXT_NUM_RESET_REG     16
+       uint8_t         reg_array_cnt;
+       uint32_t        reset_reg[BNXT_NUM_RESET_REG];
+       uint32_t        reset_reg_val[BNXT_NUM_RESET_REG];
+       uint8_t         delay_after_reset[BNXT_NUM_RESET_REG];
+#define BNXT_FLAG_ERROR_RECOVERY_HOST  (1 << 0)
+#define BNXT_FLAG_ERROR_RECOVERY_CO_CPU        (1 << 1)
+       uint32_t        flags;
+};
+
 #define BNXT_HWRM_SHORT_REQ_LEN                sizeof(struct hwrm_short_input)
 struct bnxt {
        void                            *bar0;
@@ -372,6 +395,7 @@ struct bnxt {
 #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_FW_CAP_ERROR_RECOVERY                (1 << 19)
 #define BNXT_FLAG_EXT_STATS_SUPPORTED  (1 << 29)
 #define BNXT_FLAG_NEW_RM       (1 << 30)
 #define BNXT_FLAG_INIT_DONE    (1U << 31)
@@ -478,6 +502,9 @@ struct bnxt {
 
        uint16_t                fw_reset_min_msecs;
        uint16_t                fw_reset_max_msecs;
+
+       /* Struct to hold adapter error recovery related info */
+       struct bnxt_error_recovery_info *recovery_info;
 };
 
 int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete);
index 768b6cd..95d6343 100644 (file)
@@ -4170,6 +4170,11 @@ static int bnxt_init_fw(struct bnxt *bp)
        if (rc)
                return rc;
 
+       /* Get the adapter error recovery support info */
+       rc = bnxt_hwrm_error_recovery_qcfg(bp);
+       if (rc)
+               bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+
        if (mtu >= RTE_ETHER_MIN_MTU && mtu <= BNXT_MAX_MTU &&
            mtu != bp->eth_dev->data->mtu)
                bp->eth_dev->data->mtu = mtu;
@@ -4328,9 +4333,15 @@ bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev)
        rc = bnxt_hwrm_func_driver_unregister(bp, 0);
        bp->flags &= ~BNXT_FLAG_REGISTERED;
        bnxt_free_ctx_mem(bp);
-       if (!reconfig_dev)
+       if (!reconfig_dev) {
                bnxt_free_hwrm_resources(bp);
 
+               if (bp->recovery_info != NULL) {
+                       rte_free(bp->recovery_info);
+                       bp->recovery_info = NULL;
+               }
+       }
+
        return rc;
 }
 
index 1bdbb14..f197997 100644 (file)
@@ -630,6 +630,13 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
        if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
                bp->flags |= BNXT_FLAG_EXT_STATS_SUPPORTED;
 
+       if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE) {
+               bp->flags |= BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+               PMD_DRV_LOG(DEBUG, "Adapter Error recovery SUPPORTED\n");
+       } else {
+               bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+       }
+
        HWRM_UNLOCK();
 
        return rc;
@@ -4701,3 +4708,89 @@ int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
 
        return 0;
 }
+
+int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
+{
+       struct hwrm_error_recovery_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+       struct bnxt_error_recovery_info *info = bp->recovery_info;
+       struct hwrm_error_recovery_qcfg_input req = {0};
+       uint32_t flags = 0;
+       unsigned int i;
+       int rc;
+
+       /* Older FW does not have error recovery support */
+       if (!(bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY))
+               return 0;
+
+       if (!info) {
+               info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg",
+                                  sizeof(*info), 0);
+               bp->recovery_info = info;
+               if (info == NULL)
+                       return -ENOMEM;
+       } else {
+               memset(info, 0, sizeof(*info));
+       }
+
+       HWRM_PREP(req, ERROR_RECOVERY_QCFG, BNXT_USE_CHIMP_MB);
+
+       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_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_HOST)
+               info->flags |= BNXT_FLAG_ERROR_RECOVERY_HOST;
+       else if (flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_CO_CPU)
+               info->flags |= BNXT_FLAG_ERROR_RECOVERY_CO_CPU;
+
+       if ((info->flags & BNXT_FLAG_ERROR_RECOVERY_CO_CPU) &&
+           !(bp->flags & BNXT_FLAG_KONG_MB_EN)) {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       /* FW returned values are in units of 100msec */
+       info->driver_polling_freq =
+               rte_le_to_cpu_32(resp->driver_polling_freq) * 100;
+       info->master_func_wait_period =
+               rte_le_to_cpu_32(resp->master_func_wait_period) * 100;
+       info->normal_func_wait_period =
+               rte_le_to_cpu_32(resp->normal_func_wait_period) * 100;
+       info->master_func_wait_period_after_reset =
+               rte_le_to_cpu_32(resp->master_func_wait_period_after_reset) * 100;
+       info->max_bailout_time_after_reset =
+               rte_le_to_cpu_32(resp->max_bailout_time_after_reset) * 100;
+       info->status_regs[BNXT_FW_STATUS_REG] =
+               rte_le_to_cpu_32(resp->fw_health_status_reg);
+       info->status_regs[BNXT_FW_HEARTBEAT_CNT_REG] =
+               rte_le_to_cpu_32(resp->fw_heartbeat_reg);
+       info->status_regs[BNXT_FW_RECOVERY_CNT_REG] =
+               rte_le_to_cpu_32(resp->fw_reset_cnt_reg);
+       info->status_regs[BNXT_FW_RESET_INPROG_REG] =
+               rte_le_to_cpu_32(resp->reset_inprogress_reg);
+       info->reg_array_cnt =
+               rte_le_to_cpu_32(resp->reg_array_cnt);
+
+       if (info->reg_array_cnt >= BNXT_NUM_RESET_REG) {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       for (i = 0; i < info->reg_array_cnt; i++) {
+               info->reset_reg[i] =
+                       rte_le_to_cpu_32(resp->reset_reg[i]);
+               info->reset_reg_val[i] =
+                       rte_le_to_cpu_32(resp->reset_reg_val[i]);
+               info->delay_after_reset[i] =
+                       resp->delay_after_reset[i];
+       }
+err:
+       HWRM_UNLOCK();
+
+       if (rc) {
+               rte_free(bp->recovery_info);
+               bp->recovery_info = NULL;
+       }
+       return rc;
+}
index 2f57e95..c332c12 100644 (file)
@@ -202,4 +202,5 @@ 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);
+int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp);
 #endif