New upstream version 16.11.7
[deb_dpdk.git] / drivers / net / bnxt / bnxt_hwrm.c
index 07e7124..d790b99 100644 (file)
@@ -174,11 +174,10 @@ int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, struct bnxt_vnic_info *vnic)
         * by ethtool.
         */
        if (vnic->flags & BNXT_VNIC_INFO_PROMISC)
-               mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS;
+               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_BCAST |
-                                   mask);
+               mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
+       req.mask = rte_cpu_to_le_32(mask);
 
        rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
 
@@ -194,6 +193,9 @@ int bnxt_hwrm_clear_filter(struct bnxt *bp,
        struct hwrm_cfa_l2_filter_free_input req = {.req_type = 0 };
        struct hwrm_cfa_l2_filter_free_output *resp = bp->hwrm_cmd_resp_addr;
 
+       if (filter->fw_l2_filter_id == UINT64_MAX)
+               return 0;
+
        HWRM_PREP(req, CFA_L2_FILTER_FREE, -1, resp);
 
        req.l2_filter_id = rte_cpu_to_le_64(filter->fw_l2_filter_id);
@@ -216,6 +218,9 @@ int bnxt_hwrm_set_filter(struct bnxt *bp,
        struct hwrm_cfa_l2_filter_alloc_output *resp = bp->hwrm_cmd_resp_addr;
        uint32_t enables = 0;
 
+       if (filter->fw_l2_filter_id != UINT64_MAX)
+               bnxt_hwrm_clear_filter(bp, filter);
+
        HWRM_PREP(req, CFA_L2_FILTER_ALLOC, -1, resp);
 
        req.flags = rte_cpu_to_le_32(filter->flags);
@@ -480,22 +485,35 @@ static int bnxt_hwrm_port_phy_cfg(struct bnxt *bp, struct bnxt_link_info *conf)
        HWRM_PREP(req, PORT_PHY_CFG, -1, resp);
 
        if (conf->link_up) {
+               /* Setting Fixed Speed. But AutoNeg is ON, So disable it */
+               if (bp->link_info.auto_mode && conf->link_speed) {
+                       req.auto_mode = HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE;
+                       RTE_LOG(DEBUG, PMD, "Disabling AutoNeg\n");
+               }
+
                req.flags = rte_cpu_to_le_32(conf->phy_flags);
                req.force_link_speed = rte_cpu_to_le_16(conf->link_speed);
+               enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
                /*
                 * Note, ChiMP FW 20.2.1 and 20.2.2 return an error when we set
                 * any auto mode, even "none".
                 */
                if (!conf->link_speed) {
-                       req.auto_mode |= conf->auto_mode;
-                       enables = HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
-                       req.auto_link_speed_mask = conf->auto_link_speed_mask;
-                       enables |=
-                          HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK;
-                       req.auto_link_speed = bp->link_info.auto_link_speed;
+                       /* No speeds specified. Enable AutoNeg - all speeds */
+                       req.auto_mode =
+                               HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
+               }
+               /* AutoNeg - Advertise speeds specified. */
+               if (conf->auto_link_speed_mask &&
+                   !(conf->phy_flags & HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE)) {
+                       req.auto_mode =
+                               HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK;
+                       req.auto_link_speed_mask =
+                               conf->auto_link_speed_mask;
                        enables |=
-                               HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED;
+                       HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK;
                }
+
                req.auto_duplex = conf->duplex;
                enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX;
                req.auto_pause = conf->auto_pause;
@@ -534,22 +552,22 @@ static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
        HWRM_CHECK_RESULT;
 
        link_info->phy_link_status = resp->link;
-       if (link_info->phy_link_status != HWRM_PORT_PHY_QCFG_OUTPUT_LINK_NO_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->link_up =
+               (link_info->phy_link_status ==
+                HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) ? 1 : 0;
+       link_info->link_speed = rte_le_to_cpu_16(resp->link_speed);
        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->phy_type = resp->phy_type;
+       link_info->media_type = resp->media_type;
 
        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->force_link_speed = rte_le_to_cpu_16(resp->force_link_speed);
        link_info->phy_ver[0] = resp->phy_maj;
        link_info->phy_ver[1] = resp->phy_min;
        link_info->phy_ver[2] = resp->phy_bld;
@@ -588,7 +606,7 @@ int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 int bnxt_hwrm_ring_alloc(struct bnxt *bp,
                         struct bnxt_ring *ring,
                         uint32_t ring_type, uint32_t map_index,
-                        uint32_t stats_ctx_id)
+                        uint32_t stats_ctx_id, uint32_t cmpl_ring_id)
 {
        int rc = 0;
        struct hwrm_ring_alloc_input req = {.req_type = 0 };
@@ -609,11 +627,12 @@ int bnxt_hwrm_ring_alloc(struct bnxt *bp,
                /* FALLTHROUGH */
        case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
                req.ring_type = ring_type;
-               req.cmpl_ring_id =
-                   rte_cpu_to_le_16(bp->grp_info[map_index].cp_fw_ring_id);
+               req.cmpl_ring_id = rte_cpu_to_le_16(cmpl_ring_id);
                req.length = rte_cpu_to_le_32(ring->ring_size);
                req.stat_ctx_id = rte_cpu_to_le_16(stats_ctx_id);
-               req.enables = rte_cpu_to_le_32(rte_le_to_cpu_32(req.enables) |
+               if (stats_ctx_id != INVALID_STATS_CTX_ID)
+                       req.enables =
+                       rte_cpu_to_le_32(rte_le_to_cpu_32(req.enables) |
                        HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
                break;
        case HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL:
@@ -780,7 +799,9 @@ int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp,
        HWRM_CHECK_RESULT;
 
        cpr->hw_stats_ctx_id = rte_le_to_cpu_16(resp->stat_ctx_id);
-       bp->grp_info[idx].fw_stats_ctx = cpr->hw_stats_ctx_id;
+       //Tx rings don't need grp_info entry. It is a Rx only attribute.
+       if (idx)
+               bp->grp_info[idx].fw_stats_ctx = cpr->hw_stats_ctx_id;
 
        return rc;
 }
@@ -802,7 +823,9 @@ int bnxt_hwrm_stat_ctx_free(struct bnxt *bp,
        HWRM_CHECK_RESULT;
 
        cpr->hw_stats_ctx_id = HWRM_NA_SIGNATURE;
-       bp->grp_info[idx].fw_stats_ctx = cpr->hw_stats_ctx_id;
+       //Tx rings don't have a grp_info entry. It is a Rx only attribute.
+       if (idx)
+               bp->grp_info[idx].fw_stats_ctx = cpr->hw_stats_ctx_id;
 
        return rc;
 }
@@ -829,11 +852,15 @@ int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 
        HWRM_PREP(req, VNIC_ALLOC, -1, resp);
 
+       if (vnic->func_default)
+               req.flags =
+                       rte_cpu_to_le_32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
        rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
 
        HWRM_CHECK_RESULT;
 
        vnic->fw_vnic_id = rte_le_to_cpu_16(resp->vnic_id);
+       RTE_LOG(DEBUG, PMD, "VNIC ID %x\n", vnic->fw_vnic_id);
        return rc;
 }
 
@@ -843,6 +870,11 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
        struct hwrm_vnic_cfg_input req = {.req_type = 0 };
        struct hwrm_vnic_cfg_output *resp = bp->hwrm_cmd_resp_addr;
 
+       if (vnic->fw_vnic_id == INVALID_HW_RING_ID) {
+               RTE_LOG(DEBUG, PMD, "VNIC ID %x\n", vnic->fw_vnic_id);
+               return rc;
+       }
+
        HWRM_PREP(req, VNIC_CFG, -1, resp);
 
        /* Only RSS support for now TBD: COS & LB */
@@ -885,6 +917,7 @@ int bnxt_hwrm_vnic_ctx_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
        HWRM_CHECK_RESULT;
 
        vnic->fw_rss_cos_lb_ctx = rte_le_to_cpu_16(resp->rss_cos_lb_ctx_id);
+       RTE_LOG(DEBUG, PMD, "VNIC RSS Rule %x\n", vnic->fw_rss_cos_lb_ctx);
 
        return rc;
 }
@@ -896,6 +929,12 @@ int bnxt_hwrm_vnic_ctx_free(struct bnxt *bp, struct bnxt_vnic_info *vnic)
        struct hwrm_vnic_rss_cos_lb_ctx_free_output *resp =
                                                bp->hwrm_cmd_resp_addr;
 
+       if (vnic->fw_rss_cos_lb_ctx == 0xffff) {
+               RTE_LOG(DEBUG, PMD,
+                       "VNIC RSS Rule %x\n", vnic->fw_rss_cos_lb_ctx);
+               return rc;
+       }
+
        HWRM_PREP(req, VNIC_RSS_COS_LB_CTX_FREE, -1, resp);
 
        req.rss_cos_lb_ctx_id = rte_cpu_to_le_16(vnic->fw_rss_cos_lb_ctx);
@@ -915,8 +954,10 @@ int bnxt_hwrm_vnic_free(struct bnxt *bp, struct bnxt_vnic_info *vnic)
        struct hwrm_vnic_free_input req = {.req_type = 0 };
        struct hwrm_vnic_free_output *resp = bp->hwrm_cmd_resp_addr;
 
-       if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
+       if (vnic->fw_vnic_id == INVALID_HW_RING_ID) {
+               RTE_LOG(DEBUG, PMD, "VNIC FREE ID %x\n", vnic->fw_vnic_id);
                return rc;
+       }
 
        HWRM_PREP(req, VNIC_FREE, -1, resp);
 
@@ -992,10 +1033,13 @@ int bnxt_free_all_hwrm_stat_ctxs(struct bnxt *bp)
        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)
+               if (i >= bp->rx_cp_nr_rings) {
                        cpr = bp->tx_queues[i - bp->rx_cp_nr_rings]->cp_ring;
-               else
+                       //Tx rings don't have a grp_info entry.
+                       idx = 0;
+               } 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)
@@ -1019,6 +1063,8 @@ int bnxt_alloc_all_hwrm_stat_ctxs(struct bnxt *bp)
                if (i >= bp->rx_cp_nr_rings) {
                        txq = bp->tx_queues[i - bp->rx_cp_nr_rings];
                        cpr = txq->cp_ring;
+                       //Tx rings don't need grp_info entry.
+                       idx = 0;
                } else {
                        rxq = bp->rx_queues[i];
                        cpr = rxq->cp_ring;
@@ -1056,14 +1102,13 @@ int bnxt_free_all_hwrm_ring_grps(struct bnxt *bp)
 }
 
 static void bnxt_free_cp_ring(struct bnxt *bp,
-                             struct bnxt_cp_ring_info *cpr, unsigned int idx)
+                             struct bnxt_cp_ring_info *cpr)
 {
        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;
@@ -1079,7 +1124,6 @@ int bnxt_free_all_hwrm_rings(struct bnxt *bp)
                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,
@@ -1095,7 +1139,7 @@ int bnxt_free_all_hwrm_rings(struct bnxt *bp)
                        txr->tx_cons = 0;
                }
                if (cpr->cp_ring_struct->fw_ring_id != INVALID_HW_RING_ID)
-                       bnxt_free_cp_ring(bp, cpr, idx);
+                       bnxt_free_cp_ring(bp, cpr);
        }
 
        for (i = 0; i < bp->rx_cp_nr_rings; i++) {
@@ -1119,7 +1163,8 @@ int bnxt_free_all_hwrm_rings(struct bnxt *bp)
                        rxr->rx_prod = 0;
                }
                if (cpr->cp_ring_struct->fw_ring_id != INVALID_HW_RING_ID)
