net/qede/base: add SmartAN support
[dpdk.git] / drivers / net / qede / base / ecore_dev.c
index 65b89b8..b206b44 100644 (file)
@@ -1232,7 +1232,7 @@ static enum _ecore_status_t ecore_hw_init_chip(struct ecore_hwfn *p_hwfn,
 static void ecore_init_cau_rt_data(struct ecore_dev *p_dev)
 {
        u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET;
-       int i, sb_id;
+       int i, igu_sb_id;
 
        for_each_hwfn(p_dev, i) {
                struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
@@ -1242,20 +1242,77 @@ static void ecore_init_cau_rt_data(struct ecore_dev *p_dev)
 
                p_igu_info = p_hwfn->hw_info.p_igu_info;
 
-               for (sb_id = 0; sb_id < ECORE_MAPPING_MEMORY_SIZE(p_dev);
-                    sb_id++) {
-                       p_block = &p_igu_info->igu_map.igu_blocks[sb_id];
+               for (igu_sb_id = 0;
+                    igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_dev);
+                    igu_sb_id++) {
+                       p_block = &p_igu_info->entry[igu_sb_id];
 
                        if (!p_block->is_pf)
                                continue;
 
                        ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
                                                p_block->function_id, 0, 0);
-                       STORE_RT_REG_AGG(p_hwfn, offset + sb_id * 2, sb_entry);
+                       STORE_RT_REG_AGG(p_hwfn, offset + igu_sb_id * 2,
+                                        sb_entry);
                }
        }
 }
 
+static void ecore_init_cache_line_size(struct ecore_hwfn *p_hwfn,
+                                      struct ecore_ptt *p_ptt)
+{
+       u32 val, wr_mbs, cache_line_size;
+
+       val = ecore_rd(p_hwfn, p_ptt, PSWRQ2_REG_WR_MBS0);
+       switch (val) {
+       case 0:
+               wr_mbs = 128;
+               break;
+       case 1:
+               wr_mbs = 256;
+               break;
+       case 2:
+               wr_mbs = 512;
+               break;
+       default:
+               DP_INFO(p_hwfn,
+                       "Unexpected value of PSWRQ2_REG_WR_MBS0 [0x%x]. Avoid configuring PGLUE_B_REG_CACHE_LINE_SIZE.\n",
+                       val);
+               return;
+       }
+
+       cache_line_size = OSAL_MIN_T(u32, OSAL_CACHE_LINE_SIZE, wr_mbs);
+       switch (cache_line_size) {
+       case 32:
+               val = 0;
+               break;
+       case 64:
+               val = 1;
+               break;
+       case 128:
+               val = 2;
+               break;
+       case 256:
+               val = 3;
+               break;
+       default:
+               DP_INFO(p_hwfn,
+                       "Unexpected value of cache line size [0x%x]. Avoid configuring PGLUE_B_REG_CACHE_LINE_SIZE.\n",
+                       cache_line_size);
+       }
+
+       if (wr_mbs < OSAL_CACHE_LINE_SIZE)
+               DP_INFO(p_hwfn,
+                       "The cache line size for padding is suboptimal for performance [OS cache line size 0x%x, wr mbs 0x%x]\n",
+                       OSAL_CACHE_LINE_SIZE, wr_mbs);
+
+       STORE_RT_REG(p_hwfn, PGLUE_REG_B_CACHE_LINE_SIZE_RT_OFFSET, val);
+       if (val > 0) {
+               STORE_RT_REG(p_hwfn, PSWRQ2_REG_DRAM_ALIGN_WR_RT_OFFSET, val);
+               STORE_RT_REG(p_hwfn, PSWRQ2_REG_DRAM_ALIGN_RD_RT_OFFSET, val);
+       }
+}
+
 static enum _ecore_status_t ecore_hw_init_common(struct ecore_hwfn *p_hwfn,
                                                 struct ecore_ptt *p_ptt,
                                                 int hw_mode)
