+static int bnxt_reta_update_op(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ struct bnxt_vnic_info *vnic;
+ int i;
+
+ if (!(dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG))
+ return -EINVAL;
+
+ if (reta_size != HW_HASH_INDEX_SIZE) {
+ RTE_LOG(ERR, PMD, "The configured hash table lookup size "
+ "(%d) must equal the size supported by the hardware "
+ "(%d)\n", reta_size, HW_HASH_INDEX_SIZE);
+ return -EINVAL;
+ }
+ /* Update the RSS VNIC(s) */
+ for (i = 0; i < MAX_FF_POOLS; i++) {
+ STAILQ_FOREACH(vnic, &bp->ff_pool[i], next) {
+ memcpy(vnic->rss_table, reta_conf, reta_size);
+
+ bnxt_hwrm_vnic_rss_cfg(bp, vnic);
+ }
+ }
+ return 0;
+}
+
+static int bnxt_reta_query_op(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ struct rte_intr_handle *intr_handle
+ = &bp->pdev->intr_handle;
+
+ /* Retrieve from the default VNIC */
+ if (!vnic)
+ return -EINVAL;
+ if (!vnic->rss_table)
+ return -EINVAL;
+
+ if (reta_size != HW_HASH_INDEX_SIZE) {
+ RTE_LOG(ERR, PMD, "The configured hash table lookup size "
+ "(%d) must equal the size supported by the hardware "
+ "(%d)\n", reta_size, HW_HASH_INDEX_SIZE);
+ return -EINVAL;
+ }
+ /* EW - need to revisit here copying from u64 to u16 */
+ memcpy(reta_conf, vnic->rss_table, reta_size);
+
+ if (rte_intr_allow_others(intr_handle)) {
+ if (eth_dev->data->dev_conf.intr_conf.lsc != 0)
+ bnxt_dev_lsc_intr_setup(eth_dev);
+ }
+
+ return 0;
+}
+
+static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ struct bnxt_vnic_info *vnic;
+ uint16_t hash_type = 0;
+ int i;
+
+ /*
+ * If RSS enablement were different than dev_configure,
+ * then return -EINVAL
+ */
+ if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
+ if (!rss_conf->rss_hf)
+ return -EINVAL;
+ } else {
+ if (rss_conf->rss_hf & BNXT_ETH_RSS_SUPPORT)
+ return -EINVAL;
+ }
+ if (rss_conf->rss_hf & ETH_RSS_IPV4)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
+ if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
+ if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
+ if (rss_conf->rss_hf & ETH_RSS_IPV6)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
+ if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
+ if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
+ hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
+
+ /* Update the RSS VNIC(s) */
+ for (i = 0; i < MAX_FF_POOLS; i++) {
+ STAILQ_FOREACH(vnic, &bp->ff_pool[i], next) {
+ vnic->hash_type = hash_type;
+
+ /*
+ * Use the supplied key if the key length is
+ * acceptable and the rss_key is not NULL
+ */
+ if (rss_conf->rss_key &&
+ rss_conf->rss_key_len <= HW_HASH_KEY_SIZE)
+ memcpy(vnic->rss_hash_key, rss_conf->rss_key,
+ rss_conf->rss_key_len);
+
+ bnxt_hwrm_vnic_rss_cfg(bp, vnic);
+ }
+ }
+ return 0;
+}
+
+static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+ int len;
+ uint32_t hash_types;
+
+ /* RSS configuration is the same for all VNICs */
+ if (vnic && vnic->rss_hash_key) {
+ if (rss_conf->rss_key) {
+ len = rss_conf->rss_key_len <= HW_HASH_KEY_SIZE ?
+ rss_conf->rss_key_len : HW_HASH_KEY_SIZE;
+ memcpy(rss_conf->rss_key, vnic->rss_hash_key, len);
+ }
+
+ hash_types = vnic->hash_type;
+ rss_conf->rss_hf = 0;
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4) {
+ rss_conf->rss_hf |= ETH_RSS_IPV4;
+ hash_types &= ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
+ }
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4) {
+ rss_conf->rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
+ hash_types &=
+ ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
+ }
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4) {
+ rss_conf->rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
+ hash_types &=
+ ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
+ }
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6) {
+ rss_conf->rss_hf |= ETH_RSS_IPV6;
+ hash_types &= ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
+ }
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6) {
+ rss_conf->rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
+ hash_types &=
+ ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
+ }
+ if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6) {
+ rss_conf->rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
+ hash_types &=
+ ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
+ }
+ if (hash_types) {
+ RTE_LOG(ERR, PMD,
+ "Unknwon RSS config from firmware (%08x), RSS disabled",
+ vnic->hash_type);
+ return -ENOTSUP;
+ }
+ } else {
+ rss_conf->rss_hf = 0;
+ }
+ return 0;
+}
+
+static int bnxt_flow_ctrl_get_op(struct rte_eth_dev *dev,
+ struct rte_eth_fc_conf *fc_conf __rte_unused)
+{
+ struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+ struct rte_eth_link link_info;
+ int rc;
+
+ rc = bnxt_get_hwrm_link_config(bp, &link_info);
+ if (rc)
+ return rc;
+
+ memset(fc_conf, 0, sizeof(*fc_conf));
+ if (bp->link_info.auto_pause)
+ fc_conf->autoneg = 1;
+ switch (bp->link_info.pause) {
+ case 0:
+ fc_conf->mode = RTE_FC_NONE;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX:
+ fc_conf->mode = RTE_FC_TX_PAUSE;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX:
+ fc_conf->mode = RTE_FC_RX_PAUSE;
+ break;
+ case (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX):
+ fc_conf->mode = RTE_FC_FULL;
+ break;
+ }
+ return 0;
+}
+
+static int bnxt_flow_ctrl_set_op(struct rte_eth_dev *dev,
+ struct rte_eth_fc_conf *fc_conf)
+{
+ struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+
+ if (BNXT_NPAR_PF(bp) || BNXT_VF(bp)) {
+ RTE_LOG(ERR, PMD, "Flow Control Settings cannot be modified\n");
+ return -ENOTSUP;
+ }
+
+ switch (fc_conf->mode) {
+ case RTE_FC_NONE:
+ bp->link_info.auto_pause = 0;
+ bp->link_info.force_pause = 0;
+ break;
+ case RTE_FC_RX_PAUSE:
+ if (fc_conf->autoneg) {
+ bp->link_info.auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ bp->link_info.force_pause = 0;
+ } else {
+ bp->link_info.auto_pause = 0;
+ bp->link_info.force_pause =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
+ }
+ break;
+ case RTE_FC_TX_PAUSE:
+ if (fc_conf->autoneg) {
+ bp->link_info.auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
+ bp->link_info.force_pause = 0;
+ } else {
+ bp->link_info.auto_pause = 0;
+ bp->link_info.force_pause =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
+ }
+ break;
+ case RTE_FC_FULL:
+ if (fc_conf->autoneg) {
+ bp->link_info.auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX |
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ bp->link_info.force_pause = 0;
+ } else {
+ bp->link_info.auto_pause = 0;
+ bp->link_info.force_pause =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX |
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
+ }
+ break;
+ }
+ return bnxt_set_hwrm_link_config(bp, true);
+}
+