static void bnxt_cancel_fw_health_check(struct bnxt *bp);
static int bnxt_restore_vlan_filters(struct bnxt *bp);
static void bnxt_dev_recover(void *arg);
+static void bnxt_free_error_recovery_info(struct bnxt *bp);
int is_bnxt_in_error(struct bnxt *bp)
{
* Device configuration and status function
*/
+static uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
+{
+ uint32_t link_speed = bp->link_info.support_speeds;
+ uint32_t speed_capa = 0;
+
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB)
+ speed_capa |= ETH_LINK_SPEED_100M;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MBHD)
+ speed_capa |= ETH_LINK_SPEED_100M_HD;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
+ speed_capa |= ETH_LINK_SPEED_1G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
+ speed_capa |= ETH_LINK_SPEED_2_5G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ speed_capa |= ETH_LINK_SPEED_10G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
+ speed_capa |= ETH_LINK_SPEED_20G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
+ speed_capa |= ETH_LINK_SPEED_25G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ speed_capa |= ETH_LINK_SPEED_40G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
+ speed_capa |= ETH_LINK_SPEED_50G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
+ speed_capa |= ETH_LINK_SPEED_100G;
+
+ if (bp->link_info.auto_mode == HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE)
+ speed_capa |= ETH_LINK_SPEED_FIXED;
+ else
+ speed_capa |= ETH_LINK_SPEED_AUTONEG;
+
+ return speed_capa;
+}
+
static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
struct rte_eth_dev_info *dev_info)
{
dev_info->tx_offload_capa = BNXT_DEV_TX_OFFLOAD_SUPPORT;
dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
+ dev_info->speed_capa = bnxt_get_speed_capabilities(bp);
+
/* *INDENT-OFF* */
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
struct bnxt *bp = eth_dev->data->dev_private;
uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
int vlan_mask = 0;
- int rc;
+ int rc, retry_cnt = BNXT_IF_CHANGE_RETRY_COUNT;
if (!eth_dev->data->nb_tx_queues || !eth_dev->data->nb_rx_queues) {
PMD_DRV_LOG(ERR, "Queues are not configured yet!\n");
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;
- }
+ do {
+ rc = bnxt_hwrm_if_change(bp, true);
+ if (rc == 0 || rc != -EAGAIN)
+ break;
+
+ rte_delay_ms(BNXT_IF_CHANGE_RETRY_INTERVAL);
+ } while (retry_cnt--);
+
+ if (rc)
+ return rc;
+
+ if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) {
+ rc = bnxt_handle_if_change_status(bp);
+ if (rc)
+ return rc;
}
+
bnxt_enable_int(bp);
rc = bnxt_init_chip(bp);
return 0;
error:
- bnxt_hwrm_if_change(bp, 0);
bnxt_shutdown_nic(bp);
bnxt_free_tx_mbufs(bp);
bnxt_free_rx_mbufs(bp);
+ bnxt_hwrm_if_change(bp, false);
eth_dev->data->dev_started = 0;
return rc;
}
/* Process any remaining notifications in default completion queue */
bnxt_int_handler(eth_dev);
bnxt_shutdown_nic(bp);
- bnxt_hwrm_if_change(bp, 0);
+ bnxt_hwrm_if_change(bp, false);
rte_free(bp->mark_table);
bp->mark_table = NULL;
}
if (hash_types) {
PMD_DRV_LOG(ERR,
- "Unknwon RSS config from firmware (%08x), RSS disabled",
+ "Unknown RSS config from firmware (%08x), RSS disabled",
vnic->hash_type);
return -ENOTSUP;
}
if (rc)
return rc;
+ if (!eth_dev->data->dev_started) {
+ PMD_DRV_LOG(ERR, "port must be started before setting vlan\n");
+ return -EINVAL;
+ }
+
/* These operations apply to ALL existing MAC/VLAN filters */
if (on)
return bnxt_add_vlan_filter(bp, vlan_id);
rte_free(vnic->fw_grp_ids);
vnic->fw_grp_ids = NULL;
+ vnic->rx_queue_cnt = 0;
+
return 0;
}
return bp->fw_fid;
}
+static void bnxt_alloc_error_recovery_info(struct bnxt *bp)
+{
+ struct bnxt_error_recovery_info *info = bp->recovery_info;
+
+ if (info) {
+ if (!(bp->fw_cap & BNXT_FW_CAP_HCOMM_FW_STATUS))
+ memset(info, 0, sizeof(*info));
+ return;
+ }
+
+ if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+ return;
+
+ info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg",
+ sizeof(*info), 0);
+ if (!info)
+ bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+
+ bp->recovery_info = info;
+}
+
+static void bnxt_check_fw_status(struct bnxt *bp)
+{
+ uint32_t fw_status;
+
+ if (!(bp->recovery_info &&
+ (bp->fw_cap & BNXT_FW_CAP_HCOMM_FW_STATUS)))
+ return;
+
+ fw_status = bnxt_read_fw_status_reg(bp, BNXT_FW_STATUS_REG);
+ if (fw_status != BNXT_FW_STATUS_HEALTHY)
+ PMD_DRV_LOG(ERR, "Firmware not responding, status: %#x\n",
+ fw_status);
+}
+
+static int bnxt_map_hcomm_fw_status_reg(struct bnxt *bp)
+{
+ struct bnxt_error_recovery_info *info = bp->recovery_info;
+ uint32_t status_loc;
+ uint32_t sig_ver;
+
+ rte_write32(HCOMM_STATUS_STRUCT_LOC, (uint8_t *)bp->bar0 +
+ BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4);
+ sig_ver = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+ BNXT_GRCP_WINDOW_2_BASE +
+ offsetof(struct hcomm_status,
+ sig_ver)));
+ /* If the signature is absent, then FW does not support this feature */
+ if ((sig_ver & HCOMM_STATUS_SIGNATURE_MASK) !=
+ HCOMM_STATUS_SIGNATURE_VAL)
+ return 0;
+
+ if (!info) {
+ info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg",
+ sizeof(*info), 0);
+ if (!info)
+ return -ENOMEM;
+ bp->recovery_info = info;
+ } else {
+ memset(info, 0, sizeof(*info));
+ }
+
+ status_loc = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+ BNXT_GRCP_WINDOW_2_BASE +
+ offsetof(struct hcomm_status,
+ fw_status_loc)));
+
+ /* Only pre-map the FW health status GRC register */
+ if (BNXT_FW_STATUS_REG_TYPE(status_loc) != BNXT_FW_STATUS_REG_TYPE_GRC)
+ return 0;
+
+ info->status_regs[BNXT_FW_STATUS_REG] = status_loc;
+ info->mapped_status_regs[BNXT_FW_STATUS_REG] =
+ BNXT_GRCP_WINDOW_2_BASE + (status_loc & BNXT_GRCP_OFFSET_MASK);
+
+ rte_write32((status_loc & BNXT_GRCP_BASE_MASK), (uint8_t *)bp->bar0 +
+ BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4);
+
+ bp->fw_cap |= BNXT_FW_CAP_HCOMM_FW_STATUS;
+
+ return 0;
+}
+
static int bnxt_init_fw(struct bnxt *bp)
{
uint16_t mtu;
bp->fw_cap = 0;
- rc = bnxt_hwrm_ver_get(bp, DFLT_HWRM_CMD_TIMEOUT);
+ rc = bnxt_map_hcomm_fw_status_reg(bp);
if (rc)
return rc;
+ rc = bnxt_hwrm_ver_get(bp, DFLT_HWRM_CMD_TIMEOUT);
+ if (rc) {
+ bnxt_check_fw_status(bp);
+ return rc;
+ }
+
rc = bnxt_hwrm_func_reset(bp);
if (rc)
return -EIO;
if (rc)
return rc;
+ bnxt_alloc_error_recovery_info(bp);
/* Get the adapter error recovery support info */
rc = bnxt_hwrm_error_recovery_qcfg(bp);
if (rc)
bnxt_uninit_fc_ctx_mem(bp);
}
+static void
+bnxt_free_error_recovery_info(struct bnxt *bp)
+{
+ rte_free(bp->recovery_info);
+ bp->recovery_info = NULL;
+ bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+}
+
static void
bnxt_uninit_locks(struct bnxt *bp)
{
bnxt_free_ctx_mem(bp);
if (!reconfig_dev) {
bnxt_free_hwrm_resources(bp);
-
- if (bp->recovery_info != NULL) {
- rte_free(bp->recovery_info);
- bp->recovery_info = NULL;
- }
+ bnxt_free_error_recovery_info(bp);
}
bnxt_uninit_ctx_mem(bp);