-                       bnxt_free_cp_ring(bp, cpr, idx);
+                       bnxt_free_cp_ring(bp, cpr);
+               bp->grp_info[idx].cp_fw_ring_id = INVALID_HW_RING_ID;
        }
 
        /* Default completion ring */
@@ -1127,7 +1172,8 @@ int bnxt_free_all_hwrm_rings(struct bnxt *bp)
                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);
+                       bnxt_free_cp_ring(bp, cpr);
+               bp->grp_info[0].cp_fw_ring_id = INVALID_HW_RING_ID;
        }
 
        return rc;
@@ -1247,6 +1293,11 @@ static uint16_t bnxt_parse_eth_link_duplex(uint32_t conf_link_speed)
        return hw_link_duplex;
 }
 
+static uint16_t bnxt_check_eth_link_autoneg(uint32_t conf_link)
+{
+       return (conf_link & ETH_LINK_SPEED_FIXED) ? 0 : 1;
+}
+
 static uint16_t bnxt_parse_eth_link_speed(uint32_t conf_link_speed)
 {
        uint16_t eth_link_speed = 0;
@@ -1335,12 +1386,16 @@ static int bnxt_valid_link_speed(uint32_t link_speed, uint8_t port_id)
        return 0;
 }
 
-static uint16_t bnxt_parse_eth_link_speed_mask(uint32_t link_speed)
+static uint16_t
+bnxt_parse_eth_link_speed_mask(struct bnxt *bp, uint32_t link_speed)
 {
        uint16_t ret = 0;
 
-       if (link_speed == ETH_LINK_SPEED_AUTONEG)
+       if (link_speed == ETH_LINK_SPEED_AUTONEG) {
+               if (bp->link_info.support_speeds)
+                       return bp->link_info.support_speeds;
                link_speed = BNXT_SUPPORTED_SPEEDS;
+       }
 
        if (link_speed & ETH_LINK_SPEED_100M)
                ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MB;
@@ -1432,16 +1487,16 @@ int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link)
                        "Get link config failed with rc %d\n", rc);
                goto exit;
        }
