#include "bnxt_filter.h"
#include "bnxt_hwrm.h"
#include "bnxt_rxq.h"
+#include "bnxt_rxr.h"
#include "bnxt_ring.h"
#include "bnxt_txq.h"
+#include "bnxt_txr.h"
#include "bnxt_vnic.h"
#include "hsi_struct_def_dpdk.h"
mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS;
if (vnic->flags & BNXT_VNIC_INFO_ALLMULTI)
mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
- req.mask = rte_cpu_to_le_32(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST |
- HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST |
+ req.mask = rte_cpu_to_le_32(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST |
mask);
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
return rc;
}
+static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
+ struct bnxt_link_info *link_info)
+{
+ int rc = 0;
+ struct hwrm_port_phy_qcfg_input req = {.req_type = 0};
+ struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+
+ HWRM_PREP(req, PORT_PHY_QCFG, -1, resp);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+ HWRM_CHECK_RESULT;
+
+ link_info->phy_link_status = resp->link;
+ if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) {
+ link_info->link_up = 1;
+ link_info->link_speed = rte_le_to_cpu_16(resp->link_speed);
+ } else {
+ link_info->link_up = 0;
+ link_info->link_speed = 0;
+ }
+ link_info->duplex = resp->duplex;
+ link_info->pause = resp->pause;
+ link_info->auto_pause = resp->auto_pause;
+ link_info->force_pause = resp->force_pause;
+ link_info->auto_mode = resp->auto_mode;
+
+ link_info->support_speeds = rte_le_to_cpu_16(resp->support_speeds);
+ link_info->auto_link_speed = rte_le_to_cpu_16(resp->auto_link_speed);
+ link_info->preemphasis = rte_le_to_cpu_32(resp->preemphasis);
+ link_info->phy_ver[0] = resp->phy_maj;
+ link_info->phy_ver[1] = resp->phy_min;
+ link_info->phy_ver[2] = resp->phy_bld;
+
+ return rc;
+}
+
int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
{
int rc = 0;
break;
case HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL:
req.ring_type = ring_type;
- req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
+ /*
+ * TODO: Some HWRM versions crash with
+ * HWRM_RING_ALLOC_INPUT_INT_MODE_POLL
+ */
+ req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
req.length = rte_cpu_to_le_32(ring->ring_size);
break;
default:
return 0;
}
+int bnxt_hwrm_ring_grp_alloc(struct bnxt *bp, unsigned int idx)
+{
+ int rc = 0;
+ struct hwrm_ring_grp_alloc_input req = {.req_type = 0 };
+ struct hwrm_ring_grp_alloc_output *resp = bp->hwrm_cmd_resp_addr;
+
+ HWRM_PREP(req, RING_GRP_ALLOC, -1, resp);
+
+ req.cr = rte_cpu_to_le_16(bp->grp_info[idx].cp_fw_ring_id);
+ req.rr = rte_cpu_to_le_16(bp->grp_info[idx].rx_fw_ring_id);
+ req.ar = rte_cpu_to_le_16(bp->grp_info[idx].ag_fw_ring_id);
+ req.sc = rte_cpu_to_le_16(bp->grp_info[idx].fw_stats_ctx);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+ HWRM_CHECK_RESULT;
+
+ bp->grp_info[idx].fw_grp_id =
+ rte_le_to_cpu_16(resp->ring_group_id);
+
+ return rc;
+}
+
+int bnxt_hwrm_ring_grp_free(struct bnxt *bp, unsigned int idx)
+{
+ int rc;
+ struct hwrm_ring_grp_free_input req = {.req_type = 0 };
+ struct hwrm_ring_grp_free_output *resp = bp->hwrm_cmd_resp_addr;
+
+ HWRM_PREP(req, RING_GRP_FREE, -1, resp);
+
+ req.ring_group_id = rte_cpu_to_le_16(bp->grp_info[idx].fw_grp_id);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+ HWRM_CHECK_RESULT;
+
+ bp->grp_info[idx].fw_grp_id = INVALID_HW_RING_ID;
+ return rc;
+}
+
int bnxt_hwrm_stat_clear(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
{
int rc = 0;
return rc;
}
+int bnxt_hwrm_stat_ctx_free(struct bnxt *bp,
+ struct bnxt_cp_ring_info *cpr, unsigned int idx)
+{
+ int rc;
+ struct hwrm_stat_ctx_free_input req = {.req_type = 0 };
+ struct hwrm_stat_ctx_free_output *resp = bp->hwrm_cmd_resp_addr;
+
+ HWRM_PREP(req, STAT_CTX_FREE, -1, resp);
+
+ req.stat_ctx_id = rte_cpu_to_le_16(cpr->hw_stats_ctx_id);
+ req.seq_id = rte_cpu_to_le_16(bp->hwrm_cmd_seq++);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+ HWRM_CHECK_RESULT;
+
+ cpr->hw_stats_ctx_id = HWRM_NA_SIGNATURE;
+ bp->grp_info[idx].fw_stats_ctx = cpr->hw_stats_ctx_id;
+
+ return rc;
+}
+
int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
{
int rc = 0, i, j;
return 0;
}
+int bnxt_free_all_hwrm_stat_ctxs(struct bnxt *bp)
+{
+ int rc;
+ unsigned int i;
+ struct bnxt_cp_ring_info *cpr;
+
+ for (i = 0; i < bp->rx_cp_nr_rings + bp->tx_cp_nr_rings; i++) {
+ unsigned int idx = i + 1;
+
+ if (i >= bp->rx_cp_nr_rings)
+ cpr = bp->tx_queues[i - bp->rx_cp_nr_rings]->cp_ring;
+ else
+ cpr = bp->rx_queues[i]->cp_ring;
+ if (cpr->hw_stats_ctx_id != HWRM_NA_SIGNATURE) {
+ rc = bnxt_hwrm_stat_ctx_free(bp, cpr, idx);
+ if (rc)
+ return rc;
+ }
+ }
+ return 0;
+}
+
int bnxt_alloc_all_hwrm_stat_ctxs(struct bnxt *bp)
{
unsigned int i;
return rc;
}
+int bnxt_free_all_hwrm_ring_grps(struct bnxt *bp)
+{
+ uint16_t i;
+ uint32_t rc = 0;
+
+ for (i = 0; i < bp->rx_cp_nr_rings; i++) {
+ unsigned int idx = i + 1;
+
+ if (bp->grp_info[idx].fw_grp_id == INVALID_HW_RING_ID) {
+ RTE_LOG(ERR, PMD,
+ "Attempt to free invalid ring group %d\n",
+ idx);
+ continue;
+ }
+
+ rc = bnxt_hwrm_ring_grp_free(bp, idx);
+
+ if (rc)
+ return rc;
+ }
+ return rc;
+}
+
+static void bnxt_free_cp_ring(struct bnxt *bp,
+ struct bnxt_cp_ring_info *cpr, unsigned int idx)
+{
+ struct bnxt_ring *cp_ring = cpr->cp_ring_struct;
+
+ bnxt_hwrm_ring_free(bp, cp_ring,
+ HWRM_RING_FREE_INPUT_RING_TYPE_CMPL);
+ cp_ring->fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[idx].cp_fw_ring_id = INVALID_HW_RING_ID;
+ memset(cpr->cp_desc_ring, 0, cpr->cp_ring_struct->ring_size *
+ sizeof(*cpr->cp_desc_ring));
+ cpr->cp_raw_cons = 0;
+}
+
+int bnxt_free_all_hwrm_rings(struct bnxt *bp)
+{
+ unsigned int i;
+ int rc = 0;
+
+ for (i = 0; i < bp->tx_cp_nr_rings; i++) {
+ struct bnxt_tx_queue *txq = bp->tx_queues[i];
+ struct bnxt_tx_ring_info *txr = txq->tx_ring;
+ struct bnxt_ring *ring = txr->tx_ring_struct;
+ struct bnxt_cp_ring_info *cpr = txq->cp_ring;
+ unsigned int idx = bp->rx_cp_nr_rings + i + 1;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ bnxt_hwrm_ring_free(bp, ring,
+ HWRM_RING_FREE_INPUT_RING_TYPE_TX);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ memset(txr->tx_desc_ring, 0,
+ txr->tx_ring_struct->ring_size *
+ sizeof(*txr->tx_desc_ring));
+ memset(txr->tx_buf_ring, 0,
+ txr->tx_ring_struct->ring_size *
+ sizeof(*txr->tx_buf_ring));
+ txr->tx_prod = 0;
+ txr->tx_cons = 0;
+ }
+ if (cpr->cp_ring_struct->fw_ring_id != INVALID_HW_RING_ID)
+ bnxt_free_cp_ring(bp, cpr, idx);
+ }
+
+ for (i = 0; i < bp->rx_cp_nr_rings; i++) {
+ struct bnxt_rx_queue *rxq = bp->rx_queues[i];
+ struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
+ struct bnxt_ring *ring = rxr->rx_ring_struct;
+ struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
+ unsigned int idx = i + 1;
+
+ if (ring->fw_ring_id != INVALID_HW_RING_ID) {
+ bnxt_hwrm_ring_free(bp, ring,
+ HWRM_RING_FREE_INPUT_RING_TYPE_RX);
+ ring->fw_ring_id = INVALID_HW_RING_ID;
+ bp->grp_info[idx].rx_fw_ring_id = INVALID_HW_RING_ID;
+ memset(rxr->rx_desc_ring, 0,
+ rxr->rx_ring_struct->ring_size *
+ sizeof(*rxr->rx_desc_ring));
+ memset(rxr->rx_buf_ring, 0,
+ rxr->rx_ring_struct->ring_size *
+ sizeof(*rxr->rx_buf_ring));
+ rxr->rx_prod = 0;
+ }
+ if (cpr->cp_ring_struct->fw_ring_id != INVALID_HW_RING_ID)
+ bnxt_free_cp_ring(bp, cpr, idx);
+ }
+
+ /* Default completion ring */
+ {
+ struct bnxt_cp_ring_info *cpr = bp->def_cp_ring;
+
+ if (cpr->cp_ring_struct->fw_ring_id != INVALID_HW_RING_ID)
+ bnxt_free_cp_ring(bp, cpr, 0);
+ }
+
+ return rc;
+}
+
+int bnxt_alloc_all_hwrm_ring_grps(struct bnxt *bp)
+{
+ uint16_t i;
+ uint32_t rc = 0;
+
+ for (i = 0; i < bp->rx_cp_nr_rings; i++) {
+ unsigned int idx = i + 1;
+
+ if (bp->grp_info[idx].cp_fw_ring_id == INVALID_HW_RING_ID ||
+ bp->grp_info[idx].rx_fw_ring_id == INVALID_HW_RING_ID)
+ continue;
+
+ rc = bnxt_hwrm_ring_grp_alloc(bp, idx);
+
+ if (rc)
+ return rc;
+ }
+ return rc;
+}
+
void bnxt_free_hwrm_resources(struct bnxt *bp)
{
/* Release memzone */
return 0;
}
+int bnxt_clear_hwrm_vnic_filters(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+{
+ struct bnxt_filter_info *filter;
+ int rc = 0;
+
+ STAILQ_FOREACH(filter, &vnic->filter, next) {
+ rc = bnxt_hwrm_clear_filter(bp, filter);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+int bnxt_set_hwrm_vnic_filters(struct bnxt *bp, struct bnxt_vnic_info *vnic)
+{
+ struct bnxt_filter_info *filter;
+ int rc = 0;
+
+ STAILQ_FOREACH(filter, &vnic->filter, next) {
+ rc = bnxt_hwrm_set_filter(bp, vnic, filter);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+void bnxt_free_all_hwrm_resources(struct bnxt *bp)
+{
+ struct bnxt_vnic_info *vnic;
+ unsigned int i;
+
+ if (bp->vnic_info == NULL)
+ return;
+
+ vnic = &bp->vnic_info[0];
+ bnxt_hwrm_cfa_l2_clear_rx_mask(bp, vnic);
+
+ /* VNIC resources */
+ for (i = 0; i < bp->nr_vnics; i++) {
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+ bnxt_clear_hwrm_vnic_filters(bp, vnic);
+
+ bnxt_hwrm_vnic_ctx_free(bp, vnic);
+ bnxt_hwrm_vnic_free(bp, vnic);
+ }
+ /* Ring resources */
+ bnxt_free_all_hwrm_rings(bp);
+ bnxt_free_all_hwrm_ring_grps(bp);
+ bnxt_free_all_hwrm_stat_ctxs(bp);
+}
+
static uint16_t bnxt_parse_eth_link_duplex(uint32_t conf_link_speed)
{
uint8_t hw_link_duplex = HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH;
return ret;
}
+static uint32_t bnxt_parse_hw_link_speed(uint16_t hw_link_speed)
+{
+ uint32_t eth_link_speed = ETH_SPEED_NUM_NONE;
+
+ switch (hw_link_speed) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
+ eth_link_speed = ETH_SPEED_NUM_100M;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
+ eth_link_speed = ETH_SPEED_NUM_1G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
+ eth_link_speed = ETH_SPEED_NUM_2_5G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
+ eth_link_speed = ETH_SPEED_NUM_10G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
+ eth_link_speed = ETH_SPEED_NUM_20G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
+ eth_link_speed = ETH_SPEED_NUM_25G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
+ eth_link_speed = ETH_SPEED_NUM_40G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
+ eth_link_speed = ETH_SPEED_NUM_50G;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
+ default:
+ RTE_LOG(ERR, PMD, "HWRM link speed %d not defined\n",
+ hw_link_speed);
+ break;
+ }
+ return eth_link_speed;
+}
+
+static uint16_t bnxt_parse_hw_link_duplex(uint16_t hw_link_duplex)
+{
+ uint16_t eth_link_duplex = ETH_LINK_FULL_DUPLEX;
+
+ switch (hw_link_duplex) {
+ case HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH:
+ case HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_FULL:
+ eth_link_duplex = ETH_LINK_FULL_DUPLEX;
+ break;
+ case HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_HALF:
+ eth_link_duplex = ETH_LINK_HALF_DUPLEX;
+ break;
+ default:
+ RTE_LOG(ERR, PMD, "HWRM link duplex %d not defined\n",
+ hw_link_duplex);
+ break;
+ }
+ return eth_link_duplex;
+}
+
+int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link)
+{
+ int rc = 0;
+ struct bnxt_link_info *link_info = &bp->link_info;
+
+ rc = bnxt_hwrm_port_phy_qcfg(bp, link_info);
+ if (rc) {
+ RTE_LOG(ERR, PMD,
+ "Get link config failed with rc %d\n", rc);
+ goto exit;
+ }
+ if (link_info->link_up)
+ link->link_speed =
+ bnxt_parse_hw_link_speed(link_info->link_speed);
+ else
+ link->link_speed = ETH_LINK_SPEED_10M;
+ link->link_duplex = bnxt_parse_hw_link_duplex(link_info->duplex);
+ link->link_status = link_info->link_up;
+ link->link_autoneg = link_info->auto_mode ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE ?
+ ETH_LINK_SPEED_FIXED : ETH_LINK_SPEED_AUTONEG;
+exit:
+ return rc;
+}
+
int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
{
int rc = 0;
struct bnxt_link_info link_req;
uint16_t speed;
+ if (BNXT_NPAR_PF(bp) || BNXT_VF(bp))
+ return 0;
+
rc = bnxt_valid_link_speed(dev_conf->link_speeds,
bp->eth_dev->data->port_id);
if (rc)
error:
return rc;
}
+
+/* JIRA 22088 */
+int bnxt_hwrm_func_qcfg(struct bnxt *bp)
+{
+ struct hwrm_func_qcfg_input req = {0};
+ struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ int rc = 0;
+
+ HWRM_PREP(req, FUNC_QCFG, -1, resp);
+ req.fid = rte_cpu_to_le_16(0xffff);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+ HWRM_CHECK_RESULT;
+
+ if (BNXT_VF(bp)) {
+ struct bnxt_vf_info *vf = &bp->vf;
+
+ /* Hard Coded.. 0xfff VLAN ID mask */
+ vf->vlan = rte_le_to_cpu_16(resp->vlan) & 0xfff;
+ }
+
+ switch (resp->port_partition_type) {
+ case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0:
+ case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5:
+ case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0:
+ bp->port_partition_type = resp->port_partition_type;
+ break;
+ default:
+ bp->port_partition_type = 0;
+ break;
+ }
+
+ return rc;
+}