#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;
#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)
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);
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;
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;
}
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;
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;
+}