-       if (link_info->link_up)
+       if (link_info->link_speed)
                link->link_speed =
                        bnxt_parse_hw_link_speed(link_info->link_speed);
        else
-               link->link_speed = ETH_LINK_SPEED_10M;
+               link->link_speed = ETH_SPEED_NUM_NONE;
        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;
+               ETH_LINK_FIXED : ETH_LINK_AUTONEG;
 exit:
        return rc;
 }
@@ -1451,7 +1506,7 @@ int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
        int rc = 0;
        struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
        struct bnxt_link_info link_req;
-       uint16_t speed;
+       uint16_t speed, autoneg;
 
        if (BNXT_NPAR_PF(bp) || BNXT_VF(bp))
                return 0;
@@ -1466,19 +1521,36 @@ int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
        if (!link_up)
                goto port_phy_cfg;
 
+       autoneg = bnxt_check_eth_link_autoneg(dev_conf->link_speeds);
        speed = bnxt_parse_eth_link_speed(dev_conf->link_speeds);
        link_req.phy_flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY;
-       if (speed == 0) {
+       /* Autoneg can be done only when the FW allows */
+       if (autoneg == 1 && !(bp->link_info.auto_link_speed ||
+                               bp->link_info.force_link_speed)) {
                link_req.phy_flags |=
                                HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG;
-               link_req.auto_mode =
-                               HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK;
                link_req.auto_link_speed_mask =
-                       bnxt_parse_eth_link_speed_mask(dev_conf->link_speeds);
+                       bnxt_parse_eth_link_speed_mask(bp,
+                                                      dev_conf->link_speeds);
        } else {
+               if (bp->link_info.phy_type ==
+                   HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
+                   bp->link_info.phy_type ==
+                   HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE ||
+                   bp->link_info.media_type ==
+                   HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP) {
+                       RTE_LOG(ERR, PMD, "10GBase-T devices must autoneg\n");
+                       return -EINVAL;
+               }
+
                link_req.phy_flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE;
-               link_req.link_speed = speed;
-               RTE_LOG(INFO, PMD, "Set Link Speed %x\n", speed);
+               /* If user wants a particular speed try that first. */
+               if (speed)
+                       link_req.link_speed = speed;
+               else if (bp->link_info.force_link_speed)
+                       link_req.link_speed = bp->link_info.force_link_speed;
+               else
+                       link_req.link_speed = bp->link_info.auto_link_speed;
        }
        link_req.duplex = bnxt_parse_eth_link_duplex(dev_conf->link_speeds);
        link_req.auto_pause = bp->link_info.auto_pause;
@@ -1491,7 +1563,6 @@ port_phy_cfg:
                        "Set link config failed with rc %d\n", rc);
        }
 
-       rte_delay_ms(BNXT_LINK_WAIT_INTERVAL);
 error:
        return rc;
 }