net/qede/base: add UFP support
[dpdk.git] / drivers / net / qede / base / ecore_dev.c
index 67d8dd8..283c65b 100644 (file)
@@ -103,7 +103,7 @@ struct ecore_hwfn *ecore_db_rec_find_hwfn(struct ecore_dev *p_dev,
        /* In CMT doorbell bar is split down the middle between engine 0 and
         * enigne 1
         */
-       if (p_dev->num_hwfns > 1)
+       if (ECORE_IS_CMT(p_dev))
                p_hwfn = db_addr < p_dev->hwfns[1].doorbells ?
                        &p_dev->hwfns[0] : &p_dev->hwfns[1];
        else
@@ -361,7 +361,7 @@ void ecore_db_recovery_execute(struct ecore_hwfn *p_hwfn,
                                         */
 
 /* Derived */
-#define ECORE_MIN_PWM_REGION   ((ECORE_WID_SIZE) * (ECORE_MIN_DPIS))
+#define ECORE_MIN_PWM_REGION   (ECORE_WID_SIZE * ECORE_MIN_DPIS)
 
 enum BAR_ID {
        BAR_ID_0,               /* used for GRC */
@@ -392,7 +392,7 @@ static u32 ecore_hw_bar_size(struct ecore_hwfn *p_hwfn,
         * they were found to be useful MFW started updating them from 8.7.7.0.
         * In older MFW versions they are set to 0 which means disabled.
         */
-       if (p_hwfn->p_dev->num_hwfns > 1) {
+       if (ECORE_IS_CMT(p_hwfn->p_dev)) {
                DP_INFO(p_hwfn,
                        "BAR size not configured. Assuming BAR size of 256kB for GRC and 512kB for DB\n");
                val = BAR_ID_0 ? 256 * 1024 : 512 * 1024;
@@ -665,7 +665,7 @@ static void ecore_init_qm_port_params(struct ecore_hwfn *p_hwfn)
 
                p_qm_port->active = 1;
                p_qm_port->active_phys_tcs = active_phys_tcs;
-               p_qm_port->num_pbf_cmd_lines = PBF_MAX_CMD_LINES / num_ports;
+               p_qm_port->num_pbf_cmd_lines = PBF_MAX_CMD_LINES_E4 / num_ports;
                p_qm_port->num_btb_blocks = BTB_MAX_BLOCKS / num_ports;
        }
 }
@@ -1455,19 +1455,11 @@ static enum _ecore_status_t ecore_calc_hw_mode(struct ecore_hwfn *p_hwfn)
                return ECORE_INVAL;
        }
 
-       switch (p_hwfn->p_dev->mf_mode) {
-       case ECORE_MF_DEFAULT:
-       case ECORE_MF_NPAR:
-               hw_mode |= 1 << MODE_MF_SI;
-               break;
-       case ECORE_MF_OVLAN:
+       if (OSAL_TEST_BIT(ECORE_MF_OVLAN_CLSS,
+                         &p_hwfn->p_dev->mf_bits))
                hw_mode |= 1 << MODE_MF_SD;
-               break;
-       default:
-               DP_NOTICE(p_hwfn, true,
-                         "Unsupported MF mode, init as DEFAULT\n");
+       else
                hw_mode |= 1 << MODE_MF_SI;
-       }
 
 #ifndef ASIC_ONLY
        if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
@@ -1483,7 +1475,7 @@ static enum _ecore_status_t ecore_calc_hw_mode(struct ecore_hwfn *p_hwfn)
 #endif
                hw_mode |= 1 << MODE_ASIC;
 
-       if (p_hwfn->p_dev->num_hwfns > 1)
+       if (ECORE_IS_CMT(p_hwfn->p_dev))
                hw_mode |= 1 << MODE_100G;
 
        p_hwfn->hw_info.hw_mode = hw_mode;
@@ -1892,9 +1884,9 @@ static enum _ecore_status_t
 ecore_hw_init_dpi_size(struct ecore_hwfn *p_hwfn,
                       struct ecore_ptt *p_ptt, u32 pwm_region_size, u32 n_cpus)
 {
-       u32 dpi_page_size_1, dpi_page_size_2, dpi_page_size;
-       u32 dpi_bit_shift, dpi_count;
+       u32 dpi_bit_shift, dpi_count, dpi_page_size;
        u32 min_dpis;
+       u32 n_wids;
 
        /* Calculate DPI size
         * ------------------
@@ -1917,12 +1909,11 @@ ecore_hw_init_dpi_size(struct ecore_hwfn *p_hwfn,
         * 0 is 4kB, 1 is 8kB and etc. Hence the minimum size is 4,096
         * containing 4 WIDs.
         */
-       dpi_page_size_1 = ECORE_WID_SIZE * n_cpus;
-       dpi_page_size_2 = OSAL_MAX_T(u32, ECORE_WID_SIZE, OSAL_PAGE_SIZE);
-       dpi_page_size = OSAL_MAX_T(u32, dpi_page_size_1, dpi_page_size_2);
-       dpi_page_size = OSAL_ROUNDUP_POW_OF_TWO(dpi_page_size);
+       n_wids = OSAL_MAX_T(u32, ECORE_MIN_WIDS, n_cpus);
+       dpi_page_size = ECORE_WID_SIZE * OSAL_ROUNDUP_POW_OF_TWO(n_wids);
+       dpi_page_size = (dpi_page_size + OSAL_PAGE_SIZE - 1) &
+                       ~(OSAL_PAGE_SIZE - 1);
        dpi_bit_shift = OSAL_LOG2(dpi_page_size / 4096);
-
        dpi_count = pwm_region_size / dpi_page_size;
 
        min_dpis = p_hwfn->pf_params.rdma_pf_params.min_dpis;
@@ -1960,7 +1951,7 @@ ecore_hw_init_pf_doorbell_bar(struct ecore_hwfn *p_hwfn,
        u8 cond;
 
        db_bar_size = ecore_hw_bar_size(p_hwfn, p_ptt, BAR_ID_1);
-       if (p_hwfn->p_dev->num_hwfns > 1)
+       if (ECORE_IS_CMT(p_hwfn->p_dev))
                db_bar_size /= 2;
 
        /* Calculate doorbell regions
@@ -1981,7 +1972,8 @@ ecore_hw_init_pf_doorbell_bar(struct ecore_hwfn *p_hwfn,
            ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_CORE,
                                          OSAL_NULL) +
            ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, OSAL_NULL);
-       norm_regsize = ROUNDUP(ECORE_PF_DEMS_SIZE * non_pwm_conn, 4096);
+       norm_regsize = ROUNDUP(ECORE_PF_DEMS_SIZE * non_pwm_conn,
+                              OSAL_PAGE_SIZE);
        min_addr_reg1 = norm_regsize / 4096;
        pwm_regsize = db_bar_size - norm_regsize;
 
@@ -2059,7 +2051,21 @@ static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
                                               struct ecore_ptt *p_ptt,
                                               int hw_mode)
 {
+       u32 ppf_to_eng_sel[NIG_REG_PPF_TO_ENGINE_SEL_RT_SIZE];
+       u32 val;
        enum _ecore_status_t rc = ECORE_SUCCESS;
+       u8 i;
+
+       /* In CMT for non-RoCE packets - use connection based classification */
+       val = ECORE_IS_CMT(p_hwfn->p_dev) ? 0x8 : 0x0;
+       for (i = 0; i < NIG_REG_PPF_TO_ENGINE_SEL_RT_SIZE; i++)
+               ppf_to_eng_sel[i] = val;
+       STORE_RT_REG_AGG(p_hwfn, NIG_REG_PPF_TO_ENGINE_SEL_RT_OFFSET,
+                        ppf_to_eng_sel);
+
+       /* In CMT the gate should be cleared by the 2nd hwfn */
+       if (!ECORE_IS_CMT(p_hwfn->p_dev) || !IS_LEAD_HWFN(p_hwfn))
+               STORE_RT_REG(p_hwfn, NIG_REG_BRB_GATE_DNTFWD_PORT_RT_OFFSET, 0);
 
        rc = ecore_init_run(p_hwfn, p_ptt, PHASE_PORT, p_hwfn->port_id,
                            hw_mode);
@@ -2078,7 +2084,7 @@ static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
                else if (ECORE_IS_BB(p_hwfn->p_dev))
                        ecore_link_init_bb(p_hwfn, p_ptt, p_hwfn->port_id);
        } else if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
-               if (p_hwfn->p_dev->num_hwfns > 1) {
+               if (ECORE_IS_CMT(p_hwfn->p_dev)) {
                        /* Activate OPTE in CMT */
                        u32 val;
 
@@ -2140,6 +2146,11 @@ ecore_hw_init_pf(struct ecore_hwfn *p_hwfn,
                STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET, 1);
                STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET,
                             p_hwfn->hw_info.ovlan);
+
+               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
+                          "Configuring LLH_FUNC_FILTER_HDR_SEL\n");
+               STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_OFFSET,
+                            1);
        }
 
        /* Enable classification by MAC if needed */
@@ -2200,7 +2211,6 @@ ecore_hw_init_pf(struct ecore_hwfn *p_hwfn,
 
                /* send function start command */
                rc = ecore_sp_pf_start(p_hwfn, p_ptt, p_tunn,
-                                      p_hwfn->p_dev->mf_mode,
                                       allow_npar_tx_switch);
                if (rc) {
                        DP_NOTICE(p_hwfn, true,
@@ -2337,8 +2347,7 @@ enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
        enum _ecore_status_t rc = ECORE_SUCCESS;
        int i;
 
-       if ((p_params->int_mode == ECORE_INT_MODE_MSI) &&
-           (p_dev->num_hwfns > 1)) {
+       if ((p_params->int_mode == ECORE_INT_MODE_MSI) && ECORE_IS_CMT(p_dev)) {
                DP_NOTICE(p_dev, false,
                          "MSI mode is not supported for CMT devices\n");
                return ECORE_INVAL;
@@ -3490,6 +3499,37 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
            NVM_CFG1_GLOB_MF_MODE_OFFSET;
 
        switch (mf_mode) {
+       case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED:
+               p_hwfn->p_dev->mf_bits = 1 << ECORE_MF_OVLAN_CLSS;
+               break;
+       case NVM_CFG1_GLOB_MF_MODE_UFP:
+               p_hwfn->p_dev->mf_bits = 1 << ECORE_MF_OVLAN_CLSS |
+                                        1 << ECORE_MF_UFP_SPECIFIC;
+               break;
+
+       case NVM_CFG1_GLOB_MF_MODE_NPAR1_0:
+               p_hwfn->p_dev->mf_bits = 1 << ECORE_MF_LLH_MAC_CLSS |
+                                        1 << ECORE_MF_LLH_PROTO_CLSS |
+                                        1 << ECORE_MF_LL2_NON_UNICAST |
+                                        1 << ECORE_MF_INTER_PF_SWITCH;
+               break;
+       case NVM_CFG1_GLOB_MF_MODE_DEFAULT:
+               p_hwfn->p_dev->mf_bits = 1 << ECORE_MF_LLH_MAC_CLSS |
+                                        1 << ECORE_MF_LLH_PROTO_CLSS |
+                                        1 << ECORE_MF_LL2_NON_UNICAST;
+               if (ECORE_IS_BB(p_hwfn->p_dev))
+                       p_hwfn->p_dev->mf_bits |= 1 << ECORE_MF_NEED_DEF_PF;
+               break;
+       }
+       DP_INFO(p_hwfn, "Multi function mode is 0x%lx\n",
+               p_hwfn->p_dev->mf_bits);
+
+       /* It's funny since we have another switch, but it's easier
+        * to throw this away in linux this way. Long term, it might be
+        * better to have have getters for needed ECORE_MF_* fields,
+        * convert client code and eliminate this.
+        */
+       switch (mf_mode) {
        case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED:
                p_hwfn->p_dev->mf_mode = ECORE_MF_OVLAN;
                break;
@@ -3499,9 +3539,10 @@ ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
        case NVM_CFG1_GLOB_MF_MODE_DEFAULT:
                p_hwfn->p_dev->mf_mode = ECORE_MF_DEFAULT;
                break;
+       case NVM_CFG1_GLOB_MF_MODE_UFP:
+               p_hwfn->p_dev->mf_mode = ECORE_MF_UFP;
+               break;
        }
-       DP_INFO(p_hwfn, "Multi function mode is %08x\n",
-               p_hwfn->p_dev->mf_mode);
 
        /* Read Multi-function information from shmem */
        addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
@@ -3560,7 +3601,7 @@ static void ecore_get_num_funcs(struct ecore_hwfn *p_hwfn,
 
        if (reg_function_hide & 0x1) {
                if (ECORE_IS_BB(p_dev)) {
-                       if (ECORE_PATH_ID(p_hwfn) && p_dev->num_hwfns == 1) {
+                       if (ECORE_PATH_ID(p_hwfn) && !ECORE_IS_CMT(p_dev)) {
                                num_funcs = 0;
                                eng_mask = 0xaaaa;
                        } else {
@@ -3617,7 +3658,7 @@ static void ecore_hw_info_port_num_bb(struct ecore_hwfn *p_hwfn,
        /* Read the port mode */
        if (CHIP_REV_IS_FPGA(p_dev))
                port_mode = 4;
-       else if (CHIP_REV_IS_EMUL(p_dev) && p_dev->num_hwfns > 1)
+       else if (CHIP_REV_IS_EMUL(p_dev) && ECORE_IS_CMT(p_dev))
                /* In CMT on emulation, assume 1 port */
                port_mode = 1;
        else
@@ -3694,7 +3735,7 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
                ecore_hw_info_port_num_ah_e5(p_hwfn, p_ptt);
 
        /* Get the total number of ports of the device */
-       if (p_dev->num_hwfns > 1) {
+       if (ECORE_IS_CMT(p_dev)) {
                /* In CMT there is always only one port */
                p_dev->num_ports = 1;
 #ifndef ASIC_ONLY
@@ -3800,6 +3841,8 @@ ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
                ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
 
                ecore_mcp_get_eee_caps(p_hwfn, p_ptt);
+
+               ecore_mcp_read_ufp_config(p_hwfn, p_ptt);
        }
 
        if (personality != ECORE_PCI_DEFAULT) {
@@ -3960,7 +4003,6 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
                           "Mark hw/fw uninitialized\n");
 
                p_hwfn->hw_init_done = false;
-               p_hwfn->first_on_engine = false;
 
                ecore_ptt_invalidate(p_hwfn);
        }
@@ -4133,7 +4175,7 @@ enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
        p_params->personality = p_hwfn->hw_info.personality;
 
        /* initilalize 2nd hwfn if necessary */
-       if (p_dev->num_hwfns > 1) {
+       if (ECORE_IS_CMT(p_dev)) {
                void OSAL_IOMEM *p_regview, *p_doorbell;
                u8 OSAL_IOMEM *addr;
 
@@ -4597,7 +4639,8 @@ enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_hwfn *p_hwfn,
        u32 high, low, entry_num;
        enum _ecore_status_t rc;
 
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
+                          &p_hwfn->p_dev->mf_bits))
                return ECORE_SUCCESS;
 
        high = p_filter[1] | (p_filter[0] << 8);
@@ -4664,7 +4707,8 @@ void ecore_llh_remove_mac_filter(struct ecore_hwfn *p_hwfn,
        u32 high, low, entry_num;
        enum _ecore_status_t rc;
 
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
+                          &p_hwfn->p_dev->mf_bits))
                return;
 
        high = p_filter[1] | (p_filter[0] << 8);
@@ -4738,7 +4782,8 @@ ecore_llh_add_protocol_filter(struct ecore_hwfn *p_hwfn,
        u32 high, low, entry_num;
        enum _ecore_status_t rc;
 
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
+                          &p_hwfn->p_dev->mf_bits))
                return ECORE_SUCCESS;
 
        high = 0;
@@ -4881,7 +4926,8 @@ ecore_llh_remove_protocol_filter(struct ecore_hwfn *p_hwfn,
        u32 high, low, entry_num;
        enum _ecore_status_t rc;
 
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
+                          &p_hwfn->p_dev->mf_bits))
                return;
 
        high = 0;
@@ -4949,7 +4995,10 @@ static void ecore_llh_clear_all_filters_bb_ah(struct ecore_hwfn *p_hwfn,
 void ecore_llh_clear_all_filters(struct ecore_hwfn *p_hwfn,
                             struct ecore_ptt *p_ptt)
 {
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
+                          &p_hwfn->p_dev->mf_bits) &&
+           !OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
+                          &p_hwfn->p_dev->mf_bits))
                return;
 
        if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
@@ -4960,7 +5009,7 @@ enum _ecore_status_t
 ecore_llh_set_function_as_default(struct ecore_hwfn *p_hwfn,
                                  struct ecore_ptt *p_ptt)
 {
-       if (IS_MF_DEFAULT(p_hwfn) && ECORE_IS_BB(p_hwfn->p_dev)) {
+       if (OSAL_TEST_BIT(ECORE_MF_NEED_DEF_PF, &p_hwfn->p_dev->mf_bits)) {
                ecore_wr(p_hwfn, p_ptt,
                         NIG_REG_LLH_TAGMAC_DEF_PF_VECTOR,
                         1 << p_hwfn->abs_pf_id / 2);
@@ -5323,7 +5372,7 @@ int ecore_configure_vport_wfq(struct ecore_dev *p_dev, u16 vp_id, u32 rate)
        int i, rc = ECORE_INVAL;
 
        /* TBD - for multiple hardware functions - that is 100 gig */
-       if (p_dev->num_hwfns > 1) {
+       if (ECORE_IS_CMT(p_dev)) {
                DP_NOTICE(p_dev, false,
                          "WFQ configuration is not supported for this device\n");
                return rc;
@@ -5358,7 +5407,7 @@ void ecore_configure_vp_wfq_on_link_change(struct ecore_dev *p_dev,
        int i;
 
        /* TBD - for multiple hardware functions - that is 100 gig */
-       if (p_dev->num_hwfns > 1) {
+       if (ECORE_IS_CMT(p_dev)) {
                DP_VERBOSE(p_dev, ECORE_MSG_LINK,
                           "WFQ configuration is not supported for this device\n");
                return;