@@ -1296,6 +1353,8 @@ static enum _ecore_status_t ecore_hw_init_common(struct ecore_hwfn *p_hwfn,
 
        ecore_cxt_hw_init_common(p_hwfn);
 
+       ecore_init_cache_line_size(p_hwfn, p_ptt);
+
        rc = ecore_init_run(p_hwfn, p_ptt, PHASE_ENGINE, ANY_PHASE_ID, hw_mode);
        if (rc != ECORE_SUCCESS)
                return rc;
@@ -1684,6 +1743,9 @@ static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
                            hw_mode);
        if (rc != ECORE_SUCCESS)
                return rc;
+
+       ecore_wr(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_WRITE_PAD_ENABLE, 0);
+
 #ifndef ASIC_ONLY
        if (CHIP_REV_IS_ASIC(p_hwfn->p_dev))
                return ECORE_SUCCESS;
@@ -1978,6 +2040,8 @@ enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
                           "Load request was sent. Load code: 0x%x\n",
                           load_code);
 
+               ecore_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt);
+
                /* CQ75580:
                 * When coming back from hiberbate state, the registers from
                 * which shadow is read initially are not initialized. It turns
@@ -2255,6 +2319,13 @@ enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
                ecore_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0);
                ecore_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0);
                ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true);
+               rc = ecore_int_igu_reset_cam_default(p_hwfn, p_ptt);
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_hwfn, true,
+                                 "Failed to return IGU CAM to default\n");
+                       rc2 = ECORE_UNKNOWN_ERROR;
+               }
+
                /* Need to wait 1ms to guarantee SBs are cleared */
                OSAL_MSLEEP(1);
 
@@ -2423,27 +2494,32 @@ static void get_function_id(struct ecore_hwfn *p_hwfn)
 static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
 {
        u32 *feat_num = p_hwfn->hw_info.feat_num;
-       struct ecore_sb_cnt_info sb_cnt_info;
-       int num_features = 1;
+       struct ecore_sb_cnt_info sb_cnt;
+       u32 non_l2_sbs = 0;
+
+       OSAL_MEM_ZERO(&sb_cnt, sizeof(sb_cnt));
+       ecore_int_get_num_sbs(p_hwfn, &sb_cnt);
 
        /* L2 Queues require each: 1 status block. 1 L2 queue */
-       feat_num[ECORE_PF_L2_QUE] =
-           OSAL_MIN_T(u32,
-                      RESC_NUM(p_hwfn, ECORE_SB) / num_features,
-                      RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
-
-       OSAL_MEM_ZERO(&sb_cnt_info, sizeof(sb_cnt_info));
-       ecore_int_get_num_sbs(p_hwfn, &sb_cnt_info);
-       feat_num[ECORE_VF_L2_QUE] =
-               OSAL_MIN_T(u32,
-                          RESC_NUM(p_hwfn, ECORE_L2_QUEUE) -
-                          FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE),
-                          sb_cnt_info.sb_iov_cnt);
-
-       feat_num[ECORE_FCOE_CQ] = OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_SB),
-                                            RESC_NUM(p_hwfn, ECORE_CMDQS_CQS));
-       feat_num[ECORE_ISCSI_CQ] = OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_SB),
-                                            RESC_NUM(p_hwfn, ECORE_CMDQS_CQS));
+       if (ECORE_IS_L2_PERSONALITY(p_hwfn)) {
+               /* Start by allocating VF queues, then PF's */
+               feat_num[ECORE_VF_L2_QUE] =
+                       OSAL_MIN_T(u32,
+                                  RESC_NUM(p_hwfn, ECORE_L2_QUEUE),
+                                  sb_cnt.iov_cnt);
+               feat_num[ECORE_PF_L2_QUE] =
+                       OSAL_MIN_T(u32,
+                                  sb_cnt.cnt - non_l2_sbs,
+                                  RESC_NUM(p_hwfn, ECORE_L2_QUEUE) -
+                                  FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE));
+       }
+
+       feat_num[ECORE_FCOE_CQ] = OSAL_MIN_T(u32, sb_cnt.cnt,
+                                            RESC_NUM(p_hwfn,
+                                                     ECORE_CMDQS_CQS));
+       feat_num[ECORE_ISCSI_CQ] = OSAL_MIN_T(u32, sb_cnt.cnt,
+                                             RESC_NUM(p_hwfn,
+                                                      ECORE_CMDQS_CQS));
 
        DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
                   "#PF_L2_QUEUE=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #FCOE_CQ=%d #ISCSI_CQ=%d #SB=%d\n",
@@ -2452,14 +2528,12 @@ static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
                   (int)FEAT_NUM(p_hwfn, ECORE_RDMA_CNQ),
                   (int)FEAT_NUM(p_hwfn, ECORE_FCOE_CQ),
                   (int)FEAT_NUM(p_hwfn, ECORE_ISCSI_CQ),
-                  RESC_NUM(p_hwfn, ECORE_SB));
+                  (int)sb_cnt.cnt);
 }
 
 const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
 {
        switch (res_id) {
-       case ECORE_SB:
-               return "SB";
        case ECORE_L2_QUEUE:
                return "L2_QUEUE";
        case ECORE_VPORT:
@@ -2486,6 +2560,8 @@ const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
                return "RDMA_STATS_QUEUE";
        case ECORE_BDQ:
                return "BDQ";
+       case ECORE_SB:
+               return "SB";
        default:
                return "UNKNOWN_RESOURCE";
        }
@@ -2561,14 +2637,8 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
 {
        u8 num_funcs = p_hwfn->num_funcs_on_engine;
        bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
-       struct ecore_sb_cnt_info sb_cnt_info;
 
        switch (res_id) {
-       case ECORE_SB:
-               OSAL_MEM_ZERO(&sb_cnt_info, sizeof(sb_cnt_info));
-               ecore_int_get_num_sbs(p_hwfn, &sb_cnt_info);
-               *p_resc_num = sb_cnt_info.sb_cnt;
-               break;
        case ECORE_L2_QUEUE:
                *p_resc_num = (b_ah ? MAX_NUM_L2_QUEUES_K2 :
                                 MAX_NUM_L2_QUEUES_BB) / num_funcs;
@@ -2625,6 +2695,12 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
                if (!*p_resc_num)
                        *p_resc_start = 0;
                break;
+       case ECORE_SB:
+               /* Since we want its value to reflect whether MFW supports
+                * the new scheme, have a default of 0.
+                */
+               *p_resc_num = 0;
+               break;
        default:
                *p_resc_start = *p_resc_num * p_hwfn->enabled_func_idx;
                break;
@@ -2689,14 +2765,9 @@ __ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
                goto out;
        }
 
-       /* TBD - remove this when revising the handling of the SB resource */
-       if (res_id == ECORE_SB) {
-               /* Excluding the slowpath SB */
-               *p_resc_num -= 1;
-               *p_resc_start -= p_hwfn->enabled_func_idx;
-       }
-
-       if (*p_resc_num != dflt_resc_num || *p_resc_start != dflt_resc_start) {
+       if ((*p_resc_num != dflt_resc_num ||
+            *p_resc_start != dflt_resc_start) &&
+           res_id != ECORE_SB) {
                DP_INFO(p_hwfn,
                        "MFW allocation for resource %d [%s] differs from default values [%d,%d vs. %d,%d]%s\n",
                        res_id, ecore_hw_get_resc_name(res_id), *p_resc_num,
@@ -2846,6 +2917,10 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                return ECORE_INVAL;
        }
 
+       /* This will also learn the number of SBs from MFW */
+       if (ecore_int_igu_reset_cam(p_hwfn, p_hwfn->p_main_ptt))
+               return ECORE_INVAL;
+
        ecore_hw_set_feat(p_hwfn);
 
        DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
@@ -2870,6 +2945,7 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
 {
        u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg, dcbx_mode;
        u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
+       struct ecore_mcp_link_capabilities *p_caps;
        struct ecore_mcp_link_params *link;
        enum _ecore_status_t rc;
 
@@ -2959,6 +3035,7 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
 
        /* Read default link configuration */
        link = &p_hwfn->mcp_info->link_input;
+       p_caps = &p_hwfn->mcp_info->link_capabilities;
        port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
            OFFSETOF(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
        link_temp = ecore_rd(p_hwfn, p_ptt,
@@ -2966,9 +3043,7 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
                             OFFSETOF(struct nvm_cfg1_port, speed_cap_mask));
        link_temp &= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;
        link->speed.advertised_speeds = link_temp;
-
-       link_temp = link->speed.advertised_speeds;
-       p_hwfn->mcp_info->link_capabilities.speed_capabilities = link_temp;
+       p_caps->speed_capabilities = link->speed.advertised_speeds;
 
        link_temp = ecore_rd(p_hwfn, p_ptt,
                             port_cfg_addr +
@@ -3000,10 +3075,8 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
                DP_NOTICE(p_hwfn, true, "Unknown Speed in 0x%08x\n", link_temp);
        }
 
-       p_hwfn->mcp_info->link_capabilities.default_speed =
-           link->speed.forced_speed;
-       p_hwfn->mcp_info->link_capabilities.default_speed_autoneg =
-           link->speed.autoneg;
+       p_caps->default_speed = link->speed.forced_speed;
+       p_caps->default_speed_autoneg = link->speed.autoneg;
 
        link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
        link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
@@ -3253,6 +3326,8 @@ ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
         */
        ecore_hw_info_port_num(p_hwfn, p_ptt);
 
+       ecore_mcp_get_capabilities(p_hwfn, p_ptt);
+
 #ifndef ASIC_ONLY
        if (CHIP_REV_IS_ASIC(p_hwfn->p_dev)) {
 #endif
@@ -3348,6 +3423,7 @@ ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
 static enum _ecore_status_t ecore_get_dev_info(struct ecore_dev *p_dev)
 {
        struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       u16 device_id_mask;
        u32 tmp;
 
        /* Read Vendor Id / Device Id */
@@ -3357,10 +3433,19 @@ static enum _ecore_status_t ecore_get_dev_info(struct ecore_dev *p_dev)
                                  &p_dev->device_id);
 
        /* Determine type */
-       if ((p_dev->device_id & ECORE_DEV_ID_MASK) == ECORE_DEV_ID_MASK_AH)
-               p_dev->type = ECORE_DEV_TYPE_AH;
-       else
+       device_id_mask = p_dev->device_id & ECORE_DEV_ID_MASK;
+       switch (device_id_mask) {
+       case ECORE_DEV_ID_MASK_BB:
                p_dev->type = ECORE_DEV_TYPE_BB;
+               break;
+       case ECORE_DEV_ID_MASK_AH:
+               p_dev->type = ECORE_DEV_TYPE_AH;
+               break;
+       default:
+               DP_NOTICE(p_hwfn, true, "Unknown device id 0x%x\n",
+                         p_dev->device_id);
+               return ECORE_ABORTED;
+       }
 
        p_dev->chip_num = (u16)ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
                                         MISCS_REG_CHIP_NUM);
@@ -4526,7 +4611,7 @@ enum _ecore_status_t ecore_set_rxq_coalesce(struct ecore_hwfn *p_hwfn,
        timeset = (u8)(coalesce >> timer_res);
 
        rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
-                                    p_cid->abs.sb_idx, false);
+                                    p_cid->sb_igu_id, false);
        if (rc != ECORE_SUCCESS)
                goto out;
 
@@ -4567,7 +4652,7 @@ enum _ecore_status_t ecore_set_txq_coalesce(struct ecore_hwfn *p_hwfn,
        timeset = (u8)(coalesce >> timer_res);
 
        rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
-                                    p_cid->abs.sb_idx, true);
+                                    p_cid->sb_igu_id, true);
        if (rc != ECORE_SUCCESS)
                goto out;
 
@@ -4820,6 +4905,7 @@ int ecore_configure_vport_wfq(struct ecore_dev *p_dev, u16 vp_id, u32 rate)
 
 /* API to configure WFQ from mcp link change */
 void ecore_configure_vp_wfq_on_link_change(struct ecore_dev *p_dev,
+                                          struct ecore_ptt *p_ptt,
                                           u32 min_pf_rate)
 {
        int i;
@@ -4834,8 +4920,7 @@ void ecore_configure_vp_wfq_on_link_change(struct ecore_dev *p_dev,
        for_each_hwfn(p_dev, i) {
                struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
 
-               __ecore_configure_vp_wfq_on_link_change(p_hwfn,
-                                                       p_hwfn->p_dpc_ptt,
+               __ecore_configure_vp_wfq_on_link_change(p_hwfn, p_ptt,
                                                        min_pf_rate);
        }
 }