114b24e2bSVaishali Kulkarni /*
214b24e2bSVaishali Kulkarni * CDDL HEADER START
314b24e2bSVaishali Kulkarni *
414b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the
514b24e2bSVaishali Kulkarni * Common Development and Distribution License, v.1,  (the "License").
614b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
714b24e2bSVaishali Kulkarni *
814b24e2bSVaishali Kulkarni * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
914b24e2bSVaishali Kulkarni * or http://opensource.org/licenses/CDDL-1.0.
1014b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions
1114b24e2bSVaishali Kulkarni * and limitations under the License.
1214b24e2bSVaishali Kulkarni *
1314b24e2bSVaishali Kulkarni * When distributing Covered Code, include this CDDL HEADER in each
1414b24e2bSVaishali Kulkarni * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1514b24e2bSVaishali Kulkarni * If applicable, add the following below this CDDL HEADER, with the
1614b24e2bSVaishali Kulkarni * fields enclosed by brackets "[]" replaced with your own identifying
1714b24e2bSVaishali Kulkarni * information: Portions Copyright [yyyy] [name of copyright owner]
1814b24e2bSVaishali Kulkarni *
1914b24e2bSVaishali Kulkarni * CDDL HEADER END
2014b24e2bSVaishali Kulkarni */
2114b24e2bSVaishali Kulkarni 
2214b24e2bSVaishali Kulkarni /*
2314b24e2bSVaishali Kulkarni * Copyright 2014-2017 Cavium, Inc.
2414b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the Common Development
2514b24e2bSVaishali Kulkarni * and Distribution License, v.1,  (the "License").
2614b24e2bSVaishali Kulkarni 
2714b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
2814b24e2bSVaishali Kulkarni 
2914b24e2bSVaishali Kulkarni * You can obtain a copy of the License at available
3014b24e2bSVaishali Kulkarni * at http://opensource.org/licenses/CDDL-1.0
3114b24e2bSVaishali Kulkarni 
3214b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions and
3314b24e2bSVaishali Kulkarni * limitations under the License.
3414b24e2bSVaishali Kulkarni */
3514b24e2bSVaishali Kulkarni 
3614b24e2bSVaishali Kulkarni #include "bcm_osal.h"
3714b24e2bSVaishali Kulkarni #include "reg_addr.h"
3814b24e2bSVaishali Kulkarni #include "ecore_gtt_reg_addr.h"
3914b24e2bSVaishali Kulkarni #include "ecore.h"
4014b24e2bSVaishali Kulkarni #include "ecore_chain.h"
4114b24e2bSVaishali Kulkarni #include "ecore_status.h"
4214b24e2bSVaishali Kulkarni #include "ecore_hw.h"
4314b24e2bSVaishali Kulkarni #include "ecore_rt_defs.h"
4414b24e2bSVaishali Kulkarni #include "ecore_init_ops.h"
4514b24e2bSVaishali Kulkarni #include "ecore_int.h"
4614b24e2bSVaishali Kulkarni #include "ecore_cxt.h"
4714b24e2bSVaishali Kulkarni #include "ecore_spq.h"
4814b24e2bSVaishali Kulkarni #include "ecore_init_fw_funcs.h"
4914b24e2bSVaishali Kulkarni #include "ecore_sp_commands.h"
5014b24e2bSVaishali Kulkarni #include "ecore_dev_api.h"
5114b24e2bSVaishali Kulkarni #include "ecore_sriov.h"
5214b24e2bSVaishali Kulkarni #include "ecore_vf.h"
5314b24e2bSVaishali Kulkarni #include "ecore_ll2.h"
5414b24e2bSVaishali Kulkarni #include "ecore_fcoe.h"
5514b24e2bSVaishali Kulkarni #include "ecore_iscsi.h"
5614b24e2bSVaishali Kulkarni #include "ecore_ooo.h"
5714b24e2bSVaishali Kulkarni #include "ecore_mcp.h"
5814b24e2bSVaishali Kulkarni #include "ecore_hw_defs.h"
5914b24e2bSVaishali Kulkarni #include "mcp_public.h"
6014b24e2bSVaishali Kulkarni #include "ecore_roce.h"
6114b24e2bSVaishali Kulkarni #include "ecore_iro.h"
6214b24e2bSVaishali Kulkarni #include "nvm_cfg.h"
6314b24e2bSVaishali Kulkarni #include "ecore_dev_api.h"
6414b24e2bSVaishali Kulkarni #include "ecore_dcbx.h"
6514b24e2bSVaishali Kulkarni #include "pcics_reg_driver.h"
6614b24e2bSVaishali Kulkarni #include "ecore_l2.h"
6714b24e2bSVaishali Kulkarni 
6814b24e2bSVaishali Kulkarni /* TODO - there's a bug in DCBx re-configuration flows in MF, as the QM
6914b24e2bSVaishali Kulkarni  * registers involved are not split and thus configuration is a race where
7014b24e2bSVaishali Kulkarni  * some of the PFs configuration might be lost.
7114b24e2bSVaishali Kulkarni  * Eventually, this needs to move into a MFW-covered HW-lock as arbitration
7214b24e2bSVaishali Kulkarni  * mechanism as this doesn't cover some cases [E.g., PDA or scenarios where
7314b24e2bSVaishali Kulkarni  * there's more than a single compiled ecore component in system].
7414b24e2bSVaishali Kulkarni  */
7514b24e2bSVaishali Kulkarni static osal_spinlock_t qm_lock;
7614b24e2bSVaishali Kulkarni static bool qm_lock_init = false;
7714b24e2bSVaishali Kulkarni 
7814b24e2bSVaishali Kulkarni /* Configurable */
7914b24e2bSVaishali Kulkarni #define ECORE_MIN_DPIS		(4)  /* The minimal number of DPIs required to
8014b24e2bSVaishali Kulkarni 				      * load the driver. The number was
8114b24e2bSVaishali Kulkarni 				      * arbitrarily set.
8214b24e2bSVaishali Kulkarni 				      */
8314b24e2bSVaishali Kulkarni 
8414b24e2bSVaishali Kulkarni /* Derived */
8514b24e2bSVaishali Kulkarni #define ECORE_MIN_PWM_REGION	((ECORE_WID_SIZE) * (ECORE_MIN_DPIS))
8614b24e2bSVaishali Kulkarni 
8714b24e2bSVaishali Kulkarni enum BAR_ID {
8814b24e2bSVaishali Kulkarni 	BAR_ID_0,	/* used for GRC */
8914b24e2bSVaishali Kulkarni 	BAR_ID_1	/* Used for doorbells */
9014b24e2bSVaishali Kulkarni };
9114b24e2bSVaishali Kulkarni 
ecore_hw_bar_size(struct ecore_hwfn * p_hwfn,enum BAR_ID bar_id)9214b24e2bSVaishali Kulkarni static u32 ecore_hw_bar_size(struct ecore_hwfn *p_hwfn, enum BAR_ID bar_id)
9314b24e2bSVaishali Kulkarni {
9414b24e2bSVaishali Kulkarni 	u32 bar_reg = (bar_id == BAR_ID_0 ?
9514b24e2bSVaishali Kulkarni 		       PGLUE_B_REG_PF_BAR0_SIZE : PGLUE_B_REG_PF_BAR1_SIZE);
9614b24e2bSVaishali Kulkarni 	u32 val;
9714b24e2bSVaishali Kulkarni 
9814b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev)) {
9914b24e2bSVaishali Kulkarni 		/* TODO - assume each VF hwfn has 64Kb for Bar0; Bar1 can be
10014b24e2bSVaishali Kulkarni 		 * read from actual register, but we're currently not using
10114b24e2bSVaishali Kulkarni 		 * it for actual doorbelling.
10214b24e2bSVaishali Kulkarni 		 */
10314b24e2bSVaishali Kulkarni 		return 1 << 17;
10414b24e2bSVaishali Kulkarni 	}
10514b24e2bSVaishali Kulkarni 
10614b24e2bSVaishali Kulkarni 	val = ecore_rd(p_hwfn, p_hwfn->p_main_ptt, bar_reg);
10714b24e2bSVaishali Kulkarni 	if (val)
10814b24e2bSVaishali Kulkarni 		return 1 << (val + 15);
10914b24e2bSVaishali Kulkarni 
11014b24e2bSVaishali Kulkarni 	/* The above registers were updated in the past only in CMT mode. Since
11114b24e2bSVaishali Kulkarni 	 * they were found to be useful MFW started updating them from 8.7.7.0.
11214b24e2bSVaishali Kulkarni 	 * In older MFW versions they are set to 0 which means disabled.
11314b24e2bSVaishali Kulkarni 	 */
11414b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->num_hwfns > 1) {
11514b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
11614b24e2bSVaishali Kulkarni 			  "BAR size not configured. Assuming BAR size of 256kB for GRC and 512kB for DB\n");
11714b24e2bSVaishali Kulkarni 		return BAR_ID_0 ? 256 * 1024 : 512 * 1024;
11814b24e2bSVaishali Kulkarni 	} else {
11914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
12014b24e2bSVaishali Kulkarni 			  "BAR size not configured. Assuming BAR size of 512kB for GRC and 512kB for DB\n");
12114b24e2bSVaishali Kulkarni 		return 512 * 1024;
12214b24e2bSVaishali Kulkarni 	}
12314b24e2bSVaishali Kulkarni }
12414b24e2bSVaishali Kulkarni 
ecore_init_dp(struct ecore_dev * p_dev,u32 dp_module,u8 dp_level,void * dp_ctx)12514b24e2bSVaishali Kulkarni void ecore_init_dp(struct ecore_dev	*p_dev,
12614b24e2bSVaishali Kulkarni 		   u32			dp_module,
12714b24e2bSVaishali Kulkarni 		   u8			dp_level,
12814b24e2bSVaishali Kulkarni 		   void		 *dp_ctx)
12914b24e2bSVaishali Kulkarni {
13014b24e2bSVaishali Kulkarni 	u32 i;
13114b24e2bSVaishali Kulkarni 
13214b24e2bSVaishali Kulkarni 	p_dev->dp_level = dp_level;
13314b24e2bSVaishali Kulkarni 	p_dev->dp_module = dp_module;
13414b24e2bSVaishali Kulkarni 	p_dev->dp_ctx = dp_ctx;
13514b24e2bSVaishali Kulkarni 	for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) {
13614b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
13714b24e2bSVaishali Kulkarni 
13814b24e2bSVaishali Kulkarni 		p_hwfn->dp_level = dp_level;
13914b24e2bSVaishali Kulkarni 		p_hwfn->dp_module = dp_module;
14014b24e2bSVaishali Kulkarni 		p_hwfn->dp_ctx = dp_ctx;
14114b24e2bSVaishali Kulkarni 	}
14214b24e2bSVaishali Kulkarni }
14314b24e2bSVaishali Kulkarni 
ecore_init_struct(struct ecore_dev * p_dev)14414b24e2bSVaishali Kulkarni void ecore_init_struct(struct ecore_dev *p_dev)
14514b24e2bSVaishali Kulkarni {
14614b24e2bSVaishali Kulkarni 	u8 i;
14714b24e2bSVaishali Kulkarni 
14814b24e2bSVaishali Kulkarni 	for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) {
14914b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
15014b24e2bSVaishali Kulkarni 
15114b24e2bSVaishali Kulkarni 		p_hwfn->p_dev = p_dev;
15214b24e2bSVaishali Kulkarni 		p_hwfn->my_id = i;
15314b24e2bSVaishali Kulkarni 		p_hwfn->b_active = false;
15414b24e2bSVaishali Kulkarni 
15514b24e2bSVaishali Kulkarni 		OSAL_MUTEX_ALLOC(p_hwfn, &p_hwfn->dmae_info.mutex);
15614b24e2bSVaishali Kulkarni 		OSAL_MUTEX_INIT(&p_hwfn->dmae_info.mutex);
15714b24e2bSVaishali Kulkarni 	}
15814b24e2bSVaishali Kulkarni 
15914b24e2bSVaishali Kulkarni 	/* hwfn 0 is always active */
16014b24e2bSVaishali Kulkarni 	p_dev->hwfns[0].b_active = true;
16114b24e2bSVaishali Kulkarni 
16214b24e2bSVaishali Kulkarni 	/* set the default cache alignment to 128 (may be overridden later) */
16314b24e2bSVaishali Kulkarni 	p_dev->cache_shift = 7;
16414b24e2bSVaishali Kulkarni }
16514b24e2bSVaishali Kulkarni 
ecore_qm_info_free(struct ecore_hwfn * p_hwfn)16614b24e2bSVaishali Kulkarni static void ecore_qm_info_free(struct ecore_hwfn *p_hwfn)
16714b24e2bSVaishali Kulkarni {
16814b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
16914b24e2bSVaishali Kulkarni 
17014b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, qm_info->qm_pq_params);
17114b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params = OSAL_NULL;
17214b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, qm_info->qm_vport_params);
17314b24e2bSVaishali Kulkarni 	qm_info->qm_vport_params = OSAL_NULL;
17414b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, qm_info->qm_port_params);
17514b24e2bSVaishali Kulkarni 	qm_info->qm_port_params = OSAL_NULL;
17614b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, qm_info->wfq_data);
17714b24e2bSVaishali Kulkarni 	qm_info->wfq_data = OSAL_NULL;
17814b24e2bSVaishali Kulkarni }
17914b24e2bSVaishali Kulkarni 
ecore_resc_free(struct ecore_dev * p_dev)18014b24e2bSVaishali Kulkarni void ecore_resc_free(struct ecore_dev *p_dev)
18114b24e2bSVaishali Kulkarni {
18214b24e2bSVaishali Kulkarni 	int i;
18314b24e2bSVaishali Kulkarni 
18414b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev)) {
18514b24e2bSVaishali Kulkarni 		for_each_hwfn(p_dev, i)
18614b24e2bSVaishali Kulkarni 			ecore_l2_free(&p_dev->hwfns[i]);
18714b24e2bSVaishali Kulkarni 		return;
18814b24e2bSVaishali Kulkarni 	}
18914b24e2bSVaishali Kulkarni 
19014b24e2bSVaishali Kulkarni 	OSAL_FREE(p_dev, p_dev->fw_data);
19114b24e2bSVaishali Kulkarni 	p_dev->fw_data = OSAL_NULL;
19214b24e2bSVaishali Kulkarni 
19314b24e2bSVaishali Kulkarni 	OSAL_FREE(p_dev, p_dev->reset_stats);
19414b24e2bSVaishali Kulkarni 	p_dev->reset_stats = OSAL_NULL;
19514b24e2bSVaishali Kulkarni 
19614b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
19714b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
19814b24e2bSVaishali Kulkarni 
19914b24e2bSVaishali Kulkarni 		ecore_cxt_mngr_free(p_hwfn);
20014b24e2bSVaishali Kulkarni 		ecore_qm_info_free(p_hwfn);
20114b24e2bSVaishali Kulkarni 		ecore_spq_free(p_hwfn);
20214b24e2bSVaishali Kulkarni 		ecore_eq_free(p_hwfn);
20314b24e2bSVaishali Kulkarni 		ecore_consq_free(p_hwfn);
20414b24e2bSVaishali Kulkarni 		ecore_int_free(p_hwfn);
20514b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LL2
20614b24e2bSVaishali Kulkarni 		ecore_ll2_free(p_hwfn);
20714b24e2bSVaishali Kulkarni #endif
20814b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_FCOE
20914b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_FCOE)
21014b24e2bSVaishali Kulkarni 			ecore_fcoe_free(p_hwfn);
21114b24e2bSVaishali Kulkarni #endif
21214b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ISCSI
21314b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI) {
21414b24e2bSVaishali Kulkarni 			ecore_iscsi_free(p_hwfn);
21514b24e2bSVaishali Kulkarni 			ecore_ooo_free(p_hwfn);
21614b24e2bSVaishali Kulkarni 		}
21714b24e2bSVaishali Kulkarni #endif
21814b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
21914b24e2bSVaishali Kulkarni 		if (ECORE_IS_RDMA_PERSONALITY(p_hwfn))
22014b24e2bSVaishali Kulkarni 			ecore_rdma_info_free(p_hwfn);
22114b24e2bSVaishali Kulkarni #endif
22214b24e2bSVaishali Kulkarni 		ecore_iov_free(p_hwfn);
22314b24e2bSVaishali Kulkarni 		ecore_l2_free(p_hwfn);
22414b24e2bSVaishali Kulkarni 		ecore_dmae_info_free(p_hwfn);
22514b24e2bSVaishali Kulkarni 		ecore_dcbx_info_free(p_hwfn);
22614b24e2bSVaishali Kulkarni 		/* @@@TBD Flush work-queue ?*/
22714b24e2bSVaishali Kulkarni 	}
22814b24e2bSVaishali Kulkarni }
22914b24e2bSVaishali Kulkarni 
23014b24e2bSVaishali Kulkarni /******************** QM initialization *******************/
23114b24e2bSVaishali Kulkarni 
23214b24e2bSVaishali Kulkarni /* bitmaps for indicating active traffic classes. Special case for Arrowhead 4 port */
23314b24e2bSVaishali Kulkarni #define ACTIVE_TCS_BMAP 0x9f /* 0..3 actualy used, 4 serves OOO, 7 serves high priority stuff (e.g. DCQCN) */
23414b24e2bSVaishali Kulkarni #define ACTIVE_TCS_BMAP_4PORT_K2 0xf /* 0..3 actually used, OOO and high priority stuff all use 3 */
23514b24e2bSVaishali Kulkarni 
23614b24e2bSVaishali Kulkarni /* determines the physical queue flags for a given PF. */
ecore_get_pq_flags(struct ecore_hwfn * p_hwfn)23714b24e2bSVaishali Kulkarni static u32 ecore_get_pq_flags(struct ecore_hwfn *p_hwfn)
23814b24e2bSVaishali Kulkarni {
23914b24e2bSVaishali Kulkarni 	u32 flags;
24014b24e2bSVaishali Kulkarni 
24114b24e2bSVaishali Kulkarni 	/* common flags */
24214b24e2bSVaishali Kulkarni 	flags = PQ_FLAGS_LB;
24314b24e2bSVaishali Kulkarni 
24414b24e2bSVaishali Kulkarni 	/* feature flags */
24514b24e2bSVaishali Kulkarni 	if (IS_ECORE_SRIOV(p_hwfn->p_dev))
24614b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_VFS;
24714b24e2bSVaishali Kulkarni 	if (IS_ECORE_DCQCN(p_hwfn))
24814b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_RLS;
24914b24e2bSVaishali Kulkarni 
25014b24e2bSVaishali Kulkarni 	/* protocol flags */
25114b24e2bSVaishali Kulkarni 	switch (p_hwfn->hw_info.personality) {
25214b24e2bSVaishali Kulkarni 	case ECORE_PCI_ETH:
25314b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_MCOS;
25414b24e2bSVaishali Kulkarni 		break;
25514b24e2bSVaishali Kulkarni 	case ECORE_PCI_FCOE:
25614b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_OFLD;
25714b24e2bSVaishali Kulkarni 		break;
25814b24e2bSVaishali Kulkarni 	case ECORE_PCI_ISCSI:
25914b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_ACK | PQ_FLAGS_OOO | PQ_FLAGS_OFLD;
26014b24e2bSVaishali Kulkarni 		break;
26114b24e2bSVaishali Kulkarni 	case ECORE_PCI_ETH_ROCE:
26214b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_MCOS | PQ_FLAGS_OFLD | PQ_FLAGS_LLT;
26314b24e2bSVaishali Kulkarni 		break;
26414b24e2bSVaishali Kulkarni 	case ECORE_PCI_ETH_IWARP:
26514b24e2bSVaishali Kulkarni 		flags |= PQ_FLAGS_MCOS | PQ_FLAGS_ACK | PQ_FLAGS_OOO | PQ_FLAGS_OFLD;
26614b24e2bSVaishali Kulkarni 		break;
26714b24e2bSVaishali Kulkarni 	default:
26814b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "unknown personality %d\n", p_hwfn->hw_info.personality);
26914b24e2bSVaishali Kulkarni 		return 0;
27014b24e2bSVaishali Kulkarni 	}
27114b24e2bSVaishali Kulkarni 
27214b24e2bSVaishali Kulkarni 	return flags;
27314b24e2bSVaishali Kulkarni }
27414b24e2bSVaishali Kulkarni 
27514b24e2bSVaishali Kulkarni 
27614b24e2bSVaishali Kulkarni /* Getters for resource amounts necessary for qm initialization */
ecore_init_qm_get_num_tcs(struct ecore_hwfn * p_hwfn)27714b24e2bSVaishali Kulkarni u8 ecore_init_qm_get_num_tcs(struct ecore_hwfn *p_hwfn)
27814b24e2bSVaishali Kulkarni {
27914b24e2bSVaishali Kulkarni 	return p_hwfn->hw_info.num_hw_tc;
28014b24e2bSVaishali Kulkarni }
28114b24e2bSVaishali Kulkarni 
ecore_init_qm_get_num_vfs(struct ecore_hwfn * p_hwfn)28214b24e2bSVaishali Kulkarni u16 ecore_init_qm_get_num_vfs(struct ecore_hwfn *p_hwfn)
28314b24e2bSVaishali Kulkarni {
28414b24e2bSVaishali Kulkarni 	return IS_ECORE_SRIOV(p_hwfn->p_dev) ? p_hwfn->p_dev->p_iov_info->total_vfs : 0;
28514b24e2bSVaishali Kulkarni }
28614b24e2bSVaishali Kulkarni 
28714b24e2bSVaishali Kulkarni #define NUM_DEFAULT_RLS 1
28814b24e2bSVaishali Kulkarni 
ecore_init_qm_get_num_pf_rls(struct ecore_hwfn * p_hwfn)28914b24e2bSVaishali Kulkarni u16 ecore_init_qm_get_num_pf_rls(struct ecore_hwfn *p_hwfn)
29014b24e2bSVaishali Kulkarni {
29114b24e2bSVaishali Kulkarni 	u16 num_pf_rls, num_vfs = ecore_init_qm_get_num_vfs(p_hwfn);
29214b24e2bSVaishali Kulkarni 
29314b24e2bSVaishali Kulkarni 	/* num RLs can't exceed resource amount of rls or vports or the dcqcn qps */
29414b24e2bSVaishali Kulkarni 	num_pf_rls = (u16)OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_RL),
29514b24e2bSVaishali Kulkarni 				     (u16)OSAL_MIN_T(u32, RESC_NUM(p_hwfn, ECORE_VPORT),
29614b24e2bSVaishali Kulkarni 						     ROCE_DCQCN_RP_MAX_QPS));
29714b24e2bSVaishali Kulkarni 
29814b24e2bSVaishali Kulkarni 	/* make sure after we reserve the default and VF rls we'll have something left */
29914b24e2bSVaishali Kulkarni 	if (num_pf_rls < num_vfs + NUM_DEFAULT_RLS) {
30014b24e2bSVaishali Kulkarni 		if (IS_ECORE_DCQCN(p_hwfn))
30114b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false, "no rate limiters left for PF rate limiting [num_pf_rls %d num_vfs %d]\n", num_pf_rls, num_vfs);
30214b24e2bSVaishali Kulkarni 		return 0;
30314b24e2bSVaishali Kulkarni 	}
30414b24e2bSVaishali Kulkarni 
30514b24e2bSVaishali Kulkarni 	/* subtract rls necessary for VFs and one default one for the PF */
30614b24e2bSVaishali Kulkarni 	num_pf_rls -= num_vfs + NUM_DEFAULT_RLS;
30714b24e2bSVaishali Kulkarni 
30814b24e2bSVaishali Kulkarni 	return num_pf_rls;
30914b24e2bSVaishali Kulkarni }
31014b24e2bSVaishali Kulkarni 
ecore_init_qm_get_num_vports(struct ecore_hwfn * p_hwfn)31114b24e2bSVaishali Kulkarni u16 ecore_init_qm_get_num_vports(struct ecore_hwfn *p_hwfn)
31214b24e2bSVaishali Kulkarni {
31314b24e2bSVaishali Kulkarni 	u32 pq_flags = ecore_get_pq_flags(p_hwfn);
31414b24e2bSVaishali Kulkarni 
31514b24e2bSVaishali Kulkarni 	/* all pqs share the same vport (hence the 1 below), except for vfs and pf_rl pqs */
31614b24e2bSVaishali Kulkarni 	return (!!(PQ_FLAGS_RLS & pq_flags)) * ecore_init_qm_get_num_pf_rls(p_hwfn) +
31714b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_VFS & pq_flags)) * ecore_init_qm_get_num_vfs(p_hwfn) + 1;
31814b24e2bSVaishali Kulkarni }
31914b24e2bSVaishali Kulkarni 
32014b24e2bSVaishali Kulkarni /* calc amount of PQs according to the requested flags */
ecore_init_qm_get_num_pqs(struct ecore_hwfn * p_hwfn)32114b24e2bSVaishali Kulkarni u16 ecore_init_qm_get_num_pqs(struct ecore_hwfn *p_hwfn)
32214b24e2bSVaishali Kulkarni {
32314b24e2bSVaishali Kulkarni 	u32 pq_flags = ecore_get_pq_flags(p_hwfn);
32414b24e2bSVaishali Kulkarni 
32514b24e2bSVaishali Kulkarni 	return (!!(PQ_FLAGS_RLS & pq_flags)) * ecore_init_qm_get_num_pf_rls(p_hwfn) +
32614b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_MCOS & pq_flags)) * ecore_init_qm_get_num_tcs(p_hwfn) +
32714b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_LB & pq_flags)) +
32814b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_OOO & pq_flags)) +
32914b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_ACK & pq_flags)) +
33014b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_OFLD & pq_flags)) +
33114b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_LLT & pq_flags)) +
33214b24e2bSVaishali Kulkarni 	       (!!(PQ_FLAGS_VFS & pq_flags)) * ecore_init_qm_get_num_vfs(p_hwfn);
33314b24e2bSVaishali Kulkarni }
33414b24e2bSVaishali Kulkarni 
33514b24e2bSVaishali Kulkarni /* initialize the top level QM params */
ecore_init_qm_params(struct ecore_hwfn * p_hwfn)33614b24e2bSVaishali Kulkarni static void ecore_init_qm_params(struct ecore_hwfn *p_hwfn)
33714b24e2bSVaishali Kulkarni {
33814b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
33914b24e2bSVaishali Kulkarni 	bool four_port;
34014b24e2bSVaishali Kulkarni 
34114b24e2bSVaishali Kulkarni 	/* pq and vport bases for this PF */
34214b24e2bSVaishali Kulkarni 	qm_info->start_pq = (u16)RESC_START(p_hwfn, ECORE_PQ);
34314b24e2bSVaishali Kulkarni 	qm_info->start_vport = (u8)RESC_START(p_hwfn, ECORE_VPORT);
34414b24e2bSVaishali Kulkarni 
34514b24e2bSVaishali Kulkarni 	/* rate limiting and weighted fair queueing are always enabled */
34614b24e2bSVaishali Kulkarni 	qm_info->vport_rl_en = 1;
34714b24e2bSVaishali Kulkarni 	qm_info->vport_wfq_en = 1;
34814b24e2bSVaishali Kulkarni 
34914b24e2bSVaishali Kulkarni 	/* TC config is different for AH 4 port */
35014b24e2bSVaishali Kulkarni 	four_port = p_hwfn->p_dev->num_ports_in_engine == MAX_NUM_PORTS_K2;
35114b24e2bSVaishali Kulkarni 
35214b24e2bSVaishali Kulkarni 	/* in AH 4 port we have fewer TCs per port */
35314b24e2bSVaishali Kulkarni 	qm_info->max_phys_tcs_per_port = four_port ? NUM_PHYS_TCS_4PORT_K2 : NUM_OF_PHYS_TCS;
35414b24e2bSVaishali Kulkarni 
35514b24e2bSVaishali Kulkarni 	/* unless MFW indicated otherwise, ooo_tc should be 3 for AH 4 port and 4 otherwise */
35614b24e2bSVaishali Kulkarni 	if (!qm_info->ooo_tc)
35714b24e2bSVaishali Kulkarni 		qm_info->ooo_tc = four_port ? DCBX_TCP_OOO_K2_4PORT_TC : DCBX_TCP_OOO_TC;
35814b24e2bSVaishali Kulkarni }
35914b24e2bSVaishali Kulkarni 
36014b24e2bSVaishali Kulkarni /* initialize qm vport params */
ecore_init_qm_vport_params(struct ecore_hwfn * p_hwfn)36114b24e2bSVaishali Kulkarni static void ecore_init_qm_vport_params(struct ecore_hwfn *p_hwfn)
36214b24e2bSVaishali Kulkarni {
36314b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
36414b24e2bSVaishali Kulkarni 	u8 i;
36514b24e2bSVaishali Kulkarni 
36614b24e2bSVaishali Kulkarni 	/* all vports participate in weighted fair queueing */
36714b24e2bSVaishali Kulkarni 	for (i = 0; i < ecore_init_qm_get_num_vports(p_hwfn); i++)
36814b24e2bSVaishali Kulkarni 		qm_info->qm_vport_params[i].vport_wfq = 1;
36914b24e2bSVaishali Kulkarni }
37014b24e2bSVaishali Kulkarni 
37114b24e2bSVaishali Kulkarni /* initialize qm port params */
ecore_init_qm_port_params(struct ecore_hwfn * p_hwfn)37214b24e2bSVaishali Kulkarni static void ecore_init_qm_port_params(struct ecore_hwfn *p_hwfn)
37314b24e2bSVaishali Kulkarni {
37414b24e2bSVaishali Kulkarni 	/* Initialize qm port parameters */
37514b24e2bSVaishali Kulkarni 	u8 i, active_phys_tcs, num_ports = p_hwfn->p_dev->num_ports_in_engine;
37614b24e2bSVaishali Kulkarni 
37714b24e2bSVaishali Kulkarni 	/* indicate how ooo and high pri traffic is dealt with */
37814b24e2bSVaishali Kulkarni 	active_phys_tcs = num_ports == MAX_NUM_PORTS_K2 ?
37914b24e2bSVaishali Kulkarni 		ACTIVE_TCS_BMAP_4PORT_K2 : ACTIVE_TCS_BMAP;
38014b24e2bSVaishali Kulkarni 
38114b24e2bSVaishali Kulkarni 	for (i = 0; i < num_ports; i++) {
38214b24e2bSVaishali Kulkarni 		struct init_qm_port_params *p_qm_port =
38314b24e2bSVaishali Kulkarni 			&p_hwfn->qm_info.qm_port_params[i];
38414b24e2bSVaishali Kulkarni 
38514b24e2bSVaishali Kulkarni 		p_qm_port->active = 1;
38614b24e2bSVaishali Kulkarni 		p_qm_port->active_phys_tcs = active_phys_tcs;
38714b24e2bSVaishali Kulkarni 		p_qm_port->num_pbf_cmd_lines = PBF_MAX_CMD_LINES / num_ports;
38814b24e2bSVaishali Kulkarni 		p_qm_port->num_btb_blocks = BTB_MAX_BLOCKS / num_ports;
38914b24e2bSVaishali Kulkarni 	}
39014b24e2bSVaishali Kulkarni }
39114b24e2bSVaishali Kulkarni 
39214b24e2bSVaishali Kulkarni /* Reset the params which must be reset for qm init. QM init may be called as
39314b24e2bSVaishali Kulkarni  * a result of flows other than driver load (e.g. dcbx renegotiation). Other
39414b24e2bSVaishali Kulkarni  * params may be affected by the init but would simply recalculate to the same
39514b24e2bSVaishali Kulkarni  * values. The allocations made for QM init, ports, vports, pqs and vfqs are not
39614b24e2bSVaishali Kulkarni  * affected as these amounts stay the same.
39714b24e2bSVaishali Kulkarni  */
ecore_init_qm_reset_params(struct ecore_hwfn * p_hwfn)39814b24e2bSVaishali Kulkarni static void ecore_init_qm_reset_params(struct ecore_hwfn *p_hwfn)
39914b24e2bSVaishali Kulkarni {
40014b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
40114b24e2bSVaishali Kulkarni 
40214b24e2bSVaishali Kulkarni 	qm_info->num_pqs = 0;
40314b24e2bSVaishali Kulkarni 	qm_info->num_vports = 0;
40414b24e2bSVaishali Kulkarni 	qm_info->num_pf_rls = 0;
40514b24e2bSVaishali Kulkarni 	qm_info->num_vf_pqs = 0;
40614b24e2bSVaishali Kulkarni 	qm_info->first_vf_pq = 0;
40714b24e2bSVaishali Kulkarni 	qm_info->first_mcos_pq = 0;
40814b24e2bSVaishali Kulkarni 	qm_info->first_rl_pq = 0;
40914b24e2bSVaishali Kulkarni }
41014b24e2bSVaishali Kulkarni 
ecore_init_qm_advance_vport(struct ecore_hwfn * p_hwfn)41114b24e2bSVaishali Kulkarni static void ecore_init_qm_advance_vport(struct ecore_hwfn *p_hwfn)
41214b24e2bSVaishali Kulkarni {
41314b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
41414b24e2bSVaishali Kulkarni 
41514b24e2bSVaishali Kulkarni 	qm_info->num_vports++;
41614b24e2bSVaishali Kulkarni 
41714b24e2bSVaishali Kulkarni 	if (qm_info->num_vports > ecore_init_qm_get_num_vports(p_hwfn))
41814b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "vport overflow! qm_info->num_vports %d, qm_init_get_num_vports() %d\n", qm_info->num_vports, ecore_init_qm_get_num_vports(p_hwfn));
41914b24e2bSVaishali Kulkarni }
42014b24e2bSVaishali Kulkarni 
42114b24e2bSVaishali Kulkarni /* initialize a single pq and manage qm_info resources accounting.
42214b24e2bSVaishali Kulkarni  * The pq_init_flags param determines whether the PQ is rate limited (for VF or PF)
42314b24e2bSVaishali Kulkarni  * and whether a new vport is allocated to the pq or not (i.e. vport will be shared)
42414b24e2bSVaishali Kulkarni  */
42514b24e2bSVaishali Kulkarni 
42614b24e2bSVaishali Kulkarni /* flags for pq init */
42714b24e2bSVaishali Kulkarni #define PQ_INIT_SHARE_VPORT	(1 << 0)
42814b24e2bSVaishali Kulkarni #define PQ_INIT_PF_RL		(1 << 1)
42914b24e2bSVaishali Kulkarni #define PQ_INIT_VF_RL		(1 << 2)
43014b24e2bSVaishali Kulkarni 
43114b24e2bSVaishali Kulkarni /* defines for pq init */
43214b24e2bSVaishali Kulkarni #define PQ_INIT_DEFAULT_WRR_GROUP	1
43314b24e2bSVaishali Kulkarni #define PQ_INIT_DEFAULT_TC		0
43414b24e2bSVaishali Kulkarni #define PQ_INIT_OFLD_TC			(p_hwfn->hw_info.offload_tc)
43514b24e2bSVaishali Kulkarni 
ecore_init_qm_pq(struct ecore_hwfn * p_hwfn,struct ecore_qm_info * qm_info,u8 tc,u32 pq_init_flags)43614b24e2bSVaishali Kulkarni static void ecore_init_qm_pq(struct ecore_hwfn *p_hwfn,
43714b24e2bSVaishali Kulkarni 			     struct ecore_qm_info *qm_info,
43814b24e2bSVaishali Kulkarni 			     u8 tc, u32 pq_init_flags)
43914b24e2bSVaishali Kulkarni {
44014b24e2bSVaishali Kulkarni 	u16 pq_idx = qm_info->num_pqs, max_pq = ecore_init_qm_get_num_pqs(p_hwfn);
44114b24e2bSVaishali Kulkarni 
44214b24e2bSVaishali Kulkarni 	if (pq_idx > max_pq)
44314b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "pq overflow! pq %d, max pq %d\n", pq_idx, max_pq);
44414b24e2bSVaishali Kulkarni 
44514b24e2bSVaishali Kulkarni 	/* init pq params */
44614b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params[pq_idx].vport_id = qm_info->start_vport + qm_info->num_vports;
44714b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params[pq_idx].tc_id = tc;
44814b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params[pq_idx].wrr_group = PQ_INIT_DEFAULT_WRR_GROUP;
44914b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params[pq_idx].rl_valid =
45014b24e2bSVaishali Kulkarni 		(pq_init_flags & PQ_INIT_PF_RL || pq_init_flags & PQ_INIT_VF_RL);
45114b24e2bSVaishali Kulkarni 
45214b24e2bSVaishali Kulkarni 	/* qm params accounting */
45314b24e2bSVaishali Kulkarni 	qm_info->num_pqs++;
45414b24e2bSVaishali Kulkarni 	if (!(pq_init_flags & PQ_INIT_SHARE_VPORT))
45514b24e2bSVaishali Kulkarni 		qm_info->num_vports++;
45614b24e2bSVaishali Kulkarni 
45714b24e2bSVaishali Kulkarni 	if (pq_init_flags & PQ_INIT_PF_RL)
45814b24e2bSVaishali Kulkarni 		qm_info->num_pf_rls++;
45914b24e2bSVaishali Kulkarni 
46014b24e2bSVaishali Kulkarni 	if (qm_info->num_vports > ecore_init_qm_get_num_vports(p_hwfn))
46114b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "vport overflow! qm_info->num_vports %d, qm_init_get_num_vports() %d\n", qm_info->num_vports, ecore_init_qm_get_num_vports(p_hwfn));
46214b24e2bSVaishali Kulkarni 
46314b24e2bSVaishali Kulkarni 	if (qm_info->num_pf_rls > ecore_init_qm_get_num_pf_rls(p_hwfn))
46414b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "rl overflow! qm_info->num_pf_rls %d, qm_init_get_num_pf_rls() %d\n", qm_info->num_pf_rls, ecore_init_qm_get_num_pf_rls(p_hwfn));
46514b24e2bSVaishali Kulkarni }
46614b24e2bSVaishali Kulkarni 
46714b24e2bSVaishali Kulkarni /* get pq index according to PQ_FLAGS */
ecore_init_qm_get_idx_from_flags(struct ecore_hwfn * p_hwfn,u32 pq_flags)46814b24e2bSVaishali Kulkarni static u16 *ecore_init_qm_get_idx_from_flags(struct ecore_hwfn *p_hwfn,
46914b24e2bSVaishali Kulkarni 					     u32 pq_flags)
47014b24e2bSVaishali Kulkarni {
47114b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
47214b24e2bSVaishali Kulkarni 
47314b24e2bSVaishali Kulkarni 	/* Can't have multiple flags set here */
47414b24e2bSVaishali Kulkarni 	if (OSAL_BITMAP_WEIGHT((unsigned long *)&pq_flags, sizeof(pq_flags)) > 1)
47514b24e2bSVaishali Kulkarni 		goto err;
47614b24e2bSVaishali Kulkarni 
47714b24e2bSVaishali Kulkarni 	switch (pq_flags) {
47814b24e2bSVaishali Kulkarni 	case PQ_FLAGS_RLS:
47914b24e2bSVaishali Kulkarni 		return &qm_info->first_rl_pq;
48014b24e2bSVaishali Kulkarni 	case PQ_FLAGS_MCOS:
48114b24e2bSVaishali Kulkarni 		return &qm_info->first_mcos_pq;
48214b24e2bSVaishali Kulkarni 	case PQ_FLAGS_LB:
48314b24e2bSVaishali Kulkarni 		return &qm_info->pure_lb_pq;
48414b24e2bSVaishali Kulkarni 	case PQ_FLAGS_OOO:
48514b24e2bSVaishali Kulkarni 		return &qm_info->ooo_pq;
48614b24e2bSVaishali Kulkarni 	case PQ_FLAGS_ACK:
48714b24e2bSVaishali Kulkarni 		return &qm_info->pure_ack_pq;
48814b24e2bSVaishali Kulkarni 	case PQ_FLAGS_OFLD:
48914b24e2bSVaishali Kulkarni 		return &qm_info->offload_pq;
49014b24e2bSVaishali Kulkarni 	case PQ_FLAGS_LLT:
49114b24e2bSVaishali Kulkarni 		return &qm_info->low_latency_pq;
49214b24e2bSVaishali Kulkarni 	case PQ_FLAGS_VFS:
49314b24e2bSVaishali Kulkarni 		return &qm_info->first_vf_pq;
49414b24e2bSVaishali Kulkarni 	default:
49514b24e2bSVaishali Kulkarni 		goto err;
49614b24e2bSVaishali Kulkarni 	}
49714b24e2bSVaishali Kulkarni 
49814b24e2bSVaishali Kulkarni err:
49914b24e2bSVaishali Kulkarni 	DP_ERR(p_hwfn, "BAD pq flags %d\n", pq_flags);
50014b24e2bSVaishali Kulkarni 	return OSAL_NULL;
50114b24e2bSVaishali Kulkarni }
50214b24e2bSVaishali Kulkarni 
50314b24e2bSVaishali Kulkarni /* save pq index in qm info */
ecore_init_qm_set_idx(struct ecore_hwfn * p_hwfn,u32 pq_flags,u16 pq_val)50414b24e2bSVaishali Kulkarni static void ecore_init_qm_set_idx(struct ecore_hwfn *p_hwfn,
50514b24e2bSVaishali Kulkarni 				  u32 pq_flags, u16 pq_val)
50614b24e2bSVaishali Kulkarni {
50714b24e2bSVaishali Kulkarni 	u16 *base_pq_idx = ecore_init_qm_get_idx_from_flags(p_hwfn, pq_flags);
50814b24e2bSVaishali Kulkarni 
50914b24e2bSVaishali Kulkarni 	*base_pq_idx = p_hwfn->qm_info.start_pq + pq_val;
51014b24e2bSVaishali Kulkarni }
51114b24e2bSVaishali Kulkarni 
51214b24e2bSVaishali Kulkarni /* get tx pq index, with the PQ TX base already set (ready for context init) */
ecore_get_cm_pq_idx(struct ecore_hwfn * p_hwfn,u32 pq_flags)51314b24e2bSVaishali Kulkarni u16 ecore_get_cm_pq_idx(struct ecore_hwfn *p_hwfn, u32 pq_flags)
51414b24e2bSVaishali Kulkarni {
51514b24e2bSVaishali Kulkarni 	u16 *base_pq_idx = ecore_init_qm_get_idx_from_flags(p_hwfn, pq_flags);
51614b24e2bSVaishali Kulkarni 
51714b24e2bSVaishali Kulkarni 	return *base_pq_idx + CM_TX_PQ_BASE;
51814b24e2bSVaishali Kulkarni }
51914b24e2bSVaishali Kulkarni 
ecore_get_cm_pq_idx_mcos(struct ecore_hwfn * p_hwfn,u8 tc)52014b24e2bSVaishali Kulkarni u16 ecore_get_cm_pq_idx_mcos(struct ecore_hwfn *p_hwfn, u8 tc)
52114b24e2bSVaishali Kulkarni {
52214b24e2bSVaishali Kulkarni 	u8 max_tc = ecore_init_qm_get_num_tcs(p_hwfn);
52314b24e2bSVaishali Kulkarni 
52414b24e2bSVaishali Kulkarni 	if (tc > max_tc)
52514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "tc %d must be smaller than %d\n", tc, max_tc);
52614b24e2bSVaishali Kulkarni 
52714b24e2bSVaishali Kulkarni 	return ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_MCOS) + tc;
52814b24e2bSVaishali Kulkarni }
52914b24e2bSVaishali Kulkarni 
ecore_get_cm_pq_idx_vf(struct ecore_hwfn * p_hwfn,u16 vf)53014b24e2bSVaishali Kulkarni u16 ecore_get_cm_pq_idx_vf(struct ecore_hwfn *p_hwfn, u16 vf)
53114b24e2bSVaishali Kulkarni {
53214b24e2bSVaishali Kulkarni 	u16 max_vf = ecore_init_qm_get_num_vfs(p_hwfn);
53314b24e2bSVaishali Kulkarni 
53414b24e2bSVaishali Kulkarni 	if (vf > max_vf)
53514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "vf %d must be smaller than %d\n", vf, max_vf);
53614b24e2bSVaishali Kulkarni 
53714b24e2bSVaishali Kulkarni 	return ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + vf;
53814b24e2bSVaishali Kulkarni }
53914b24e2bSVaishali Kulkarni 
ecore_get_cm_pq_idx_rl(struct ecore_hwfn * p_hwfn,u8 rl)54014b24e2bSVaishali Kulkarni u16 ecore_get_cm_pq_idx_rl(struct ecore_hwfn *p_hwfn, u8 rl)
54114b24e2bSVaishali Kulkarni {
54214b24e2bSVaishali Kulkarni 	u16 max_rl = ecore_init_qm_get_num_pf_rls(p_hwfn);
54314b24e2bSVaishali Kulkarni 
54414b24e2bSVaishali Kulkarni 	if (rl > max_rl)
54514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "rl %d must be smaller than %d\n", rl, max_rl);
54614b24e2bSVaishali Kulkarni 
54714b24e2bSVaishali Kulkarni 	return ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_RLS) + rl;
54814b24e2bSVaishali Kulkarni }
54914b24e2bSVaishali Kulkarni 
55014b24e2bSVaishali Kulkarni /* Functions for creating specific types of pqs */
ecore_init_qm_lb_pq(struct ecore_hwfn * p_hwfn)55114b24e2bSVaishali Kulkarni static void ecore_init_qm_lb_pq(struct ecore_hwfn *p_hwfn)
55214b24e2bSVaishali Kulkarni {
55314b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
55414b24e2bSVaishali Kulkarni 
55514b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_LB))
55614b24e2bSVaishali Kulkarni 		return;
55714b24e2bSVaishali Kulkarni 
55814b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_LB, qm_info->num_pqs);
55914b24e2bSVaishali Kulkarni 	ecore_init_qm_pq(p_hwfn, qm_info, PURE_LB_TC, PQ_INIT_SHARE_VPORT);
56014b24e2bSVaishali Kulkarni }
56114b24e2bSVaishali Kulkarni 
ecore_init_qm_ooo_pq(struct ecore_hwfn * p_hwfn)56214b24e2bSVaishali Kulkarni static void ecore_init_qm_ooo_pq(struct ecore_hwfn *p_hwfn)
56314b24e2bSVaishali Kulkarni {
56414b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
56514b24e2bSVaishali Kulkarni 
56614b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_OOO))
56714b24e2bSVaishali Kulkarni 		return;
56814b24e2bSVaishali Kulkarni 
56914b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_OOO, qm_info->num_pqs);
57014b24e2bSVaishali Kulkarni 	ecore_init_qm_pq(p_hwfn, qm_info, qm_info->ooo_tc, PQ_INIT_SHARE_VPORT);
57114b24e2bSVaishali Kulkarni }
57214b24e2bSVaishali Kulkarni 
ecore_init_qm_pure_ack_pq(struct ecore_hwfn * p_hwfn)57314b24e2bSVaishali Kulkarni static void ecore_init_qm_pure_ack_pq(struct ecore_hwfn *p_hwfn)
57414b24e2bSVaishali Kulkarni {
57514b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
57614b24e2bSVaishali Kulkarni 
57714b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_ACK))
57814b24e2bSVaishali Kulkarni 		return;
57914b24e2bSVaishali Kulkarni 
58014b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_ACK, qm_info->num_pqs);
58114b24e2bSVaishali Kulkarni 	ecore_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
58214b24e2bSVaishali Kulkarni }
58314b24e2bSVaishali Kulkarni 
ecore_init_qm_offload_pq(struct ecore_hwfn * p_hwfn)58414b24e2bSVaishali Kulkarni static void ecore_init_qm_offload_pq(struct ecore_hwfn *p_hwfn)
58514b24e2bSVaishali Kulkarni {
58614b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
58714b24e2bSVaishali Kulkarni 
58814b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_OFLD))
58914b24e2bSVaishali Kulkarni 		return;
59014b24e2bSVaishali Kulkarni 
59114b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_OFLD, qm_info->num_pqs);
59214b24e2bSVaishali Kulkarni 	ecore_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
59314b24e2bSVaishali Kulkarni }
59414b24e2bSVaishali Kulkarni 
ecore_init_qm_low_latency_pq(struct ecore_hwfn * p_hwfn)59514b24e2bSVaishali Kulkarni static void ecore_init_qm_low_latency_pq(struct ecore_hwfn *p_hwfn)
59614b24e2bSVaishali Kulkarni {
59714b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
59814b24e2bSVaishali Kulkarni 
59914b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_LLT))
60014b24e2bSVaishali Kulkarni 		return;
60114b24e2bSVaishali Kulkarni 
60214b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_LLT, qm_info->num_pqs);
60314b24e2bSVaishali Kulkarni 	ecore_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
60414b24e2bSVaishali Kulkarni }
60514b24e2bSVaishali Kulkarni 
ecore_init_qm_mcos_pqs(struct ecore_hwfn * p_hwfn)60614b24e2bSVaishali Kulkarni static void ecore_init_qm_mcos_pqs(struct ecore_hwfn *p_hwfn)
60714b24e2bSVaishali Kulkarni {
60814b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
60914b24e2bSVaishali Kulkarni 	u8 tc_idx;
61014b24e2bSVaishali Kulkarni 
61114b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_MCOS))
61214b24e2bSVaishali Kulkarni 		return;
61314b24e2bSVaishali Kulkarni 
61414b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_MCOS, qm_info->num_pqs);
61514b24e2bSVaishali Kulkarni 	for (tc_idx = 0; tc_idx < ecore_init_qm_get_num_tcs(p_hwfn); tc_idx++)
61614b24e2bSVaishali Kulkarni 		ecore_init_qm_pq(p_hwfn, qm_info, tc_idx, PQ_INIT_SHARE_VPORT);
61714b24e2bSVaishali Kulkarni }
61814b24e2bSVaishali Kulkarni 
ecore_init_qm_vf_pqs(struct ecore_hwfn * p_hwfn)61914b24e2bSVaishali Kulkarni static void ecore_init_qm_vf_pqs(struct ecore_hwfn *p_hwfn)
62014b24e2bSVaishali Kulkarni {
62114b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
62214b24e2bSVaishali Kulkarni 	u16 vf_idx, num_vfs = ecore_init_qm_get_num_vfs(p_hwfn);
62314b24e2bSVaishali Kulkarni 
62414b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_VFS))
62514b24e2bSVaishali Kulkarni 		return;
62614b24e2bSVaishali Kulkarni 
62714b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_VFS, qm_info->num_pqs);
62814b24e2bSVaishali Kulkarni 	qm_info->num_vf_pqs = num_vfs;
62914b24e2bSVaishali Kulkarni 	for (vf_idx = 0; vf_idx < num_vfs; vf_idx++)
63014b24e2bSVaishali Kulkarni 		ecore_init_qm_pq(p_hwfn, qm_info, PQ_INIT_DEFAULT_TC, PQ_INIT_VF_RL);
63114b24e2bSVaishali Kulkarni }
63214b24e2bSVaishali Kulkarni 
ecore_init_qm_rl_pqs(struct ecore_hwfn * p_hwfn)63314b24e2bSVaishali Kulkarni static void ecore_init_qm_rl_pqs(struct ecore_hwfn *p_hwfn)
63414b24e2bSVaishali Kulkarni {
63514b24e2bSVaishali Kulkarni 	u16 pf_rls_idx, num_pf_rls = ecore_init_qm_get_num_pf_rls(p_hwfn);
63614b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
63714b24e2bSVaishali Kulkarni 
63814b24e2bSVaishali Kulkarni 	if (!(ecore_get_pq_flags(p_hwfn) & PQ_FLAGS_RLS))
63914b24e2bSVaishali Kulkarni 		return;
64014b24e2bSVaishali Kulkarni 
64114b24e2bSVaishali Kulkarni 	ecore_init_qm_set_idx(p_hwfn, PQ_FLAGS_RLS, qm_info->num_pqs);
64214b24e2bSVaishali Kulkarni 	for (pf_rls_idx = 0; pf_rls_idx < num_pf_rls; pf_rls_idx++)
64314b24e2bSVaishali Kulkarni 		ecore_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_PF_RL);
64414b24e2bSVaishali Kulkarni }
64514b24e2bSVaishali Kulkarni 
ecore_init_qm_pq_params(struct ecore_hwfn * p_hwfn)64614b24e2bSVaishali Kulkarni static void ecore_init_qm_pq_params(struct ecore_hwfn *p_hwfn)
64714b24e2bSVaishali Kulkarni {
64814b24e2bSVaishali Kulkarni 	/* rate limited pqs, must come first (FW assumption) */
64914b24e2bSVaishali Kulkarni 	ecore_init_qm_rl_pqs(p_hwfn);
65014b24e2bSVaishali Kulkarni 
65114b24e2bSVaishali Kulkarni 	/* pqs for multi cos */
65214b24e2bSVaishali Kulkarni 	ecore_init_qm_mcos_pqs(p_hwfn);
65314b24e2bSVaishali Kulkarni 
65414b24e2bSVaishali Kulkarni 	/* pure loopback pq */
65514b24e2bSVaishali Kulkarni 	ecore_init_qm_lb_pq(p_hwfn);
65614b24e2bSVaishali Kulkarni 
65714b24e2bSVaishali Kulkarni 	/* out of order pq */
65814b24e2bSVaishali Kulkarni 	ecore_init_qm_ooo_pq(p_hwfn);
65914b24e2bSVaishali Kulkarni 
66014b24e2bSVaishali Kulkarni 	/* pure ack pq */
66114b24e2bSVaishali Kulkarni 	ecore_init_qm_pure_ack_pq(p_hwfn);
66214b24e2bSVaishali Kulkarni 
66314b24e2bSVaishali Kulkarni 	/* pq for offloaded protocol */
66414b24e2bSVaishali Kulkarni 	ecore_init_qm_offload_pq(p_hwfn);
66514b24e2bSVaishali Kulkarni 
66614b24e2bSVaishali Kulkarni 	/* low latency pq */
66714b24e2bSVaishali Kulkarni 	ecore_init_qm_low_latency_pq(p_hwfn);
66814b24e2bSVaishali Kulkarni 
66914b24e2bSVaishali Kulkarni 	/* done sharing vports */
67014b24e2bSVaishali Kulkarni 	ecore_init_qm_advance_vport(p_hwfn);
67114b24e2bSVaishali Kulkarni 
67214b24e2bSVaishali Kulkarni 	/* pqs for vfs */
67314b24e2bSVaishali Kulkarni 	ecore_init_qm_vf_pqs(p_hwfn);
67414b24e2bSVaishali Kulkarni }
67514b24e2bSVaishali Kulkarni 
67614b24e2bSVaishali Kulkarni /* compare values of getters against resources amounts */
ecore_init_qm_sanity(struct ecore_hwfn * p_hwfn)67714b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_init_qm_sanity(struct ecore_hwfn *p_hwfn)
67814b24e2bSVaishali Kulkarni {
67914b24e2bSVaishali Kulkarni 	if (ecore_init_qm_get_num_vports(p_hwfn) > RESC_NUM(p_hwfn, ECORE_VPORT)) {
68014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "requested amount of vports exceeds resource\n");
68114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
68214b24e2bSVaishali Kulkarni 	}
68314b24e2bSVaishali Kulkarni 
68414b24e2bSVaishali Kulkarni 	if (ecore_init_qm_get_num_pqs(p_hwfn) > RESC_NUM(p_hwfn, ECORE_PQ)) {
68514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "requested amount of pqs exceeds resource\n");
68614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
68714b24e2bSVaishali Kulkarni 	}
68814b24e2bSVaishali Kulkarni 
68914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
69014b24e2bSVaishali Kulkarni }
69114b24e2bSVaishali Kulkarni 
69214b24e2bSVaishali Kulkarni /*
69314b24e2bSVaishali Kulkarni  * Function for verbose printing of the qm initialization results
69414b24e2bSVaishali Kulkarni  */
ecore_dp_init_qm_params(struct ecore_hwfn * p_hwfn)69514b24e2bSVaishali Kulkarni static void ecore_dp_init_qm_params(struct ecore_hwfn *p_hwfn)
69614b24e2bSVaishali Kulkarni {
69714b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
69814b24e2bSVaishali Kulkarni 	struct init_qm_vport_params *vport;
69914b24e2bSVaishali Kulkarni 	struct init_qm_port_params *port;
70014b24e2bSVaishali Kulkarni 	struct init_qm_pq_params *pq;
70114b24e2bSVaishali Kulkarni 	int i, tc;
70214b24e2bSVaishali Kulkarni 
70314b24e2bSVaishali Kulkarni 	/* top level params */
70414b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "qm init top level params: start_pq %d, start_vport %d, pure_lb_pq %d, offload_pq %d, pure_ack_pq %d\n",
70514b24e2bSVaishali Kulkarni 		   qm_info->start_pq, qm_info->start_vport, qm_info->pure_lb_pq, qm_info->offload_pq, qm_info->pure_ack_pq);
70614b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "ooo_pq %d, first_vf_pq %d, num_pqs %d, num_vf_pqs %d, num_vports %d, max_phys_tcs_per_port %d\n",
70714b24e2bSVaishali Kulkarni 		   qm_info->ooo_pq, qm_info->first_vf_pq, qm_info->num_pqs, qm_info->num_vf_pqs, qm_info->num_vports, qm_info->max_phys_tcs_per_port);
70814b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "pf_rl_en %d, pf_wfq_en %d, vport_rl_en %d, vport_wfq_en %d, pf_wfq %d, pf_rl %d, num_pf_rls %d, pq_flags %x\n",
70914b24e2bSVaishali Kulkarni 		   qm_info->pf_rl_en, qm_info->pf_wfq_en, qm_info->vport_rl_en, qm_info->vport_wfq_en, qm_info->pf_wfq, qm_info->pf_rl, qm_info->num_pf_rls, ecore_get_pq_flags(p_hwfn));
71014b24e2bSVaishali Kulkarni 
71114b24e2bSVaishali Kulkarni 	/* port table */
71214b24e2bSVaishali Kulkarni 	for (i = 0; i < p_hwfn->p_dev->num_ports_in_engine; i++) {
71314b24e2bSVaishali Kulkarni 		port = &(qm_info->qm_port_params[i]);
71414b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "port idx %d, active %d, active_phys_tcs %d, num_pbf_cmd_lines %d, num_btb_blocks %d, reserved %d\n",
71514b24e2bSVaishali Kulkarni 			   i, port->active, port->active_phys_tcs, port->num_pbf_cmd_lines, port->num_btb_blocks, port->reserved);
71614b24e2bSVaishali Kulkarni 	}
71714b24e2bSVaishali Kulkarni 
71814b24e2bSVaishali Kulkarni 	/* vport table */
71914b24e2bSVaishali Kulkarni 	for (i = 0; i < qm_info->num_vports; i++) {
72014b24e2bSVaishali Kulkarni 		vport = &(qm_info->qm_vport_params[i]);
72114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "vport idx %d, vport_rl %d, wfq %d, first_tx_pq_id [ ",
72214b24e2bSVaishali Kulkarni 			   qm_info->start_vport + i, vport->vport_rl, vport->vport_wfq);
72314b24e2bSVaishali Kulkarni 		for (tc = 0; tc < NUM_OF_TCS; tc++)
72414b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "%d ", vport->first_tx_pq_id[tc]);
72514b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "]\n");
72614b24e2bSVaishali Kulkarni 	}
72714b24e2bSVaishali Kulkarni 
72814b24e2bSVaishali Kulkarni 	/* pq table */
72914b24e2bSVaishali Kulkarni 	for (i = 0; i < qm_info->num_pqs; i++) {
73014b24e2bSVaishali Kulkarni 		pq = &(qm_info->qm_pq_params[i]);
73114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "pq idx %d, vport_id %d, tc %d, wrr_grp %d, rl_valid %d\n",
73214b24e2bSVaishali Kulkarni 			   qm_info->start_pq + i, pq->vport_id, pq->tc_id, pq->wrr_group, pq->rl_valid);
73314b24e2bSVaishali Kulkarni 	}
73414b24e2bSVaishali Kulkarni }
73514b24e2bSVaishali Kulkarni 
ecore_init_qm_info(struct ecore_hwfn * p_hwfn)73614b24e2bSVaishali Kulkarni static void ecore_init_qm_info(struct ecore_hwfn *p_hwfn)
73714b24e2bSVaishali Kulkarni {
73814b24e2bSVaishali Kulkarni 	/* reset params required for init run */
73914b24e2bSVaishali Kulkarni 	ecore_init_qm_reset_params(p_hwfn);
74014b24e2bSVaishali Kulkarni 
74114b24e2bSVaishali Kulkarni 	/* init QM top level params */
74214b24e2bSVaishali Kulkarni 	ecore_init_qm_params(p_hwfn);
74314b24e2bSVaishali Kulkarni 
74414b24e2bSVaishali Kulkarni 	/* init QM port params */
74514b24e2bSVaishali Kulkarni 	ecore_init_qm_port_params(p_hwfn);
74614b24e2bSVaishali Kulkarni 
74714b24e2bSVaishali Kulkarni 	/* init QM vport params */
74814b24e2bSVaishali Kulkarni 	ecore_init_qm_vport_params(p_hwfn);
74914b24e2bSVaishali Kulkarni 
75014b24e2bSVaishali Kulkarni 	/* init QM physical queue params */
75114b24e2bSVaishali Kulkarni 	ecore_init_qm_pq_params(p_hwfn);
75214b24e2bSVaishali Kulkarni 
75314b24e2bSVaishali Kulkarni 	/* display all that init */
75414b24e2bSVaishali Kulkarni 	ecore_dp_init_qm_params(p_hwfn);
75514b24e2bSVaishali Kulkarni }
75614b24e2bSVaishali Kulkarni 
75714b24e2bSVaishali Kulkarni /* This function reconfigures the QM pf on the fly.
75814b24e2bSVaishali Kulkarni  * For this purpose we:
75914b24e2bSVaishali Kulkarni  * 1. reconfigure the QM database
76014b24e2bSVaishali Kulkarni  * 2. set new values to runtime array
76114b24e2bSVaishali Kulkarni  * 3. send an sdm_qm_cmd through the rbc interface to stop the QM
76214b24e2bSVaishali Kulkarni  * 4. activate init tool in QM_PF stage
76314b24e2bSVaishali Kulkarni  * 5. send an sdm_qm_cmd through rbc interface to release the QM
76414b24e2bSVaishali Kulkarni  */
ecore_qm_reconf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)76514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_qm_reconf(struct ecore_hwfn *p_hwfn,
76614b24e2bSVaishali Kulkarni 				     struct ecore_ptt *p_ptt)
76714b24e2bSVaishali Kulkarni {
76814b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
76914b24e2bSVaishali Kulkarni 	bool b_rc;
77014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
77114b24e2bSVaishali Kulkarni 
77214b24e2bSVaishali Kulkarni 	/* initialize ecore's qm data structure */
77314b24e2bSVaishali Kulkarni 	ecore_init_qm_info(p_hwfn);
77414b24e2bSVaishali Kulkarni 
77514b24e2bSVaishali Kulkarni 	/* stop PF's qm queues */
77614b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&qm_lock);
77714b24e2bSVaishali Kulkarni 	b_rc = ecore_send_qm_stop_cmd(p_hwfn, p_ptt, false, true,
77814b24e2bSVaishali Kulkarni 				      qm_info->start_pq, qm_info->num_pqs);
77914b24e2bSVaishali Kulkarni 	OSAL_SPIN_UNLOCK(&qm_lock);
78014b24e2bSVaishali Kulkarni 	if (!b_rc)
78114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
78214b24e2bSVaishali Kulkarni 
78314b24e2bSVaishali Kulkarni 	/* clear the QM_PF runtime phase leftovers from previous init */
78414b24e2bSVaishali Kulkarni 	ecore_init_clear_rt_data(p_hwfn);
78514b24e2bSVaishali Kulkarni 
78614b24e2bSVaishali Kulkarni 	/* prepare QM portion of runtime array */
78714b24e2bSVaishali Kulkarni 	ecore_qm_init_pf(p_hwfn);
78814b24e2bSVaishali Kulkarni 
78914b24e2bSVaishali Kulkarni 	/* activate init tool on runtime array */
79014b24e2bSVaishali Kulkarni 	rc = ecore_init_run(p_hwfn, p_ptt, PHASE_QM_PF, p_hwfn->rel_pf_id,
79114b24e2bSVaishali Kulkarni 			    p_hwfn->hw_info.hw_mode);
79214b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
79314b24e2bSVaishali Kulkarni 		return rc;
79414b24e2bSVaishali Kulkarni 
79514b24e2bSVaishali Kulkarni 	/* start PF's qm queues */
79614b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&qm_lock);
79714b24e2bSVaishali Kulkarni 	b_rc = ecore_send_qm_stop_cmd(p_hwfn, p_ptt, true, true,
79814b24e2bSVaishali Kulkarni 				      qm_info->start_pq, qm_info->num_pqs);
79914b24e2bSVaishali Kulkarni 	OSAL_SPIN_UNLOCK(&qm_lock);
80014b24e2bSVaishali Kulkarni 	if (!b_rc)
80114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
80214b24e2bSVaishali Kulkarni 
80314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
80414b24e2bSVaishali Kulkarni }
80514b24e2bSVaishali Kulkarni 
ecore_alloc_qm_data(struct ecore_hwfn * p_hwfn)80614b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_alloc_qm_data(struct ecore_hwfn *p_hwfn)
80714b24e2bSVaishali Kulkarni {
80814b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
80914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
81014b24e2bSVaishali Kulkarni 
81114b24e2bSVaishali Kulkarni 	rc = ecore_init_qm_sanity(p_hwfn);
81214b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
81314b24e2bSVaishali Kulkarni 		goto alloc_err;
81414b24e2bSVaishali Kulkarni 
81514b24e2bSVaishali Kulkarni 	qm_info->qm_pq_params = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
81614b24e2bSVaishali Kulkarni 					    sizeof(struct init_qm_pq_params) *
81714b24e2bSVaishali Kulkarni 					    ecore_init_qm_get_num_pqs(p_hwfn));
81814b24e2bSVaishali Kulkarni 	if (!qm_info->qm_pq_params)
81914b24e2bSVaishali Kulkarni 		goto alloc_err;
82014b24e2bSVaishali Kulkarni 
82114b24e2bSVaishali Kulkarni 	qm_info->qm_vport_params = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
82214b24e2bSVaishali Kulkarni 					       sizeof(struct init_qm_vport_params) *
82314b24e2bSVaishali Kulkarni 					       ecore_init_qm_get_num_vports(p_hwfn));
82414b24e2bSVaishali Kulkarni 	if (!qm_info->qm_vport_params)
82514b24e2bSVaishali Kulkarni 		goto alloc_err;
82614b24e2bSVaishali Kulkarni 
82714b24e2bSVaishali Kulkarni 	qm_info->qm_port_params = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
82814b24e2bSVaishali Kulkarni 					      sizeof(struct init_qm_port_params) *
82914b24e2bSVaishali Kulkarni 					      p_hwfn->p_dev->num_ports_in_engine);
83014b24e2bSVaishali Kulkarni 	if (!qm_info->qm_port_params)
83114b24e2bSVaishali Kulkarni 		goto alloc_err;
83214b24e2bSVaishali Kulkarni 
83314b24e2bSVaishali Kulkarni 	qm_info->wfq_data = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
83414b24e2bSVaishali Kulkarni 					sizeof(struct ecore_wfq_data) *
83514b24e2bSVaishali Kulkarni 					ecore_init_qm_get_num_vports(p_hwfn));
83614b24e2bSVaishali Kulkarni 	if (!qm_info->wfq_data)
83714b24e2bSVaishali Kulkarni 		goto alloc_err;
83814b24e2bSVaishali Kulkarni 
83914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
84014b24e2bSVaishali Kulkarni 
84114b24e2bSVaishali Kulkarni alloc_err:
84214b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Failed to allocate memory for QM params\n");
84314b24e2bSVaishali Kulkarni 	ecore_qm_info_free(p_hwfn);
84414b24e2bSVaishali Kulkarni 	return ECORE_NOMEM;
84514b24e2bSVaishali Kulkarni }
84614b24e2bSVaishali Kulkarni /******************** End QM initialization ***************/
84714b24e2bSVaishali Kulkarni 
ecore_resc_alloc(struct ecore_dev * p_dev)84814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
84914b24e2bSVaishali Kulkarni {
85014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
85114b24e2bSVaishali Kulkarni 	u32 rdma_tasks, excess_tasks;
85214b24e2bSVaishali Kulkarni 	u32 line_count;
85314b24e2bSVaishali Kulkarni 	int i;
85414b24e2bSVaishali Kulkarni 
85514b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev)) {
85614b24e2bSVaishali Kulkarni 		for_each_hwfn(p_dev, i) {
85714b24e2bSVaishali Kulkarni 			rc = ecore_l2_alloc(&p_dev->hwfns[i]);
85814b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
85914b24e2bSVaishali Kulkarni 				return rc;
86014b24e2bSVaishali Kulkarni 		}
86114b24e2bSVaishali Kulkarni 		return rc;
86214b24e2bSVaishali Kulkarni 	}
86314b24e2bSVaishali Kulkarni 
86414b24e2bSVaishali Kulkarni 	p_dev->fw_data = OSAL_ZALLOC(p_dev, GFP_KERNEL,
86514b24e2bSVaishali Kulkarni 				     sizeof(*p_dev->fw_data));
86614b24e2bSVaishali Kulkarni 	if (!p_dev->fw_data)
86714b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
86814b24e2bSVaishali Kulkarni 
86914b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
87014b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
87114b24e2bSVaishali Kulkarni 		u32 n_eqes, num_cons;
87214b24e2bSVaishali Kulkarni 
87314b24e2bSVaishali Kulkarni 		/* First allocate the context manager structure */
87414b24e2bSVaishali Kulkarni 		rc = ecore_cxt_mngr_alloc(p_hwfn);
87514b24e2bSVaishali Kulkarni 		if (rc)
87614b24e2bSVaishali Kulkarni 			goto alloc_err;
87714b24e2bSVaishali Kulkarni 
87814b24e2bSVaishali Kulkarni 		/* Set the HW cid/tid numbers (in the contest manager)
87914b24e2bSVaishali Kulkarni 		 * Must be done prior to any further computations.
88014b24e2bSVaishali Kulkarni 		 */
88114b24e2bSVaishali Kulkarni 		rc = ecore_cxt_set_pf_params(p_hwfn, RDMA_MAX_TIDS);
88214b24e2bSVaishali Kulkarni 		if (rc)
88314b24e2bSVaishali Kulkarni 			goto alloc_err;
88414b24e2bSVaishali Kulkarni 
88514b24e2bSVaishali Kulkarni 		rc = ecore_alloc_qm_data(p_hwfn);
88614b24e2bSVaishali Kulkarni 		if (rc)
88714b24e2bSVaishali Kulkarni 			goto alloc_err;
88814b24e2bSVaishali Kulkarni 
88914b24e2bSVaishali Kulkarni 		/* init qm info */
89014b24e2bSVaishali Kulkarni 		ecore_init_qm_info(p_hwfn);
89114b24e2bSVaishali Kulkarni 
89214b24e2bSVaishali Kulkarni 		/* Compute the ILT client partition */
89314b24e2bSVaishali Kulkarni 		rc = ecore_cxt_cfg_ilt_compute(p_hwfn, &line_count);
89414b24e2bSVaishali Kulkarni 		if (rc) {
89514b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false, "too many ILT lines; re-computing with less lines\n");
89614b24e2bSVaishali Kulkarni 			/* In case there are not enough ILT lines we reduce the
89714b24e2bSVaishali Kulkarni 			 * number of RDMA tasks and re-compute.
89814b24e2bSVaishali Kulkarni 			 */
89914b24e2bSVaishali Kulkarni 			excess_tasks = ecore_cxt_cfg_ilt_compute_excess(
90014b24e2bSVaishali Kulkarni 					p_hwfn, line_count);
90114b24e2bSVaishali Kulkarni 			if (!excess_tasks)
90214b24e2bSVaishali Kulkarni 				goto alloc_err;
90314b24e2bSVaishali Kulkarni 
90414b24e2bSVaishali Kulkarni 			rdma_tasks = RDMA_MAX_TIDS - excess_tasks;
90514b24e2bSVaishali Kulkarni 			rc = ecore_cxt_set_pf_params(p_hwfn, rdma_tasks);
90614b24e2bSVaishali Kulkarni 			if (rc)
90714b24e2bSVaishali Kulkarni 				goto alloc_err;
90814b24e2bSVaishali Kulkarni 
90914b24e2bSVaishali Kulkarni 			rc = ecore_cxt_cfg_ilt_compute(p_hwfn, &line_count);
91014b24e2bSVaishali Kulkarni 			if (rc) {
91114b24e2bSVaishali Kulkarni 				DP_ERR(p_hwfn, "failed ILT compute. Requested too many lines: %u\n",
91214b24e2bSVaishali Kulkarni 				       line_count);
91314b24e2bSVaishali Kulkarni 
91414b24e2bSVaishali Kulkarni 				goto alloc_err;
91514b24e2bSVaishali Kulkarni 			}
91614b24e2bSVaishali Kulkarni 		}
91714b24e2bSVaishali Kulkarni 
91814b24e2bSVaishali Kulkarni 		/* CID map / ILT shadow table / T2
91914b24e2bSVaishali Kulkarni 		 * The talbes sizes are determined by the computations above
92014b24e2bSVaishali Kulkarni 		 */
92114b24e2bSVaishali Kulkarni 		rc = ecore_cxt_tables_alloc(p_hwfn);
92214b24e2bSVaishali Kulkarni 		if (rc)
92314b24e2bSVaishali Kulkarni 			goto alloc_err;
92414b24e2bSVaishali Kulkarni 
92514b24e2bSVaishali Kulkarni 		/* SPQ, must follow ILT because initializes SPQ context */
92614b24e2bSVaishali Kulkarni 		rc = ecore_spq_alloc(p_hwfn);
92714b24e2bSVaishali Kulkarni 		if (rc)
92814b24e2bSVaishali Kulkarni 			goto alloc_err;
92914b24e2bSVaishali Kulkarni 
93014b24e2bSVaishali Kulkarni 		/* SP status block allocation */
93114b24e2bSVaishali Kulkarni 		p_hwfn->p_dpc_ptt = ecore_get_reserved_ptt(p_hwfn,
93214b24e2bSVaishali Kulkarni 							   RESERVED_PTT_DPC);
93314b24e2bSVaishali Kulkarni 
93414b24e2bSVaishali Kulkarni 		rc = ecore_int_alloc(p_hwfn, p_hwfn->p_main_ptt);
93514b24e2bSVaishali Kulkarni 		if (rc)
93614b24e2bSVaishali Kulkarni 			goto alloc_err;
93714b24e2bSVaishali Kulkarni 
93814b24e2bSVaishali Kulkarni 		rc = ecore_iov_alloc(p_hwfn);
93914b24e2bSVaishali Kulkarni 		if (rc)
94014b24e2bSVaishali Kulkarni 			goto alloc_err;
94114b24e2bSVaishali Kulkarni 
94214b24e2bSVaishali Kulkarni 		/* EQ */
94314b24e2bSVaishali Kulkarni 		n_eqes = ecore_chain_get_capacity(&p_hwfn->p_spq->chain);
94414b24e2bSVaishali Kulkarni 		if (ECORE_IS_RDMA_PERSONALITY(p_hwfn)) {
94514b24e2bSVaishali Kulkarni 			/* Calculate the EQ size
94614b24e2bSVaishali Kulkarni 			 * ---------------------
94714b24e2bSVaishali Kulkarni 			 * Each ICID may generate up to one event at a time i.e.
94814b24e2bSVaishali Kulkarni 			 * the event must be handled/cleared before a new one
94914b24e2bSVaishali Kulkarni 			 * can be generated. We calculate the sum of events per
95014b24e2bSVaishali Kulkarni 			 * protocol and create an EQ deep enough to handle the
95114b24e2bSVaishali Kulkarni 			 * worst case:
95214b24e2bSVaishali Kulkarni 			 * - Core - according to SPQ.
95314b24e2bSVaishali Kulkarni 			 * - RoCE - per QP there are a couple of ICIDs, one
95414b24e2bSVaishali Kulkarni 			 *	  responder and one requester, each can
95514b24e2bSVaishali Kulkarni 			 *	  generate an EQE => n_eqes_qp = 2 * n_qp.
95614b24e2bSVaishali Kulkarni 			 *	  Each CQ can generate an EQE. There are 2 CQs
95714b24e2bSVaishali Kulkarni 			 *	  per QP => n_eqes_cq = 2 * n_qp.
95814b24e2bSVaishali Kulkarni 			 *	  Hence the RoCE total is 4 * n_qp or
95914b24e2bSVaishali Kulkarni 			 *	  2 * num_cons.
96014b24e2bSVaishali Kulkarni 			 * - ENet - There can be up to two events per VF. One
96114b24e2bSVaishali Kulkarni 			 *	  for VF-PF channel and another for VF FLR
96214b24e2bSVaishali Kulkarni 			 *	  initial cleanup. The number of VFs is
96314b24e2bSVaishali Kulkarni 			 *	  bounded by MAX_NUM_VFS_BB, and is much
96414b24e2bSVaishali Kulkarni 			 *	  smaller than RoCE's so we avoid exact
96514b24e2bSVaishali Kulkarni 			 *	  calculation.
96614b24e2bSVaishali Kulkarni 			 */
96714b24e2bSVaishali Kulkarni 			if (p_hwfn->hw_info.personality == ECORE_PCI_ETH_ROCE) {
96814b24e2bSVaishali Kulkarni 				num_cons = ecore_cxt_get_proto_cid_count(
96914b24e2bSVaishali Kulkarni 					p_hwfn, PROTOCOLID_ROCE, OSAL_NULL);
97014b24e2bSVaishali Kulkarni 				num_cons *= 2;
97114b24e2bSVaishali Kulkarni 			} else {
97214b24e2bSVaishali Kulkarni 				num_cons = ecore_cxt_get_proto_cid_count(
97314b24e2bSVaishali Kulkarni 						p_hwfn, PROTOCOLID_IWARP,
97414b24e2bSVaishali Kulkarni 						OSAL_NULL);
97514b24e2bSVaishali Kulkarni 			}
97614b24e2bSVaishali Kulkarni 			n_eqes += num_cons + 2 * MAX_NUM_VFS_BB;
97714b24e2bSVaishali Kulkarni 		} else if (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI) {
97814b24e2bSVaishali Kulkarni 			num_cons = ecore_cxt_get_proto_cid_count(
97914b24e2bSVaishali Kulkarni 					p_hwfn, PROTOCOLID_ISCSI, OSAL_NULL);
98014b24e2bSVaishali Kulkarni 			n_eqes += 2 * num_cons;
98114b24e2bSVaishali Kulkarni 		}
98214b24e2bSVaishali Kulkarni 
98314b24e2bSVaishali Kulkarni 		if (n_eqes > 0xFFFF) {
98414b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn,
98514b24e2bSVaishali Kulkarni 			       "Cannot allocate 0x%x EQ elements. The maximum of a u16 chain is 0x%x\n",
98614b24e2bSVaishali Kulkarni 			       n_eqes, 0xFFFF);
98714b24e2bSVaishali Kulkarni 			goto alloc_no_mem;
98814b24e2bSVaishali Kulkarni 		}
98914b24e2bSVaishali Kulkarni 
99014b24e2bSVaishali Kulkarni 		rc = ecore_eq_alloc(p_hwfn, (u16)n_eqes);
99114b24e2bSVaishali Kulkarni 		if (rc)
99214b24e2bSVaishali Kulkarni 			goto alloc_err;
99314b24e2bSVaishali Kulkarni 
99414b24e2bSVaishali Kulkarni 		rc = ecore_consq_alloc(p_hwfn);
99514b24e2bSVaishali Kulkarni 		if (rc)
99614b24e2bSVaishali Kulkarni 			goto alloc_err;
99714b24e2bSVaishali Kulkarni 
99814b24e2bSVaishali Kulkarni 		rc = ecore_l2_alloc(p_hwfn);
99914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
100014b24e2bSVaishali Kulkarni 			goto alloc_err;
100114b24e2bSVaishali Kulkarni 
100214b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LL2
100314b24e2bSVaishali Kulkarni 		if (p_hwfn->using_ll2) {
100414b24e2bSVaishali Kulkarni 			rc = ecore_ll2_alloc(p_hwfn);
100514b24e2bSVaishali Kulkarni 			if (rc)
100614b24e2bSVaishali Kulkarni 				goto alloc_err;
100714b24e2bSVaishali Kulkarni 		}
100814b24e2bSVaishali Kulkarni #endif
100914b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_FCOE
101014b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_FCOE) {
101114b24e2bSVaishali Kulkarni 			rc = ecore_fcoe_alloc(p_hwfn);
101214b24e2bSVaishali Kulkarni 			if (rc)
101314b24e2bSVaishali Kulkarni 				goto alloc_err;
101414b24e2bSVaishali Kulkarni 		}
101514b24e2bSVaishali Kulkarni #endif
101614b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ISCSI
101714b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI) {
101814b24e2bSVaishali Kulkarni 			rc = ecore_iscsi_alloc(p_hwfn);
101914b24e2bSVaishali Kulkarni 			if (rc)
102014b24e2bSVaishali Kulkarni 				goto alloc_err;
102114b24e2bSVaishali Kulkarni 			rc = ecore_ooo_alloc(p_hwfn);
102214b24e2bSVaishali Kulkarni 			if (rc)
102314b24e2bSVaishali Kulkarni 				goto alloc_err;
102414b24e2bSVaishali Kulkarni 		}
102514b24e2bSVaishali Kulkarni #endif
102614b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
102714b24e2bSVaishali Kulkarni 		if (ECORE_IS_RDMA_PERSONALITY(p_hwfn)) {
102814b24e2bSVaishali Kulkarni 			rc = ecore_rdma_info_alloc(p_hwfn);
102914b24e2bSVaishali Kulkarni 			if (rc)
103014b24e2bSVaishali Kulkarni 				goto alloc_err;
103114b24e2bSVaishali Kulkarni 		}
103214b24e2bSVaishali Kulkarni #endif
103314b24e2bSVaishali Kulkarni 
103414b24e2bSVaishali Kulkarni 		/* DMA info initialization */
103514b24e2bSVaishali Kulkarni 		rc = ecore_dmae_info_alloc(p_hwfn);
103614b24e2bSVaishali Kulkarni 		if (rc) {
103714b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
103814b24e2bSVaishali Kulkarni 				  "Failed to allocate memory for dmae_info structure\n");
103914b24e2bSVaishali Kulkarni 			goto alloc_err;
104014b24e2bSVaishali Kulkarni 		}
104114b24e2bSVaishali Kulkarni 
104214b24e2bSVaishali Kulkarni 		/* DCBX initialization */
104314b24e2bSVaishali Kulkarni 		rc = ecore_dcbx_info_alloc(p_hwfn);
104414b24e2bSVaishali Kulkarni 		if (rc) {
104514b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
104614b24e2bSVaishali Kulkarni 				  "Failed to allocate memory for dcbx structure\n");
104714b24e2bSVaishali Kulkarni 			goto alloc_err;
104814b24e2bSVaishali Kulkarni 		}
104914b24e2bSVaishali Kulkarni 	}
105014b24e2bSVaishali Kulkarni 
105114b24e2bSVaishali Kulkarni 	p_dev->reset_stats = OSAL_ZALLOC(p_dev, GFP_KERNEL,
105214b24e2bSVaishali Kulkarni 					 sizeof(*p_dev->reset_stats));
105314b24e2bSVaishali Kulkarni 	if (!p_dev->reset_stats) {
105414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true,
105514b24e2bSVaishali Kulkarni 			  "Failed to allocate reset statistics\n");
105614b24e2bSVaishali Kulkarni 		goto alloc_no_mem;
105714b24e2bSVaishali Kulkarni 	}
105814b24e2bSVaishali Kulkarni 
105914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
106014b24e2bSVaishali Kulkarni 
106114b24e2bSVaishali Kulkarni alloc_no_mem:
106214b24e2bSVaishali Kulkarni 	rc = ECORE_NOMEM;
106314b24e2bSVaishali Kulkarni alloc_err:
106414b24e2bSVaishali Kulkarni 	ecore_resc_free(p_dev);
106514b24e2bSVaishali Kulkarni 	return rc;
106614b24e2bSVaishali Kulkarni }
106714b24e2bSVaishali Kulkarni 
ecore_resc_setup(struct ecore_dev * p_dev)106814b24e2bSVaishali Kulkarni void ecore_resc_setup(struct ecore_dev *p_dev)
106914b24e2bSVaishali Kulkarni {
107014b24e2bSVaishali Kulkarni 	int i;
107114b24e2bSVaishali Kulkarni 
107214b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev)) {
107314b24e2bSVaishali Kulkarni 		for_each_hwfn(p_dev, i)
107414b24e2bSVaishali Kulkarni 			ecore_l2_setup(&p_dev->hwfns[i]);
107514b24e2bSVaishali Kulkarni 		return;
107614b24e2bSVaishali Kulkarni 	}
107714b24e2bSVaishali Kulkarni 
107814b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
107914b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
108014b24e2bSVaishali Kulkarni 
108114b24e2bSVaishali Kulkarni 		ecore_cxt_mngr_setup(p_hwfn);
108214b24e2bSVaishali Kulkarni 		ecore_spq_setup(p_hwfn);
108314b24e2bSVaishali Kulkarni 		ecore_eq_setup(p_hwfn);
108414b24e2bSVaishali Kulkarni 		ecore_consq_setup(p_hwfn);
108514b24e2bSVaishali Kulkarni 
108614b24e2bSVaishali Kulkarni 		/* Read shadow of current MFW mailbox */
108714b24e2bSVaishali Kulkarni 		ecore_mcp_read_mb(p_hwfn, p_hwfn->p_main_ptt);
108814b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_hwfn->mcp_info->mfw_mb_shadow,
108914b24e2bSVaishali Kulkarni 			    p_hwfn->mcp_info->mfw_mb_cur,
109014b24e2bSVaishali Kulkarni 			    p_hwfn->mcp_info->mfw_mb_length);
109114b24e2bSVaishali Kulkarni 
109214b24e2bSVaishali Kulkarni 		ecore_int_setup(p_hwfn, p_hwfn->p_main_ptt);
109314b24e2bSVaishali Kulkarni 
109414b24e2bSVaishali Kulkarni 		ecore_l2_setup(p_hwfn);
109514b24e2bSVaishali Kulkarni 		ecore_iov_setup(p_hwfn, p_hwfn->p_main_ptt);
109614b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LL2
109714b24e2bSVaishali Kulkarni 		if (p_hwfn->using_ll2)
109814b24e2bSVaishali Kulkarni 			ecore_ll2_setup(p_hwfn);
109914b24e2bSVaishali Kulkarni #endif
110014b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_FCOE
110114b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_FCOE)
110214b24e2bSVaishali Kulkarni 			ecore_fcoe_setup(p_hwfn);
110314b24e2bSVaishali Kulkarni #endif
110414b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ISCSI
110514b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI) {
110614b24e2bSVaishali Kulkarni 			ecore_iscsi_setup(p_hwfn);
110714b24e2bSVaishali Kulkarni 			ecore_ooo_setup(p_hwfn);
110814b24e2bSVaishali Kulkarni 		}
110914b24e2bSVaishali Kulkarni #endif
111014b24e2bSVaishali Kulkarni 	}
111114b24e2bSVaishali Kulkarni }
111214b24e2bSVaishali Kulkarni 
111314b24e2bSVaishali Kulkarni #define FINAL_CLEANUP_POLL_CNT	(100)
111414b24e2bSVaishali Kulkarni #define FINAL_CLEANUP_POLL_TIME	(10)
ecore_final_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 id,bool is_vf)111514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_final_cleanup(struct ecore_hwfn *p_hwfn,
111614b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
111714b24e2bSVaishali Kulkarni 					 u16 id, bool is_vf)
111814b24e2bSVaishali Kulkarni {
111914b24e2bSVaishali Kulkarni 	u32 command = 0, addr, count = FINAL_CLEANUP_POLL_CNT;
112014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_TIMEOUT;
112114b24e2bSVaishali Kulkarni 
112214b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
112314b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev) ||
112414b24e2bSVaishali Kulkarni 	    CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
112514b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn, "Skipping final cleanup for non-ASIC\n");
112614b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
112714b24e2bSVaishali Kulkarni 	}
112814b24e2bSVaishali Kulkarni #endif
112914b24e2bSVaishali Kulkarni 
113014b24e2bSVaishali Kulkarni 	addr = GTT_BAR0_MAP_REG_USDM_RAM +
113114b24e2bSVaishali Kulkarni 	       USTORM_FLR_FINAL_ACK_OFFSET(p_hwfn->rel_pf_id);
113214b24e2bSVaishali Kulkarni 
113314b24e2bSVaishali Kulkarni 	if (is_vf)
113414b24e2bSVaishali Kulkarni 		id += 0x10;
113514b24e2bSVaishali Kulkarni 
113614b24e2bSVaishali Kulkarni 	command |= X_FINAL_CLEANUP_AGG_INT <<
113714b24e2bSVaishali Kulkarni 		   SDM_AGG_INT_COMP_PARAMS_AGG_INT_INDEX_SHIFT;
113814b24e2bSVaishali Kulkarni 	command |= 1 << SDM_AGG_INT_COMP_PARAMS_AGG_VECTOR_ENABLE_SHIFT;
113914b24e2bSVaishali Kulkarni 	command |= id << SDM_AGG_INT_COMP_PARAMS_AGG_VECTOR_BIT_SHIFT;
114014b24e2bSVaishali Kulkarni 	command |= SDM_COMP_TYPE_AGG_INT << SDM_OP_GEN_COMP_TYPE_SHIFT;
114114b24e2bSVaishali Kulkarni 
114214b24e2bSVaishali Kulkarni 	/* Make sure notification is not set before initiating final cleanup */
114314b24e2bSVaishali Kulkarni 	if (REG_RD(p_hwfn, addr)) {
114414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
114514b24e2bSVaishali Kulkarni 			  "Unexpected; Found final cleanup notification before initiating final cleanup\n");
114614b24e2bSVaishali Kulkarni 		REG_WR(p_hwfn, addr, 0);
114714b24e2bSVaishali Kulkarni 	}
114814b24e2bSVaishali Kulkarni 
114914b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
115014b24e2bSVaishali Kulkarni 		   "Sending final cleanup for PFVF[%d] [Command %08x\n]",
115114b24e2bSVaishali Kulkarni 		   id, command);
115214b24e2bSVaishali Kulkarni 
115314b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, XSDM_REG_OPERATION_GEN, command);
115414b24e2bSVaishali Kulkarni 
115514b24e2bSVaishali Kulkarni 	/* Poll until completion */
115614b24e2bSVaishali Kulkarni 	while (!REG_RD(p_hwfn, addr) && count--)
115714b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(FINAL_CLEANUP_POLL_TIME);
115814b24e2bSVaishali Kulkarni 
115914b24e2bSVaishali Kulkarni 	if (REG_RD(p_hwfn, addr))
116014b24e2bSVaishali Kulkarni 		rc = ECORE_SUCCESS;
116114b24e2bSVaishali Kulkarni 	else
116214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Failed to receive FW final cleanup notification\n");
116314b24e2bSVaishali Kulkarni 
116414b24e2bSVaishali Kulkarni 	/* Cleanup afterwards */
116514b24e2bSVaishali Kulkarni 	REG_WR(p_hwfn, addr, 0);
116614b24e2bSVaishali Kulkarni 
116714b24e2bSVaishali Kulkarni 	return rc;
116814b24e2bSVaishali Kulkarni }
116914b24e2bSVaishali Kulkarni 
ecore_calc_hw_mode(struct ecore_hwfn * p_hwfn)117014b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_calc_hw_mode(struct ecore_hwfn *p_hwfn)
117114b24e2bSVaishali Kulkarni {
117214b24e2bSVaishali Kulkarni 	int hw_mode = 0;
117314b24e2bSVaishali Kulkarni 
117414b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
117514b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_BB;
117614b24e2bSVaishali Kulkarni 	} else if (ECORE_IS_AH(p_hwfn->p_dev)) {
117714b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_K2;
117814b24e2bSVaishali Kulkarni 	} else {
117914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Unknown chip type %#x\n",
118014b24e2bSVaishali Kulkarni 			  p_hwfn->p_dev->type);
118114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
118214b24e2bSVaishali Kulkarni 	}
118314b24e2bSVaishali Kulkarni 
118414b24e2bSVaishali Kulkarni 	/* Ports per engine is based on the values in CNIG_REG_NW_PORT_MODE*/
118514b24e2bSVaishali Kulkarni 	switch (p_hwfn->p_dev->num_ports_in_engine) {
118614b24e2bSVaishali Kulkarni 	case 1:
118714b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_PORTS_PER_ENG_1;
118814b24e2bSVaishali Kulkarni 		break;
118914b24e2bSVaishali Kulkarni 	case 2:
119014b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_PORTS_PER_ENG_2;
119114b24e2bSVaishali Kulkarni 		break;
119214b24e2bSVaishali Kulkarni 	case 4:
119314b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_PORTS_PER_ENG_4;
119414b24e2bSVaishali Kulkarni 		break;
119514b24e2bSVaishali Kulkarni 	default:
119614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "num_ports_in_engine = %d not supported\n",
119714b24e2bSVaishali Kulkarni 			  p_hwfn->p_dev->num_ports_in_engine);
119814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
119914b24e2bSVaishali Kulkarni 	}
120014b24e2bSVaishali Kulkarni 
120114b24e2bSVaishali Kulkarni 	switch (p_hwfn->p_dev->mf_mode) {
120214b24e2bSVaishali Kulkarni 	case ECORE_MF_DEFAULT:
120314b24e2bSVaishali Kulkarni 	case ECORE_MF_NPAR:
120414b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_MF_SI;
120514b24e2bSVaishali Kulkarni 		break;
120614b24e2bSVaishali Kulkarni 	case ECORE_MF_OVLAN:
120714b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_MF_SD;
120814b24e2bSVaishali Kulkarni 		break;
120914b24e2bSVaishali Kulkarni 	default:
121014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Unsupported MF mode, init as DEFAULT\n");
121114b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_MF_SI;
121214b24e2bSVaishali Kulkarni 	}
121314b24e2bSVaishali Kulkarni 
121414b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
121514b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
121614b24e2bSVaishali Kulkarni 		if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
121714b24e2bSVaishali Kulkarni 			hw_mode |= 1 << MODE_FPGA;
121814b24e2bSVaishali Kulkarni 		} else {
121914b24e2bSVaishali Kulkarni 			if (p_hwfn->p_dev->b_is_emul_full)
122014b24e2bSVaishali Kulkarni 				hw_mode |= 1 << MODE_EMUL_FULL;
122114b24e2bSVaishali Kulkarni 			else
122214b24e2bSVaishali Kulkarni 				hw_mode |= 1 << MODE_EMUL_REDUCED;
122314b24e2bSVaishali Kulkarni 		}
122414b24e2bSVaishali Kulkarni 	} else
122514b24e2bSVaishali Kulkarni #endif
122614b24e2bSVaishali Kulkarni 	hw_mode |= 1 << MODE_ASIC;
122714b24e2bSVaishali Kulkarni 
122814b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->num_hwfns > 1)
122914b24e2bSVaishali Kulkarni 		hw_mode |= 1 << MODE_100G;
123014b24e2bSVaishali Kulkarni 
123114b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.hw_mode = hw_mode;
123214b24e2bSVaishali Kulkarni 
123314b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, (ECORE_MSG_PROBE | ECORE_MSG_IFUP),
123414b24e2bSVaishali Kulkarni 		   "Configuring function for hw_mode: 0x%08x\n",
123514b24e2bSVaishali Kulkarni 		   p_hwfn->hw_info.hw_mode);
123614b24e2bSVaishali Kulkarni 
123714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
123814b24e2bSVaishali Kulkarni }
123914b24e2bSVaishali Kulkarni 
124014b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
124114b24e2bSVaishali Kulkarni /* MFW-replacement initializations for non-ASIC */
ecore_hw_init_chip(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)124214b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_init_chip(struct ecore_hwfn *p_hwfn,
124314b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt)
124414b24e2bSVaishali Kulkarni {
124514b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
124614b24e2bSVaishali Kulkarni 	u32 pl_hv = 1;
124714b24e2bSVaishali Kulkarni 	int i;
124814b24e2bSVaishali Kulkarni 
124914b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev)) {
125014b24e2bSVaishali Kulkarni 		if (ECORE_IS_AH(p_dev))
125114b24e2bSVaishali Kulkarni 			pl_hv |= 0x600;
125214b24e2bSVaishali Kulkarni 		else if (ECORE_IS_E5(p_dev))
125314b24e2bSVaishali Kulkarni 			ECORE_E5_MISSING_CODE;
125414b24e2bSVaishali Kulkarni 	}
125514b24e2bSVaishali Kulkarni 
125614b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISCS_REG_RESET_PL_HV + 4, pl_hv);
125714b24e2bSVaishali Kulkarni 
125814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev) &&
125914b24e2bSVaishali Kulkarni 	    (ECORE_IS_AH(p_dev) || ECORE_IS_E5(p_dev)))
126014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, MISCS_REG_RESET_PL_HV_2_K2_E5,
126114b24e2bSVaishali Kulkarni 			 0x3ffffff);
126214b24e2bSVaishali Kulkarni 
126314b24e2bSVaishali Kulkarni 	/* initialize port mode to 4x10G_E (10G with 4x10 SERDES) */
126414b24e2bSVaishali Kulkarni 	/* CNIG_REG_NW_PORT_MODE is same for A0 and B0 */
126514b24e2bSVaishali Kulkarni 	if (!CHIP_REV_IS_EMUL(p_dev) || ECORE_IS_BB(p_dev))
126614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, CNIG_REG_NW_PORT_MODE_BB, 4);
126714b24e2bSVaishali Kulkarni 
126814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev)) {
126914b24e2bSVaishali Kulkarni 		if (ECORE_IS_AH(p_dev)) {
127014b24e2bSVaishali Kulkarni 			/* 2 for 4-port, 1 for 2-port, 0 for 1-port */
127114b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISC_REG_PORT_MODE,
127214b24e2bSVaishali Kulkarni 				 (p_dev->num_ports_in_engine >> 1));
127314b24e2bSVaishali Kulkarni 
127414b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISC_REG_BLOCK_256B_EN,
127514b24e2bSVaishali Kulkarni 				 p_dev->num_ports_in_engine == 4 ? 0 : 3);
127614b24e2bSVaishali Kulkarni 		} else if (ECORE_IS_E5(p_dev)) {
127714b24e2bSVaishali Kulkarni 			ECORE_E5_MISSING_CODE;
127814b24e2bSVaishali Kulkarni 		}
127914b24e2bSVaishali Kulkarni 	}
128014b24e2bSVaishali Kulkarni 
128114b24e2bSVaishali Kulkarni 	/* Poll on RBC */
128214b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, PSWRQ2_REG_RBC_DONE, 1);
128314b24e2bSVaishali Kulkarni 	for (i = 0; i < 100; i++) {
128414b24e2bSVaishali Kulkarni 		OSAL_UDELAY(50);
128514b24e2bSVaishali Kulkarni 		if (ecore_rd(p_hwfn, p_ptt, PSWRQ2_REG_CFG_DONE) == 1)
128614b24e2bSVaishali Kulkarni 			break;
128714b24e2bSVaishali Kulkarni 	}
128814b24e2bSVaishali Kulkarni 	if (i == 100)
128914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "RBC done failed to complete in PSWRQ2\n");
129014b24e2bSVaishali Kulkarni 
129114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
129214b24e2bSVaishali Kulkarni }
129314b24e2bSVaishali Kulkarni #endif
129414b24e2bSVaishali Kulkarni 
129514b24e2bSVaishali Kulkarni /* Init run time data for all PFs and their VFs on an engine.
129614b24e2bSVaishali Kulkarni  * TBD - for VFs - Once we have parent PF info for each VF in
129714b24e2bSVaishali Kulkarni  * shmem available as CAU requires knowledge of parent PF for each VF.
129814b24e2bSVaishali Kulkarni  */
ecore_init_cau_rt_data(struct ecore_dev * p_dev)129914b24e2bSVaishali Kulkarni static void ecore_init_cau_rt_data(struct ecore_dev *p_dev)
130014b24e2bSVaishali Kulkarni {
130114b24e2bSVaishali Kulkarni 	u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET;
130214b24e2bSVaishali Kulkarni 	int i, igu_sb_id;
130314b24e2bSVaishali Kulkarni 
130414b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
130514b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
130614b24e2bSVaishali Kulkarni 		struct ecore_igu_info *p_igu_info;
130714b24e2bSVaishali Kulkarni 		struct ecore_igu_block *p_block;
130814b24e2bSVaishali Kulkarni 		struct cau_sb_entry sb_entry;
130914b24e2bSVaishali Kulkarni 
131014b24e2bSVaishali Kulkarni 		p_igu_info = p_hwfn->hw_info.p_igu_info;
131114b24e2bSVaishali Kulkarni 
131214b24e2bSVaishali Kulkarni 		for (igu_sb_id = 0;
131314b24e2bSVaishali Kulkarni 		     igu_sb_id < ECORE_MAPPING_MEMORY_SIZE(p_dev);
131414b24e2bSVaishali Kulkarni 		     igu_sb_id++) {
131514b24e2bSVaishali Kulkarni 			p_block = &p_igu_info->entry[igu_sb_id];
131614b24e2bSVaishali Kulkarni 
131714b24e2bSVaishali Kulkarni 			if (!p_block->is_pf)
131814b24e2bSVaishali Kulkarni 				continue;
131914b24e2bSVaishali Kulkarni 
132014b24e2bSVaishali Kulkarni 			ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
132114b24e2bSVaishali Kulkarni 						p_block->function_id,
132214b24e2bSVaishali Kulkarni 						0, 0);
132314b24e2bSVaishali Kulkarni 			STORE_RT_REG_AGG(p_hwfn, offset + igu_sb_id * 2,
132414b24e2bSVaishali Kulkarni 					 sb_entry);
132514b24e2bSVaishali Kulkarni 		}
132614b24e2bSVaishali Kulkarni 	}
132714b24e2bSVaishali Kulkarni }
132814b24e2bSVaishali Kulkarni 
ecore_init_cache_line_size(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)132914b24e2bSVaishali Kulkarni static void ecore_init_cache_line_size(struct ecore_hwfn *p_hwfn,
133014b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt)
133114b24e2bSVaishali Kulkarni {
133214b24e2bSVaishali Kulkarni 	u32 val, wr_mbs, cache_line_size;
133314b24e2bSVaishali Kulkarni 
133414b24e2bSVaishali Kulkarni 	val = ecore_rd(p_hwfn, p_ptt, PSWRQ2_REG_WR_MBS0);
133514b24e2bSVaishali Kulkarni 	switch (val) {
133614b24e2bSVaishali Kulkarni 	case 0:
133714b24e2bSVaishali Kulkarni 		wr_mbs = 128;
133814b24e2bSVaishali Kulkarni 		break;
133914b24e2bSVaishali Kulkarni 	case 1:
134014b24e2bSVaishali Kulkarni 		wr_mbs = 256;
134114b24e2bSVaishali Kulkarni 		break;
134214b24e2bSVaishali Kulkarni 	case 2:
134314b24e2bSVaishali Kulkarni 		wr_mbs = 512;
134414b24e2bSVaishali Kulkarni 		break;
134514b24e2bSVaishali Kulkarni 	default:
134614b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
134714b24e2bSVaishali Kulkarni 			"Unexpected value of PSWRQ2_REG_WR_MBS0 [0x%x]. Avoid configuring PGLUE_B_REG_CACHE_LINE_SIZE.\n",
134814b24e2bSVaishali Kulkarni 			val);
134914b24e2bSVaishali Kulkarni 		return;
135014b24e2bSVaishali Kulkarni 	}
135114b24e2bSVaishali Kulkarni 
135214b24e2bSVaishali Kulkarni 	cache_line_size = OSAL_MIN_T(u32, OSAL_CACHE_LINE_SIZE, wr_mbs);
135314b24e2bSVaishali Kulkarni 	switch (cache_line_size) {
135414b24e2bSVaishali Kulkarni 	case 32:
135514b24e2bSVaishali Kulkarni 		val = 0;
135614b24e2bSVaishali Kulkarni 		break;
135714b24e2bSVaishali Kulkarni 	case 64:
135814b24e2bSVaishali Kulkarni 		val = 1;
135914b24e2bSVaishali Kulkarni 		break;
136014b24e2bSVaishali Kulkarni 	case 128:
136114b24e2bSVaishali Kulkarni 		val = 2;
136214b24e2bSVaishali Kulkarni 		break;
136314b24e2bSVaishali Kulkarni 	case 256:
136414b24e2bSVaishali Kulkarni 		val = 3;
136514b24e2bSVaishali Kulkarni 		break;
136614b24e2bSVaishali Kulkarni 	default:
136714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
136814b24e2bSVaishali Kulkarni 			"Unexpected value of cache line size [0x%x]. Avoid configuring PGLUE_B_REG_CACHE_LINE_SIZE.\n",
136914b24e2bSVaishali Kulkarni 			cache_line_size);
137014b24e2bSVaishali Kulkarni 	}
137114b24e2bSVaishali Kulkarni 
137214b24e2bSVaishali Kulkarni 	if (OSAL_CACHE_LINE_SIZE > wr_mbs)
137314b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
137414b24e2bSVaishali Kulkarni 			"The cache line size for padding is suboptimal for performance [OS cache line size 0x%x, wr mbs 0x%x]\n",
137514b24e2bSVaishali Kulkarni 			OSAL_CACHE_LINE_SIZE, wr_mbs);
137614b24e2bSVaishali Kulkarni 
137714b24e2bSVaishali Kulkarni 	STORE_RT_REG(p_hwfn, PGLUE_REG_B_CACHE_LINE_SIZE_RT_OFFSET, val);
137814b24e2bSVaishali Kulkarni }
137914b24e2bSVaishali Kulkarni 
ecore_hw_init_common(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int hw_mode)138014b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_init_common(struct ecore_hwfn *p_hwfn,
138114b24e2bSVaishali Kulkarni 						 struct ecore_ptt *p_ptt,
138214b24e2bSVaishali Kulkarni 						 int hw_mode)
138314b24e2bSVaishali Kulkarni {
138414b24e2bSVaishali Kulkarni 	struct ecore_qm_info *qm_info = &p_hwfn->qm_info;
138514b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
138614b24e2bSVaishali Kulkarni 	u8 vf_id, max_num_vfs;
138714b24e2bSVaishali Kulkarni 	u16 num_pfs, pf_id;
138814b24e2bSVaishali Kulkarni 	u32 concrete_fid;
138914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc	= ECORE_SUCCESS;
139014b24e2bSVaishali Kulkarni 
139114b24e2bSVaishali Kulkarni 	ecore_init_cau_rt_data(p_dev);
139214b24e2bSVaishali Kulkarni 
139314b24e2bSVaishali Kulkarni 	/* Program GTT windows */
139414b24e2bSVaishali Kulkarni 	ecore_gtt_init(p_hwfn);
139514b24e2bSVaishali Kulkarni 
139614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
139714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev)) {
139814b24e2bSVaishali Kulkarni 		rc = ecore_hw_init_chip(p_hwfn, p_hwfn->p_main_ptt);
139914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
140014b24e2bSVaishali Kulkarni 			return rc;
140114b24e2bSVaishali Kulkarni 	}
140214b24e2bSVaishali Kulkarni #endif
140314b24e2bSVaishali Kulkarni 
140414b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info) {
140514b24e2bSVaishali Kulkarni 		if (p_hwfn->mcp_info->func_info.bandwidth_max)
140614b24e2bSVaishali Kulkarni 			qm_info->pf_rl_en = 1;
140714b24e2bSVaishali Kulkarni 		if (p_hwfn->mcp_info->func_info.bandwidth_min)
140814b24e2bSVaishali Kulkarni 			qm_info->pf_wfq_en = 1;
140914b24e2bSVaishali Kulkarni 	}
141014b24e2bSVaishali Kulkarni 
141114b24e2bSVaishali Kulkarni 	ecore_qm_common_rt_init(p_hwfn,
141214b24e2bSVaishali Kulkarni 				p_dev->num_ports_in_engine,
141314b24e2bSVaishali Kulkarni 				qm_info->max_phys_tcs_per_port,
141414b24e2bSVaishali Kulkarni 				qm_info->pf_rl_en, qm_info->pf_wfq_en,
141514b24e2bSVaishali Kulkarni 				qm_info->vport_rl_en, qm_info->vport_wfq_en,
141614b24e2bSVaishali Kulkarni 				qm_info->qm_port_params);
141714b24e2bSVaishali Kulkarni 
141814b24e2bSVaishali Kulkarni 	ecore_cxt_hw_init_common(p_hwfn);
141914b24e2bSVaishali Kulkarni 
142014b24e2bSVaishali Kulkarni 	ecore_init_cache_line_size(p_hwfn, p_ptt);
142114b24e2bSVaishali Kulkarni 
142214b24e2bSVaishali Kulkarni 	rc = ecore_init_run(p_hwfn, p_ptt, PHASE_ENGINE, ANY_PHASE_ID, hw_mode);
142314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
142414b24e2bSVaishali Kulkarni 		return rc;
142514b24e2bSVaishali Kulkarni 
142614b24e2bSVaishali Kulkarni 	/* @@TBD MichalK - should add VALIDATE_VFID to init tool...
142714b24e2bSVaishali Kulkarni 	 * need to decide with which value, maybe runtime
142814b24e2bSVaishali Kulkarni 	 */
142914b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, PSWRQ2_REG_L2P_VALIDATE_VFID, 0);
143014b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, PGLUE_B_REG_USE_CLIENTID_IN_TAG, 1);
143114b24e2bSVaishali Kulkarni 
143214b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_dev)) {
143314b24e2bSVaishali Kulkarni 		/* Workaround clears ROCE search for all functions to prevent
143414b24e2bSVaishali Kulkarni 		 * involving non intialized function in processing ROCE packet.
143514b24e2bSVaishali Kulkarni 		 */
143614b24e2bSVaishali Kulkarni 		num_pfs = NUM_OF_ENG_PFS(p_dev);
143714b24e2bSVaishali Kulkarni 		for (pf_id = 0; pf_id < num_pfs; pf_id++) {
143814b24e2bSVaishali Kulkarni 			ecore_fid_pretend(p_hwfn, p_ptt, pf_id);
143914b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0);
144014b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0);
144114b24e2bSVaishali Kulkarni 		}
144214b24e2bSVaishali Kulkarni 		/* pretend to original PF */
144314b24e2bSVaishali Kulkarni 		ecore_fid_pretend(p_hwfn, p_ptt, p_hwfn->rel_pf_id);
144414b24e2bSVaishali Kulkarni 	}
144514b24e2bSVaishali Kulkarni 
144614b24e2bSVaishali Kulkarni 	/* Workaround for avoiding CCFC execution error when getting packets
144714b24e2bSVaishali Kulkarni 	 * with CRC errors, and allowing instead the invoking of the FW error
144814b24e2bSVaishali Kulkarni 	 * handler.
144914b24e2bSVaishali Kulkarni 	 * This is not done inside the init tool since it currently can't
145014b24e2bSVaishali Kulkarni 	 * perform a pretending to VFs.
145114b24e2bSVaishali Kulkarni 	 */
145214b24e2bSVaishali Kulkarni 	max_num_vfs = ECORE_IS_AH(p_dev) ? MAX_NUM_VFS_K2 : MAX_NUM_VFS_BB;
145314b24e2bSVaishali Kulkarni 	for (vf_id = 0; vf_id < max_num_vfs; vf_id++) {
145414b24e2bSVaishali Kulkarni 		concrete_fid = ecore_vfid_to_concrete(p_hwfn, vf_id);
145514b24e2bSVaishali Kulkarni 		ecore_fid_pretend(p_hwfn, p_ptt, (u16)concrete_fid);
145614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, CCFC_REG_STRONG_ENABLE_VF, 0x1);
145714b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, CCFC_REG_WEAK_ENABLE_VF, 0x0);
145814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, TCFC_REG_STRONG_ENABLE_VF, 0x1);
145914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, TCFC_REG_WEAK_ENABLE_VF, 0x0);
146014b24e2bSVaishali Kulkarni 	}
146114b24e2bSVaishali Kulkarni 	/* pretend to original PF */
146214b24e2bSVaishali Kulkarni 	ecore_fid_pretend(p_hwfn, p_ptt, p_hwfn->rel_pf_id);
146314b24e2bSVaishali Kulkarni 
146414b24e2bSVaishali Kulkarni 	return rc;
146514b24e2bSVaishali Kulkarni }
146614b24e2bSVaishali Kulkarni 
146714b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
146814b24e2bSVaishali Kulkarni #define MISC_REG_RESET_REG_2_XMAC_BIT (1<<4)
146914b24e2bSVaishali Kulkarni #define MISC_REG_RESET_REG_2_XMAC_SOFT_BIT (1<<5)
147014b24e2bSVaishali Kulkarni 
147114b24e2bSVaishali Kulkarni #define PMEG_IF_BYTE_COUNT	8
147214b24e2bSVaishali Kulkarni 
ecore_wr_nw_port(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 addr,u64 data,u8 reg_type,u8 port)147314b24e2bSVaishali Kulkarni static void ecore_wr_nw_port(struct ecore_hwfn	*p_hwfn,
147414b24e2bSVaishali Kulkarni 			     struct ecore_ptt	*p_ptt,
147514b24e2bSVaishali Kulkarni 			     u32		addr,
147614b24e2bSVaishali Kulkarni 			     u64		data,
147714b24e2bSVaishali Kulkarni 			     u8			reg_type,
147814b24e2bSVaishali Kulkarni 			     u8			port)
147914b24e2bSVaishali Kulkarni {
148014b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
148114b24e2bSVaishali Kulkarni 		   "CMD: %08x, ADDR: 0x%08x, DATA: %08x:%08x\n",
148214b24e2bSVaishali Kulkarni 		   ecore_rd(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_CMD_BB) |
148314b24e2bSVaishali Kulkarni 		   (8 << PMEG_IF_BYTE_COUNT),
148414b24e2bSVaishali Kulkarni 		   (reg_type << 25) | (addr << 8) | port,
148514b24e2bSVaishali Kulkarni 		   (u32)((data >> 32) & 0xffffffff),
148614b24e2bSVaishali Kulkarni 		   (u32)(data & 0xffffffff));
148714b24e2bSVaishali Kulkarni 
148814b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_CMD_BB,
148914b24e2bSVaishali Kulkarni 		 (ecore_rd(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_CMD_BB) &
149014b24e2bSVaishali Kulkarni 		  0xffff00fe) |
149114b24e2bSVaishali Kulkarni 		 (8 << PMEG_IF_BYTE_COUNT));
149214b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_ADDR_BB,
149314b24e2bSVaishali Kulkarni 		 (reg_type << 25) | (addr << 8) | port);
149414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_WRDATA_BB, data & 0xffffffff);
149514b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, CNIG_REG_PMEG_IF_WRDATA_BB,
149614b24e2bSVaishali Kulkarni 		 (data >> 32) & 0xffffffff);
149714b24e2bSVaishali Kulkarni }
149814b24e2bSVaishali Kulkarni 
149914b24e2bSVaishali Kulkarni #define XLPORT_MODE_REG	(0x20a)
150014b24e2bSVaishali Kulkarni #define XLPORT_MAC_CONTROL (0x210)
150114b24e2bSVaishali Kulkarni #define XLPORT_FLOW_CONTROL_CONFIG (0x207)
150214b24e2bSVaishali Kulkarni #define XLPORT_ENABLE_REG (0x20b)
150314b24e2bSVaishali Kulkarni 
150414b24e2bSVaishali Kulkarni #define XLMAC_CTRL (0x600)
150514b24e2bSVaishali Kulkarni #define XLMAC_MODE (0x601)
150614b24e2bSVaishali Kulkarni #define XLMAC_RX_MAX_SIZE (0x608)
150714b24e2bSVaishali Kulkarni #define XLMAC_TX_CTRL (0x604)
150814b24e2bSVaishali Kulkarni #define XLMAC_PAUSE_CTRL (0x60d)
150914b24e2bSVaishali Kulkarni #define XLMAC_PFC_CTRL (0x60e)
151014b24e2bSVaishali Kulkarni 
ecore_emul_link_init_bb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)151114b24e2bSVaishali Kulkarni static void ecore_emul_link_init_bb(struct ecore_hwfn *p_hwfn,
151214b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt)
151314b24e2bSVaishali Kulkarni {
151414b24e2bSVaishali Kulkarni 	u8 loopback = 0, port = p_hwfn->port_id * 2;
151514b24e2bSVaishali Kulkarni 
151614b24e2bSVaishali Kulkarni 	DP_INFO(p_hwfn->p_dev, "Configurating Emulation Link %02x\n", port);
151714b24e2bSVaishali Kulkarni 
151814b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLPORT_MODE_REG,
151914b24e2bSVaishali Kulkarni 			 (0x4 << 4) | 0x4, 1, port); /* XLPORT MAC MODE */ /* 0 Quad, 4 Single... */
152014b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLPORT_MAC_CONTROL, 0, 1, port);
152114b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_CTRL,
152214b24e2bSVaishali Kulkarni 			 0x40, 0, port); /*XLMAC: SOFT RESET */
152314b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_MODE,
152414b24e2bSVaishali Kulkarni 			 0x40, 0, port); /*XLMAC: Port Speed >= 10Gbps */
152514b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_RX_MAX_SIZE,
152614b24e2bSVaishali Kulkarni 			 0x3fff, 0, port); /* XLMAC: Max Size */
152714b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_TX_CTRL,
152814b24e2bSVaishali Kulkarni 			 0x01000000800ULL | (0xa << 12) | ((u64)1 << 38),
152914b24e2bSVaishali Kulkarni 			 0, port);
153014b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_PAUSE_CTRL,
153114b24e2bSVaishali Kulkarni 			 0x7c000, 0, port);
153214b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_PFC_CTRL,
153314b24e2bSVaishali Kulkarni 			 0x30ffffc000ULL, 0, port);
153414b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_CTRL, 0x3 | (loopback << 2),
153514b24e2bSVaishali Kulkarni 			 0, port); /* XLMAC: TX_EN, RX_EN */
153614b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLMAC_CTRL, 0x1003 | (loopback << 2),
153714b24e2bSVaishali Kulkarni 			 0, port); /* XLMAC: TX_EN, RX_EN, SW_LINK_STATUS */
153814b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLPORT_FLOW_CONTROL_CONFIG,
153914b24e2bSVaishali Kulkarni 			 1, 0, port); /* Enabled Parallel PFC interface */
154014b24e2bSVaishali Kulkarni 	ecore_wr_nw_port(p_hwfn, p_ptt, XLPORT_ENABLE_REG,
154114b24e2bSVaishali Kulkarni 			 0xf, 1, port); /* XLPORT port enable */
154214b24e2bSVaishali Kulkarni }
154314b24e2bSVaishali Kulkarni 
ecore_emul_link_init_ah_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)154414b24e2bSVaishali Kulkarni static void ecore_emul_link_init_ah_e5(struct ecore_hwfn *p_hwfn,
154514b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt)
154614b24e2bSVaishali Kulkarni {
154714b24e2bSVaishali Kulkarni 	u8 port = p_hwfn->port_id;
154814b24e2bSVaishali Kulkarni 	u32 mac_base = NWM_REG_MAC0_K2_E5 + (port << 2) * NWM_REG_MAC0_SIZE;
154914b24e2bSVaishali Kulkarni 
155014b24e2bSVaishali Kulkarni 	DP_INFO(p_hwfn->p_dev, "Configurating Emulation Link %02x\n", port);
155114b24e2bSVaishali Kulkarni 
155214b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, CNIG_REG_NIG_PORT0_CONF_K2_E5 + (port << 2),
155314b24e2bSVaishali Kulkarni 		 (1 << CNIG_REG_NIG_PORT0_CONF_NIG_PORT_ENABLE_0_K2_E5_SHIFT) |
155414b24e2bSVaishali Kulkarni 		 (port <<
155514b24e2bSVaishali Kulkarni 		  CNIG_REG_NIG_PORT0_CONF_NIG_PORT_NWM_PORT_MAP_0_K2_E5_SHIFT) |
155614b24e2bSVaishali Kulkarni 		 (0 << CNIG_REG_NIG_PORT0_CONF_NIG_PORT_RATE_0_K2_E5_SHIFT));
155714b24e2bSVaishali Kulkarni 
155814b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_XIF_MODE_K2_E5,
155914b24e2bSVaishali Kulkarni 		 1 << ETH_MAC_REG_XIF_MODE_XGMII_K2_E5_SHIFT);
156014b24e2bSVaishali Kulkarni 
156114b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_FRM_LENGTH_K2_E5,
156214b24e2bSVaishali Kulkarni 		 9018 << ETH_MAC_REG_FRM_LENGTH_FRM_LENGTH_K2_E5_SHIFT);
156314b24e2bSVaishali Kulkarni 
156414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_TX_IPG_LENGTH_K2_E5,
156514b24e2bSVaishali Kulkarni 		 0xc << ETH_MAC_REG_TX_IPG_LENGTH_TXIPG_K2_E5_SHIFT);
156614b24e2bSVaishali Kulkarni 
156714b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_RX_FIFO_SECTIONS_K2_E5,
156814b24e2bSVaishali Kulkarni 		 8 << ETH_MAC_REG_RX_FIFO_SECTIONS_RX_SECTION_FULL_K2_E5_SHIFT);
156914b24e2bSVaishali Kulkarni 
157014b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_TX_FIFO_SECTIONS_K2_E5,
157114b24e2bSVaishali Kulkarni 		 (0xA <<
157214b24e2bSVaishali Kulkarni 		  ETH_MAC_REG_TX_FIFO_SECTIONS_TX_SECTION_EMPTY_K2_E5_SHIFT) |
157314b24e2bSVaishali Kulkarni 		 (8 <<
157414b24e2bSVaishali Kulkarni 		  ETH_MAC_REG_TX_FIFO_SECTIONS_TX_SECTION_FULL_K2_E5_SHIFT));
157514b24e2bSVaishali Kulkarni 
157614b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, mac_base + ETH_MAC_REG_COMMAND_CONFIG_K2_E5,
157714b24e2bSVaishali Kulkarni 		 0xa853);
157814b24e2bSVaishali Kulkarni }
157914b24e2bSVaishali Kulkarni 
ecore_emul_link_init(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)158014b24e2bSVaishali Kulkarni static void ecore_emul_link_init(struct ecore_hwfn *p_hwfn,
158114b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt)
158214b24e2bSVaishali Kulkarni {
158314b24e2bSVaishali Kulkarni 	if (ECORE_IS_AH(p_hwfn->p_dev) || ECORE_IS_E5(p_hwfn->p_dev))
158414b24e2bSVaishali Kulkarni 		ecore_emul_link_init_ah_e5(p_hwfn, p_ptt);
158514b24e2bSVaishali Kulkarni 	else /* BB */
158614b24e2bSVaishali Kulkarni 		ecore_emul_link_init_bb(p_hwfn, p_ptt);
158714b24e2bSVaishali Kulkarni 
158814b24e2bSVaishali Kulkarni 	return;
158914b24e2bSVaishali Kulkarni }
159014b24e2bSVaishali Kulkarni 
ecore_link_init_bb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 port)159114b24e2bSVaishali Kulkarni static void ecore_link_init_bb(struct ecore_hwfn *p_hwfn,
159214b24e2bSVaishali Kulkarni 			       struct ecore_ptt *p_ptt,  u8 port)
159314b24e2bSVaishali Kulkarni {
159414b24e2bSVaishali Kulkarni 	int port_offset = port ? 0x800 : 0;
159514b24e2bSVaishali Kulkarni 	u32 xmac_rxctrl	= 0;
159614b24e2bSVaishali Kulkarni 
159714b24e2bSVaishali Kulkarni 	/* Reset of XMAC */
159814b24e2bSVaishali Kulkarni 	/* FIXME: move to common start */
159914b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_RESET_PL_PDA_VAUX + 2*sizeof(u32),
160014b24e2bSVaishali Kulkarni 		 MISC_REG_RESET_REG_2_XMAC_BIT); /* Clear */
160114b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(1);
160214b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_RESET_PL_PDA_VAUX + sizeof(u32),
160314b24e2bSVaishali Kulkarni 		 MISC_REG_RESET_REG_2_XMAC_BIT); /* Set */
160414b24e2bSVaishali Kulkarni 
160514b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_XMAC_CORE_PORT_MODE_BB, 1);
160614b24e2bSVaishali Kulkarni 
160714b24e2bSVaishali Kulkarni 	/* Set the number of ports on the Warp Core to 10G */
160814b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_XMAC_PHY_PORT_MODE_BB, 3);
160914b24e2bSVaishali Kulkarni 
161014b24e2bSVaishali Kulkarni 	/* Soft reset of XMAC */
161114b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_RESET_PL_PDA_VAUX + 2 * sizeof(u32),
161214b24e2bSVaishali Kulkarni 		 MISC_REG_RESET_REG_2_XMAC_SOFT_BIT);
161314b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(1);
161414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_RESET_PL_PDA_VAUX + sizeof(u32),
161514b24e2bSVaishali Kulkarni 		 MISC_REG_RESET_REG_2_XMAC_SOFT_BIT);
161614b24e2bSVaishali Kulkarni 
161714b24e2bSVaishali Kulkarni 	/* FIXME: move to common end */
161814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev))
161914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, XMAC_REG_MODE_BB + port_offset, 0x20);
162014b24e2bSVaishali Kulkarni 
162114b24e2bSVaishali Kulkarni 	/* Set Max packet size: initialize XMAC block register for port 0 */
162214b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, XMAC_REG_RX_MAX_SIZE_BB + port_offset, 0x2710);
162314b24e2bSVaishali Kulkarni 
162414b24e2bSVaishali Kulkarni 	/* CRC append for Tx packets: init XMAC block register for port 1 */
162514b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, XMAC_REG_TX_CTRL_LO_BB + port_offset, 0xC800);
162614b24e2bSVaishali Kulkarni 
162714b24e2bSVaishali Kulkarni 	/* Enable TX and RX: initialize XMAC block register for port 1 */
162814b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, XMAC_REG_CTRL_BB + port_offset,
162914b24e2bSVaishali Kulkarni 		 XMAC_REG_CTRL_TX_EN_BB | XMAC_REG_CTRL_RX_EN_BB);
163014b24e2bSVaishali Kulkarni 	xmac_rxctrl = ecore_rd(p_hwfn, p_ptt,
163114b24e2bSVaishali Kulkarni 			       XMAC_REG_RX_CTRL_BB + port_offset);
163214b24e2bSVaishali Kulkarni 	xmac_rxctrl |= XMAC_REG_RX_CTRL_PROCESS_VARIABLE_PREAMBLE_BB;
163314b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, XMAC_REG_RX_CTRL_BB + port_offset, xmac_rxctrl);
163414b24e2bSVaishali Kulkarni }
163514b24e2bSVaishali Kulkarni #endif
163614b24e2bSVaishali Kulkarni 
163714b24e2bSVaishali Kulkarni 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)163814b24e2bSVaishali Kulkarni ecore_hw_init_dpi_size(struct ecore_hwfn *p_hwfn,
163914b24e2bSVaishali Kulkarni 		       struct ecore_ptt *p_ptt,
164014b24e2bSVaishali Kulkarni 		       u32 pwm_region_size,
164114b24e2bSVaishali Kulkarni 		       u32 n_cpus)
164214b24e2bSVaishali Kulkarni {
164314b24e2bSVaishali Kulkarni 	u32 dpi_page_size_1, dpi_page_size_2, dpi_page_size;
164414b24e2bSVaishali Kulkarni 	u32 dpi_bit_shift, dpi_count;
164514b24e2bSVaishali Kulkarni 	u32 min_dpis;
164614b24e2bSVaishali Kulkarni 
164714b24e2bSVaishali Kulkarni 	/* Calculate DPI size
164814b24e2bSVaishali Kulkarni 	 * ------------------
164914b24e2bSVaishali Kulkarni 	 * The PWM region contains Doorbell Pages. The first is reserverd for
165014b24e2bSVaishali Kulkarni 	 * the kernel for, e.g, L2. The others are free to be used by non-
165114b24e2bSVaishali Kulkarni 	 * trusted applications, typically from user space. Each page, called a
165214b24e2bSVaishali Kulkarni 	 * doorbell page is sectioned into windows that allow doorbells to be
165314b24e2bSVaishali Kulkarni 	 * issued in parallel by the kernel/application. The size of such a
165414b24e2bSVaishali Kulkarni 	 * window (a.k.a. WID) is 1kB.
165514b24e2bSVaishali Kulkarni 	 * Summary:
165614b24e2bSVaishali Kulkarni 	 *    1kB WID x N WIDS = DPI page size
165714b24e2bSVaishali Kulkarni 	 *    DPI page size x N DPIs = PWM region size
165814b24e2bSVaishali Kulkarni 	 * Notes:
165914b24e2bSVaishali Kulkarni 	 * The size of the DPI page size must be in multiples of OSAL_PAGE_SIZE
166014b24e2bSVaishali Kulkarni 	 * in order to ensure that two applications won't share the same page.
166114b24e2bSVaishali Kulkarni 	 * It also must contain at least one WID per CPU to allow parallelism.
166214b24e2bSVaishali Kulkarni 	 * It also must be a power of 2, since it is stored as a bit shift.
166314b24e2bSVaishali Kulkarni 	 *
166414b24e2bSVaishali Kulkarni 	 * The DPI page size is stored in a register as 'dpi_bit_shift' so that
166514b24e2bSVaishali Kulkarni 	 * 0 is 4kB, 1 is 8kB and etc. Hence the minimum size is 4,096
166614b24e2bSVaishali Kulkarni 	 * containing 4 WIDs.
166714b24e2bSVaishali Kulkarni 	 */
166814b24e2bSVaishali Kulkarni 	dpi_page_size_1 = ECORE_WID_SIZE * n_cpus;
166914b24e2bSVaishali Kulkarni 	dpi_page_size_2 = OSAL_MAX_T(u32, ECORE_WID_SIZE, OSAL_PAGE_SIZE);
167014b24e2bSVaishali Kulkarni 	dpi_page_size = OSAL_MAX_T(u32, dpi_page_size_1, dpi_page_size_2);
167114b24e2bSVaishali Kulkarni 	dpi_page_size = OSAL_ROUNDUP_POW_OF_TWO(dpi_page_size);
167214b24e2bSVaishali Kulkarni 	dpi_bit_shift = OSAL_LOG2(dpi_page_size / 4096);
167314b24e2bSVaishali Kulkarni 
167414b24e2bSVaishali Kulkarni 	dpi_count = pwm_region_size / dpi_page_size;
167514b24e2bSVaishali Kulkarni 
167614b24e2bSVaishali Kulkarni 	min_dpis = p_hwfn->pf_params.rdma_pf_params.min_dpis;
167714b24e2bSVaishali Kulkarni 	min_dpis = OSAL_MAX_T(u32, ECORE_MIN_DPIS, min_dpis);
167814b24e2bSVaishali Kulkarni 
167914b24e2bSVaishali Kulkarni 	/* Update hwfn */
168014b24e2bSVaishali Kulkarni 	p_hwfn->dpi_size = dpi_page_size;
168114b24e2bSVaishali Kulkarni 	p_hwfn->dpi_count = dpi_count;
168214b24e2bSVaishali Kulkarni 
168314b24e2bSVaishali Kulkarni 	/* Update registers */
168414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_DPI_BIT_SHIFT, dpi_bit_shift);
168514b24e2bSVaishali Kulkarni 
168614b24e2bSVaishali Kulkarni 	if (dpi_count < min_dpis)
168714b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
168814b24e2bSVaishali Kulkarni 
168914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
169014b24e2bSVaishali Kulkarni }
169114b24e2bSVaishali Kulkarni 
169214b24e2bSVaishali Kulkarni enum ECORE_ROCE_EDPM_MODE {
169314b24e2bSVaishali Kulkarni 	ECORE_ROCE_EDPM_MODE_ENABLE	= 0,
169414b24e2bSVaishali Kulkarni 	ECORE_ROCE_EDPM_MODE_FORCE_ON	= 1,
169514b24e2bSVaishali Kulkarni 	ECORE_ROCE_EDPM_MODE_DISABLE	= 2,
169614b24e2bSVaishali Kulkarni };
169714b24e2bSVaishali Kulkarni 
169814b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_hw_init_pf_doorbell_bar(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)169914b24e2bSVaishali Kulkarni ecore_hw_init_pf_doorbell_bar(struct ecore_hwfn *p_hwfn,
170014b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt)
170114b24e2bSVaishali Kulkarni {
170214b24e2bSVaishali Kulkarni 	u32 pwm_regsize, norm_regsize;
170314b24e2bSVaishali Kulkarni 	u32 non_pwm_conn, min_addr_reg1;
170414b24e2bSVaishali Kulkarni 	u32 db_bar_size, n_cpus = 1;
170514b24e2bSVaishali Kulkarni 	u32 roce_edpm_mode;
170614b24e2bSVaishali Kulkarni 	u32 pf_dems_shift;
170714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
170814b24e2bSVaishali Kulkarni 	u8 cond;
170914b24e2bSVaishali Kulkarni 
171014b24e2bSVaishali Kulkarni 	db_bar_size = ecore_hw_bar_size(p_hwfn, BAR_ID_1);
171114b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->num_hwfns > 1)
171214b24e2bSVaishali Kulkarni 		db_bar_size /= 2;
171314b24e2bSVaishali Kulkarni 
171414b24e2bSVaishali Kulkarni 	/* Calculate doorbell regions
171514b24e2bSVaishali Kulkarni 	 * -----------------------------------
171614b24e2bSVaishali Kulkarni 	 * The doorbell BAR is made of two regions. The first is called normal
171714b24e2bSVaishali Kulkarni 	 * region and the second is called PWM region. In the normal region
171814b24e2bSVaishali Kulkarni 	 * each ICID has its own set of addresses so that writing to that
171914b24e2bSVaishali Kulkarni 	 * specific address identifies the ICID. In the Process Window Mode
172014b24e2bSVaishali Kulkarni 	 * region the ICID is given in the data written to the doorbell. The
172114b24e2bSVaishali Kulkarni 	 * above per PF register denotes the offset in the doorbell BAR in which
172214b24e2bSVaishali Kulkarni 	 * the PWM region begins.
172314b24e2bSVaishali Kulkarni 	 * The normal region has ECORE_PF_DEMS_SIZE bytes per ICID, that is per
172414b24e2bSVaishali Kulkarni 	 * non-PWM connection. The calculation below computes the total non-PWM
172514b24e2bSVaishali Kulkarni 	 * connections. The DORQ_REG_PF_MIN_ADDR_REG1 register is
172614b24e2bSVaishali Kulkarni 	 * in units of 4,096 bytes.
172714b24e2bSVaishali Kulkarni 	 */
172814b24e2bSVaishali Kulkarni 	non_pwm_conn = ecore_cxt_get_proto_cid_start(p_hwfn, PROTOCOLID_CORE) +
172914b24e2bSVaishali Kulkarni 		       ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_CORE,
173014b24e2bSVaishali Kulkarni 						     OSAL_NULL) +
173114b24e2bSVaishali Kulkarni 		       ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
173214b24e2bSVaishali Kulkarni 						     OSAL_NULL);
173314b24e2bSVaishali Kulkarni 	norm_regsize = ROUNDUP(ECORE_PF_DEMS_SIZE * non_pwm_conn, 4096);
173414b24e2bSVaishali Kulkarni 	min_addr_reg1 = norm_regsize / 4096;
173514b24e2bSVaishali Kulkarni 	pwm_regsize = db_bar_size - norm_regsize;
173614b24e2bSVaishali Kulkarni 
173714b24e2bSVaishali Kulkarni 	/* Check that the normal and PWM sizes are valid */
173814b24e2bSVaishali Kulkarni 	if (db_bar_size < norm_regsize) {
173914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn->p_dev, "Doorbell BAR size 0x%x is too small (normal region is 0x%0x )\n", db_bar_size, norm_regsize);
174014b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
174114b24e2bSVaishali Kulkarni 	}
174214b24e2bSVaishali Kulkarni 	if (pwm_regsize < ECORE_MIN_PWM_REGION) {
174314b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn->p_dev, "PWM region size 0x%0x is too small. Should be at least 0x%0x (Doorbell BAR size is 0x%x and normal region size is 0x%0x)\n", pwm_regsize, ECORE_MIN_PWM_REGION, db_bar_size, norm_regsize);
174414b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
174514b24e2bSVaishali Kulkarni 	}
174614b24e2bSVaishali Kulkarni 
174714b24e2bSVaishali Kulkarni 	/* Calculate number of DPIs */
174814b24e2bSVaishali Kulkarni 	roce_edpm_mode = p_hwfn->pf_params.rdma_pf_params.roce_edpm_mode;
174914b24e2bSVaishali Kulkarni 	if ((roce_edpm_mode == ECORE_ROCE_EDPM_MODE_ENABLE) ||
175014b24e2bSVaishali Kulkarni 	    ((roce_edpm_mode == ECORE_ROCE_EDPM_MODE_FORCE_ON))) {
175114b24e2bSVaishali Kulkarni 		/* Either EDPM is mandatory, or we are attempting to allocate a
175214b24e2bSVaishali Kulkarni 		 * WID per CPU.
175314b24e2bSVaishali Kulkarni 		 */
175414b24e2bSVaishali Kulkarni 		n_cpus = OSAL_NUM_ACTIVE_CPU();
175514b24e2bSVaishali Kulkarni 		rc = ecore_hw_init_dpi_size(p_hwfn, p_ptt, pwm_regsize, n_cpus);
175614b24e2bSVaishali Kulkarni 	}
175714b24e2bSVaishali Kulkarni 
175814b24e2bSVaishali Kulkarni 	cond = ((rc != ECORE_SUCCESS) &&
175914b24e2bSVaishali Kulkarni 		(roce_edpm_mode == ECORE_ROCE_EDPM_MODE_ENABLE)) ||
176014b24e2bSVaishali Kulkarni 		(roce_edpm_mode == ECORE_ROCE_EDPM_MODE_DISABLE);
176114b24e2bSVaishali Kulkarni 	if (cond || p_hwfn->dcbx_no_edpm) {
176214b24e2bSVaishali Kulkarni 		/* Either EDPM is disabled from user configuration, or it is
176314b24e2bSVaishali Kulkarni 		 * disabled via DCBx, or it is not mandatory and we failed to
176414b24e2bSVaishali Kulkarni 		 * allocated a WID per CPU.
176514b24e2bSVaishali Kulkarni 		 */
176614b24e2bSVaishali Kulkarni 		n_cpus = 1;
176714b24e2bSVaishali Kulkarni 		rc = ecore_hw_init_dpi_size(p_hwfn, p_ptt, pwm_regsize, n_cpus);
176814b24e2bSVaishali Kulkarni 
176914b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
177014b24e2bSVaishali Kulkarni 		/* If we entered this flow due to DCBX then the DPM register is
177114b24e2bSVaishali Kulkarni 		 * already configured.
177214b24e2bSVaishali Kulkarni 		 */
177314b24e2bSVaishali Kulkarni 		if (cond)
177414b24e2bSVaishali Kulkarni 			ecore_rdma_dpm_bar(p_hwfn, p_ptt);
177514b24e2bSVaishali Kulkarni #endif
177614b24e2bSVaishali Kulkarni 	}
177714b24e2bSVaishali Kulkarni 
177814b24e2bSVaishali Kulkarni 	p_hwfn->wid_count = (u16)n_cpus;
177914b24e2bSVaishali Kulkarni 
178014b24e2bSVaishali Kulkarni 	DP_INFO(p_hwfn, "doorbell bar: normal_region_size=%d, pwm_region_size=%d, dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
178114b24e2bSVaishali Kulkarni 		norm_regsize, pwm_regsize, p_hwfn->dpi_size, p_hwfn->dpi_count,
178214b24e2bSVaishali Kulkarni 		((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
178314b24e2bSVaishali Kulkarni 		"disabled" : "enabled");
178414b24e2bSVaishali Kulkarni 
178514b24e2bSVaishali Kulkarni 	/* Check return codes from above calls */
178614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
178714b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
178814b24e2bSVaishali Kulkarni 		       "Failed to allocate enough DPIs. Allocated %d but the current minimum is %d. You can try reducing this down to %d via user configuration n_dpi or by disabling EDPM via user configuration roce_edpm\n",
178914b24e2bSVaishali Kulkarni 		       p_hwfn->dpi_count,
179014b24e2bSVaishali Kulkarni 		       p_hwfn->pf_params.rdma_pf_params.min_dpis,
179114b24e2bSVaishali Kulkarni 		       ECORE_MIN_DPIS);
179214b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
179314b24e2bSVaishali Kulkarni 	}
179414b24e2bSVaishali Kulkarni 
179514b24e2bSVaishali Kulkarni 	/* Update hwfn */
179614b24e2bSVaishali Kulkarni 	p_hwfn->dpi_start_offset = norm_regsize; /* this is later used to
179714b24e2bSVaishali Kulkarni 						      * calculate the doorbell
179814b24e2bSVaishali Kulkarni 						      * address
179914b24e2bSVaishali Kulkarni 						      */
180014b24e2bSVaishali Kulkarni 
180114b24e2bSVaishali Kulkarni 	/* Update registers */
180214b24e2bSVaishali Kulkarni 	/* DEMS size is configured log2 of DWORDs, hence the division by 4 */
180314b24e2bSVaishali Kulkarni 	pf_dems_shift = OSAL_LOG2(ECORE_PF_DEMS_SIZE / 4);
180414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_ICID_BIT_SHIFT_NORM, pf_dems_shift);
180514b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_MIN_ADDR_REG1, min_addr_reg1);
180614b24e2bSVaishali Kulkarni 
180714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
180814b24e2bSVaishali Kulkarni }
180914b24e2bSVaishali Kulkarni 
ecore_hw_init_port(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int hw_mode)181014b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
181114b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt,
181214b24e2bSVaishali Kulkarni 					       int hw_mode)
181314b24e2bSVaishali Kulkarni {
181414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc	= ECORE_SUCCESS;
181514b24e2bSVaishali Kulkarni 
181614b24e2bSVaishali Kulkarni 	rc = ecore_init_run(p_hwfn, p_ptt, PHASE_PORT, p_hwfn->port_id,
181714b24e2bSVaishali Kulkarni 			    hw_mode);
181814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
181914b24e2bSVaishali Kulkarni 		return rc;
182014b24e2bSVaishali Kulkarni #if 0
182114b24e2bSVaishali Kulkarni 	/* FW 8.10.5.0 requires us to configure PF_VECTOR and DUALMODE in LLH.
182214b24e2bSVaishali Kulkarni 	 * This would hopefully be moved to MFW.
182314b24e2bSVaishali Kulkarni 	 */
182414b24e2bSVaishali Kulkarni 	if (IS_MF_DEFAULT(p_hwfn) || IS_MF_SI(p_hwfn)) {
182514b24e2bSVaishali Kulkarni 		u8 pf_id = 0;
182614b24e2bSVaishali Kulkarni 
182714b24e2bSVaishali Kulkarni 		if (ecore_hw_init_first_eth(p_hwfn, p_ptt, &pf_id) ==
182814b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS) {
182914b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
183014b24e2bSVaishali Kulkarni 				   "PF[%08x] is first eth on engine\n",
183114b24e2bSVaishali Kulkarni 				   pf_id);
183214b24e2bSVaishali Kulkarni 
183314b24e2bSVaishali Kulkarni 			/* We should have configured BIT for ppfid, i.e., the
183414b24e2bSVaishali Kulkarni 			 * relative function number in the port. But there's a
183514b24e2bSVaishali Kulkarni 			 * bug in LLH in BB where the ppfid is actually engine
183614b24e2bSVaishali Kulkarni 			 * based, so we need to take this into account.
183714b24e2bSVaishali Kulkarni 			 */
183814b24e2bSVaishali Kulkarni 			if (!ECORE_IS_BB(p_hwfn->p_dev))
183914b24e2bSVaishali Kulkarni 				pf_id /= p_hwfn->p_dev->num_ports_in_engine;
184014b24e2bSVaishali Kulkarni 
184114b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt,
184214b24e2bSVaishali Kulkarni 				 NIG_REG_LLH_TAGMAC_DEF_PF_VECTOR, 1 << pf_id);
184314b24e2bSVaishali Kulkarni 		}
184414b24e2bSVaishali Kulkarni 
184514b24e2bSVaishali Kulkarni 		/* Take the protocol-based hit vector if there is a hit,
184614b24e2bSVaishali Kulkarni 		 * otherwise take the other vector.
184714b24e2bSVaishali Kulkarni 		 */
184814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, NIG_REG_LLH_CLS_TYPE_DUALMODE, 0x2);
184914b24e2bSVaishali Kulkarni 	}
185014b24e2bSVaishali Kulkarni #endif
185114b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
185214b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_ASIC(p_hwfn->p_dev))
185314b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
185414b24e2bSVaishali Kulkarni 
185514b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
185614b24e2bSVaishali Kulkarni 		if (ECORE_IS_AH(p_hwfn->p_dev))
185714b24e2bSVaishali Kulkarni 			return ECORE_SUCCESS;
185814b24e2bSVaishali Kulkarni 		else if (ECORE_IS_BB(p_hwfn->p_dev))
185914b24e2bSVaishali Kulkarni 			ecore_link_init_bb(p_hwfn, p_ptt, p_hwfn->port_id);
186014b24e2bSVaishali Kulkarni 		else /* E5 */
186114b24e2bSVaishali Kulkarni 			ECORE_E5_MISSING_CODE;
186214b24e2bSVaishali Kulkarni 	} else if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
186314b24e2bSVaishali Kulkarni 		if (p_hwfn->p_dev->num_hwfns > 1) {
186414b24e2bSVaishali Kulkarni 			/* Activate OPTE in CMT */
186514b24e2bSVaishali Kulkarni 			u32 val;
186614b24e2bSVaishali Kulkarni 
186714b24e2bSVaishali Kulkarni 			val = ecore_rd(p_hwfn, p_ptt, MISCS_REG_RESET_PL_HV);
186814b24e2bSVaishali Kulkarni 			val |= 0x10;
186914b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISCS_REG_RESET_PL_HV, val);
187014b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISC_REG_CLK_100G_MODE, 1);
187114b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISCS_REG_CLK_100G_MODE, 1);
187214b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, MISC_REG_OPTE_MODE, 1);
187314b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt,
187414b24e2bSVaishali Kulkarni 				 NIG_REG_LLH_ENG_CLS_TCP_4_TUPLE_SEARCH, 1);
187514b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt,
187614b24e2bSVaishali Kulkarni 				 NIG_REG_LLH_ENG_CLS_ENG_ID_TBL, 0x55555555);
187714b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt,
187814b24e2bSVaishali Kulkarni 				 NIG_REG_LLH_ENG_CLS_ENG_ID_TBL + 0x4,
187914b24e2bSVaishali Kulkarni 				 0x55555555);
188014b24e2bSVaishali Kulkarni 		}
188114b24e2bSVaishali Kulkarni 
188214b24e2bSVaishali Kulkarni 		ecore_emul_link_init(p_hwfn, p_ptt);
188314b24e2bSVaishali Kulkarni 	} else {
188414b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn->p_dev, "link is not being configured\n");
188514b24e2bSVaishali Kulkarni 	}
188614b24e2bSVaishali Kulkarni #endif
188714b24e2bSVaishali Kulkarni 
188814b24e2bSVaishali Kulkarni 	return rc;
188914b24e2bSVaishali Kulkarni }
189014b24e2bSVaishali Kulkarni 
ecore_hw_init_pf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_tunnel_info * p_tunn,int hw_mode,bool b_hw_start,enum ecore_int_mode int_mode,bool allow_npar_tx_switch)189114b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_init_pf(struct ecore_hwfn *p_hwfn,
189214b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
189314b24e2bSVaishali Kulkarni 					      struct ecore_tunnel_info *p_tunn,
189414b24e2bSVaishali Kulkarni 					      int hw_mode,
189514b24e2bSVaishali Kulkarni 					      bool b_hw_start,
189614b24e2bSVaishali Kulkarni 					      enum ecore_int_mode int_mode,
189714b24e2bSVaishali Kulkarni 					      bool allow_npar_tx_switch)
189814b24e2bSVaishali Kulkarni {
189914b24e2bSVaishali Kulkarni 	u8 rel_pf_id = p_hwfn->rel_pf_id;
190014b24e2bSVaishali Kulkarni 	u32 prs_reg;
190114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc	= ECORE_SUCCESS;
190214b24e2bSVaishali Kulkarni 	u16 ctrl;
190314b24e2bSVaishali Kulkarni 	int pos;
190414b24e2bSVaishali Kulkarni 
190514b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info) {
190614b24e2bSVaishali Kulkarni 		struct ecore_mcp_function_info *p_info;
190714b24e2bSVaishali Kulkarni 
190814b24e2bSVaishali Kulkarni 		p_info = &p_hwfn->mcp_info->func_info;
190914b24e2bSVaishali Kulkarni 		if (p_info->bandwidth_min)
191014b24e2bSVaishali Kulkarni 			p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min;
191114b24e2bSVaishali Kulkarni 
191214b24e2bSVaishali Kulkarni 		/* Update rate limit once we'll actually have a link */
191314b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.pf_rl = 100000;
191414b24e2bSVaishali Kulkarni 	}
191514b24e2bSVaishali Kulkarni 	ecore_cxt_hw_init_pf(p_hwfn);
191614b24e2bSVaishali Kulkarni 
191714b24e2bSVaishali Kulkarni 	ecore_int_igu_init_rt(p_hwfn);
191814b24e2bSVaishali Kulkarni 
191914b24e2bSVaishali Kulkarni 	/* Set VLAN in NIG if needed */
192014b24e2bSVaishali Kulkarni 	if (hw_mode & (1 << MODE_MF_SD)) {
192114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "Configuring LLH_FUNC_TAG\n");
192214b24e2bSVaishali Kulkarni 		STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET, 1);
192314b24e2bSVaishali Kulkarni 		STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET,
192414b24e2bSVaishali Kulkarni 			     p_hwfn->hw_info.ovlan);
192514b24e2bSVaishali Kulkarni 	}
192614b24e2bSVaishali Kulkarni 
192714b24e2bSVaishali Kulkarni 	/* Enable classification by MAC if needed */
192814b24e2bSVaishali Kulkarni 	if (hw_mode & (1 << MODE_MF_SI)) {
192914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW, "Configuring TAGMAC_CLS_TYPE\n");
193014b24e2bSVaishali Kulkarni 		STORE_RT_REG(p_hwfn,
193114b24e2bSVaishali Kulkarni 			     NIG_REG_LLH_FUNC_TAGMAC_CLS_TYPE_RT_OFFSET, 1);
193214b24e2bSVaishali Kulkarni 	}
193314b24e2bSVaishali Kulkarni 
193414b24e2bSVaishali Kulkarni 	/* Protocl Configuration  - @@@TBD - should we set 0 otherwise?*/
193514b24e2bSVaishali Kulkarni 	STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET,
193614b24e2bSVaishali Kulkarni 		     (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI) ? 1 : 0);
193714b24e2bSVaishali Kulkarni 	STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_FCOE_RT_OFFSET,
193814b24e2bSVaishali Kulkarni 		     (p_hwfn->hw_info.personality == ECORE_PCI_FCOE) ? 1 : 0);
193914b24e2bSVaishali Kulkarni 	STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0);
194014b24e2bSVaishali Kulkarni 
194114b24e2bSVaishali Kulkarni 	/* perform debug configuration when chip is out of reset */
194214b24e2bSVaishali Kulkarni 	OSAL_BEFORE_PF_START((void *)p_hwfn->p_dev, p_hwfn->my_id);
194314b24e2bSVaishali Kulkarni 
194414b24e2bSVaishali Kulkarni 	/* Cleanup chip from previous driver if such remains exist */
194514b24e2bSVaishali Kulkarni 	rc = ecore_final_cleanup(p_hwfn, p_ptt, rel_pf_id, false);
194614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
194714b24e2bSVaishali Kulkarni 		ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_RAMROD_FAIL);
194814b24e2bSVaishali Kulkarni 		return rc;
194914b24e2bSVaishali Kulkarni 	}
195014b24e2bSVaishali Kulkarni 
195114b24e2bSVaishali Kulkarni 	/* PF Init sequence */
195214b24e2bSVaishali Kulkarni 	rc = ecore_init_run(p_hwfn, p_ptt, PHASE_PF, rel_pf_id, hw_mode);
195314b24e2bSVaishali Kulkarni 	if (rc)
195414b24e2bSVaishali Kulkarni 		return rc;
195514b24e2bSVaishali Kulkarni 
195614b24e2bSVaishali Kulkarni 	/* QM_PF Init sequence (may be invoked separately e.g. for DCB) */
195714b24e2bSVaishali Kulkarni 	rc = ecore_init_run(p_hwfn, p_ptt, PHASE_QM_PF, rel_pf_id, hw_mode);
195814b24e2bSVaishali Kulkarni 	if (rc)
195914b24e2bSVaishali Kulkarni 		return rc;
196014b24e2bSVaishali Kulkarni 
196114b24e2bSVaishali Kulkarni 	/* Pure runtime initializations - directly to the HW  */
196214b24e2bSVaishali Kulkarni 	ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true);
196314b24e2bSVaishali Kulkarni 
196414b24e2bSVaishali Kulkarni 	/* PCI relaxed ordering causes a decrease in the performance on some
196514b24e2bSVaishali Kulkarni 	 * systems. Till a root cause is found, disable this attribute in the
196614b24e2bSVaishali Kulkarni 	 * PCI config space.
196714b24e2bSVaishali Kulkarni 	 */
196814b24e2bSVaishali Kulkarni 	pos = OSAL_PCI_FIND_CAPABILITY(p_hwfn->p_dev, PCI_CAP_ID_EXP);
196914b24e2bSVaishali Kulkarni 	if (!pos) {
197014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
197114b24e2bSVaishali Kulkarni 			  "Failed to find the PCI Express Capability structure in the PCI config space\n");
197214b24e2bSVaishali Kulkarni 		return ECORE_IO;
197314b24e2bSVaishali Kulkarni 	}
197414b24e2bSVaishali Kulkarni 	OSAL_PCI_READ_CONFIG_WORD(p_hwfn->p_dev, pos + PCI_EXP_DEVCTL, &ctrl);
197514b24e2bSVaishali Kulkarni 	ctrl &= ~PCI_EXP_DEVCTL_RELAX_EN;
197614b24e2bSVaishali Kulkarni 	OSAL_PCI_WRITE_CONFIG_WORD(p_hwfn->p_dev, pos + PCI_EXP_DEVCTL, ctrl);
197714b24e2bSVaishali Kulkarni 
197814b24e2bSVaishali Kulkarni 	rc = ecore_hw_init_pf_doorbell_bar(p_hwfn, p_ptt);
197914b24e2bSVaishali Kulkarni 	if (rc)
198014b24e2bSVaishali Kulkarni 		return rc;
198114b24e2bSVaishali Kulkarni #if 0
198214b24e2bSVaishali Kulkarni 	/* FW 8.10.5.0 requires us to configure MSG_INFO in PRS.
198314b24e2bSVaishali Kulkarni 	 * This would hopefully be moved to MFW.
198414b24e2bSVaishali Kulkarni 	 */
198514b24e2bSVaishali Kulkarni 	if (IS_MF_SI(p_hwfn)) {
198614b24e2bSVaishali Kulkarni 		u8 pf_id = 0;
198714b24e2bSVaishali Kulkarni 		u32 val;
198814b24e2bSVaishali Kulkarni 
198914b24e2bSVaishali Kulkarni 		if (ecore_hw_init_first_eth(p_hwfn, p_ptt, &pf_id) ==
199014b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS) {
199114b24e2bSVaishali Kulkarni 			if (p_hwfn->rel_pf_id == pf_id) {
199214b24e2bSVaishali Kulkarni 				DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
199314b24e2bSVaishali Kulkarni 					   "PF[%d] is first ETH on engine\n",
199414b24e2bSVaishali Kulkarni 					   pf_id);
199514b24e2bSVaishali Kulkarni 				val = 1;
199614b24e2bSVaishali Kulkarni 			}
199714b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt, PRS_REG_MSG_INFO, val);
199814b24e2bSVaishali Kulkarni 		}
199914b24e2bSVaishali Kulkarni 	}
200014b24e2bSVaishali Kulkarni #endif
200114b24e2bSVaishali Kulkarni 	if (b_hw_start) {
200214b24e2bSVaishali Kulkarni 		/* enable interrupts */
200314b24e2bSVaishali Kulkarni 		rc = ecore_int_igu_enable(p_hwfn, p_ptt, int_mode);
200414b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
200514b24e2bSVaishali Kulkarni 			return rc;
200614b24e2bSVaishali Kulkarni 
200714b24e2bSVaishali Kulkarni 		/* send function start command */
200814b24e2bSVaishali Kulkarni 		rc = ecore_sp_pf_start(p_hwfn, p_tunn, p_hwfn->p_dev->mf_mode,
200914b24e2bSVaishali Kulkarni 				       allow_npar_tx_switch);
201014b24e2bSVaishali Kulkarni 		if (rc) {
201114b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true, "Function start ramrod failed\n");
201214b24e2bSVaishali Kulkarni 		} else {
201314b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_TAG1);
201414b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
201514b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_TAG1: %x\n", prs_reg);
201614b24e2bSVaishali Kulkarni 
201714b24e2bSVaishali Kulkarni 			if (p_hwfn->hw_info.personality == ECORE_PCI_FCOE)
201814b24e2bSVaishali Kulkarni 			{
201914b24e2bSVaishali Kulkarni 				ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TAG1,
202014b24e2bSVaishali Kulkarni 					 (1 << 2));
202114b24e2bSVaishali Kulkarni 				ecore_wr(p_hwfn, p_ptt,
202214b24e2bSVaishali Kulkarni 					 PRS_REG_PKT_LEN_STAT_TAGS_NOT_COUNTED_FIRST,
202314b24e2bSVaishali Kulkarni 					 0x100);
202414b24e2bSVaishali Kulkarni 			}
202514b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
202614b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH registers after start PFn\n");
202714b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP);
202814b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
202914b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_TCP: %x\n", prs_reg);
203014b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP);
203114b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
203214b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_UDP: %x\n", prs_reg);
203314b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE);
203414b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
203514b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_FCOE: %x\n", prs_reg);
203614b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE);
203714b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
203814b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_ROCE: %x\n", prs_reg);
203914b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt,
204014b24e2bSVaishali Kulkarni 					   PRS_REG_SEARCH_TCP_FIRST_FRAG);
204114b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
204214b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_TCP_FIRST_FRAG: %x\n",
204314b24e2bSVaishali Kulkarni 				   prs_reg);
204414b24e2bSVaishali Kulkarni 			prs_reg = ecore_rd(p_hwfn, p_ptt, PRS_REG_SEARCH_TAG1);
204514b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
204614b24e2bSVaishali Kulkarni 				   "PRS_REG_SEARCH_TAG1: %x\n", prs_reg);
204714b24e2bSVaishali Kulkarni 		}
204814b24e2bSVaishali Kulkarni 	}
204914b24e2bSVaishali Kulkarni 	return rc;
205014b24e2bSVaishali Kulkarni }
205114b24e2bSVaishali Kulkarni 
ecore_change_pci_hwfn(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 enable)205214b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_change_pci_hwfn(struct ecore_hwfn *p_hwfn,
205314b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
205414b24e2bSVaishali Kulkarni 					   u8 enable)
205514b24e2bSVaishali Kulkarni {
205614b24e2bSVaishali Kulkarni 	u32 delay_idx = 0, val, set_val = enable ? 1 : 0;
205714b24e2bSVaishali Kulkarni 
205814b24e2bSVaishali Kulkarni 	/* Change PF in PXP */
205914b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt,
206014b24e2bSVaishali Kulkarni 		 PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val);
206114b24e2bSVaishali Kulkarni 
206214b24e2bSVaishali Kulkarni 	/* wait until value is set - try for 1 second every 50us */
206314b24e2bSVaishali Kulkarni 	for (delay_idx = 0; delay_idx < 20000; delay_idx++) {
206414b24e2bSVaishali Kulkarni 		val = ecore_rd(p_hwfn, p_ptt,
206514b24e2bSVaishali Kulkarni 			       PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
206614b24e2bSVaishali Kulkarni 		if (val == set_val)
206714b24e2bSVaishali Kulkarni 			break;
206814b24e2bSVaishali Kulkarni 
206914b24e2bSVaishali Kulkarni 		OSAL_UDELAY(50);
207014b24e2bSVaishali Kulkarni 	}
207114b24e2bSVaishali Kulkarni 
207214b24e2bSVaishali Kulkarni 	if (val != set_val) {
207314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
207414b24e2bSVaishali Kulkarni 			  "PFID_ENABLE_MASTER wasn't changed after a second\n");
207514b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
207614b24e2bSVaishali Kulkarni 	}
207714b24e2bSVaishali Kulkarni 
207814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
207914b24e2bSVaishali Kulkarni }
208014b24e2bSVaishali Kulkarni 
ecore_reset_mb_shadow(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_main_ptt)208114b24e2bSVaishali Kulkarni static void ecore_reset_mb_shadow(struct ecore_hwfn *p_hwfn,
208214b24e2bSVaishali Kulkarni 			struct ecore_ptt *p_main_ptt)
208314b24e2bSVaishali Kulkarni {
208414b24e2bSVaishali Kulkarni 	/* Read shadow of current MFW mailbox */
208514b24e2bSVaishali Kulkarni 	ecore_mcp_read_mb(p_hwfn, p_main_ptt);
208614b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_hwfn->mcp_info->mfw_mb_shadow,
208714b24e2bSVaishali Kulkarni 		    p_hwfn->mcp_info->mfw_mb_cur,
208814b24e2bSVaishali Kulkarni 		    p_hwfn->mcp_info->mfw_mb_length);
208914b24e2bSVaishali Kulkarni }
209014b24e2bSVaishali Kulkarni 
ecore_vf_start(struct ecore_hwfn * p_hwfn,struct ecore_hw_init_params * p_params)209114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_vf_start(struct ecore_hwfn *p_hwfn,
209214b24e2bSVaishali Kulkarni 				    struct ecore_hw_init_params *p_params)
209314b24e2bSVaishali Kulkarni {
209414b24e2bSVaishali Kulkarni 	if (p_params->p_tunn) {
209514b24e2bSVaishali Kulkarni 		ecore_vf_set_vf_start_tunn_update_param(p_params->p_tunn);
209614b24e2bSVaishali Kulkarni 		ecore_vf_pf_tunnel_param_update(p_hwfn, p_params->p_tunn);
209714b24e2bSVaishali Kulkarni 	}
209814b24e2bSVaishali Kulkarni 
209914b24e2bSVaishali Kulkarni 	p_hwfn->b_int_enabled = 1;
210014b24e2bSVaishali Kulkarni 
210114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
210214b24e2bSVaishali Kulkarni }
210314b24e2bSVaishali Kulkarni 
210414b24e2bSVaishali Kulkarni static void
ecore_fill_load_req_params(struct ecore_load_req_params * p_load_req,struct ecore_drv_load_params * p_drv_load)210514b24e2bSVaishali Kulkarni ecore_fill_load_req_params(struct ecore_load_req_params *p_load_req,
210614b24e2bSVaishali Kulkarni 			   struct ecore_drv_load_params *p_drv_load)
210714b24e2bSVaishali Kulkarni {
210814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(p_load_req, sizeof(*p_load_req));
210914b24e2bSVaishali Kulkarni 
211014b24e2bSVaishali Kulkarni 	if (p_drv_load != OSAL_NULL) {
211114b24e2bSVaishali Kulkarni 		p_load_req->drv_role = p_drv_load->is_crash_kernel ?
211214b24e2bSVaishali Kulkarni 				       ECORE_DRV_ROLE_KDUMP :
211314b24e2bSVaishali Kulkarni 				       ECORE_DRV_ROLE_OS;
211414b24e2bSVaishali Kulkarni 		p_load_req->timeout_val = p_drv_load->mfw_timeout_val;
211514b24e2bSVaishali Kulkarni 		p_load_req->avoid_eng_reset = p_drv_load->avoid_eng_reset;
211614b24e2bSVaishali Kulkarni 		p_load_req->override_force_load =
211714b24e2bSVaishali Kulkarni 			p_drv_load->override_force_load;
211814b24e2bSVaishali Kulkarni 	} else {
211914b24e2bSVaishali Kulkarni 		p_load_req->drv_role = ECORE_DRV_ROLE_OS;
212014b24e2bSVaishali Kulkarni 		p_load_req->timeout_val = ECORE_LOAD_REQ_LOCK_TO_DEFAULT;
212114b24e2bSVaishali Kulkarni 		p_load_req->avoid_eng_reset = false;
212214b24e2bSVaishali Kulkarni 		p_load_req->override_force_load =
212314b24e2bSVaishali Kulkarni 			ECORE_OVERRIDE_FORCE_LOAD_NONE;
212414b24e2bSVaishali Kulkarni 	}
212514b24e2bSVaishali Kulkarni }
212614b24e2bSVaishali Kulkarni 
ecore_hw_init(struct ecore_dev * p_dev,struct ecore_hw_init_params * p_params)212714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
212814b24e2bSVaishali Kulkarni 				   struct ecore_hw_init_params *p_params)
212914b24e2bSVaishali Kulkarni {
213014b24e2bSVaishali Kulkarni 	struct ecore_load_req_params load_req_params;
213114b24e2bSVaishali Kulkarni 	u32 load_code, param, drv_mb_param;
213214b24e2bSVaishali Kulkarni 	bool b_default_mtu = true;
213314b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn;
213414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS, mfw_rc;
213514b24e2bSVaishali Kulkarni 	int i;
213614b24e2bSVaishali Kulkarni 
213714b24e2bSVaishali Kulkarni 	if ((p_params->int_mode == ECORE_INT_MODE_MSI) && (p_dev->num_hwfns > 1)) {
213814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false,
213914b24e2bSVaishali Kulkarni 			  "MSI mode is not supported for CMT devices\n");
214014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
214114b24e2bSVaishali Kulkarni 	}
214214b24e2bSVaishali Kulkarni 
214314b24e2bSVaishali Kulkarni 	if (IS_PF(p_dev)) {
214414b24e2bSVaishali Kulkarni 		rc = ecore_init_fw_data(p_dev, p_params->bin_fw_data);
214514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
214614b24e2bSVaishali Kulkarni 			return rc;
214714b24e2bSVaishali Kulkarni 	}
214814b24e2bSVaishali Kulkarni 
214914b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
215014b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
215114b24e2bSVaishali Kulkarni 
215214b24e2bSVaishali Kulkarni 		/* If management didn't provide a default, set one of our own */
215314b24e2bSVaishali Kulkarni 		if (!p_hwfn->hw_info.mtu) {
215414b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.mtu = 1500;
215514b24e2bSVaishali Kulkarni 			b_default_mtu = false;
215614b24e2bSVaishali Kulkarni 		}
215714b24e2bSVaishali Kulkarni 
215814b24e2bSVaishali Kulkarni 		if (IS_VF(p_dev)) {
215914b24e2bSVaishali Kulkarni 			ecore_vf_start(p_hwfn, p_params);
216014b24e2bSVaishali Kulkarni 			continue;
216114b24e2bSVaishali Kulkarni 		}
216214b24e2bSVaishali Kulkarni 
216314b24e2bSVaishali Kulkarni 		/* Enable DMAE in PXP */
216414b24e2bSVaishali Kulkarni 		rc = ecore_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true);
216514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
216614b24e2bSVaishali Kulkarni 			return rc;
216714b24e2bSVaishali Kulkarni 
216814b24e2bSVaishali Kulkarni 		rc = ecore_calc_hw_mode(p_hwfn);
216914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
217014b24e2bSVaishali Kulkarni 			return rc;
217114b24e2bSVaishali Kulkarni 
217214b24e2bSVaishali Kulkarni 		ecore_fill_load_req_params(&load_req_params,
217314b24e2bSVaishali Kulkarni 					   p_params->p_drv_load_params);
217414b24e2bSVaishali Kulkarni 		rc = ecore_mcp_load_req(p_hwfn, p_hwfn->p_main_ptt,
217514b24e2bSVaishali Kulkarni 					&load_req_params);
217614b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
217714b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
217814b24e2bSVaishali Kulkarni 				  "Failed sending a LOAD_REQ command\n");
217914b24e2bSVaishali Kulkarni 			return rc;
218014b24e2bSVaishali Kulkarni 		}
218114b24e2bSVaishali Kulkarni 
218214b24e2bSVaishali Kulkarni 		load_code = load_req_params.load_code;
218314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
218414b24e2bSVaishali Kulkarni 			   "Load request was sent. Load code: 0x%x\n",
218514b24e2bSVaishali Kulkarni 			   load_code);
218614b24e2bSVaishali Kulkarni 
218714b24e2bSVaishali Kulkarni 		ecore_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt);
218814b24e2bSVaishali Kulkarni 
218914b24e2bSVaishali Kulkarni 		/* CQ75580:
219014b24e2bSVaishali Kulkarni 		 * When comming back from hiberbate state, the registers from
219114b24e2bSVaishali Kulkarni 		 * which shadow is read initially are not initialized. It turns
219214b24e2bSVaishali Kulkarni 		 * out that these registers get initialized during the call to
219314b24e2bSVaishali Kulkarni 		 * ecore_mcp_load_req request. So we need to reread them here
219414b24e2bSVaishali Kulkarni 		 * to get the proper shadow register value.
219514b24e2bSVaishali Kulkarni 		 * Note: This is a workaround for the missing MFW
219614b24e2bSVaishali Kulkarni 		 * initialization. It may be removed once the implementation
219714b24e2bSVaishali Kulkarni 		 * is done.
219814b24e2bSVaishali Kulkarni 		 */
219914b24e2bSVaishali Kulkarni 		ecore_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt);
220014b24e2bSVaishali Kulkarni 
220114b24e2bSVaishali Kulkarni 		/* Only relevant for recovery:
220214b24e2bSVaishali Kulkarni 		 * Clear the indication after the LOAD_REQ command is responded
220314b24e2bSVaishali Kulkarni 		 * by the MFW.
220414b24e2bSVaishali Kulkarni 		 */
220514b24e2bSVaishali Kulkarni 		p_dev->recov_in_prog = false;
220614b24e2bSVaishali Kulkarni 
220714b24e2bSVaishali Kulkarni 		p_hwfn->first_on_engine = (load_code ==
220814b24e2bSVaishali Kulkarni 					   FW_MSG_CODE_DRV_LOAD_ENGINE);
220914b24e2bSVaishali Kulkarni 
221014b24e2bSVaishali Kulkarni 		if (!qm_lock_init) {
221114b24e2bSVaishali Kulkarni 			OSAL_SPIN_LOCK_INIT(&qm_lock);
221214b24e2bSVaishali Kulkarni 			qm_lock_init = true;
221314b24e2bSVaishali Kulkarni 		}
221414b24e2bSVaishali Kulkarni 
221514b24e2bSVaishali Kulkarni 		switch (load_code) {
221614b24e2bSVaishali Kulkarni 		case FW_MSG_CODE_DRV_LOAD_ENGINE:
221714b24e2bSVaishali Kulkarni 			rc = ecore_hw_init_common(p_hwfn, p_hwfn->p_main_ptt,
221814b24e2bSVaishali Kulkarni 					     p_hwfn->hw_info.hw_mode);
221914b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
222014b24e2bSVaishali Kulkarni 				break;
22210d7de619SToomas Soome 			/* FALLTHROUGH */
222214b24e2bSVaishali Kulkarni 		case FW_MSG_CODE_DRV_LOAD_PORT:
222314b24e2bSVaishali Kulkarni 			rc = ecore_hw_init_port(p_hwfn, p_hwfn->p_main_ptt,
222414b24e2bSVaishali Kulkarni 						p_hwfn->hw_info.hw_mode);
222514b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
222614b24e2bSVaishali Kulkarni 				break;
22270d7de619SToomas Soome 			/* FALLTHROUGH */
222814b24e2bSVaishali Kulkarni 		case FW_MSG_CODE_DRV_LOAD_FUNCTION:
222914b24e2bSVaishali Kulkarni 			rc = ecore_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt,
223014b24e2bSVaishali Kulkarni 					      p_params->p_tunn,
223114b24e2bSVaishali Kulkarni 					      p_hwfn->hw_info.hw_mode,
223214b24e2bSVaishali Kulkarni 					      p_params->b_hw_start,
223314b24e2bSVaishali Kulkarni 					      p_params->int_mode,
223414b24e2bSVaishali Kulkarni 					      p_params->allow_npar_tx_switch);
223514b24e2bSVaishali Kulkarni 			break;
223614b24e2bSVaishali Kulkarni 		default:
223714b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
223814b24e2bSVaishali Kulkarni 				  "Unexpected load code [0x%08x]", load_code);
223914b24e2bSVaishali Kulkarni 			rc = ECORE_NOTIMPL;
224014b24e2bSVaishali Kulkarni 			break;
224114b24e2bSVaishali Kulkarni 		}
224214b24e2bSVaishali Kulkarni 
224314b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
224414b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
224514b24e2bSVaishali Kulkarni 				  "init phase failed for loadcode 0x%x (rc %d)\n",
224614b24e2bSVaishali Kulkarni 				  load_code, rc);
224714b24e2bSVaishali Kulkarni 
224814b24e2bSVaishali Kulkarni 		/* ACK mfw regardless of success or failure of initialization */
224914b24e2bSVaishali Kulkarni 		mfw_rc = ecore_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
225014b24e2bSVaishali Kulkarni 				       DRV_MSG_CODE_LOAD_DONE,
225114b24e2bSVaishali Kulkarni 				       0, &load_code, &param);
225214b24e2bSVaishali Kulkarni 
225314b24e2bSVaishali Kulkarni 		/* Check the return value of the ecore_hw_init_*() function */
225414b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
225514b24e2bSVaishali Kulkarni 			return rc;
225614b24e2bSVaishali Kulkarni 
225714b24e2bSVaishali Kulkarni 		/* Check the return value of the LOAD_DONE command */
225814b24e2bSVaishali Kulkarni 		if (mfw_rc != ECORE_SUCCESS) {
225914b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
226014b24e2bSVaishali Kulkarni 				  "Failed sending a LOAD_DONE command\n");
226114b24e2bSVaishali Kulkarni 			return mfw_rc;
226214b24e2bSVaishali Kulkarni 		}
226314b24e2bSVaishali Kulkarni 
226414b24e2bSVaishali Kulkarni 		/* Check if there is a DID mismatch between nvm-cfg/efuse */
226514b24e2bSVaishali Kulkarni 		if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR)
226614b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
226714b24e2bSVaishali Kulkarni 				  "warning: device configuration is not supported on this board type. The device may not function as expected.\n");
226814b24e2bSVaishali Kulkarni 
226914b24e2bSVaishali Kulkarni 		/* send DCBX attention request command */
227014b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
227114b24e2bSVaishali Kulkarni 			   "sending phony dcbx set command to trigger DCBx attention handling\n");
227214b24e2bSVaishali Kulkarni 		mfw_rc = ecore_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
227314b24e2bSVaishali Kulkarni 				       DRV_MSG_CODE_SET_DCBX,
227414b24e2bSVaishali Kulkarni 				       1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT,
227514b24e2bSVaishali Kulkarni 				       &load_code, &param);
227614b24e2bSVaishali Kulkarni 		if (mfw_rc != ECORE_SUCCESS) {
227714b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
227814b24e2bSVaishali Kulkarni 				  "Failed to send DCBX attention request\n");
227914b24e2bSVaishali Kulkarni 			return mfw_rc;
228014b24e2bSVaishali Kulkarni 		}
228114b24e2bSVaishali Kulkarni 
228214b24e2bSVaishali Kulkarni 		p_hwfn->hw_init_done = true;
228314b24e2bSVaishali Kulkarni 	}
228414b24e2bSVaishali Kulkarni 
228514b24e2bSVaishali Kulkarni 	if (IS_PF(p_dev)) {
228614b24e2bSVaishali Kulkarni 		p_hwfn = ECORE_LEADING_HWFN(p_dev);
228714b24e2bSVaishali Kulkarni 		drv_mb_param = STORM_FW_VERSION;
228814b24e2bSVaishali Kulkarni 		rc = ecore_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
228914b24e2bSVaishali Kulkarni 				   DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER,
229014b24e2bSVaishali Kulkarni 				   drv_mb_param, &load_code, &param);
229114b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
229214b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Failed to update firmware version\n");
229314b24e2bSVaishali Kulkarni 
229414b24e2bSVaishali Kulkarni 		if (!b_default_mtu) {
229514b24e2bSVaishali Kulkarni 			rc = ecore_mcp_ov_update_mtu(p_hwfn, p_hwfn->p_main_ptt,
229614b24e2bSVaishali Kulkarni 						      p_hwfn->hw_info.mtu);
229714b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
229814b24e2bSVaishali Kulkarni 				DP_INFO(p_hwfn, "Failed to update default mtu\n");
229914b24e2bSVaishali Kulkarni 		}
230014b24e2bSVaishali Kulkarni 
230114b24e2bSVaishali Kulkarni 		rc = ecore_mcp_ov_update_driver_state(p_hwfn,
230214b24e2bSVaishali Kulkarni 						      p_hwfn->p_main_ptt,
230314b24e2bSVaishali Kulkarni 						      ECORE_OV_DRIVER_STATE_DISABLED);
230414b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
230514b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Failed to update driver state\n");
230614b24e2bSVaishali Kulkarni 
230714b24e2bSVaishali Kulkarni 		rc = ecore_mcp_ov_update_eswitch(p_hwfn, p_hwfn->p_main_ptt,
230814b24e2bSVaishali Kulkarni 						 ECORE_OV_ESWITCH_VEB);
230914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
231014b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Failed to update eswitch mode\n");
231114b24e2bSVaishali Kulkarni 	}
231214b24e2bSVaishali Kulkarni 
231314b24e2bSVaishali Kulkarni 	return rc;
231414b24e2bSVaishali Kulkarni }
231514b24e2bSVaishali Kulkarni 
231614b24e2bSVaishali Kulkarni #define ECORE_HW_STOP_RETRY_LIMIT	(10)
ecore_hw_timers_stop(struct ecore_dev * p_dev,struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)231714b24e2bSVaishali Kulkarni static void ecore_hw_timers_stop(struct ecore_dev *p_dev,
231814b24e2bSVaishali Kulkarni 				 struct ecore_hwfn *p_hwfn,
231914b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt)
232014b24e2bSVaishali Kulkarni {
232114b24e2bSVaishali Kulkarni 	int i;
232214b24e2bSVaishali Kulkarni 
232314b24e2bSVaishali Kulkarni 	/* close timers */
232414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0);
232514b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0);
232614b24e2bSVaishali Kulkarni 	for (i = 0;
232714b24e2bSVaishali Kulkarni 	     i < ECORE_HW_STOP_RETRY_LIMIT && !p_dev->recov_in_prog;
232814b24e2bSVaishali Kulkarni 	     i++) {
232914b24e2bSVaishali Kulkarni 		if ((!ecore_rd(p_hwfn, p_ptt,
233014b24e2bSVaishali Kulkarni 			       TM_REG_PF_SCAN_ACTIVE_CONN)) &&
233114b24e2bSVaishali Kulkarni 		    (!ecore_rd(p_hwfn, p_ptt,
233214b24e2bSVaishali Kulkarni 			       TM_REG_PF_SCAN_ACTIVE_TASK)))
233314b24e2bSVaishali Kulkarni 			break;
233414b24e2bSVaishali Kulkarni 
233514b24e2bSVaishali Kulkarni 		/* Dependent on number of connection/tasks, possibly
233614b24e2bSVaishali Kulkarni 		 * 1ms sleep is required between polls
233714b24e2bSVaishali Kulkarni 		 */
233814b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(1);
233914b24e2bSVaishali Kulkarni 	}
234014b24e2bSVaishali Kulkarni 
234114b24e2bSVaishali Kulkarni 	if (i < ECORE_HW_STOP_RETRY_LIMIT)
234214b24e2bSVaishali Kulkarni 		return;
234314b24e2bSVaishali Kulkarni 
234414b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, true,
234514b24e2bSVaishali Kulkarni 		  "Timers linear scans are not over [Connection %02x Tasks %02x]\n",
234614b24e2bSVaishali Kulkarni 		  (u8)ecore_rd(p_hwfn, p_ptt, TM_REG_PF_SCAN_ACTIVE_CONN),
234714b24e2bSVaishali Kulkarni 		  (u8)ecore_rd(p_hwfn, p_ptt, TM_REG_PF_SCAN_ACTIVE_TASK));
234814b24e2bSVaishali Kulkarni }
234914b24e2bSVaishali Kulkarni 
ecore_hw_timers_stop_all(struct ecore_dev * p_dev)235014b24e2bSVaishali Kulkarni void ecore_hw_timers_stop_all(struct ecore_dev *p_dev)
235114b24e2bSVaishali Kulkarni {
235214b24e2bSVaishali Kulkarni 	int j;
235314b24e2bSVaishali Kulkarni 
235414b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, j) {
235514b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[j];
235614b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt = p_hwfn->p_main_ptt;
235714b24e2bSVaishali Kulkarni 
235814b24e2bSVaishali Kulkarni 		ecore_hw_timers_stop(p_dev, p_hwfn, p_ptt);
235914b24e2bSVaishali Kulkarni 	}
236014b24e2bSVaishali Kulkarni }
236114b24e2bSVaishali Kulkarni 
ecore_verify_reg_val(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 addr,u32 expected_val)236214b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_verify_reg_val(struct ecore_hwfn *p_hwfn,
236314b24e2bSVaishali Kulkarni 						 struct ecore_ptt *p_ptt,
236414b24e2bSVaishali Kulkarni 						 u32 addr, u32 expected_val)
236514b24e2bSVaishali Kulkarni {
236614b24e2bSVaishali Kulkarni 	u32 val = ecore_rd(p_hwfn, p_ptt, addr);
236714b24e2bSVaishali Kulkarni 
236814b24e2bSVaishali Kulkarni 	if (val != expected_val) {
236914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
237014b24e2bSVaishali Kulkarni 			  "Value at address 0x%08x is 0x%08x while the expected value is 0x%08x\n",
237114b24e2bSVaishali Kulkarni 			  addr, val, expected_val);
237214b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
237314b24e2bSVaishali Kulkarni 	}
237414b24e2bSVaishali Kulkarni 
237514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
237614b24e2bSVaishali Kulkarni }
237714b24e2bSVaishali Kulkarni 
ecore_hw_stop(struct ecore_dev * p_dev)237814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
237914b24e2bSVaishali Kulkarni {
238014b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn;
238114b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
238214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc, rc2 = ECORE_SUCCESS;
238314b24e2bSVaishali Kulkarni 	int j;
238414b24e2bSVaishali Kulkarni 
238514b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, j) {
238614b24e2bSVaishali Kulkarni 		p_hwfn = &p_dev->hwfns[j];
238714b24e2bSVaishali Kulkarni 		p_ptt = p_hwfn->p_main_ptt;
238814b24e2bSVaishali Kulkarni 
238914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN, "Stopping hw/fw\n");
239014b24e2bSVaishali Kulkarni 
239114b24e2bSVaishali Kulkarni 		if (IS_VF(p_dev)) {
239214b24e2bSVaishali Kulkarni 			ecore_vf_pf_int_cleanup(p_hwfn);
239314b24e2bSVaishali Kulkarni 			rc = ecore_vf_pf_reset(p_hwfn);
239414b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS) {
239514b24e2bSVaishali Kulkarni 				DP_NOTICE(p_hwfn, true,
239614b24e2bSVaishali Kulkarni 					  "ecore_vf_pf_reset failed. rc = %d.\n",
239714b24e2bSVaishali Kulkarni 					  rc);
239814b24e2bSVaishali Kulkarni 				rc2 = ECORE_UNKNOWN_ERROR;
239914b24e2bSVaishali Kulkarni 			}
240014b24e2bSVaishali Kulkarni 			continue;
240114b24e2bSVaishali Kulkarni 		}
240214b24e2bSVaishali Kulkarni 
240314b24e2bSVaishali Kulkarni 		/* mark the hw as uninitialized... */
240414b24e2bSVaishali Kulkarni 		p_hwfn->hw_init_done = false;
240514b24e2bSVaishali Kulkarni 
240614b24e2bSVaishali Kulkarni 		/* Send unload command to MCP */
240714b24e2bSVaishali Kulkarni 		if (!p_dev->recov_in_prog) {
240814b24e2bSVaishali Kulkarni 			rc = ecore_mcp_unload_req(p_hwfn, p_ptt);
240914b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS) {
241014b24e2bSVaishali Kulkarni 				DP_NOTICE(p_hwfn, true,
241114b24e2bSVaishali Kulkarni 					  "Failed sending a UNLOAD_REQ command. rc = %d.\n",
241214b24e2bSVaishali Kulkarni 					  rc);
241314b24e2bSVaishali Kulkarni 				rc2 = ECORE_UNKNOWN_ERROR;
241414b24e2bSVaishali Kulkarni 			}
241514b24e2bSVaishali Kulkarni 		}
241614b24e2bSVaishali Kulkarni 
241714b24e2bSVaishali Kulkarni 		OSAL_DPC_SYNC(p_hwfn);
241814b24e2bSVaishali Kulkarni 
241914b24e2bSVaishali Kulkarni 		/* After this point no MFW attentions are expected, e.g. prevent
242014b24e2bSVaishali Kulkarni 		 * race between pf stop and dcbx pf update.
242114b24e2bSVaishali Kulkarni 		 */
242214b24e2bSVaishali Kulkarni 
242314b24e2bSVaishali Kulkarni 		rc = ecore_sp_pf_stop(p_hwfn);
242414b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
242514b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
242614b24e2bSVaishali Kulkarni 				  "Failed to close PF against FW [rc = %d]. Continue to stop HW to prevent illegal host access by the device.\n",
242714b24e2bSVaishali Kulkarni 				  rc);
242814b24e2bSVaishali Kulkarni 			rc2 = ECORE_UNKNOWN_ERROR;
242914b24e2bSVaishali Kulkarni 		}
243014b24e2bSVaishali Kulkarni 
243114b24e2bSVaishali Kulkarni 		/* perform debug action after PF stop was sent */
243214b24e2bSVaishali Kulkarni 		OSAL_AFTER_PF_STOP((void *)p_dev, p_hwfn->my_id);
243314b24e2bSVaishali Kulkarni 
243414b24e2bSVaishali Kulkarni 		/* close NIG to BRB gate */
243514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
243614b24e2bSVaishali Kulkarni 			 NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1);
243714b24e2bSVaishali Kulkarni 
243814b24e2bSVaishali Kulkarni 		/* close parser */
243914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0);
244014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0);
244114b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0);
244214b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0);
244314b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0);
244414b24e2bSVaishali Kulkarni 
244514b24e2bSVaishali Kulkarni 		/* @@@TBD - clean transmission queues (5.b) */
244614b24e2bSVaishali Kulkarni 		/* @@@TBD - clean BTB (5.c) */
244714b24e2bSVaishali Kulkarni 
244814b24e2bSVaishali Kulkarni 		ecore_hw_timers_stop(p_dev, p_hwfn, p_ptt);
244914b24e2bSVaishali Kulkarni 
245014b24e2bSVaishali Kulkarni 		/* @@@TBD - verify DMAE requests are done (8) */
245114b24e2bSVaishali Kulkarni 
245214b24e2bSVaishali Kulkarni 		/* Disable Attention Generation */
245314b24e2bSVaishali Kulkarni 		ecore_int_igu_disable_int(p_hwfn, p_ptt);
245414b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0);
245514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0);
245614b24e2bSVaishali Kulkarni 		ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true);
245714b24e2bSVaishali Kulkarni 		rc = ecore_int_igu_reset_cam_default(p_hwfn, p_ptt);
245814b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
245914b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
246014b24e2bSVaishali Kulkarni 				  "Failed to return IGU CAM to default\n");
246114b24e2bSVaishali Kulkarni 			rc2 = ECORE_UNKNOWN_ERROR;
246214b24e2bSVaishali Kulkarni 		}
246314b24e2bSVaishali Kulkarni 
246414b24e2bSVaishali Kulkarni 		/* Need to wait 1ms to guarantee SBs are cleared */
246514b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(1);
246614b24e2bSVaishali Kulkarni 
246714b24e2bSVaishali Kulkarni 		if (!p_dev->recov_in_prog) {
246814b24e2bSVaishali Kulkarni 			ecore_verify_reg_val(p_hwfn, p_ptt,
246914b24e2bSVaishali Kulkarni 					     QM_REG_USG_CNT_PF_TX, 0);
247014b24e2bSVaishali Kulkarni 			ecore_verify_reg_val(p_hwfn, p_ptt,
247114b24e2bSVaishali Kulkarni 					     QM_REG_USG_CNT_PF_OTHER, 0);
247214b24e2bSVaishali Kulkarni 			/* @@@TBD - assert on incorrect xCFC values (10.b) */
247314b24e2bSVaishali Kulkarni 		}
247414b24e2bSVaishali Kulkarni 
247514b24e2bSVaishali Kulkarni 		/* Disable PF in HW blocks */
247614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0);
247714b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0);
247814b24e2bSVaishali Kulkarni 
247914b24e2bSVaishali Kulkarni 		if (!p_dev->recov_in_prog) {
248014b24e2bSVaishali Kulkarni 			ecore_mcp_unload_done(p_hwfn, p_ptt);
248114b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS) {
248214b24e2bSVaishali Kulkarni 				DP_NOTICE(p_hwfn, true,
248314b24e2bSVaishali Kulkarni 					  "Failed sending a UNLOAD_DONE command. rc = %d.\n",
248414b24e2bSVaishali Kulkarni 					  rc);
248514b24e2bSVaishali Kulkarni 				rc2 = ECORE_UNKNOWN_ERROR;
248614b24e2bSVaishali Kulkarni 			}
248714b24e2bSVaishali Kulkarni 		}
248814b24e2bSVaishali Kulkarni 	} /* hwfn loop */
248914b24e2bSVaishali Kulkarni 
249014b24e2bSVaishali Kulkarni 	if (IS_PF(p_dev)) {
249114b24e2bSVaishali Kulkarni 		p_hwfn = ECORE_LEADING_HWFN(p_dev);
249214b24e2bSVaishali Kulkarni 		p_ptt = ECORE_LEADING_HWFN(p_dev)->p_main_ptt;
249314b24e2bSVaishali Kulkarni 
249414b24e2bSVaishali Kulkarni 		/* Disable DMAE in PXP - in CMT, this should only be done for
249514b24e2bSVaishali Kulkarni 		 * first hw-function, and only after all transactions have
249614b24e2bSVaishali Kulkarni 		 * stopped for all active hw-functions.
249714b24e2bSVaishali Kulkarni 		 */
249814b24e2bSVaishali Kulkarni 		rc = ecore_change_pci_hwfn(p_hwfn, p_ptt, false);
249914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
250014b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true,
250114b24e2bSVaishali Kulkarni 				  "ecore_change_pci_hwfn failed. rc = %d.\n",
250214b24e2bSVaishali Kulkarni 				  rc);
250314b24e2bSVaishali Kulkarni 			rc2 = ECORE_UNKNOWN_ERROR;
250414b24e2bSVaishali Kulkarni 		}
250514b24e2bSVaishali Kulkarni 	}
250614b24e2bSVaishali Kulkarni 
250714b24e2bSVaishali Kulkarni 	return rc2;
250814b24e2bSVaishali Kulkarni }
250914b24e2bSVaishali Kulkarni 
ecore_hw_stop_fastpath(struct ecore_dev * p_dev)251014b24e2bSVaishali Kulkarni void ecore_hw_stop_fastpath(struct ecore_dev *p_dev)
251114b24e2bSVaishali Kulkarni {
251214b24e2bSVaishali Kulkarni 	int j;
251314b24e2bSVaishali Kulkarni 
251414b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, j) {
251514b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[j];
251614b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt = p_hwfn->p_main_ptt;
251714b24e2bSVaishali Kulkarni 
251814b24e2bSVaishali Kulkarni 		if (IS_VF(p_dev)) {
251914b24e2bSVaishali Kulkarni 			ecore_vf_pf_int_cleanup(p_hwfn);
252014b24e2bSVaishali Kulkarni 			continue;
252114b24e2bSVaishali Kulkarni 		}
252214b24e2bSVaishali Kulkarni 
252314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN, "Shutting down the fastpath\n");
252414b24e2bSVaishali Kulkarni 
252514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
252614b24e2bSVaishali Kulkarni 			 NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1);
252714b24e2bSVaishali Kulkarni 
252814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0);
252914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0);
253014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0);
253114b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0);
253214b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0);
253314b24e2bSVaishali Kulkarni 
253414b24e2bSVaishali Kulkarni 		/* @@@TBD - clean transmission queues (5.b) */
253514b24e2bSVaishali Kulkarni 		/* @@@TBD - clean BTB (5.c) */
253614b24e2bSVaishali Kulkarni 
253714b24e2bSVaishali Kulkarni 		/* @@@TBD - verify DMAE requests are done (8) */
253814b24e2bSVaishali Kulkarni 
253914b24e2bSVaishali Kulkarni 		ecore_int_igu_init_pure_rt(p_hwfn, p_ptt, false, false);
254014b24e2bSVaishali Kulkarni 		/* Need to wait 1ms to guarantee SBs are cleared */
254114b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(1);
254214b24e2bSVaishali Kulkarni 	}
254314b24e2bSVaishali Kulkarni }
254414b24e2bSVaishali Kulkarni 
ecore_hw_start_fastpath(struct ecore_hwfn * p_hwfn)254514b24e2bSVaishali Kulkarni void ecore_hw_start_fastpath(struct ecore_hwfn *p_hwfn)
254614b24e2bSVaishali Kulkarni {
254714b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt = p_hwfn->p_main_ptt;
254814b24e2bSVaishali Kulkarni 
254914b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
255014b24e2bSVaishali Kulkarni 		return;
255114b24e2bSVaishali Kulkarni 
255214b24e2bSVaishali Kulkarni 	/* If roce info is allocated it means roce is initialized and should
255314b24e2bSVaishali Kulkarni 	 * be enabled in searcher.
255414b24e2bSVaishali Kulkarni 	 */
255514b24e2bSVaishali Kulkarni 	if (p_hwfn->p_rdma_info) {
255614b24e2bSVaishali Kulkarni 		if (p_hwfn->b_rdma_enabled_in_prs)
255714b24e2bSVaishali Kulkarni 			ecore_wr(p_hwfn, p_ptt,
255814b24e2bSVaishali Kulkarni 				 p_hwfn->rdma_prs_search_reg, 0x1);
255914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x1);
256014b24e2bSVaishali Kulkarni 	}
256114b24e2bSVaishali Kulkarni 
256214b24e2bSVaishali Kulkarni 	/* Re-open incoming traffic */
256314b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
256414b24e2bSVaishali Kulkarni 		 NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x0);
256514b24e2bSVaishali Kulkarni }
256614b24e2bSVaishali Kulkarni /* TEMP macro to be removed when wol code revisted */
256714b24e2bSVaishali Kulkarni #define ECORE_WOL_WR(_p_hwfn, _p_ptt, _offset, _val) ECORE_IS_BB(_p_hwfn->p_dev) ? \
256814b24e2bSVaishali Kulkarni 	ecore_wr(_p_hwfn, _p_ptt, _offset, _val) : \
256914b24e2bSVaishali Kulkarni 	ecore_mcp_wol_wr(_p_hwfn, _p_ptt, _offset, _val);
257014b24e2bSVaishali Kulkarni 
ecore_set_nwuf_reg(struct ecore_dev * p_dev,const bool b_enable,u32 reg_idx,u32 pattern_size,u32 crc)257114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_set_nwuf_reg(struct ecore_dev *p_dev,
257214b24e2bSVaishali Kulkarni 	const bool b_enable,
257314b24e2bSVaishali Kulkarni 	u32 reg_idx,
257414b24e2bSVaishali Kulkarni 	u32 pattern_size,
257514b24e2bSVaishali Kulkarni 	u32 crc)
257614b24e2bSVaishali Kulkarni {
257714b24e2bSVaishali Kulkarni 	struct ecore_hwfn *hwfn = &p_dev->hwfns[0];
257814b24e2bSVaishali Kulkarni 	u32 reg_len = 0;
257914b24e2bSVaishali Kulkarni 	u32 reg_crc = 0;
258014b24e2bSVaishali Kulkarni 
258114b24e2bSVaishali Kulkarni 	/* Get length and CRC register offsets */
258214b24e2bSVaishali Kulkarni 	switch (reg_idx)
258314b24e2bSVaishali Kulkarni 	{
258414b24e2bSVaishali Kulkarni 	case 0:
258514b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_0_LEN_BB :
258614b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_0_LEN_K2_E5;
258714b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_0_CRC_BB :
258814b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_0_CRC_K2_E5;
258914b24e2bSVaishali Kulkarni 		break;
259014b24e2bSVaishali Kulkarni 	case 1:
259114b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_1_LEN_BB :
259214b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_1_LEN_K2_E5;
259314b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_1_CRC_BB :
259414b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_1_CRC_K2_E5;
259514b24e2bSVaishali Kulkarni 		break;
259614b24e2bSVaishali Kulkarni 	case 2:
259714b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_2_LEN_BB :
259814b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_2_LEN_K2_E5;
259914b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_2_CRC_BB :
260014b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_2_CRC_K2_E5;
260114b24e2bSVaishali Kulkarni 		break;
260214b24e2bSVaishali Kulkarni 	case 3:
260314b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_3_LEN_BB :
260414b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_3_LEN_K2_E5;
260514b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_3_CRC_BB :
260614b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_3_CRC_K2_E5;
260714b24e2bSVaishali Kulkarni 		break;
260814b24e2bSVaishali Kulkarni 	case 4:
260914b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_4_LEN_BB :
261014b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_4_LEN_K2_E5;
261114b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_4_CRC_BB :
261214b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_4_CRC_K2_E5;
261314b24e2bSVaishali Kulkarni 		break;
261414b24e2bSVaishali Kulkarni 	case 5:
261514b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_5_LEN_BB :
261614b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_5_LEN_K2_E5;
261714b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_5_CRC_BB :
261814b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_5_CRC_K2_E5;
261914b24e2bSVaishali Kulkarni 		break;
262014b24e2bSVaishali Kulkarni 	case 6:
262114b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_6_LEN_BB :
262214b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_6_LEN_K2_E5;
262314b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_6_CRC_BB :
262414b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_6_CRC_K2_E5;
262514b24e2bSVaishali Kulkarni 		break;
262614b24e2bSVaishali Kulkarni 	case 7:
262714b24e2bSVaishali Kulkarni 		reg_len = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_7_LEN_BB :
262814b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_7_LEN_K2_E5;
262914b24e2bSVaishali Kulkarni 		reg_crc = ECORE_IS_BB(p_dev) ? NIG_REG_ACPI_PAT_7_CRC_BB :
263014b24e2bSVaishali Kulkarni 				WOL_REG_ACPI_PAT_7_CRC_K2_E5;
263114b24e2bSVaishali Kulkarni 		break;
263214b24e2bSVaishali Kulkarni 	default:
263314b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
263414b24e2bSVaishali Kulkarni 	}
263514b24e2bSVaishali Kulkarni 
263614b24e2bSVaishali Kulkarni 	/* Allign pattern size to 4 */
263714b24e2bSVaishali Kulkarni 	while (pattern_size % 4)
263814b24e2bSVaishali Kulkarni 	{
263914b24e2bSVaishali Kulkarni 		pattern_size++;
264014b24e2bSVaishali Kulkarni 	}
264114b24e2bSVaishali Kulkarni 	/* write pattern length */
264214b24e2bSVaishali Kulkarni 	ECORE_WOL_WR(hwfn, hwfn->p_main_ptt, reg_len, pattern_size);
264314b24e2bSVaishali Kulkarni 
264414b24e2bSVaishali Kulkarni 	/* write crc value*/
264514b24e2bSVaishali Kulkarni 	ECORE_WOL_WR(hwfn, hwfn->p_main_ptt, reg_crc, crc);
264614b24e2bSVaishali Kulkarni 
264714b24e2bSVaishali Kulkarni 	DP_INFO(p_dev,
264814b24e2bSVaishali Kulkarni 		"ecore_set_nwuf_reg: idx[%d] reg_crc[0x%x=0x%08x] "
264914b24e2bSVaishali Kulkarni 		"reg_len[0x%x=0x%x]\n",
265014b24e2bSVaishali Kulkarni 		reg_idx, reg_crc, crc, reg_len, pattern_size);
265114b24e2bSVaishali Kulkarni 
265214b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
265314b24e2bSVaishali Kulkarni }
265414b24e2bSVaishali Kulkarni 
ecore_wol_buffer_clear(struct ecore_dev * p_dev)265514b24e2bSVaishali Kulkarni void ecore_wol_buffer_clear(struct ecore_dev *p_dev)
265614b24e2bSVaishali Kulkarni {
265714b24e2bSVaishali Kulkarni 	struct ecore_hwfn *hwfn = &p_dev->hwfns[0];
265814b24e2bSVaishali Kulkarni 	const u32 wake_buffer_clear_offset =
265914b24e2bSVaishali Kulkarni 		ECORE_IS_BB(p_dev) ?
266014b24e2bSVaishali Kulkarni 		NIG_REG_WAKE_BUFFER_CLEAR_BB : WOL_REG_WAKE_BUFFER_CLEAR_K2_E5;
266114b24e2bSVaishali Kulkarni 
266214b24e2bSVaishali Kulkarni 	DP_INFO(p_dev,
266314b24e2bSVaishali Kulkarni 		"ecore_wol_buffer_clear: reset "
266414b24e2bSVaishali Kulkarni 		"REG_WAKE_BUFFER_CLEAR offset=0x%08x\n",
266514b24e2bSVaishali Kulkarni 		wake_buffer_clear_offset);
266614b24e2bSVaishali Kulkarni 
266714b24e2bSVaishali Kulkarni 	ECORE_WOL_WR(hwfn, hwfn->p_main_ptt, wake_buffer_clear_offset, 1);
266814b24e2bSVaishali Kulkarni 	ECORE_WOL_WR(hwfn, hwfn->p_main_ptt, wake_buffer_clear_offset, 0);
266914b24e2bSVaishali Kulkarni }
267014b24e2bSVaishali Kulkarni 
ecore_get_wake_info(struct ecore_dev * p_dev,struct ecore_wake_info * wake_info)267114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_get_wake_info(struct ecore_dev *p_dev,
267214b24e2bSVaishali Kulkarni 	struct ecore_wake_info *wake_info)
267314b24e2bSVaishali Kulkarni {
267414b24e2bSVaishali Kulkarni 	struct ecore_hwfn *hwfn = &p_dev->hwfns[0];
267514b24e2bSVaishali Kulkarni 	u32 *buf = OSAL_NULL;
267614b24e2bSVaishali Kulkarni 	u32 i    = 0;
267714b24e2bSVaishali Kulkarni 	const u32 reg_wake_buffer_offest =
267814b24e2bSVaishali Kulkarni 		ECORE_IS_BB(p_dev) ? NIG_REG_WAKE_BUFFER_BB :
267914b24e2bSVaishali Kulkarni 			WOL_REG_WAKE_BUFFER_K2_E5;
268014b24e2bSVaishali Kulkarni 
268114b24e2bSVaishali Kulkarni 	wake_info->wk_info    = ecore_rd(hwfn, hwfn->p_main_ptt,
268214b24e2bSVaishali Kulkarni 				ECORE_IS_BB(p_dev) ? NIG_REG_WAKE_INFO_BB :
268314b24e2bSVaishali Kulkarni 				WOL_REG_WAKE_INFO_K2_E5);
268414b24e2bSVaishali Kulkarni 	wake_info->wk_details = ecore_rd(hwfn, hwfn->p_main_ptt,
268514b24e2bSVaishali Kulkarni 				ECORE_IS_BB(p_dev) ? NIG_REG_WAKE_DETAILS_BB :
268614b24e2bSVaishali Kulkarni 				WOL_REG_WAKE_DETAILS_K2_E5);
268714b24e2bSVaishali Kulkarni 	wake_info->wk_pkt_len = ecore_rd(hwfn, hwfn->p_main_ptt,
268814b24e2bSVaishali Kulkarni 				ECORE_IS_BB(p_dev) ? NIG_REG_WAKE_PKT_LEN_BB :
268914b24e2bSVaishali Kulkarni 				WOL_REG_WAKE_PKT_LEN_K2_E5);
269014b24e2bSVaishali Kulkarni 
269114b24e2bSVaishali Kulkarni 	DP_INFO(p_dev,
269214b24e2bSVaishali Kulkarni 		"ecore_get_wake_info: REG_WAKE_INFO=0x%08x "
269314b24e2bSVaishali Kulkarni 		"REG_WAKE_DETAILS=0x%08x "
269414b24e2bSVaishali Kulkarni 		"REG_WAKE_PKT_LEN=0x%08x\n",
269514b24e2bSVaishali Kulkarni 		wake_info->wk_info,
269614b24e2bSVaishali Kulkarni 		wake_info->wk_details,
269714b24e2bSVaishali Kulkarni 		wake_info->wk_pkt_len);
269814b24e2bSVaishali Kulkarni 
269914b24e2bSVaishali Kulkarni 	buf = (u32 *)wake_info->wk_buffer;
270014b24e2bSVaishali Kulkarni 
270114b24e2bSVaishali Kulkarni 	for (i = 0; i < (wake_info->wk_pkt_len / sizeof(u32)); i++)
270214b24e2bSVaishali Kulkarni 	{
270314b24e2bSVaishali Kulkarni 		if ((i*sizeof(u32)) >=  sizeof(wake_info->wk_buffer))
270414b24e2bSVaishali Kulkarni 		{
270514b24e2bSVaishali Kulkarni 			DP_INFO(p_dev,
270614b24e2bSVaishali Kulkarni 				"ecore_get_wake_info: i index to 0 high=%d\n",
270714b24e2bSVaishali Kulkarni 				 i);
270814b24e2bSVaishali Kulkarni 			break;
270914b24e2bSVaishali Kulkarni 		}
271014b24e2bSVaishali Kulkarni 		buf[i] = ecore_rd(hwfn, hwfn->p_main_ptt,
271114b24e2bSVaishali Kulkarni 				  reg_wake_buffer_offest + (i * sizeof(u32)));
271214b24e2bSVaishali Kulkarni 		DP_INFO(p_dev, "ecore_get_wake_info: wk_buffer[%u]: 0x%08x\n",
271314b24e2bSVaishali Kulkarni 			i, buf[i]);
271414b24e2bSVaishali Kulkarni 	}
271514b24e2bSVaishali Kulkarni 
271614b24e2bSVaishali Kulkarni 	ecore_wol_buffer_clear(p_dev);
271714b24e2bSVaishali Kulkarni 
271814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
271914b24e2bSVaishali Kulkarni }
272014b24e2bSVaishali Kulkarni 
272114b24e2bSVaishali Kulkarni /* Free hwfn memory and resources acquired in hw_hwfn_prepare */
ecore_hw_hwfn_free(struct ecore_hwfn * p_hwfn)272214b24e2bSVaishali Kulkarni static void ecore_hw_hwfn_free(struct ecore_hwfn *p_hwfn)
272314b24e2bSVaishali Kulkarni {
272414b24e2bSVaishali Kulkarni 	ecore_ptt_pool_free(p_hwfn);
272514b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->hw_info.p_igu_info);
272614b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.p_igu_info = OSAL_NULL;
272714b24e2bSVaishali Kulkarni }
272814b24e2bSVaishali Kulkarni 
272914b24e2bSVaishali Kulkarni /* Setup bar access */
ecore_hw_hwfn_prepare(struct ecore_hwfn * p_hwfn)273014b24e2bSVaishali Kulkarni static void ecore_hw_hwfn_prepare(struct ecore_hwfn *p_hwfn)
273114b24e2bSVaishali Kulkarni {
273214b24e2bSVaishali Kulkarni 	/* clear indirect access */
273314b24e2bSVaishali Kulkarni 	if (ECORE_IS_AH(p_hwfn->p_dev) || ECORE_IS_E5(p_hwfn->p_dev)) {
273414b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
273514b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_E8_F0_K2_E5, 0);
273614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
273714b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_EC_F0_K2_E5, 0);
273814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
273914b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_F0_F0_K2_E5, 0);
274014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
274114b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_F4_F0_K2_E5, 0);
274214b24e2bSVaishali Kulkarni 	} else {
274314b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
274414b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_88_F0_BB, 0);
274514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
274614b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_8C_F0_BB, 0);
274714b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
274814b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_90_F0_BB, 0);
274914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
275014b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_PGL_ADDR_94_F0_BB, 0);
275114b24e2bSVaishali Kulkarni 	}
275214b24e2bSVaishali Kulkarni 
275314b24e2bSVaishali Kulkarni 	/* Clean Previous errors if such exist */
275414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
275514b24e2bSVaishali Kulkarni 		 PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR,
275614b24e2bSVaishali Kulkarni 		 1 << p_hwfn->abs_pf_id);
275714b24e2bSVaishali Kulkarni 
275814b24e2bSVaishali Kulkarni 	/* enable internal target-read */
275914b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
276014b24e2bSVaishali Kulkarni 		 PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
276114b24e2bSVaishali Kulkarni }
276214b24e2bSVaishali Kulkarni 
get_function_id(struct ecore_hwfn * p_hwfn)276314b24e2bSVaishali Kulkarni static void get_function_id(struct ecore_hwfn *p_hwfn)
276414b24e2bSVaishali Kulkarni {
276514b24e2bSVaishali Kulkarni 	/* ME Register */
276614b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.opaque_fid = (u16) REG_RD(p_hwfn,
276714b24e2bSVaishali Kulkarni 						  PXP_PF_ME_OPAQUE_ADDR);
276814b24e2bSVaishali Kulkarni 
276914b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, PXP_PF_ME_CONCRETE_ADDR);
277014b24e2bSVaishali Kulkarni 
277114b24e2bSVaishali Kulkarni 	/* Bits 16-19 from the ME registers are the pf_num */
277214b24e2bSVaishali Kulkarni 	p_hwfn->abs_pf_id = (p_hwfn->hw_info.concrete_fid >> 16) & 0xf;
277314b24e2bSVaishali Kulkarni 	p_hwfn->rel_pf_id = GET_FIELD(p_hwfn->hw_info.concrete_fid,
277414b24e2bSVaishali Kulkarni 				      PXP_CONCRETE_FID_PFID);
277514b24e2bSVaishali Kulkarni 	p_hwfn->port_id = GET_FIELD(p_hwfn->hw_info.concrete_fid,
277614b24e2bSVaishali Kulkarni 				    PXP_CONCRETE_FID_PORT);
277714b24e2bSVaishali Kulkarni 
277814b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
277914b24e2bSVaishali Kulkarni 		   "Read ME register: Concrete 0x%08x Opaque 0x%04x\n",
278014b24e2bSVaishali Kulkarni 		   p_hwfn->hw_info.concrete_fid, p_hwfn->hw_info.opaque_fid);
278114b24e2bSVaishali Kulkarni }
278214b24e2bSVaishali Kulkarni 
ecore_hw_set_feat(struct ecore_hwfn * p_hwfn)278314b24e2bSVaishali Kulkarni void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
278414b24e2bSVaishali Kulkarni {
278514b24e2bSVaishali Kulkarni 	u32 *feat_num = p_hwfn->hw_info.feat_num;
278614b24e2bSVaishali Kulkarni 	struct ecore_sb_cnt_info sb_cnt;
278714b24e2bSVaishali Kulkarni 	u32 non_l2_sbs = 0;
278814b24e2bSVaishali Kulkarni 
278914b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&sb_cnt, sizeof(sb_cnt));
279014b24e2bSVaishali Kulkarni 	ecore_int_get_num_sbs(p_hwfn, &sb_cnt);
279114b24e2bSVaishali Kulkarni 
279214b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
279314b24e2bSVaishali Kulkarni 	/* Roce CNQ require each: 1 status block. 1 CNQ, we divide the
279414b24e2bSVaishali Kulkarni 	 * status blocks equally between L2 / RoCE but with consideration as
279514b24e2bSVaishali Kulkarni 	 * to how many l2 queues / cnqs we have
279614b24e2bSVaishali Kulkarni 	 */
279714b24e2bSVaishali Kulkarni 	if (ECORE_IS_RDMA_PERSONALITY(p_hwfn)) {
279814b24e2bSVaishali Kulkarni 		u32 max_cnqs;
279914b24e2bSVaishali Kulkarni 
280014b24e2bSVaishali Kulkarni 		feat_num[ECORE_RDMA_CNQ] =
280114b24e2bSVaishali Kulkarni 			OSAL_MIN_T(u32,
280214b24e2bSVaishali Kulkarni 				   sb_cnt.cnt / 2,
280314b24e2bSVaishali Kulkarni 				   RESC_NUM(p_hwfn, ECORE_RDMA_CNQ_RAM));
280414b24e2bSVaishali Kulkarni 
280514b24e2bSVaishali Kulkarni 		/* Upper layer might require less */
280614b24e2bSVaishali Kulkarni 		max_cnqs = (u32)p_hwfn->pf_params.rdma_pf_params.max_cnqs;
280714b24e2bSVaishali Kulkarni 		if (max_cnqs) {
280814b24e2bSVaishali Kulkarni 			if (max_cnqs == ECORE_RDMA_PF_PARAMS_CNQS_NONE)
280914b24e2bSVaishali Kulkarni 				max_cnqs = 0;
281014b24e2bSVaishali Kulkarni 			feat_num[ECORE_RDMA_CNQ] =
281114b24e2bSVaishali Kulkarni 				OSAL_MIN_T(u32,
281214b24e2bSVaishali Kulkarni 					   feat_num[ECORE_RDMA_CNQ],
281314b24e2bSVaishali Kulkarni 					   max_cnqs);
281414b24e2bSVaishali Kulkarni 		}
281514b24e2bSVaishali Kulkarni 
281614b24e2bSVaishali Kulkarni 		non_l2_sbs = feat_num[ECORE_RDMA_CNQ];
281714b24e2bSVaishali Kulkarni 	}
281814b24e2bSVaishali Kulkarni #endif
281914b24e2bSVaishali Kulkarni 
282014b24e2bSVaishali Kulkarni 	/* L2 Queues require each: 1 status block. 1 L2 queue */
282114b24e2bSVaishali Kulkarni 	if (ECORE_IS_L2_PERSONALITY(p_hwfn)) {
282214b24e2bSVaishali Kulkarni 		/* Start by allocating VF queues, then PF's */
282314b24e2bSVaishali Kulkarni 		feat_num[ECORE_VF_L2_QUE] =
282414b24e2bSVaishali Kulkarni 			OSAL_MIN_T(u32,
282514b24e2bSVaishali Kulkarni 				   RESC_NUM(p_hwfn, ECORE_L2_QUEUE),
282614b24e2bSVaishali Kulkarni 				   sb_cnt.iov_cnt);
282714b24e2bSVaishali Kulkarni 		feat_num[ECORE_PF_L2_QUE] =
282814b24e2bSVaishali Kulkarni 			OSAL_MIN_T(u32,
282914b24e2bSVaishali Kulkarni 				   sb_cnt.cnt - non_l2_sbs,
283014b24e2bSVaishali Kulkarni 				   RESC_NUM(p_hwfn, ECORE_L2_QUEUE) -
283114b24e2bSVaishali Kulkarni 				   FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE));
283214b24e2bSVaishali Kulkarni 	}
283314b24e2bSVaishali Kulkarni 
283414b24e2bSVaishali Kulkarni 	if (ECORE_IS_FCOE_PERSONALITY(p_hwfn))
283514b24e2bSVaishali Kulkarni 		feat_num[ECORE_FCOE_CQ] =
283614b24e2bSVaishali Kulkarni 			OSAL_MIN_T(u32, sb_cnt.cnt, RESC_NUM(p_hwfn,
283714b24e2bSVaishali Kulkarni 							     ECORE_CMDQS_CQS));
283814b24e2bSVaishali Kulkarni 
283914b24e2bSVaishali Kulkarni 	if (ECORE_IS_ISCSI_PERSONALITY(p_hwfn))
284014b24e2bSVaishali Kulkarni 		feat_num[ECORE_ISCSI_CQ] =
284114b24e2bSVaishali Kulkarni 			OSAL_MIN_T(u32, sb_cnt.cnt, RESC_NUM(p_hwfn,
284214b24e2bSVaishali Kulkarni 							     ECORE_CMDQS_CQS));
284314b24e2bSVaishali Kulkarni 
284414b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
284514b24e2bSVaishali Kulkarni 		   "#PF_L2_QUEUE=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #FCOE_CQ=%d #ISCSI_CQ=%d #SB=%d\n",
284614b24e2bSVaishali Kulkarni 		   (int)FEAT_NUM(p_hwfn, ECORE_PF_L2_QUE),
284714b24e2bSVaishali Kulkarni 		   (int)FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE),
284814b24e2bSVaishali Kulkarni 		   (int)FEAT_NUM(p_hwfn, ECORE_RDMA_CNQ),
284914b24e2bSVaishali Kulkarni 		   (int)FEAT_NUM(p_hwfn, ECORE_FCOE_CQ),
285014b24e2bSVaishali Kulkarni 		   (int)FEAT_NUM(p_hwfn, ECORE_ISCSI_CQ),
285114b24e2bSVaishali Kulkarni 		   (int)sb_cnt.cnt);
285214b24e2bSVaishali Kulkarni }
285314b24e2bSVaishali Kulkarni 
ecore_hw_get_resc_name(enum ecore_resources res_id)285414b24e2bSVaishali Kulkarni const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
285514b24e2bSVaishali Kulkarni {
285614b24e2bSVaishali Kulkarni 	switch (res_id) {
285714b24e2bSVaishali Kulkarni 	case ECORE_L2_QUEUE:
285814b24e2bSVaishali Kulkarni 		return "L2_QUEUE";
285914b24e2bSVaishali Kulkarni 	case ECORE_VPORT:
286014b24e2bSVaishali Kulkarni 		return "VPORT";
286114b24e2bSVaishali Kulkarni 	case ECORE_RSS_ENG:
286214b24e2bSVaishali Kulkarni 		return "RSS_ENG";
286314b24e2bSVaishali Kulkarni 	case ECORE_PQ:
286414b24e2bSVaishali Kulkarni 		return "PQ";
286514b24e2bSVaishali Kulkarni 	case ECORE_RL:
286614b24e2bSVaishali Kulkarni 		return "RL";
286714b24e2bSVaishali Kulkarni 	case ECORE_MAC:
286814b24e2bSVaishali Kulkarni 		return "MAC";
286914b24e2bSVaishali Kulkarni 	case ECORE_VLAN:
287014b24e2bSVaishali Kulkarni 		return "VLAN";
287114b24e2bSVaishali Kulkarni 	case ECORE_RDMA_CNQ_RAM:
287214b24e2bSVaishali Kulkarni 		return "RDMA_CNQ_RAM";
287314b24e2bSVaishali Kulkarni 	case ECORE_ILT:
287414b24e2bSVaishali Kulkarni 		return "ILT";
287514b24e2bSVaishali Kulkarni 	case ECORE_LL2_QUEUE:
287614b24e2bSVaishali Kulkarni 		return "LL2_QUEUE";
287714b24e2bSVaishali Kulkarni 	case ECORE_CMDQS_CQS:
287814b24e2bSVaishali Kulkarni 		return "CMDQS_CQS";
287914b24e2bSVaishali Kulkarni 	case ECORE_RDMA_STATS_QUEUE:
288014b24e2bSVaishali Kulkarni 		return "RDMA_STATS_QUEUE";
288114b24e2bSVaishali Kulkarni 	case ECORE_BDQ:
288214b24e2bSVaishali Kulkarni 		return "BDQ";
288314b24e2bSVaishali Kulkarni 	case ECORE_SB:
288414b24e2bSVaishali Kulkarni 		return "SB";
288514b24e2bSVaishali Kulkarni 	default:
288614b24e2bSVaishali Kulkarni 		return "UNKNOWN_RESOURCE";
288714b24e2bSVaishali Kulkarni 	}
288814b24e2bSVaishali Kulkarni }
288914b24e2bSVaishali Kulkarni 
289014b24e2bSVaishali Kulkarni static enum _ecore_status_t
__ecore_hw_set_soft_resc_size(struct ecore_hwfn * p_hwfn,enum ecore_resources res_id,u32 resc_max_val,u32 * p_mcp_resp)289114b24e2bSVaishali Kulkarni __ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn,
289214b24e2bSVaishali Kulkarni 			      enum ecore_resources res_id, u32 resc_max_val,
289314b24e2bSVaishali Kulkarni 			      u32 *p_mcp_resp)
289414b24e2bSVaishali Kulkarni {
289514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
289614b24e2bSVaishali Kulkarni 
289714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_set_resc_max_val(p_hwfn, p_hwfn->p_main_ptt, res_id,
289814b24e2bSVaishali Kulkarni 					resc_max_val, p_mcp_resp);
289914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
290014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
290114b24e2bSVaishali Kulkarni 			  "MFW response failure for a max value setting of resource %d [%s]\n",
290214b24e2bSVaishali Kulkarni 			  res_id, ecore_hw_get_resc_name(res_id));
290314b24e2bSVaishali Kulkarni 		return rc;
290414b24e2bSVaishali Kulkarni 	}
290514b24e2bSVaishali Kulkarni 
290614b24e2bSVaishali Kulkarni 	if (*p_mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK)
290714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
290814b24e2bSVaishali Kulkarni 			"Failed to set the max value of resource %d [%s]. mcp_resp = 0x%08x.\n",
290914b24e2bSVaishali Kulkarni 			res_id, ecore_hw_get_resc_name(res_id), *p_mcp_resp);
291014b24e2bSVaishali Kulkarni 
291114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
291214b24e2bSVaishali Kulkarni }
291314b24e2bSVaishali Kulkarni 
291414b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_hw_set_soft_resc_size(struct ecore_hwfn * p_hwfn)291514b24e2bSVaishali Kulkarni ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn)
291614b24e2bSVaishali Kulkarni {
291714b24e2bSVaishali Kulkarni 	bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
291814b24e2bSVaishali Kulkarni 	u32 resc_max_val, mcp_resp;
291914b24e2bSVaishali Kulkarni 	u8 res_id;
292014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
292114b24e2bSVaishali Kulkarni 
292214b24e2bSVaishali Kulkarni 	for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
292314b24e2bSVaishali Kulkarni 		switch (res_id) {
292414b24e2bSVaishali Kulkarni 		case ECORE_LL2_QUEUE:
292514b24e2bSVaishali Kulkarni 			resc_max_val = MAX_NUM_LL2_RX_QUEUES;
292614b24e2bSVaishali Kulkarni 			break;
292714b24e2bSVaishali Kulkarni 		case ECORE_RDMA_CNQ_RAM:
292814b24e2bSVaishali Kulkarni 			/* No need for a case for ECORE_CMDQS_CQS since
292914b24e2bSVaishali Kulkarni 			 * CNQ/CMDQS are the same resource.
293014b24e2bSVaishali Kulkarni 			 */
293114b24e2bSVaishali Kulkarni 			resc_max_val = NUM_OF_GLOBAL_QUEUES;
293214b24e2bSVaishali Kulkarni 			break;
293314b24e2bSVaishali Kulkarni 		case ECORE_RDMA_STATS_QUEUE:
293414b24e2bSVaishali Kulkarni 			resc_max_val = b_ah ? RDMA_NUM_STATISTIC_COUNTERS_K2
293514b24e2bSVaishali Kulkarni 					    : RDMA_NUM_STATISTIC_COUNTERS_BB;
293614b24e2bSVaishali Kulkarni 			break;
293714b24e2bSVaishali Kulkarni 		case ECORE_BDQ:
293814b24e2bSVaishali Kulkarni 			resc_max_val = BDQ_NUM_RESOURCES;
293914b24e2bSVaishali Kulkarni 			break;
294014b24e2bSVaishali Kulkarni 		default:
294114b24e2bSVaishali Kulkarni 			continue;
294214b24e2bSVaishali Kulkarni 		}
294314b24e2bSVaishali Kulkarni 
294414b24e2bSVaishali Kulkarni 		rc = __ecore_hw_set_soft_resc_size(p_hwfn, res_id,
294514b24e2bSVaishali Kulkarni 						   resc_max_val, &mcp_resp);
294614b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
294714b24e2bSVaishali Kulkarni 			return rc;
294814b24e2bSVaishali Kulkarni 
294914b24e2bSVaishali Kulkarni 		/* There's no point to continue to the next resource if the
295014b24e2bSVaishali Kulkarni 		 * command is not supported by the MFW.
295114b24e2bSVaishali Kulkarni 		 * We do continue if the command is supported but the resource
295214b24e2bSVaishali Kulkarni 		 * is unknown to the MFW. Such a resource will be later
295314b24e2bSVaishali Kulkarni 		 * configured with the default allocation values.
295414b24e2bSVaishali Kulkarni 		 */
295514b24e2bSVaishali Kulkarni 		if (mcp_resp == FW_MSG_CODE_UNSUPPORTED)
295614b24e2bSVaishali Kulkarni 			return ECORE_NOTIMPL;
295714b24e2bSVaishali Kulkarni 	}
295814b24e2bSVaishali Kulkarni 
295914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
296014b24e2bSVaishali Kulkarni }
296114b24e2bSVaishali Kulkarni 
296214b24e2bSVaishali Kulkarni static
ecore_hw_get_dflt_resc(struct ecore_hwfn * p_hwfn,enum ecore_resources res_id,u32 * p_resc_num,u32 * p_resc_start)296314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
296414b24e2bSVaishali Kulkarni 					    enum ecore_resources res_id,
296514b24e2bSVaishali Kulkarni 					    u32 *p_resc_num, u32 *p_resc_start)
296614b24e2bSVaishali Kulkarni {
296714b24e2bSVaishali Kulkarni 	u8 num_funcs = p_hwfn->num_funcs_on_engine;
296814b24e2bSVaishali Kulkarni 	bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
296914b24e2bSVaishali Kulkarni 
297014b24e2bSVaishali Kulkarni 	switch (res_id) {
297114b24e2bSVaishali Kulkarni 	case ECORE_L2_QUEUE:
297214b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? MAX_NUM_L2_QUEUES_K2 :
297314b24e2bSVaishali Kulkarni 				      MAX_NUM_L2_QUEUES_BB) / num_funcs;
297414b24e2bSVaishali Kulkarni 		break;
297514b24e2bSVaishali Kulkarni 	case ECORE_VPORT:
297614b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? MAX_NUM_VPORTS_K2 :
297714b24e2bSVaishali Kulkarni 				      MAX_NUM_VPORTS_BB) / num_funcs;
297814b24e2bSVaishali Kulkarni 		break;
297914b24e2bSVaishali Kulkarni 	case ECORE_RSS_ENG:
298014b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? ETH_RSS_ENGINE_NUM_K2 :
298114b24e2bSVaishali Kulkarni 				      ETH_RSS_ENGINE_NUM_BB) / num_funcs;
298214b24e2bSVaishali Kulkarni 		break;
298314b24e2bSVaishali Kulkarni 	case ECORE_PQ:
298414b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? MAX_QM_TX_QUEUES_K2 :
298514b24e2bSVaishali Kulkarni 				      MAX_QM_TX_QUEUES_BB) / num_funcs;
298614b24e2bSVaishali Kulkarni 		*p_resc_num &= ~0x7; /* The granularity of the PQs is 8 */
298714b24e2bSVaishali Kulkarni 		break;
298814b24e2bSVaishali Kulkarni 	case ECORE_RL:
298914b24e2bSVaishali Kulkarni 		*p_resc_num = MAX_QM_GLOBAL_RLS / num_funcs;
299014b24e2bSVaishali Kulkarni 		break;
299114b24e2bSVaishali Kulkarni 	case ECORE_MAC:
299214b24e2bSVaishali Kulkarni 	case ECORE_VLAN:
299314b24e2bSVaishali Kulkarni 		/* Each VFC resource can accommodate both a MAC and a VLAN */
299414b24e2bSVaishali Kulkarni 		*p_resc_num = ETH_NUM_MAC_FILTERS / num_funcs;
299514b24e2bSVaishali Kulkarni 		break;
299614b24e2bSVaishali Kulkarni 	case ECORE_ILT:
299714b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? PXP_NUM_ILT_RECORDS_K2 :
299814b24e2bSVaishali Kulkarni 				      PXP_NUM_ILT_RECORDS_BB) / num_funcs;
299914b24e2bSVaishali Kulkarni 		break;
300014b24e2bSVaishali Kulkarni 	case ECORE_LL2_QUEUE:
300114b24e2bSVaishali Kulkarni 		*p_resc_num = MAX_NUM_LL2_RX_QUEUES / num_funcs;
300214b24e2bSVaishali Kulkarni 		break;
300314b24e2bSVaishali Kulkarni 	case ECORE_RDMA_CNQ_RAM:
300414b24e2bSVaishali Kulkarni 	case ECORE_CMDQS_CQS:
300514b24e2bSVaishali Kulkarni 		/* CNQ/CMDQS are the same resource */
300614b24e2bSVaishali Kulkarni 		*p_resc_num = NUM_OF_GLOBAL_QUEUES / num_funcs;
300714b24e2bSVaishali Kulkarni 		break;
300814b24e2bSVaishali Kulkarni 	case ECORE_RDMA_STATS_QUEUE:
300914b24e2bSVaishali Kulkarni 		*p_resc_num = (b_ah ? RDMA_NUM_STATISTIC_COUNTERS_K2 :
301014b24e2bSVaishali Kulkarni 				      RDMA_NUM_STATISTIC_COUNTERS_BB) /
301114b24e2bSVaishali Kulkarni 			      num_funcs;
301214b24e2bSVaishali Kulkarni 		break;
301314b24e2bSVaishali Kulkarni 	case ECORE_BDQ:
301414b24e2bSVaishali Kulkarni 		if (p_hwfn->hw_info.personality != ECORE_PCI_ISCSI &&
301514b24e2bSVaishali Kulkarni 		    p_hwfn->hw_info.personality != ECORE_PCI_FCOE)
301614b24e2bSVaishali Kulkarni 			*p_resc_num = 0;
301714b24e2bSVaishali Kulkarni 		else
301814b24e2bSVaishali Kulkarni 			*p_resc_num = 1;
301914b24e2bSVaishali Kulkarni 		break;
302014b24e2bSVaishali Kulkarni 	case ECORE_SB:
302114b24e2bSVaishali Kulkarni 		/* Since we want its value to reflect whether MFW supports
302214b24e2bSVaishali Kulkarni 		 * the new scheme, have a default of 0.
302314b24e2bSVaishali Kulkarni 		 */
302414b24e2bSVaishali Kulkarni 		*p_resc_num = 0;
302514b24e2bSVaishali Kulkarni 		break;
302614b24e2bSVaishali Kulkarni 	default:
302714b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
302814b24e2bSVaishali Kulkarni 	}
302914b24e2bSVaishali Kulkarni 
303014b24e2bSVaishali Kulkarni 	switch (res_id) {
303114b24e2bSVaishali Kulkarni 	case ECORE_BDQ:
303214b24e2bSVaishali Kulkarni 		if (!*p_resc_num)
303314b24e2bSVaishali Kulkarni 			*p_resc_start = 0;
303414b24e2bSVaishali Kulkarni 		else if (p_hwfn->p_dev->num_ports_in_engine == 4)
303514b24e2bSVaishali Kulkarni 			*p_resc_start = p_hwfn->port_id;
303614b24e2bSVaishali Kulkarni 		else if (p_hwfn->hw_info.personality == ECORE_PCI_ISCSI)
303714b24e2bSVaishali Kulkarni 			*p_resc_start = p_hwfn->port_id;
303814b24e2bSVaishali Kulkarni 		else if (p_hwfn->hw_info.personality == ECORE_PCI_FCOE)
303914b24e2bSVaishali Kulkarni 			*p_resc_start = p_hwfn->port_id + 2;
304014b24e2bSVaishali Kulkarni 		break;
304114b24e2bSVaishali Kulkarni 	default:
304214b24e2bSVaishali Kulkarni 		*p_resc_start = *p_resc_num * p_hwfn->enabled_func_idx;
304314b24e2bSVaishali Kulkarni 		break;
304414b24e2bSVaishali Kulkarni 	}
304514b24e2bSVaishali Kulkarni 
304614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
304714b24e2bSVaishali Kulkarni }
304814b24e2bSVaishali Kulkarni 
304914b24e2bSVaishali Kulkarni static enum _ecore_status_t
__ecore_hw_set_resc_info(struct ecore_hwfn * p_hwfn,enum ecore_resources res_id,bool drv_resc_alloc)305014b24e2bSVaishali Kulkarni __ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
305114b24e2bSVaishali Kulkarni 			 bool drv_resc_alloc)
305214b24e2bSVaishali Kulkarni {
305314b24e2bSVaishali Kulkarni 	u32 dflt_resc_num = 0, dflt_resc_start = 0;
305414b24e2bSVaishali Kulkarni 	u32 mcp_resp, *p_resc_num, *p_resc_start;
305514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
305614b24e2bSVaishali Kulkarni 
305714b24e2bSVaishali Kulkarni 	p_resc_num = &RESC_NUM(p_hwfn, res_id);
305814b24e2bSVaishali Kulkarni 	p_resc_start = &RESC_START(p_hwfn, res_id);
305914b24e2bSVaishali Kulkarni 
306014b24e2bSVaishali Kulkarni 	rc = ecore_hw_get_dflt_resc(p_hwfn, res_id, &dflt_resc_num,
306114b24e2bSVaishali Kulkarni 				    &dflt_resc_start);
306214b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
306314b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
306414b24e2bSVaishali Kulkarni 		       "Failed to get default amount for resource %d [%s]\n",
306514b24e2bSVaishali Kulkarni 			res_id, ecore_hw_get_resc_name(res_id));
306614b24e2bSVaishali Kulkarni 		return rc;
306714b24e2bSVaishali Kulkarni 	}
306814b24e2bSVaishali Kulkarni 
306914b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
307014b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
307114b24e2bSVaishali Kulkarni 		*p_resc_num = dflt_resc_num;
307214b24e2bSVaishali Kulkarni 		*p_resc_start = dflt_resc_start;
307314b24e2bSVaishali Kulkarni 		goto out;
307414b24e2bSVaishali Kulkarni 	}
307514b24e2bSVaishali Kulkarni #endif
307614b24e2bSVaishali Kulkarni 
307714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, res_id,
307814b24e2bSVaishali Kulkarni 				     &mcp_resp, p_resc_num, p_resc_start);
307914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
308014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
308114b24e2bSVaishali Kulkarni 			  "MFW response failure for an allocation request for resource %d [%s]\n",
308214b24e2bSVaishali Kulkarni 			  res_id, ecore_hw_get_resc_name(res_id));
308314b24e2bSVaishali Kulkarni 		return rc;
308414b24e2bSVaishali Kulkarni 	}
308514b24e2bSVaishali Kulkarni 
308614b24e2bSVaishali Kulkarni 	/* Default driver values are applied in the following cases:
308714b24e2bSVaishali Kulkarni 	 * - The resource allocation MB command is not supported by the MFW
308814b24e2bSVaishali Kulkarni 	 * - There is an internal error in the MFW while processing the request
308914b24e2bSVaishali Kulkarni 	 * - The resource ID is unknown to the MFW
309014b24e2bSVaishali Kulkarni 	 */
309114b24e2bSVaishali Kulkarni 	if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK) {
309214b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
309314b24e2bSVaishali Kulkarni 			"Failed to receive allocation info for resource %d [%s]. mcp_resp = 0x%x. Applying default values [%d,%d].\n",
309414b24e2bSVaishali Kulkarni 			res_id, ecore_hw_get_resc_name(res_id), mcp_resp,
309514b24e2bSVaishali Kulkarni 			dflt_resc_num, dflt_resc_start);
309614b24e2bSVaishali Kulkarni 		*p_resc_num = dflt_resc_num;
309714b24e2bSVaishali Kulkarni 		*p_resc_start = dflt_resc_start;
309814b24e2bSVaishali Kulkarni 		goto out;
309914b24e2bSVaishali Kulkarni 	}
310014b24e2bSVaishali Kulkarni 
310114b24e2bSVaishali Kulkarni 	if ((*p_resc_num != dflt_resc_num ||
310214b24e2bSVaishali Kulkarni 	     *p_resc_start != dflt_resc_start) &&
310314b24e2bSVaishali Kulkarni 	    res_id != ECORE_SB) {
310414b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
310514b24e2bSVaishali Kulkarni 			"MFW allocation for resource %d [%s] differs from default values [%d,%d vs. %d,%d]%s\n",
310614b24e2bSVaishali Kulkarni 			res_id, ecore_hw_get_resc_name(res_id), *p_resc_num,
310714b24e2bSVaishali Kulkarni 			*p_resc_start, dflt_resc_num, dflt_resc_start,
310814b24e2bSVaishali Kulkarni 			drv_resc_alloc ? " - Applying default values" : "");
310914b24e2bSVaishali Kulkarni 		if (drv_resc_alloc) {
311014b24e2bSVaishali Kulkarni 			*p_resc_num = dflt_resc_num;
311114b24e2bSVaishali Kulkarni 			*p_resc_start = dflt_resc_start;
311214b24e2bSVaishali Kulkarni 		}
311314b24e2bSVaishali Kulkarni 	}
311414b24e2bSVaishali Kulkarni out:
311514b24e2bSVaishali Kulkarni 	/* PQs have to divide by 8 [that's the HW granularity].
311614b24e2bSVaishali Kulkarni 	 * Reduce number so it would fit.
311714b24e2bSVaishali Kulkarni 	 */
311814b24e2bSVaishali Kulkarni 	if ((res_id == ECORE_PQ) &&
311914b24e2bSVaishali Kulkarni 	    ((*p_resc_num % 8) || (*p_resc_start % 8))) {
312014b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
312114b24e2bSVaishali Kulkarni 			"PQs need to align by 8; Number %08x --> %08x, Start %08x --> %08x\n",
312214b24e2bSVaishali Kulkarni 			*p_resc_num, (*p_resc_num) & ~0x7,
312314b24e2bSVaishali Kulkarni 			*p_resc_start, (*p_resc_start) & ~0x7);
312414b24e2bSVaishali Kulkarni 		*p_resc_num &= ~0x7;
312514b24e2bSVaishali Kulkarni 		*p_resc_start &= ~0x7;
312614b24e2bSVaishali Kulkarni 	}
312714b24e2bSVaishali Kulkarni 
312814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
312914b24e2bSVaishali Kulkarni }
313014b24e2bSVaishali Kulkarni 
ecore_hw_set_resc_info(struct ecore_hwfn * p_hwfn,bool drv_resc_alloc)313114b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
313214b24e2bSVaishali Kulkarni 						   bool drv_resc_alloc)
313314b24e2bSVaishali Kulkarni {
313414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
313514b24e2bSVaishali Kulkarni 	u8 res_id;
313614b24e2bSVaishali Kulkarni 
313714b24e2bSVaishali Kulkarni 	for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
313814b24e2bSVaishali Kulkarni 		rc = __ecore_hw_set_resc_info(p_hwfn, res_id, drv_resc_alloc);
313914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
314014b24e2bSVaishali Kulkarni 			return rc;
314114b24e2bSVaishali Kulkarni 	}
314214b24e2bSVaishali Kulkarni 
314314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
314414b24e2bSVaishali Kulkarni }
314514b24e2bSVaishali Kulkarni 
314614b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_LOCK_RETRY_CNT		10
314714b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US	10000 /* 10 msec */
314814b24e2bSVaishali Kulkarni 
ecore_hw_get_resc(struct ecore_hwfn * p_hwfn,bool drv_resc_alloc)314914b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
315014b24e2bSVaishali Kulkarni 					      bool drv_resc_alloc)
315114b24e2bSVaishali Kulkarni {
315214b24e2bSVaishali Kulkarni 	struct ecore_resc_unlock_params resc_unlock_params;
315314b24e2bSVaishali Kulkarni 	struct ecore_resc_lock_params resc_lock_params;
315414b24e2bSVaishali Kulkarni 	bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
315514b24e2bSVaishali Kulkarni 	u8 res_id;
315614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
315714b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
315814b24e2bSVaishali Kulkarni 	u32 *resc_start = p_hwfn->hw_info.resc_start;
315914b24e2bSVaishali Kulkarni 	u32 *resc_num = p_hwfn->hw_info.resc_num;
316014b24e2bSVaishali Kulkarni 	/* For AH, an equal share of the ILT lines between the maximal number of
316114b24e2bSVaishali Kulkarni 	 * PFs is not enough for RoCE. This would be solved by the future
316214b24e2bSVaishali Kulkarni 	 * resource allocation scheme, but isn't currently present for
316314b24e2bSVaishali Kulkarni 	 * FPGA/emulation. For now we keep a number that is sufficient for RoCE
316414b24e2bSVaishali Kulkarni 	 * to work - the BB number of ILT lines divided by its max PFs number.
316514b24e2bSVaishali Kulkarni 	 */
316614b24e2bSVaishali Kulkarni 	u32 roce_min_ilt_lines = PXP_NUM_ILT_RECORDS_BB / MAX_NUM_PFS_BB;
316714b24e2bSVaishali Kulkarni #endif
316814b24e2bSVaishali Kulkarni 
316914b24e2bSVaishali Kulkarni 	/* Setting the max values of the soft resources and the following
317014b24e2bSVaishali Kulkarni 	 * resources allocation queries should be atomic. Since several PFs can
317114b24e2bSVaishali Kulkarni 	 * run in parallel - a resource lock is needed.
317214b24e2bSVaishali Kulkarni 	 * If either the resource lock or resource set value commands are not
317314b24e2bSVaishali Kulkarni 	 * supported - skip the the max values setting, release the lock if
317414b24e2bSVaishali Kulkarni 	 * needed, and proceed to the queries. Other failures, including a
317514b24e2bSVaishali Kulkarni 	 * failure to acquire the lock, will cause this function to fail.
317614b24e2bSVaishali Kulkarni 	 * Old drivers that don't acquire the lock can run in parallel, and
317714b24e2bSVaishali Kulkarni 	 * their allocation values won't be affected by the updated max values.
317814b24e2bSVaishali Kulkarni 	 */
317914b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&resc_lock_params, sizeof(resc_lock_params));
318014b24e2bSVaishali Kulkarni 	resc_lock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
318114b24e2bSVaishali Kulkarni 	resc_lock_params.retry_num = ECORE_RESC_ALLOC_LOCK_RETRY_CNT;
318214b24e2bSVaishali Kulkarni 	resc_lock_params.retry_interval = ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US;
318314b24e2bSVaishali Kulkarni 	resc_lock_params.sleep_b4_retry = true;
318414b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&resc_unlock_params, sizeof(resc_unlock_params));
318514b24e2bSVaishali Kulkarni 	resc_unlock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
318614b24e2bSVaishali Kulkarni 
318714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resc_lock(p_hwfn, p_hwfn->p_main_ptt, &resc_lock_params);
318814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
318914b24e2bSVaishali Kulkarni 		return rc;
319014b24e2bSVaishali Kulkarni 	} else if (rc == ECORE_NOTIMPL) {
319114b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
319214b24e2bSVaishali Kulkarni 			"Skip the max values setting of the soft resources since the resource lock is not supported by the MFW\n");
319314b24e2bSVaishali Kulkarni 	} else if (rc == ECORE_SUCCESS && !resc_lock_params.b_granted) {
319414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
319514b24e2bSVaishali Kulkarni 			  "Failed to acquire the resource lock for the resource allocation commands\n");
319614b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
319714b24e2bSVaishali Kulkarni 	} else {
319814b24e2bSVaishali Kulkarni 		rc = ecore_hw_set_soft_resc_size(p_hwfn);
319914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
320014b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
320114b24e2bSVaishali Kulkarni 				  "Failed to set the max values of the soft resources\n");
320214b24e2bSVaishali Kulkarni 			goto unlock_and_exit;
320314b24e2bSVaishali Kulkarni 		} else if (rc == ECORE_NOTIMPL) {
320414b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn,
320514b24e2bSVaishali Kulkarni 				"Skip the max values setting of the soft resources since it is not supported by the MFW\n");
320614b24e2bSVaishali Kulkarni 			rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
320714b24e2bSVaishali Kulkarni 						   &resc_unlock_params);
320814b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
320914b24e2bSVaishali Kulkarni 				DP_INFO(p_hwfn,
321014b24e2bSVaishali Kulkarni 					"Failed to release the resource lock for the resource allocation commands\n");
321114b24e2bSVaishali Kulkarni 		}
321214b24e2bSVaishali Kulkarni 	}
321314b24e2bSVaishali Kulkarni 
321414b24e2bSVaishali Kulkarni 	rc = ecore_hw_set_resc_info(p_hwfn, drv_resc_alloc);
321514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
321614b24e2bSVaishali Kulkarni 		goto unlock_and_exit;
321714b24e2bSVaishali Kulkarni 
321814b24e2bSVaishali Kulkarni 	if (resc_lock_params.b_granted && !resc_unlock_params.b_released) {
321914b24e2bSVaishali Kulkarni 		rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
322014b24e2bSVaishali Kulkarni 					   &resc_unlock_params);
322114b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
322214b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn,
322314b24e2bSVaishali Kulkarni 				"Failed to release the resource lock for the resource allocation commands\n");
322414b24e2bSVaishali Kulkarni 	}
322514b24e2bSVaishali Kulkarni 
322614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
322714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
322814b24e2bSVaishali Kulkarni 		/* Reduced build contains less PQs */
322914b24e2bSVaishali Kulkarni 		if (!(p_hwfn->p_dev->b_is_emul_full)) {
323014b24e2bSVaishali Kulkarni 			resc_num[ECORE_PQ] = 32;
323114b24e2bSVaishali Kulkarni 			resc_start[ECORE_PQ] = resc_num[ECORE_PQ] *
323214b24e2bSVaishali Kulkarni 					       p_hwfn->enabled_func_idx;
323314b24e2bSVaishali Kulkarni 		}
323414b24e2bSVaishali Kulkarni 
323514b24e2bSVaishali Kulkarni 		/* For AH emulation, since we have a possible maximal number of
323614b24e2bSVaishali Kulkarni 		 * 16 enabled PFs, in case there are not enough ILT lines -
323714b24e2bSVaishali Kulkarni 		 * allocate only first PF as RoCE and have all the other ETH
323814b24e2bSVaishali Kulkarni 		 * only with less ILT lines.
323914b24e2bSVaishali Kulkarni 		 */
324014b24e2bSVaishali Kulkarni 		if (!p_hwfn->rel_pf_id && p_hwfn->p_dev->b_is_emul_full)
324114b24e2bSVaishali Kulkarni 			resc_num[ECORE_ILT] = OSAL_MAX_T(u32,
324214b24e2bSVaishali Kulkarni 							 resc_num[ECORE_ILT],
324314b24e2bSVaishali Kulkarni 							 roce_min_ilt_lines);
324414b24e2bSVaishali Kulkarni 	}
324514b24e2bSVaishali Kulkarni 
324614b24e2bSVaishali Kulkarni 	/* Correct the common ILT calculation if PF0 has more */
324714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev) &&
324814b24e2bSVaishali Kulkarni 	    p_hwfn->p_dev->b_is_emul_full &&
324914b24e2bSVaishali Kulkarni 	    p_hwfn->rel_pf_id &&
325014b24e2bSVaishali Kulkarni 	    resc_num[ECORE_ILT] < roce_min_ilt_lines)
325114b24e2bSVaishali Kulkarni 		resc_start[ECORE_ILT] += roce_min_ilt_lines -
325214b24e2bSVaishali Kulkarni 					 resc_num[ECORE_ILT];
325314b24e2bSVaishali Kulkarni #endif
325414b24e2bSVaishali Kulkarni 
325514b24e2bSVaishali Kulkarni 	/* Sanity for ILT */
325614b24e2bSVaishali Kulkarni 	if ((b_ah && (RESC_END(p_hwfn, ECORE_ILT) > PXP_NUM_ILT_RECORDS_K2)) ||
325714b24e2bSVaishali Kulkarni 	    (!b_ah && (RESC_END(p_hwfn, ECORE_ILT) > PXP_NUM_ILT_RECORDS_BB))) {
325814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Can't assign ILT pages [%08x,...,%08x]\n",
325914b24e2bSVaishali Kulkarni 			  RESC_START(p_hwfn, ECORE_ILT),
326014b24e2bSVaishali Kulkarni 			  RESC_END(p_hwfn, ECORE_ILT) - 1);
326114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
326214b24e2bSVaishali Kulkarni 	}
326314b24e2bSVaishali Kulkarni 
326414b24e2bSVaishali Kulkarni 	/* This will also learn the number of SBs from MFW */
326514b24e2bSVaishali Kulkarni 	if (ecore_int_igu_reset_cam(p_hwfn, p_hwfn->p_main_ptt))
326614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
326714b24e2bSVaishali Kulkarni 
326814b24e2bSVaishali Kulkarni 	ecore_hw_set_feat(p_hwfn);
326914b24e2bSVaishali Kulkarni 
327014b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
327114b24e2bSVaishali Kulkarni 		   "The numbers for each resource are:\n");
327214b24e2bSVaishali Kulkarni 	for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++)
327314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE, "%s = %d start = %d\n",
327414b24e2bSVaishali Kulkarni 			   ecore_hw_get_resc_name(res_id),
327514b24e2bSVaishali Kulkarni 			   RESC_NUM(p_hwfn, res_id),
327614b24e2bSVaishali Kulkarni 			   RESC_START(p_hwfn, res_id));
327714b24e2bSVaishali Kulkarni 
327814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
327914b24e2bSVaishali Kulkarni 
328014b24e2bSVaishali Kulkarni unlock_and_exit:
328114b24e2bSVaishali Kulkarni 	if (resc_lock_params.b_granted && !resc_unlock_params.b_released)
328214b24e2bSVaishali Kulkarni 		ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
328314b24e2bSVaishali Kulkarni 				      &resc_unlock_params);
328414b24e2bSVaishali Kulkarni 	return rc;
328514b24e2bSVaishali Kulkarni }
328614b24e2bSVaishali Kulkarni 
328714b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_hw_get_nvm_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_hw_prepare_params * p_params)328814b24e2bSVaishali Kulkarni ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
328914b24e2bSVaishali Kulkarni 		      struct ecore_ptt *p_ptt,
329014b24e2bSVaishali Kulkarni 		      struct ecore_hw_prepare_params *p_params)
329114b24e2bSVaishali Kulkarni {
329214b24e2bSVaishali Kulkarni 	u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg, dcbx_mode;
329314b24e2bSVaishali Kulkarni 	u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
329414b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_capabilities *p_caps;
329514b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_params *link;
329614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
329714b24e2bSVaishali Kulkarni 
329814b24e2bSVaishali Kulkarni 	/* Read global nvm_cfg address */
329914b24e2bSVaishali Kulkarni 	nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
330014b24e2bSVaishali Kulkarni 
330114b24e2bSVaishali Kulkarni 	/* Verify MCP has initialized it */
330214b24e2bSVaishali Kulkarni 	if (!nvm_cfg_addr) {
330314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Shared memory not initialized\n");
330414b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
330514b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_NVM;
330614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
330714b24e2bSVaishali Kulkarni 	}
330814b24e2bSVaishali Kulkarni 
330914b24e2bSVaishali Kulkarni 	/* Read nvm_cfg1  (Notice this is just offset, and not offsize (TBD) */
331014b24e2bSVaishali Kulkarni 	nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
331114b24e2bSVaishali Kulkarni 
331214b24e2bSVaishali Kulkarni 	addr = MCP_REG_SCRATCH  + nvm_cfg1_offset +
3313*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1, glob) +
3314*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1_glob, core_cfg);
331514b24e2bSVaishali Kulkarni 
331614b24e2bSVaishali Kulkarni 	core_cfg = ecore_rd(p_hwfn, p_ptt, addr);
331714b24e2bSVaishali Kulkarni 
331814b24e2bSVaishali Kulkarni 	switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >>
331914b24e2bSVaishali Kulkarni 		NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) {
332014b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G:
332114b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_2X40G;
332214b24e2bSVaishali Kulkarni 		break;
332314b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G:
332414b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_2X50G;
332514b24e2bSVaishali Kulkarni 		break;
332614b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G:
332714b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_1X100G;
332814b24e2bSVaishali Kulkarni 		break;
332914b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F:
333014b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_4X10G_F;
333114b24e2bSVaishali Kulkarni 		break;
333214b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E:
333314b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_4X10G_E;
333414b24e2bSVaishali Kulkarni 		break;
333514b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G:
333614b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_4X20G;
333714b24e2bSVaishali Kulkarni 		break;
333814b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G:
333914b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_1X40G;
334014b24e2bSVaishali Kulkarni 		break;
334114b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G:
334214b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_2X25G;
334314b24e2bSVaishali Kulkarni 		break;
334414b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G:
334514b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_2X10G;
334614b24e2bSVaishali Kulkarni 		break;
334714b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G:
334814b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_1X25G;
334914b24e2bSVaishali Kulkarni 		break;
335014b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G:
335114b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.port_mode = ECORE_PORT_MODE_DE_4X25G;
335214b24e2bSVaishali Kulkarni 		break;
335314b24e2bSVaishali Kulkarni 	default:
335414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Unknown port mode in 0x%08x\n",
335514b24e2bSVaishali Kulkarni 			  core_cfg);
335614b24e2bSVaishali Kulkarni 		break;
335714b24e2bSVaishali Kulkarni 	}
335814b24e2bSVaishali Kulkarni 
335914b24e2bSVaishali Kulkarni 	/* Read DCBX configuration */
336014b24e2bSVaishali Kulkarni 	port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
3361*04443fdeSToomas Soome 			offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
336214b24e2bSVaishali Kulkarni 	dcbx_mode = ecore_rd(p_hwfn, p_ptt,
336314b24e2bSVaishali Kulkarni 			     port_cfg_addr +
3364*04443fdeSToomas Soome 			     offsetof(struct nvm_cfg1_port, generic_cont0));
336514b24e2bSVaishali Kulkarni 	dcbx_mode = (dcbx_mode & NVM_CFG1_PORT_DCBX_MODE_MASK)
336614b24e2bSVaishali Kulkarni 		>> NVM_CFG1_PORT_DCBX_MODE_OFFSET;
336714b24e2bSVaishali Kulkarni 	switch (dcbx_mode) {
336814b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DCBX_MODE_DYNAMIC:
336914b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.dcbx_mode = ECORE_DCBX_VERSION_DYNAMIC;
337014b24e2bSVaishali Kulkarni 		break;
337114b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DCBX_MODE_CEE:
337214b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.dcbx_mode = ECORE_DCBX_VERSION_CEE;
337314b24e2bSVaishali Kulkarni 		break;
337414b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DCBX_MODE_IEEE:
337514b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.dcbx_mode = ECORE_DCBX_VERSION_IEEE;
337614b24e2bSVaishali Kulkarni 		break;
337714b24e2bSVaishali Kulkarni 	default:
337814b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.dcbx_mode = ECORE_DCBX_VERSION_DISABLED;
337914b24e2bSVaishali Kulkarni 	}
338014b24e2bSVaishali Kulkarni 
338114b24e2bSVaishali Kulkarni 	/* Read default link configuration */
338214b24e2bSVaishali Kulkarni 	link = &p_hwfn->mcp_info->link_input;
338314b24e2bSVaishali Kulkarni 	p_caps = &p_hwfn->mcp_info->link_capabilities;
338414b24e2bSVaishali Kulkarni 	port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
3385*04443fdeSToomas Soome 			offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
338614b24e2bSVaishali Kulkarni 	link_temp = ecore_rd(p_hwfn, p_ptt,
338714b24e2bSVaishali Kulkarni 			     port_cfg_addr +
3388*04443fdeSToomas Soome 			     offsetof(struct nvm_cfg1_port, speed_cap_mask));
338914b24e2bSVaishali Kulkarni 	link_temp &= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;
339014b24e2bSVaishali Kulkarni 	link->speed.advertised_speeds = link_temp;
339114b24e2bSVaishali Kulkarni 	p_caps->speed_capabilities = link->speed.advertised_speeds;
339214b24e2bSVaishali Kulkarni 
339314b24e2bSVaishali Kulkarni 	link_temp = ecore_rd(p_hwfn, p_ptt,
339414b24e2bSVaishali Kulkarni 				 port_cfg_addr +
3395*04443fdeSToomas Soome 				 offsetof(struct nvm_cfg1_port, link_settings));
339614b24e2bSVaishali Kulkarni 	switch ((link_temp & NVM_CFG1_PORT_DRV_LINK_SPEED_MASK) >>
339714b24e2bSVaishali Kulkarni 		NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET) {
339814b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG:
339914b24e2bSVaishali Kulkarni 		link->speed.autoneg = true;
340014b24e2bSVaishali Kulkarni 		break;
340114b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_1G:
340214b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 1000;
340314b24e2bSVaishali Kulkarni 		break;
340414b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_10G:
340514b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 10000;
340614b24e2bSVaishali Kulkarni 		break;
340714b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_25G:
340814b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 25000;
340914b24e2bSVaishali Kulkarni 		break;
341014b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_40G:
341114b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 40000;
341214b24e2bSVaishali Kulkarni 		break;
341314b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_50G:
341414b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 50000;
341514b24e2bSVaishali Kulkarni 		break;
341614b24e2bSVaishali Kulkarni 	case NVM_CFG1_PORT_DRV_LINK_SPEED_BB_100G:
341714b24e2bSVaishali Kulkarni 		link->speed.forced_speed = 100000;
341814b24e2bSVaishali Kulkarni 		break;
341914b24e2bSVaishali Kulkarni 	default:
342014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Unknown Speed in 0x%08x\n",
342114b24e2bSVaishali Kulkarni 			  link_temp);
342214b24e2bSVaishali Kulkarni 	}
342314b24e2bSVaishali Kulkarni 
342414b24e2bSVaishali Kulkarni 	p_caps->default_speed = link->speed.forced_speed;
342514b24e2bSVaishali Kulkarni 	p_caps->default_speed_autoneg = link->speed.autoneg;
342614b24e2bSVaishali Kulkarni 
342714b24e2bSVaishali Kulkarni 	link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
342814b24e2bSVaishali Kulkarni 	link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
342914b24e2bSVaishali Kulkarni 	link->pause.autoneg = !!(link_temp &
343014b24e2bSVaishali Kulkarni 				 NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
343114b24e2bSVaishali Kulkarni 	link->pause.forced_rx = !!(link_temp &
343214b24e2bSVaishali Kulkarni 				   NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
343314b24e2bSVaishali Kulkarni 	link->pause.forced_tx = !!(link_temp &
343414b24e2bSVaishali Kulkarni 				   NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
343514b24e2bSVaishali Kulkarni 	link->loopback_mode = 0;
343614b24e2bSVaishali Kulkarni 
343714b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
343814b24e2bSVaishali Kulkarni 		link_temp = ecore_rd(p_hwfn, p_ptt, port_cfg_addr +
3439*04443fdeSToomas Soome 				     offsetof(struct nvm_cfg1_port, ext_phy));
344014b24e2bSVaishali Kulkarni 		link_temp &= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK;
344114b24e2bSVaishali Kulkarni 		link_temp >>= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_OFFSET;
344214b24e2bSVaishali Kulkarni 		p_caps->default_eee = ECORE_MCP_EEE_ENABLED;
344314b24e2bSVaishali Kulkarni 		link->eee.enable = true;
344414b24e2bSVaishali Kulkarni 		switch (link_temp) {
344514b24e2bSVaishali Kulkarni 		case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_DISABLED:
344614b24e2bSVaishali Kulkarni 			p_caps->default_eee = ECORE_MCP_EEE_DISABLED;
344714b24e2bSVaishali Kulkarni 			link->eee.enable = false;
344814b24e2bSVaishali Kulkarni 			break;
344914b24e2bSVaishali Kulkarni 		case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_BALANCED:
345014b24e2bSVaishali Kulkarni 			p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_BALANCED_TIME;
345114b24e2bSVaishali Kulkarni 			break;
345214b24e2bSVaishali Kulkarni 		case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_AGGRESSIVE:
345314b24e2bSVaishali Kulkarni 			p_caps->eee_lpi_timer =
345414b24e2bSVaishali Kulkarni 				EEE_TX_TIMER_USEC_AGGRESSIVE_TIME;
345514b24e2bSVaishali Kulkarni 			break;
345614b24e2bSVaishali Kulkarni 		case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_LOW_LATENCY:
345714b24e2bSVaishali Kulkarni 			p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_LATENCY_TIME;
345814b24e2bSVaishali Kulkarni 			break;
345914b24e2bSVaishali Kulkarni 		}
346014b24e2bSVaishali Kulkarni 		link->eee.tx_lpi_timer = p_caps->eee_lpi_timer;
346114b24e2bSVaishali Kulkarni 		link->eee.tx_lpi_enable = link->eee.enable;
346214b24e2bSVaishali Kulkarni 		if (link->eee.enable)
346314b24e2bSVaishali Kulkarni 			link->eee.adv_caps = ECORE_EEE_1G_ADV |
346414b24e2bSVaishali Kulkarni 						ECORE_EEE_10G_ADV;
346514b24e2bSVaishali Kulkarni 	} else {
346614b24e2bSVaishali Kulkarni 		p_caps->default_eee = ECORE_MCP_EEE_UNSUPPORTED;
346714b24e2bSVaishali Kulkarni 	}
346814b24e2bSVaishali Kulkarni 
346914b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
347014b24e2bSVaishali Kulkarni 		   "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x EEE: %02x [%08x usec]\n",
347114b24e2bSVaishali Kulkarni 		   link->speed.forced_speed, link->speed.advertised_speeds,
347214b24e2bSVaishali Kulkarni 		   link->speed.autoneg, link->pause.autoneg,
347314b24e2bSVaishali Kulkarni 		   p_caps->default_eee, p_caps->eee_lpi_timer);
347414b24e2bSVaishali Kulkarni 
347514b24e2bSVaishali Kulkarni 	/* Read Multi-function information from shmem */
347614b24e2bSVaishali Kulkarni 	addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
3477*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1, glob) +
3478*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1_glob, generic_cont0);
347914b24e2bSVaishali Kulkarni 
348014b24e2bSVaishali Kulkarni 	generic_cont0 = ecore_rd(p_hwfn, p_ptt, addr);
348114b24e2bSVaishali Kulkarni 
348214b24e2bSVaishali Kulkarni 	mf_mode = (generic_cont0 & NVM_CFG1_GLOB_MF_MODE_MASK) >>
348314b24e2bSVaishali Kulkarni 		  NVM_CFG1_GLOB_MF_MODE_OFFSET;
348414b24e2bSVaishali Kulkarni 
348514b24e2bSVaishali Kulkarni 	switch (mf_mode) {
348614b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED:
348714b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->mf_mode = ECORE_MF_OVLAN;
348814b24e2bSVaishali Kulkarni 		break;
348914b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_MF_MODE_NPAR1_0:
349014b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->mf_mode = ECORE_MF_NPAR;
349114b24e2bSVaishali Kulkarni 		break;
349214b24e2bSVaishali Kulkarni 	case NVM_CFG1_GLOB_MF_MODE_DEFAULT:
349314b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->mf_mode = ECORE_MF_DEFAULT;
349414b24e2bSVaishali Kulkarni 		break;
349514b24e2bSVaishali Kulkarni 	}
349614b24e2bSVaishali Kulkarni 	DP_INFO(p_hwfn, "Multi function mode is %08x\n",
349714b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->mf_mode);
349814b24e2bSVaishali Kulkarni 
349914b24e2bSVaishali Kulkarni 	/* Read Multi-function information from shmem */
350014b24e2bSVaishali Kulkarni 	addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
3501*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1, glob) +
3502*04443fdeSToomas Soome 		   offsetof(struct nvm_cfg1_glob, device_capabilities);
350314b24e2bSVaishali Kulkarni 
350414b24e2bSVaishali Kulkarni 	device_capabilities = ecore_rd(p_hwfn, p_ptt, addr);
350514b24e2bSVaishali Kulkarni 	if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ETHERNET)
350614b24e2bSVaishali Kulkarni 		OSAL_SET_BIT(ECORE_DEV_CAP_ETH,
350714b24e2bSVaishali Kulkarni 				 &p_hwfn->hw_info.device_capabilities);
350814b24e2bSVaishali Kulkarni 	if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_FCOE)
350914b24e2bSVaishali Kulkarni 		OSAL_SET_BIT(ECORE_DEV_CAP_FCOE,
351014b24e2bSVaishali Kulkarni 				 &p_hwfn->hw_info.device_capabilities);
351114b24e2bSVaishali Kulkarni 	if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ISCSI)
351214b24e2bSVaishali Kulkarni 		OSAL_SET_BIT(ECORE_DEV_CAP_ISCSI,
351314b24e2bSVaishali Kulkarni 				 &p_hwfn->hw_info.device_capabilities);
351414b24e2bSVaishali Kulkarni 	if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ROCE)
351514b24e2bSVaishali Kulkarni 		OSAL_SET_BIT(ECORE_DEV_CAP_ROCE,
351614b24e2bSVaishali Kulkarni 				 &p_hwfn->hw_info.device_capabilities);
351714b24e2bSVaishali Kulkarni 	if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_IWARP)
351814b24e2bSVaishali Kulkarni 		OSAL_SET_BIT(ECORE_DEV_CAP_IWARP,
351914b24e2bSVaishali Kulkarni 				 &p_hwfn->hw_info.device_capabilities);
352014b24e2bSVaishali Kulkarni 
352114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_fill_shmem_func_info(p_hwfn, p_ptt);
352214b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS && p_params->b_relaxed_probe) {
352314b24e2bSVaishali Kulkarni 		rc = ECORE_SUCCESS;
352414b24e2bSVaishali Kulkarni 		p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_MCP;
352514b24e2bSVaishali Kulkarni 	}
352614b24e2bSVaishali Kulkarni 
352714b24e2bSVaishali Kulkarni 	return rc;
352814b24e2bSVaishali Kulkarni }
352914b24e2bSVaishali Kulkarni 
ecore_get_num_funcs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)353014b24e2bSVaishali Kulkarni static void ecore_get_num_funcs(struct ecore_hwfn *p_hwfn,
353114b24e2bSVaishali Kulkarni 				struct ecore_ptt *p_ptt)
353214b24e2bSVaishali Kulkarni {
353314b24e2bSVaishali Kulkarni 	u8 num_funcs, enabled_func_idx = p_hwfn->rel_pf_id;
353414b24e2bSVaishali Kulkarni 	u32 reg_function_hide, tmp, eng_mask, low_pfs_mask;
353514b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
353614b24e2bSVaishali Kulkarni 
353714b24e2bSVaishali Kulkarni 	num_funcs = ECORE_IS_AH(p_dev) ? MAX_NUM_PFS_K2 : MAX_NUM_PFS_BB;
353814b24e2bSVaishali Kulkarni 
353914b24e2bSVaishali Kulkarni 	/* Bit 0 of MISCS_REG_FUNCTION_HIDE indicates whether the bypass values
354014b24e2bSVaishali Kulkarni 	 * in the other bits are selected.
354114b24e2bSVaishali Kulkarni 	 * Bits 1-15 are for functions 1-15, respectively, and their value is
354214b24e2bSVaishali Kulkarni 	 * '0' only for enabled functions (function 0 always exists and
354314b24e2bSVaishali Kulkarni 	 * enabled).
354414b24e2bSVaishali Kulkarni 	 * In case of CMT in BB, only the "even" functions are enabled, and thus
354514b24e2bSVaishali Kulkarni 	 * the number of functions for both hwfns is learnt from the same bits.
354614b24e2bSVaishali Kulkarni 	 */
354714b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_dev) || ECORE_IS_AH(p_dev)) {
354814b24e2bSVaishali Kulkarni 		reg_function_hide = ecore_rd(p_hwfn, p_ptt,
354914b24e2bSVaishali Kulkarni 					     MISCS_REG_FUNCTION_HIDE_BB_K2);
355014b24e2bSVaishali Kulkarni 	} else { /* E5 */
355114b24e2bSVaishali Kulkarni 		reg_function_hide = 0;
355214b24e2bSVaishali Kulkarni 		ECORE_E5_MISSING_CODE;
355314b24e2bSVaishali Kulkarni 	}
355414b24e2bSVaishali Kulkarni 
355514b24e2bSVaishali Kulkarni 	if (reg_function_hide & 0x1) {
355614b24e2bSVaishali Kulkarni 		if (ECORE_IS_BB(p_dev)) {
355714b24e2bSVaishali Kulkarni 			if (ECORE_PATH_ID(p_hwfn) && p_dev->num_hwfns == 1) {
355814b24e2bSVaishali Kulkarni 				num_funcs = 0;
355914b24e2bSVaishali Kulkarni 				eng_mask = 0xaaaa;
356014b24e2bSVaishali Kulkarni 			} else {
356114b24e2bSVaishali Kulkarni 				num_funcs = 1;
356214b24e2bSVaishali Kulkarni 				eng_mask = 0x5554;
356314b24e2bSVaishali Kulkarni 			}
356414b24e2bSVaishali Kulkarni 		} else {
356514b24e2bSVaishali Kulkarni 			num_funcs = 1;
356614b24e2bSVaishali Kulkarni 			eng_mask = 0xfffe;
356714b24e2bSVaishali Kulkarni 		}
356814b24e2bSVaishali Kulkarni 
356914b24e2bSVaishali Kulkarni 		/* Get the number of the enabled functions on the engine */
357014b24e2bSVaishali Kulkarni 		tmp = (reg_function_hide ^ 0xffffffff) & eng_mask;
357114b24e2bSVaishali Kulkarni 		while (tmp) {
357214b24e2bSVaishali Kulkarni 			if (tmp & 0x1)
357314b24e2bSVaishali Kulkarni 				num_funcs++;
357414b24e2bSVaishali Kulkarni 			tmp >>= 0x1;
357514b24e2bSVaishali Kulkarni 		}
357614b24e2bSVaishali Kulkarni 
357714b24e2bSVaishali Kulkarni 		/* Get the PF index within the enabled functions */
357814b24e2bSVaishali Kulkarni 		low_pfs_mask = (0x1 << p_hwfn->abs_pf_id) - 1;
357914b24e2bSVaishali Kulkarni 		tmp = reg_function_hide & eng_mask & low_pfs_mask;
358014b24e2bSVaishali Kulkarni 		while (tmp) {
358114b24e2bSVaishali Kulkarni 			if (tmp & 0x1)
358214b24e2bSVaishali Kulkarni 				enabled_func_idx--;
358314b24e2bSVaishali Kulkarni 			tmp >>= 0x1;
358414b24e2bSVaishali Kulkarni 		}
358514b24e2bSVaishali Kulkarni 	}
358614b24e2bSVaishali Kulkarni 
358714b24e2bSVaishali Kulkarni 	p_hwfn->num_funcs_on_engine = num_funcs;
358814b24e2bSVaishali Kulkarni 	p_hwfn->enabled_func_idx = enabled_func_idx;
358914b24e2bSVaishali Kulkarni 
359014b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
359114b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_dev)) {
359214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
359314b24e2bSVaishali Kulkarni 			  "FPGA: Limit number of PFs to 4 [would affect resource allocation, needed for IOV]\n");
359414b24e2bSVaishali Kulkarni 		p_hwfn->num_funcs_on_engine = 4;
359514b24e2bSVaishali Kulkarni 	}
359614b24e2bSVaishali Kulkarni #endif
359714b24e2bSVaishali Kulkarni 
359814b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_PROBE,
359914b24e2bSVaishali Kulkarni 		   "PF [rel_id %d, abs_id %d] occupies index %d within the %d enabled functions on the engine\n",
360014b24e2bSVaishali Kulkarni 		   p_hwfn->rel_pf_id, p_hwfn->abs_pf_id,
360114b24e2bSVaishali Kulkarni 		   p_hwfn->enabled_func_idx, p_hwfn->num_funcs_on_engine);
360214b24e2bSVaishali Kulkarni }
360314b24e2bSVaishali Kulkarni 
ecore_hw_info_port_num_bb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)360414b24e2bSVaishali Kulkarni static void ecore_hw_info_port_num_bb(struct ecore_hwfn *p_hwfn,
360514b24e2bSVaishali Kulkarni 				      struct ecore_ptt *p_ptt)
360614b24e2bSVaishali Kulkarni {
360714b24e2bSVaishali Kulkarni 	u32 port_mode;
360814b24e2bSVaishali Kulkarni 
360914b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
361014b24e2bSVaishali Kulkarni 	/* Read the port mode */
361114b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev))
361214b24e2bSVaishali Kulkarni 		port_mode = 4;
361314b24e2bSVaishali Kulkarni 	else if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) &&
361414b24e2bSVaishali Kulkarni 		 (p_hwfn->p_dev->num_hwfns > 1))
361514b24e2bSVaishali Kulkarni 		/* In CMT on emulation, assume 1 port */
361614b24e2bSVaishali Kulkarni 		port_mode = 1;
361714b24e2bSVaishali Kulkarni 	else
361814b24e2bSVaishali Kulkarni #endif
361914b24e2bSVaishali Kulkarni 	port_mode = ecore_rd(p_hwfn, p_ptt, CNIG_REG_NW_PORT_MODE_BB);
362014b24e2bSVaishali Kulkarni 
362114b24e2bSVaishali Kulkarni 	if (port_mode < 3) {
362214b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->num_ports_in_engine = 1;
362314b24e2bSVaishali Kulkarni 	} else if (port_mode <= 5) {
362414b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->num_ports_in_engine = 2;
362514b24e2bSVaishali Kulkarni 	} else {
362614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "PORT MODE: %d not supported\n",
362714b24e2bSVaishali Kulkarni 			  p_hwfn->p_dev->num_ports_in_engine);
362814b24e2bSVaishali Kulkarni 
362914b24e2bSVaishali Kulkarni 		/* Default num_ports_in_engine to something */
363014b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->num_ports_in_engine = 1;
363114b24e2bSVaishali Kulkarni 	}
363214b24e2bSVaishali Kulkarni }
363314b24e2bSVaishali Kulkarni 
ecore_hw_info_port_num_ah_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)363414b24e2bSVaishali Kulkarni static void ecore_hw_info_port_num_ah_e5(struct ecore_hwfn *p_hwfn,
363514b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt)
363614b24e2bSVaishali Kulkarni {
363714b24e2bSVaishali Kulkarni 	u32 port;
363814b24e2bSVaishali Kulkarni 	int i;
363914b24e2bSVaishali Kulkarni 
364014b24e2bSVaishali Kulkarni 	p_hwfn->p_dev->num_ports_in_engine = 0;
364114b24e2bSVaishali Kulkarni 
364214b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
364314b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
364414b24e2bSVaishali Kulkarni 		port = ecore_rd(p_hwfn, p_ptt, MISCS_REG_ECO_RESERVED);
364514b24e2bSVaishali Kulkarni 		switch ((port & 0xf000) >> 12) {
364614b24e2bSVaishali Kulkarni 		case 1:
364714b24e2bSVaishali Kulkarni 			p_hwfn->p_dev->num_ports_in_engine = 1;
364814b24e2bSVaishali Kulkarni 			break;
364914b24e2bSVaishali Kulkarni 		case 3:
365014b24e2bSVaishali Kulkarni 			p_hwfn->p_dev->num_ports_in_engine = 2;
365114b24e2bSVaishali Kulkarni 			break;
365214b24e2bSVaishali Kulkarni 		case 0xf:
365314b24e2bSVaishali Kulkarni 			p_hwfn->p_dev->num_ports_in_engine = 4;
365414b24e2bSVaishali Kulkarni 			break;
365514b24e2bSVaishali Kulkarni 		default:
365614b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
365714b24e2bSVaishali Kulkarni 				  "Unknown port mode in ECO_RESERVED %08x\n",
365814b24e2bSVaishali Kulkarni 				  port);
365914b24e2bSVaishali Kulkarni 		}
366014b24e2bSVaishali Kulkarni 	} else
366114b24e2bSVaishali Kulkarni #endif
366214b24e2bSVaishali Kulkarni 	for (i = 0; i < MAX_NUM_PORTS_K2; i++) {
366314b24e2bSVaishali Kulkarni 		port = ecore_rd(p_hwfn, p_ptt,
366414b24e2bSVaishali Kulkarni 				CNIG_REG_NIG_PORT0_CONF_K2_E5 + (i * 4));
366514b24e2bSVaishali Kulkarni 		if (port & 1)
366614b24e2bSVaishali Kulkarni 			p_hwfn->p_dev->num_ports_in_engine++;
366714b24e2bSVaishali Kulkarni 	}
366814b24e2bSVaishali Kulkarni 
366914b24e2bSVaishali Kulkarni 	if (!p_hwfn->p_dev->num_ports_in_engine) {
367014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "All NIG ports are inactive\n");
367114b24e2bSVaishali Kulkarni 
367214b24e2bSVaishali Kulkarni 		/* Default num_ports_in_engine to something */
367314b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->num_ports_in_engine = 1;
367414b24e2bSVaishali Kulkarni 	}
367514b24e2bSVaishali Kulkarni }
367614b24e2bSVaishali Kulkarni 
ecore_hw_info_port_num(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)367714b24e2bSVaishali Kulkarni static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
367814b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt)
367914b24e2bSVaishali Kulkarni {
368014b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev))
368114b24e2bSVaishali Kulkarni 		ecore_hw_info_port_num_bb(p_hwfn, p_ptt);
368214b24e2bSVaishali Kulkarni 	else
368314b24e2bSVaishali Kulkarni 		ecore_hw_info_port_num_ah_e5(p_hwfn, p_ptt);
368414b24e2bSVaishali Kulkarni }
368514b24e2bSVaishali Kulkarni 
368614b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_get_hw_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_pci_personality personality,struct ecore_hw_prepare_params * p_params)368714b24e2bSVaishali Kulkarni ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
368814b24e2bSVaishali Kulkarni 		  enum ecore_pci_personality personality,
368914b24e2bSVaishali Kulkarni 		  struct ecore_hw_prepare_params *p_params)
369014b24e2bSVaishali Kulkarni {
369114b24e2bSVaishali Kulkarni 	bool drv_resc_alloc = p_params->drv_resc_alloc;
369214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
369314b24e2bSVaishali Kulkarni 
369414b24e2bSVaishali Kulkarni 	/* Since all information is common, only first hwfns should do this */
369514b24e2bSVaishali Kulkarni 	if (IS_LEAD_HWFN(p_hwfn)) {
369614b24e2bSVaishali Kulkarni 		rc = ecore_iov_hw_info(p_hwfn);
369714b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
369814b24e2bSVaishali Kulkarni 			if (p_params->b_relaxed_probe)
369914b24e2bSVaishali Kulkarni 				p_params->p_relaxed_res =
370014b24e2bSVaishali Kulkarni 						ECORE_HW_PREPARE_BAD_IOV;
370114b24e2bSVaishali Kulkarni 			else
370214b24e2bSVaishali Kulkarni 				return rc;
370314b24e2bSVaishali Kulkarni 		}
370414b24e2bSVaishali Kulkarni 	}
370514b24e2bSVaishali Kulkarni 
370614b24e2bSVaishali Kulkarni 	/* TODO In get_hw_info, amoungst others:
370714b24e2bSVaishali Kulkarni 	 * Get MCP FW revision and determine according to it the supported
370814b24e2bSVaishali Kulkarni 	 * featrues (e.g. DCB)
370914b24e2bSVaishali Kulkarni 	 * Get boot mode
371014b24e2bSVaishali Kulkarni 	 * ecore_get_pcie_width_speed, WOL capability.
371114b24e2bSVaishali Kulkarni 	 * Number of global CQ-s (for storage
371214b24e2bSVaishali Kulkarni 	 */
371314b24e2bSVaishali Kulkarni 	ecore_hw_info_port_num(p_hwfn, p_ptt);
371414b24e2bSVaishali Kulkarni 
371514b24e2bSVaishali Kulkarni 	ecore_mcp_get_capabilities(p_hwfn, p_ptt);
371614b24e2bSVaishali Kulkarni 
371714b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
371814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_ASIC(p_hwfn->p_dev)) {
371914b24e2bSVaishali Kulkarni #endif
372014b24e2bSVaishali Kulkarni 	rc = ecore_hw_get_nvm_info(p_hwfn, p_ptt, p_params);
372114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
372214b24e2bSVaishali Kulkarni 		return rc;
372314b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
372414b24e2bSVaishali Kulkarni 	}
372514b24e2bSVaishali Kulkarni #endif
372614b24e2bSVaishali Kulkarni 
372714b24e2bSVaishali Kulkarni 	rc = ecore_int_igu_read_cam(p_hwfn, p_ptt);
372814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
372914b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
373014b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_IGU;
373114b24e2bSVaishali Kulkarni 		else
373214b24e2bSVaishali Kulkarni 			return rc;
373314b24e2bSVaishali Kulkarni 	}
373414b24e2bSVaishali Kulkarni 
373514b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
373614b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_ASIC(p_hwfn->p_dev) && ecore_mcp_is_init(p_hwfn)) {
373714b24e2bSVaishali Kulkarni #endif
373814b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_hwfn->hw_info.hw_mac_addr,
373914b24e2bSVaishali Kulkarni 		    p_hwfn->mcp_info->func_info.mac, ETH_ALEN);
374014b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
374114b24e2bSVaishali Kulkarni 	} else {
374214b24e2bSVaishali Kulkarni 		static u8 mcp_hw_mac[6] = {0, 2, 3, 4, 5, 6};
374314b24e2bSVaishali Kulkarni 
374414b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_hwfn->hw_info.hw_mac_addr, mcp_hw_mac, ETH_ALEN);
374514b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.hw_mac_addr[5] = p_hwfn->abs_pf_id;
374614b24e2bSVaishali Kulkarni 	}
374714b24e2bSVaishali Kulkarni #endif
374814b24e2bSVaishali Kulkarni 
374914b24e2bSVaishali Kulkarni 	if (ecore_mcp_is_init(p_hwfn)) {
375014b24e2bSVaishali Kulkarni 		if (p_hwfn->mcp_info->func_info.ovlan != ECORE_MCP_VLAN_UNSET)
375114b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.ovlan =
375214b24e2bSVaishali Kulkarni 				p_hwfn->mcp_info->func_info.ovlan;
375314b24e2bSVaishali Kulkarni 
375414b24e2bSVaishali Kulkarni 		ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
375514b24e2bSVaishali Kulkarni 	}
375614b24e2bSVaishali Kulkarni 
375714b24e2bSVaishali Kulkarni 	if (personality != ECORE_PCI_DEFAULT) {
375814b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.personality = personality;
375914b24e2bSVaishali Kulkarni 	} else if (ecore_mcp_is_init(p_hwfn)) {
376014b24e2bSVaishali Kulkarni 		enum ecore_pci_personality protocol;
376114b24e2bSVaishali Kulkarni 
376214b24e2bSVaishali Kulkarni 		protocol = p_hwfn->mcp_info->func_info.protocol;
376314b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.personality = protocol;
376414b24e2bSVaishali Kulkarni 	}
376514b24e2bSVaishali Kulkarni 
376614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
376714b24e2bSVaishali Kulkarni 	/* To overcome ILT lack for emulation, until at least until we'll have
376814b24e2bSVaishali Kulkarni 	 * a definite answer from system about it, allow only PF0 to be RoCE.
376914b24e2bSVaishali Kulkarni 	 */
377014b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) && ECORE_IS_AH(p_hwfn->p_dev)) {
377114b24e2bSVaishali Kulkarni 		if (!p_hwfn->rel_pf_id)
377214b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.personality = ECORE_PCI_ETH_ROCE;
377314b24e2bSVaishali Kulkarni 		else
377414b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.personality = ECORE_PCI_ETH;
377514b24e2bSVaishali Kulkarni 	}
377614b24e2bSVaishali Kulkarni #endif
377714b24e2bSVaishali Kulkarni 
377814b24e2bSVaishali Kulkarni 	/* although in BB some constellations may support more than 4 tcs,
377914b24e2bSVaishali Kulkarni 	 * that can result in performance penalty in some cases. 4
378014b24e2bSVaishali Kulkarni 	 * represents a good tradeoff between performance and flexibility.
378114b24e2bSVaishali Kulkarni 	 */
378214b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.num_hw_tc = NUM_PHYS_TCS_4PORT_K2;
378314b24e2bSVaishali Kulkarni 
378414b24e2bSVaishali Kulkarni 	/* start out with a single active tc. This can be increased either
378514b24e2bSVaishali Kulkarni 	 * by dcbx negotiation or by upper layer driver
378614b24e2bSVaishali Kulkarni 	 */
378714b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.num_active_tc = 1;
378814b24e2bSVaishali Kulkarni 
378914b24e2bSVaishali Kulkarni 	ecore_get_num_funcs(p_hwfn, p_ptt);
379014b24e2bSVaishali Kulkarni 
379114b24e2bSVaishali Kulkarni 	if (ecore_mcp_is_init(p_hwfn))
379214b24e2bSVaishali Kulkarni 		p_hwfn->hw_info.mtu = p_hwfn->mcp_info->func_info.mtu;
379314b24e2bSVaishali Kulkarni 
379414b24e2bSVaishali Kulkarni 	/* In case of forcing the driver's default resource allocation, calling
379514b24e2bSVaishali Kulkarni 	 * ecore_hw_get_resc() should come after initializing the personality
379614b24e2bSVaishali Kulkarni 	 * and after getting the number of functions, since the calculation of
379714b24e2bSVaishali Kulkarni 	 * the resources/features depends on them.
379814b24e2bSVaishali Kulkarni 	 * This order is not harmful if not forcing.
379914b24e2bSVaishali Kulkarni 	 */
380014b24e2bSVaishali Kulkarni 	rc = ecore_hw_get_resc(p_hwfn, drv_resc_alloc);
380114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS && p_params->b_relaxed_probe) {
380214b24e2bSVaishali Kulkarni 		rc = ECORE_SUCCESS;
380314b24e2bSVaishali Kulkarni 		p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_MCP;
380414b24e2bSVaishali Kulkarni 	}
380514b24e2bSVaishali Kulkarni 
380614b24e2bSVaishali Kulkarni 	return rc;
380714b24e2bSVaishali Kulkarni }
380814b24e2bSVaishali Kulkarni 
ecore_get_dev_info(struct ecore_dev * p_dev)380914b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_get_dev_info(struct ecore_dev *p_dev)
381014b24e2bSVaishali Kulkarni {
381114b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
381214b24e2bSVaishali Kulkarni 	u16 device_id_mask;
381314b24e2bSVaishali Kulkarni 	u32 tmp;
381414b24e2bSVaishali Kulkarni 
381514b24e2bSVaishali Kulkarni 	/* Read Vendor Id / Device Id */
381614b24e2bSVaishali Kulkarni 	OSAL_PCI_READ_CONFIG_WORD(p_dev, PCICFG_VENDOR_ID_OFFSET,
381714b24e2bSVaishali Kulkarni 				  &p_dev->vendor_id);
381814b24e2bSVaishali Kulkarni 	OSAL_PCI_READ_CONFIG_WORD(p_dev, PCICFG_DEVICE_ID_OFFSET,
381914b24e2bSVaishali Kulkarni 				  &p_dev->device_id);
382014b24e2bSVaishali Kulkarni 
382114b24e2bSVaishali Kulkarni 	/* Determine type */
382214b24e2bSVaishali Kulkarni 	device_id_mask = p_dev->device_id & ECORE_DEV_ID_MASK;
382314b24e2bSVaishali Kulkarni 	switch (device_id_mask) {
382414b24e2bSVaishali Kulkarni 	case ECORE_DEV_ID_MASK_BB:
382514b24e2bSVaishali Kulkarni 		p_dev->type = ECORE_DEV_TYPE_BB;
382614b24e2bSVaishali Kulkarni 		break;
382714b24e2bSVaishali Kulkarni 	case ECORE_DEV_ID_MASK_AH:
382814b24e2bSVaishali Kulkarni 		p_dev->type = ECORE_DEV_TYPE_AH;
382914b24e2bSVaishali Kulkarni 		break;
383014b24e2bSVaishali Kulkarni 	default:
383114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Unknown device id 0x%x\n",
383214b24e2bSVaishali Kulkarni 			  p_dev->device_id);
383314b24e2bSVaishali Kulkarni 		return ECORE_ABORTED;
383414b24e2bSVaishali Kulkarni 	}
383514b24e2bSVaishali Kulkarni 
383614b24e2bSVaishali Kulkarni 	p_dev->chip_num = (u16)ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
383714b24e2bSVaishali Kulkarni 					MISCS_REG_CHIP_NUM);
383814b24e2bSVaishali Kulkarni 	p_dev->chip_rev = (u16)ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
383914b24e2bSVaishali Kulkarni 					MISCS_REG_CHIP_REV);
384014b24e2bSVaishali Kulkarni 
384114b24e2bSVaishali Kulkarni 	MASK_FIELD(CHIP_REV, p_dev->chip_rev);
384214b24e2bSVaishali Kulkarni 
384314b24e2bSVaishali Kulkarni 	/* Learn number of HW-functions */
384414b24e2bSVaishali Kulkarni 	tmp = ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
384514b24e2bSVaishali Kulkarni 		       MISCS_REG_CMT_ENABLED_FOR_PAIR);
384614b24e2bSVaishali Kulkarni 
384714b24e2bSVaishali Kulkarni 	if (tmp & (1 << p_hwfn->rel_pf_id)) {
384814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev->hwfns, false, "device in CMT mode\n");
384914b24e2bSVaishali Kulkarni 		p_dev->num_hwfns = 2;
385014b24e2bSVaishali Kulkarni 	} else {
385114b24e2bSVaishali Kulkarni 		p_dev->num_hwfns = 1;
385214b24e2bSVaishali Kulkarni 	}
385314b24e2bSVaishali Kulkarni 
385414b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
385514b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev)) {
385614b24e2bSVaishali Kulkarni 		/* For some reason we have problems with this register
385714b24e2bSVaishali Kulkarni 		 * in B0 emulation; Simply assume no CMT
385814b24e2bSVaishali Kulkarni 		 */
385914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev->hwfns, false, "device on emul - assume no CMT\n");
386014b24e2bSVaishali Kulkarni 		p_dev->num_hwfns = 1;
386114b24e2bSVaishali Kulkarni 	}
386214b24e2bSVaishali Kulkarni #endif
386314b24e2bSVaishali Kulkarni 
386414b24e2bSVaishali Kulkarni 	p_dev->chip_bond_id = ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
386514b24e2bSVaishali Kulkarni 				       MISCS_REG_CHIP_TEST_REG) >> 4;
386614b24e2bSVaishali Kulkarni 	MASK_FIELD(CHIP_BOND_ID, p_dev->chip_bond_id);
386714b24e2bSVaishali Kulkarni 	p_dev->chip_metal = (u16)ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
386814b24e2bSVaishali Kulkarni 					  MISCS_REG_CHIP_METAL);
386914b24e2bSVaishali Kulkarni 	MASK_FIELD(CHIP_METAL, p_dev->chip_metal);
387014b24e2bSVaishali Kulkarni 	DP_INFO(p_dev->hwfns,
387114b24e2bSVaishali Kulkarni 		"Chip details - %s %c%d, Num: %04x Rev: %04x Bond id: %04x Metal: %04x\n",
387214b24e2bSVaishali Kulkarni 		ECORE_IS_BB(p_dev) ? "BB" : "AH",
387314b24e2bSVaishali Kulkarni 		'A' + p_dev->chip_rev, (int)p_dev->chip_metal,
387414b24e2bSVaishali Kulkarni 		p_dev->chip_num, p_dev->chip_rev, p_dev->chip_bond_id,
387514b24e2bSVaishali Kulkarni 		p_dev->chip_metal);
387614b24e2bSVaishali Kulkarni 
387714b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_dev) && CHIP_REV_IS_A0(p_dev)) {
387814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev->hwfns, false,
387914b24e2bSVaishali Kulkarni 			  "The chip type/rev (BB A0) is not supported!\n");
388014b24e2bSVaishali Kulkarni 		return ECORE_ABORTED;
388114b24e2bSVaishali Kulkarni 	}
388214b24e2bSVaishali Kulkarni 
388314b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
388414b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev) && ECORE_IS_AH(p_dev))
388514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
388614b24e2bSVaishali Kulkarni 			 MISCS_REG_PLL_MAIN_CTRL_4, 0x1);
388714b24e2bSVaishali Kulkarni 
388814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_dev)) {
388914b24e2bSVaishali Kulkarni 		tmp = ecore_rd(p_hwfn, p_hwfn->p_main_ptt,
389014b24e2bSVaishali Kulkarni 			       MISCS_REG_ECO_RESERVED);
389114b24e2bSVaishali Kulkarni 		if (tmp & (1 << 29)) {
389214b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false, "Emulation: Running on a FULL build\n");
389314b24e2bSVaishali Kulkarni 			p_dev->b_is_emul_full = true;
389414b24e2bSVaishali Kulkarni 		} else {
389514b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false, "Emulation: Running on a REDUCED build\n");
389614b24e2bSVaishali Kulkarni 		}
389714b24e2bSVaishali Kulkarni 	}
389814b24e2bSVaishali Kulkarni #endif
389914b24e2bSVaishali Kulkarni 
390014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
390114b24e2bSVaishali Kulkarni }
390214b24e2bSVaishali Kulkarni 
390314b24e2bSVaishali Kulkarni #ifndef LINUX_REMOVE
ecore_hw_hibernate_prepare(struct ecore_dev * p_dev)390414b24e2bSVaishali Kulkarni void ecore_hw_hibernate_prepare(struct ecore_dev *p_dev)
390514b24e2bSVaishali Kulkarni {
390614b24e2bSVaishali Kulkarni 	int j;
390714b24e2bSVaishali Kulkarni 
390814b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev))
390914b24e2bSVaishali Kulkarni 		return;
391014b24e2bSVaishali Kulkarni 
391114b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, j) {
391214b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[j];
391314b24e2bSVaishali Kulkarni 
391414b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFDOWN, "Mark hw/fw uninitialized\n");
391514b24e2bSVaishali Kulkarni 
391614b24e2bSVaishali Kulkarni 		p_hwfn->hw_init_done = false;
391714b24e2bSVaishali Kulkarni 		p_hwfn->first_on_engine = false;
391814b24e2bSVaishali Kulkarni 
391914b24e2bSVaishali Kulkarni 		ecore_ptt_invalidate(p_hwfn);
392014b24e2bSVaishali Kulkarni 	}
392114b24e2bSVaishali Kulkarni }
392214b24e2bSVaishali Kulkarni 
ecore_hw_hibernate_resume(struct ecore_dev * p_dev)392314b24e2bSVaishali Kulkarni void ecore_hw_hibernate_resume(struct ecore_dev *p_dev)
392414b24e2bSVaishali Kulkarni {
392514b24e2bSVaishali Kulkarni 	int j = 0;
392614b24e2bSVaishali Kulkarni 
392714b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev))
392814b24e2bSVaishali Kulkarni 		return;
392914b24e2bSVaishali Kulkarni 
393014b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, j) {
393114b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[j];
393214b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
393314b24e2bSVaishali Kulkarni 
393414b24e2bSVaishali Kulkarni 		ecore_hw_hwfn_prepare(p_hwfn);
393514b24e2bSVaishali Kulkarni 
393614b24e2bSVaishali Kulkarni 		if (!p_ptt)
393714b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, true, "ptt acquire failed\n");
393814b24e2bSVaishali Kulkarni 		else {
393914b24e2bSVaishali Kulkarni 			ecore_load_mcp_offsets(p_hwfn, p_ptt);
394014b24e2bSVaishali Kulkarni 			ecore_ptt_release(p_hwfn, p_ptt);
394114b24e2bSVaishali Kulkarni 		}
394214b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP, "Reinitialized hw after low power state\n");
394314b24e2bSVaishali Kulkarni 	}
394414b24e2bSVaishali Kulkarni }
394514b24e2bSVaishali Kulkarni 
394614b24e2bSVaishali Kulkarni #endif
394714b24e2bSVaishali Kulkarni 
ecore_hw_prepare_single(struct ecore_hwfn * p_hwfn,void OSAL_IOMEM * p_regview,void OSAL_IOMEM * p_doorbells,struct ecore_hw_prepare_params * p_params)394814b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_hw_prepare_single(struct ecore_hwfn *p_hwfn,
394914b24e2bSVaishali Kulkarni 						    void OSAL_IOMEM *p_regview,
395014b24e2bSVaishali Kulkarni 						    void OSAL_IOMEM *p_doorbells,
395114b24e2bSVaishali Kulkarni 						    struct ecore_hw_prepare_params *p_params)
395214b24e2bSVaishali Kulkarni {
395314b24e2bSVaishali Kulkarni 	struct ecore_mdump_retain_data mdump_retain;
395414b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
395514b24e2bSVaishali Kulkarni 	struct ecore_mdump_info mdump_info;
395614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
395714b24e2bSVaishali Kulkarni 
395814b24e2bSVaishali Kulkarni 	/* Split PCI bars evenly between hwfns */
395914b24e2bSVaishali Kulkarni 	p_hwfn->regview = p_regview;
396014b24e2bSVaishali Kulkarni 	p_hwfn->doorbells = p_doorbells;
396114b24e2bSVaishali Kulkarni 
396214b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev))
396314b24e2bSVaishali Kulkarni 		return ecore_vf_hw_prepare(p_hwfn);
396414b24e2bSVaishali Kulkarni 
396514b24e2bSVaishali Kulkarni 	/* Validate that chip access is feasible */
396614b24e2bSVaishali Kulkarni 	if (REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR) == 0xffffffff) {
396714b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Reading the ME register returns all Fs; Preventing further chip access\n");
396814b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
396914b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_ME;
397014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
397114b24e2bSVaishali Kulkarni 	}
397214b24e2bSVaishali Kulkarni 
397314b24e2bSVaishali Kulkarni 	get_function_id(p_hwfn);
397414b24e2bSVaishali Kulkarni 
397514b24e2bSVaishali Kulkarni 	/* Allocate PTT pool */
397614b24e2bSVaishali Kulkarni 	rc = ecore_ptt_pool_alloc(p_hwfn);
397714b24e2bSVaishali Kulkarni 	if (rc) {
397814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Failed to prepare hwfn's hw\n");
397914b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
398014b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
398114b24e2bSVaishali Kulkarni 		goto err0;
398214b24e2bSVaishali Kulkarni 	}
398314b24e2bSVaishali Kulkarni 
398414b24e2bSVaishali Kulkarni 	/* Allocate the main PTT */
398514b24e2bSVaishali Kulkarni 	p_hwfn->p_main_ptt = ecore_get_reserved_ptt(p_hwfn, RESERVED_PTT_MAIN);
398614b24e2bSVaishali Kulkarni 
398714b24e2bSVaishali Kulkarni 	/* First hwfn learns basic information, e.g., number of hwfns */
398814b24e2bSVaishali Kulkarni 	if (!p_hwfn->my_id) {
398914b24e2bSVaishali Kulkarni 		rc = ecore_get_dev_info(p_dev);
399014b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
399114b24e2bSVaishali Kulkarni 			if (p_params->b_relaxed_probe)
399214b24e2bSVaishali Kulkarni 				p_params->p_relaxed_res =
399314b24e2bSVaishali Kulkarni 					ECORE_HW_PREPARE_FAILED_DEV;
399414b24e2bSVaishali Kulkarni 			goto err1;
399514b24e2bSVaishali Kulkarni 		}
399614b24e2bSVaishali Kulkarni 	}
399714b24e2bSVaishali Kulkarni 
399814b24e2bSVaishali Kulkarni 	ecore_hw_hwfn_prepare(p_hwfn);
399914b24e2bSVaishali Kulkarni 
400014b24e2bSVaishali Kulkarni 	/* Initialize MCP structure */
400114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_init(p_hwfn, p_hwfn->p_main_ptt);
400214b24e2bSVaishali Kulkarni 	if (rc) {
400314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Failed initializing mcp command\n");
400414b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
400514b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
400614b24e2bSVaishali Kulkarni 		goto err1;
400714b24e2bSVaishali Kulkarni 	}
400814b24e2bSVaishali Kulkarni 
400914b24e2bSVaishali Kulkarni 	/* Read the device configuration information from the HW and SHMEM */
401014b24e2bSVaishali Kulkarni 	rc = ecore_get_hw_info(p_hwfn, p_hwfn->p_main_ptt,
401114b24e2bSVaishali Kulkarni 			       p_params->personality, p_params);
401214b24e2bSVaishali Kulkarni 	if (rc) {
401314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Failed to get HW information\n");
401414b24e2bSVaishali Kulkarni 		goto err2;
401514b24e2bSVaishali Kulkarni 	}
401614b24e2bSVaishali Kulkarni 
401714b24e2bSVaishali Kulkarni 	/* Sending a mailbox to the MFW should be after ecore_get_hw_info() is
401814b24e2bSVaishali Kulkarni 	 * called, since among others it sets the ports number in an engine.
401914b24e2bSVaishali Kulkarni 	 */
402014b24e2bSVaishali Kulkarni 	if (p_params->initiate_pf_flr && p_hwfn == ECORE_LEADING_HWFN(p_dev) &&
402114b24e2bSVaishali Kulkarni 	    !p_dev->recov_in_prog) {
402214b24e2bSVaishali Kulkarni 		rc = ecore_mcp_initiate_pf_flr(p_hwfn, p_hwfn->p_main_ptt);
402314b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
402414b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false, "Failed to initiate PF FLR\n");
402514b24e2bSVaishali Kulkarni 	}
402614b24e2bSVaishali Kulkarni 
402714b24e2bSVaishali Kulkarni 	/* Check if mdump logs/data are present and update the epoch value */
402814b24e2bSVaishali Kulkarni 	if (p_hwfn == ECORE_LEADING_HWFN(p_hwfn->p_dev)) {
402914b24e2bSVaishali Kulkarni 		rc = ecore_mcp_mdump_get_info(p_hwfn, p_hwfn->p_main_ptt,
403014b24e2bSVaishali Kulkarni 					      &mdump_info);
403114b24e2bSVaishali Kulkarni 		if (rc == ECORE_SUCCESS && mdump_info.num_of_logs)
403214b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
403314b24e2bSVaishali Kulkarni 				  "* * * IMPORTANT - HW ERROR register dump captured by device * * *\n");
403414b24e2bSVaishali Kulkarni 
403514b24e2bSVaishali Kulkarni 		rc = ecore_mcp_mdump_get_retain(p_hwfn, p_hwfn->p_main_ptt,
403614b24e2bSVaishali Kulkarni 						&mdump_retain);
403714b24e2bSVaishali Kulkarni 		if (rc == ECORE_SUCCESS && mdump_retain.valid)
403814b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
403914b24e2bSVaishali Kulkarni 				  "mdump retained data: epoch 0x%08x, pf 0x%x, status 0x%08x\n",
404014b24e2bSVaishali Kulkarni 				  mdump_retain.epoch, mdump_retain.pf,
404114b24e2bSVaishali Kulkarni 				  mdump_retain.status);
404214b24e2bSVaishali Kulkarni 
404314b24e2bSVaishali Kulkarni 		ecore_mcp_mdump_set_values(p_hwfn, p_hwfn->p_main_ptt,
404414b24e2bSVaishali Kulkarni 					   p_params->epoch);
404514b24e2bSVaishali Kulkarni 	}
404614b24e2bSVaishali Kulkarni 
404714b24e2bSVaishali Kulkarni 	/* Allocate the init RT array and initialize the init-ops engine */
404814b24e2bSVaishali Kulkarni 	rc = ecore_init_alloc(p_hwfn);
404914b24e2bSVaishali Kulkarni 	if (rc) {
405014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Failed to allocate the init array\n");
405114b24e2bSVaishali Kulkarni 		if (p_params->b_relaxed_probe)
405214b24e2bSVaishali Kulkarni 			p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
405314b24e2bSVaishali Kulkarni 		goto err2;
405414b24e2bSVaishali Kulkarni 	}
405514b24e2bSVaishali Kulkarni 
405614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
405714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_dev)) {
405814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
405914b24e2bSVaishali Kulkarni 			  "FPGA: workaround; Prevent DMAE parities\n");
406014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt, PCIE_REG_PRTY_MASK_K2_E5,
406114b24e2bSVaishali Kulkarni 			 7);
406214b24e2bSVaishali Kulkarni 
406314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
406414b24e2bSVaishali Kulkarni 			  "FPGA: workaround: Set VF bar0 size\n");
406514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt,
406614b24e2bSVaishali Kulkarni 			 PGLUE_B_REG_VF_BAR0_SIZE_K2_E5, 4);
406714b24e2bSVaishali Kulkarni 	}
406814b24e2bSVaishali Kulkarni #endif
406914b24e2bSVaishali Kulkarni 
407014b24e2bSVaishali Kulkarni 	return rc;
407114b24e2bSVaishali Kulkarni err2:
407214b24e2bSVaishali Kulkarni 	if (IS_LEAD_HWFN(p_hwfn))
407314b24e2bSVaishali Kulkarni 		ecore_iov_free_hw_info(p_dev);
407414b24e2bSVaishali Kulkarni 	ecore_mcp_free(p_hwfn);
407514b24e2bSVaishali Kulkarni err1:
407614b24e2bSVaishali Kulkarni 	ecore_hw_hwfn_free(p_hwfn);
407714b24e2bSVaishali Kulkarni err0:
407814b24e2bSVaishali Kulkarni 	return rc;
407914b24e2bSVaishali Kulkarni }
408014b24e2bSVaishali Kulkarni 
ecore_hw_prepare(struct ecore_dev * p_dev,struct ecore_hw_prepare_params * p_params)408114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
408214b24e2bSVaishali Kulkarni 				      struct ecore_hw_prepare_params *p_params)
408314b24e2bSVaishali Kulkarni {
408414b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
408514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
408614b24e2bSVaishali Kulkarni 
408714b24e2bSVaishali Kulkarni 	p_dev->chk_reg_fifo = p_params->chk_reg_fifo;
408814b24e2bSVaishali Kulkarni 	p_dev->allow_mdump = p_params->allow_mdump;
408914b24e2bSVaishali Kulkarni 
409014b24e2bSVaishali Kulkarni 	if (p_params->b_relaxed_probe)
409114b24e2bSVaishali Kulkarni 		p_params->p_relaxed_res = ECORE_HW_PREPARE_SUCCESS;
409214b24e2bSVaishali Kulkarni 
409314b24e2bSVaishali Kulkarni 	/* Store the precompiled init data ptrs */
409414b24e2bSVaishali Kulkarni 	if (IS_PF(p_dev))
409514b24e2bSVaishali Kulkarni 		ecore_init_iro_array(p_dev);
409614b24e2bSVaishali Kulkarni 
409714b24e2bSVaishali Kulkarni 	/* Initialize the first hwfn - will learn number of hwfns */
409814b24e2bSVaishali Kulkarni 	rc = ecore_hw_prepare_single(p_hwfn,
409914b24e2bSVaishali Kulkarni 				     p_dev->regview,
410014b24e2bSVaishali Kulkarni 				     p_dev->doorbells, p_params);
410114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
410214b24e2bSVaishali Kulkarni 		return rc;
410314b24e2bSVaishali Kulkarni 
410414b24e2bSVaishali Kulkarni 	p_params->personality = p_hwfn->hw_info.personality;
410514b24e2bSVaishali Kulkarni 
410614b24e2bSVaishali Kulkarni 	/* initilalize 2nd hwfn if necessary */
410714b24e2bSVaishali Kulkarni 	if (p_dev->num_hwfns > 1) {
410814b24e2bSVaishali Kulkarni 		void OSAL_IOMEM *p_regview, *p_doorbell;
410914b24e2bSVaishali Kulkarni 		u8 OSAL_IOMEM *addr;
411014b24e2bSVaishali Kulkarni 
411114b24e2bSVaishali Kulkarni 		/* adjust bar offset for second engine */
411214b24e2bSVaishali Kulkarni 		addr = (u8 OSAL_IOMEM *)p_dev->regview +
411314b24e2bSVaishali Kulkarni 					ecore_hw_bar_size(p_hwfn, BAR_ID_0) / 2;
411414b24e2bSVaishali Kulkarni 		p_regview = (void OSAL_IOMEM *)addr;
411514b24e2bSVaishali Kulkarni 
411614b24e2bSVaishali Kulkarni 		addr = (u8 OSAL_IOMEM *)p_dev->doorbells +
411714b24e2bSVaishali Kulkarni 					ecore_hw_bar_size(p_hwfn, BAR_ID_1) / 2;
411814b24e2bSVaishali Kulkarni 		p_doorbell = (void OSAL_IOMEM *)addr;
411914b24e2bSVaishali Kulkarni 
412014b24e2bSVaishali Kulkarni 		/* prepare second hw function */
412114b24e2bSVaishali Kulkarni 		rc = ecore_hw_prepare_single(&p_dev->hwfns[1], p_regview,
412214b24e2bSVaishali Kulkarni 					     p_doorbell, p_params);
412314b24e2bSVaishali Kulkarni 
412414b24e2bSVaishali Kulkarni 		/* in case of error, need to free the previously
412514b24e2bSVaishali Kulkarni 		 * initiliazed hwfn 0.
412614b24e2bSVaishali Kulkarni 		 */
412714b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
412814b24e2bSVaishali Kulkarni 			if (p_params->b_relaxed_probe)
412914b24e2bSVaishali Kulkarni 				p_params->p_relaxed_res =
413014b24e2bSVaishali Kulkarni 						ECORE_HW_PREPARE_FAILED_ENG2;
413114b24e2bSVaishali Kulkarni 
413214b24e2bSVaishali Kulkarni 			if (IS_PF(p_dev)) {
413314b24e2bSVaishali Kulkarni 				ecore_init_free(p_hwfn);
413414b24e2bSVaishali Kulkarni 				ecore_mcp_free(p_hwfn);
413514b24e2bSVaishali Kulkarni 				ecore_hw_hwfn_free(p_hwfn);
413614b24e2bSVaishali Kulkarni 			} else {
413714b24e2bSVaishali Kulkarni 				DP_NOTICE(p_dev, true, "What do we need to free when VF hwfn1 init fails\n");
413814b24e2bSVaishali Kulkarni 			}
413914b24e2bSVaishali Kulkarni 			return rc;
414014b24e2bSVaishali Kulkarni 		}
414114b24e2bSVaishali Kulkarni 	}
414214b24e2bSVaishali Kulkarni 
414314b24e2bSVaishali Kulkarni 	return rc;
414414b24e2bSVaishali Kulkarni }
414514b24e2bSVaishali Kulkarni 
ecore_hw_remove(struct ecore_dev * p_dev)414614b24e2bSVaishali Kulkarni void ecore_hw_remove(struct ecore_dev *p_dev)
414714b24e2bSVaishali Kulkarni {
414814b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
414914b24e2bSVaishali Kulkarni 	int i;
415014b24e2bSVaishali Kulkarni 
415114b24e2bSVaishali Kulkarni 	if (IS_PF(p_dev))
415214b24e2bSVaishali Kulkarni 		ecore_mcp_ov_update_driver_state(p_hwfn, p_hwfn->p_main_ptt,
415314b24e2bSVaishali Kulkarni 						 ECORE_OV_DRIVER_STATE_NOT_LOADED);
415414b24e2bSVaishali Kulkarni 
415514b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
415614b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
415714b24e2bSVaishali Kulkarni 
415814b24e2bSVaishali Kulkarni 		if (IS_VF(p_dev)) {
415914b24e2bSVaishali Kulkarni 			ecore_vf_pf_release(p_hwfn);
416014b24e2bSVaishali Kulkarni 			continue;
416114b24e2bSVaishali Kulkarni 		}
416214b24e2bSVaishali Kulkarni 
416314b24e2bSVaishali Kulkarni 		ecore_init_free(p_hwfn);
416414b24e2bSVaishali Kulkarni 		ecore_hw_hwfn_free(p_hwfn);
416514b24e2bSVaishali Kulkarni 		ecore_mcp_free(p_hwfn);
416614b24e2bSVaishali Kulkarni 
416714b24e2bSVaishali Kulkarni 		OSAL_MUTEX_DEALLOC(&p_hwfn->dmae_info.mutex);
416814b24e2bSVaishali Kulkarni 	}
416914b24e2bSVaishali Kulkarni 
417014b24e2bSVaishali Kulkarni 	ecore_iov_free_hw_info(p_dev);
417114b24e2bSVaishali Kulkarni }
417214b24e2bSVaishali Kulkarni 
ecore_chain_free_next_ptr(struct ecore_dev * p_dev,struct ecore_chain * p_chain)417314b24e2bSVaishali Kulkarni static void ecore_chain_free_next_ptr(struct ecore_dev *p_dev,
417414b24e2bSVaishali Kulkarni 				      struct ecore_chain *p_chain)
417514b24e2bSVaishali Kulkarni {
417614b24e2bSVaishali Kulkarni 	void *p_virt = p_chain->p_virt_addr, *p_virt_next = OSAL_NULL;
417714b24e2bSVaishali Kulkarni 	dma_addr_t p_phys = p_chain->p_phys_addr, p_phys_next = 0;
417814b24e2bSVaishali Kulkarni 	struct ecore_chain_next *p_next;
417914b24e2bSVaishali Kulkarni 	u32 size, i;
418014b24e2bSVaishali Kulkarni 
418114b24e2bSVaishali Kulkarni 	if (!p_virt)
418214b24e2bSVaishali Kulkarni 		return;
418314b24e2bSVaishali Kulkarni 
418414b24e2bSVaishali Kulkarni 	size = p_chain->elem_size * p_chain->usable_per_page;
418514b24e2bSVaishali Kulkarni 
418614b24e2bSVaishali Kulkarni 	for (i = 0; i < p_chain->page_cnt; i++) {
418714b24e2bSVaishali Kulkarni 		if (!p_virt)
418814b24e2bSVaishali Kulkarni 			break;
418914b24e2bSVaishali Kulkarni 
419014b24e2bSVaishali Kulkarni 		p_next = (struct ecore_chain_next *)((u8 *)p_virt + size);
419114b24e2bSVaishali Kulkarni 		p_virt_next = p_next->next_virt;
419214b24e2bSVaishali Kulkarni 		p_phys_next = HILO_DMA_REGPAIR(p_next->next_phys);
419314b24e2bSVaishali Kulkarni 
419414b24e2bSVaishali Kulkarni 		OSAL_DMA_FREE_COHERENT(p_dev, p_virt, p_phys,
419514b24e2bSVaishali Kulkarni 				       ECORE_CHAIN_PAGE_SIZE);
419614b24e2bSVaishali Kulkarni 
419714b24e2bSVaishali Kulkarni 		p_virt = p_virt_next;
419814b24e2bSVaishali Kulkarni 		p_phys = p_phys_next;
419914b24e2bSVaishali Kulkarni 	}
420014b24e2bSVaishali Kulkarni }
420114b24e2bSVaishali Kulkarni 
ecore_chain_free_single(struct ecore_dev * p_dev,struct ecore_chain * p_chain)420214b24e2bSVaishali Kulkarni static void ecore_chain_free_single(struct ecore_dev *p_dev,
420314b24e2bSVaishali Kulkarni 				    struct ecore_chain *p_chain)
420414b24e2bSVaishali Kulkarni {
420514b24e2bSVaishali Kulkarni 	if (!p_chain->p_virt_addr)
420614b24e2bSVaishali Kulkarni 		return;
420714b24e2bSVaishali Kulkarni 
420814b24e2bSVaishali Kulkarni 	OSAL_DMA_FREE_COHERENT(p_dev, p_chain->p_virt_addr,
420914b24e2bSVaishali Kulkarni 			       p_chain->p_phys_addr, ECORE_CHAIN_PAGE_SIZE);
421014b24e2bSVaishali Kulkarni }
421114b24e2bSVaishali Kulkarni 
ecore_chain_free_pbl(struct ecore_dev * p_dev,struct ecore_chain * p_chain)421214b24e2bSVaishali Kulkarni static void ecore_chain_free_pbl(struct ecore_dev *p_dev,
421314b24e2bSVaishali Kulkarni 				 struct ecore_chain *p_chain)
421414b24e2bSVaishali Kulkarni {
421514b24e2bSVaishali Kulkarni 	void **pp_virt_addr_tbl = p_chain->pbl.pp_virt_addr_tbl;
421614b24e2bSVaishali Kulkarni 	u8 *p_pbl_virt = (u8 *)p_chain->pbl_sp.p_virt_table;
421714b24e2bSVaishali Kulkarni 	u32 page_cnt = p_chain->page_cnt, i, pbl_size;
421814b24e2bSVaishali Kulkarni 
421914b24e2bSVaishali Kulkarni 	if (!pp_virt_addr_tbl)
422014b24e2bSVaishali Kulkarni 		return;
422114b24e2bSVaishali Kulkarni 
422214b24e2bSVaishali Kulkarni 	if (!p_pbl_virt)
422314b24e2bSVaishali Kulkarni 		goto out;
422414b24e2bSVaishali Kulkarni 
422514b24e2bSVaishali Kulkarni 	for (i = 0; i < page_cnt; i++) {
422614b24e2bSVaishali Kulkarni 		if (!pp_virt_addr_tbl[i])
422714b24e2bSVaishali Kulkarni 			break;
422814b24e2bSVaishali Kulkarni 
422914b24e2bSVaishali Kulkarni 		OSAL_DMA_FREE_COHERENT(p_dev, pp_virt_addr_tbl[i],
423014b24e2bSVaishali Kulkarni 				       *(dma_addr_t *)p_pbl_virt,
423114b24e2bSVaishali Kulkarni 				       ECORE_CHAIN_PAGE_SIZE);
423214b24e2bSVaishali Kulkarni 
423314b24e2bSVaishali Kulkarni 		p_pbl_virt += ECORE_CHAIN_PBL_ENTRY_SIZE;
423414b24e2bSVaishali Kulkarni 	}
423514b24e2bSVaishali Kulkarni 
423614b24e2bSVaishali Kulkarni 	pbl_size = page_cnt * ECORE_CHAIN_PBL_ENTRY_SIZE;
423714b24e2bSVaishali Kulkarni 
423814b24e2bSVaishali Kulkarni 	if (!p_chain->b_external_pbl) {
423914b24e2bSVaishali Kulkarni 		OSAL_DMA_FREE_COHERENT(p_dev, p_chain->pbl_sp.p_virt_table,
424014b24e2bSVaishali Kulkarni 				       p_chain->pbl_sp.p_phys_table, pbl_size);
424114b24e2bSVaishali Kulkarni 	}
424214b24e2bSVaishali Kulkarni out:
424314b24e2bSVaishali Kulkarni 	OSAL_VFREE(p_dev, p_chain->pbl.pp_virt_addr_tbl);
424414b24e2bSVaishali Kulkarni 	p_chain->pbl.pp_virt_addr_tbl = OSAL_NULL;
424514b24e2bSVaishali Kulkarni }
424614b24e2bSVaishali Kulkarni 
ecore_chain_free(struct ecore_dev * p_dev,struct ecore_chain * p_chain)424714b24e2bSVaishali Kulkarni void ecore_chain_free(struct ecore_dev *p_dev,
424814b24e2bSVaishali Kulkarni 		      struct ecore_chain *p_chain)
424914b24e2bSVaishali Kulkarni {
425014b24e2bSVaishali Kulkarni 	switch (p_chain->mode) {
425114b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_NEXT_PTR:
425214b24e2bSVaishali Kulkarni 		ecore_chain_free_next_ptr(p_dev, p_chain);
425314b24e2bSVaishali Kulkarni 		break;
425414b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_SINGLE:
425514b24e2bSVaishali Kulkarni 		ecore_chain_free_single(p_dev, p_chain);
425614b24e2bSVaishali Kulkarni 		break;
425714b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_PBL:
425814b24e2bSVaishali Kulkarni 		ecore_chain_free_pbl(p_dev, p_chain);
425914b24e2bSVaishali Kulkarni 		break;
426014b24e2bSVaishali Kulkarni 	}
426114b24e2bSVaishali Kulkarni }
426214b24e2bSVaishali Kulkarni 
426314b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_chain_alloc_sanity_check(struct ecore_dev * p_dev,enum ecore_chain_cnt_type cnt_type,osal_size_t elem_size,u32 page_cnt)426414b24e2bSVaishali Kulkarni ecore_chain_alloc_sanity_check(struct ecore_dev *p_dev,
426514b24e2bSVaishali Kulkarni 			       enum ecore_chain_cnt_type cnt_type,
426614b24e2bSVaishali Kulkarni 			       osal_size_t elem_size, u32 page_cnt)
426714b24e2bSVaishali Kulkarni {
426814b24e2bSVaishali Kulkarni 	u64 chain_size = ELEMS_PER_PAGE(elem_size) * page_cnt;
426914b24e2bSVaishali Kulkarni 
427014b24e2bSVaishali Kulkarni 	/* The actual chain size can be larger than the maximal possible value
427114b24e2bSVaishali Kulkarni 	 * after rounding up the requested elements number to pages, and after
427214b24e2bSVaishali Kulkarni 	 * taking into acount the unusuable elements (next-ptr elements).
427314b24e2bSVaishali Kulkarni 	 * The size of a "u16" chain can be (U16_MAX + 1) since the chain
427414b24e2bSVaishali Kulkarni 	 * size/capacity fields are of a u32 type.
427514b24e2bSVaishali Kulkarni 	 */
427614b24e2bSVaishali Kulkarni 	if ((cnt_type == ECORE_CHAIN_CNT_TYPE_U16 &&
427714b24e2bSVaishali Kulkarni 	     chain_size > ((u32)ECORE_U16_MAX + 1)) ||
427814b24e2bSVaishali Kulkarni 	    (cnt_type == ECORE_CHAIN_CNT_TYPE_U32 &&
427914b24e2bSVaishali Kulkarni 	     chain_size > ECORE_U32_MAX)) {
428014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true,
428114b24e2bSVaishali Kulkarni 			  "The actual chain size (0x%llx) is larger than the maximal possible value\n",
428214b24e2bSVaishali Kulkarni 			  chain_size);
428314b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
428414b24e2bSVaishali Kulkarni 	}
428514b24e2bSVaishali Kulkarni 
428614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
428714b24e2bSVaishali Kulkarni }
428814b24e2bSVaishali Kulkarni 
428914b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_chain_alloc_next_ptr(struct ecore_dev * p_dev,struct ecore_chain * p_chain)429014b24e2bSVaishali Kulkarni ecore_chain_alloc_next_ptr(struct ecore_dev *p_dev, struct ecore_chain *p_chain)
429114b24e2bSVaishali Kulkarni {
429214b24e2bSVaishali Kulkarni 	void *p_virt = OSAL_NULL, *p_virt_prev = OSAL_NULL;
429314b24e2bSVaishali Kulkarni 	dma_addr_t p_phys = 0;
429414b24e2bSVaishali Kulkarni 	u32 i;
429514b24e2bSVaishali Kulkarni 
429614b24e2bSVaishali Kulkarni 	for (i = 0; i < p_chain->page_cnt; i++) {
429714b24e2bSVaishali Kulkarni 		p_virt = OSAL_DMA_ALLOC_COHERENT(p_dev, &p_phys,
429814b24e2bSVaishali Kulkarni 						 ECORE_CHAIN_PAGE_SIZE);
429914b24e2bSVaishali Kulkarni 		if (!p_virt) {
430014b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, true,
430114b24e2bSVaishali Kulkarni 				  "Failed to allocate chain memory\n");
430214b24e2bSVaishali Kulkarni 			return ECORE_NOMEM;
430314b24e2bSVaishali Kulkarni 		}
430414b24e2bSVaishali Kulkarni 
430514b24e2bSVaishali Kulkarni 		if (i == 0) {
430614b24e2bSVaishali Kulkarni 			ecore_chain_init_mem(p_chain, p_virt, p_phys);
430714b24e2bSVaishali Kulkarni 			ecore_chain_reset(p_chain);
430814b24e2bSVaishali Kulkarni 		} else {
430914b24e2bSVaishali Kulkarni 			ecore_chain_init_next_ptr_elem(p_chain, p_virt_prev,
431014b24e2bSVaishali Kulkarni 						       p_virt, p_phys);
431114b24e2bSVaishali Kulkarni 		}
431214b24e2bSVaishali Kulkarni 
431314b24e2bSVaishali Kulkarni 		p_virt_prev = p_virt;
431414b24e2bSVaishali Kulkarni 	}
431514b24e2bSVaishali Kulkarni 	/* Last page's next element should point to the beginning of the
431614b24e2bSVaishali Kulkarni 	 * chain.
431714b24e2bSVaishali Kulkarni 	 */
431814b24e2bSVaishali Kulkarni 	ecore_chain_init_next_ptr_elem(p_chain, p_virt_prev,
431914b24e2bSVaishali Kulkarni 				       p_chain->p_virt_addr,
432014b24e2bSVaishali Kulkarni 				       p_chain->p_phys_addr);
432114b24e2bSVaishali Kulkarni 
432214b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
432314b24e2bSVaishali Kulkarni }
432414b24e2bSVaishali Kulkarni 
432514b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_chain_alloc_single(struct ecore_dev * p_dev,struct ecore_chain * p_chain)432614b24e2bSVaishali Kulkarni ecore_chain_alloc_single(struct ecore_dev *p_dev, struct ecore_chain *p_chain)
432714b24e2bSVaishali Kulkarni {
432814b24e2bSVaishali Kulkarni 	dma_addr_t p_phys = 0;
432914b24e2bSVaishali Kulkarni 	void *p_virt = OSAL_NULL;
433014b24e2bSVaishali Kulkarni 
433114b24e2bSVaishali Kulkarni 	p_virt = OSAL_DMA_ALLOC_COHERENT(p_dev, &p_phys, ECORE_CHAIN_PAGE_SIZE);
433214b24e2bSVaishali Kulkarni 	if (!p_virt) {
433314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true, "Failed to allocate chain memory\n");
433414b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
433514b24e2bSVaishali Kulkarni 	}
433614b24e2bSVaishali Kulkarni 
433714b24e2bSVaishali Kulkarni 	ecore_chain_init_mem(p_chain, p_virt, p_phys);
433814b24e2bSVaishali Kulkarni 	ecore_chain_reset(p_chain);
433914b24e2bSVaishali Kulkarni 
434014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
434114b24e2bSVaishali Kulkarni }
434214b24e2bSVaishali Kulkarni 
434314b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_chain_alloc_pbl(struct ecore_dev * p_dev,struct ecore_chain * p_chain,struct ecore_chain_ext_pbl * ext_pbl)434414b24e2bSVaishali Kulkarni ecore_chain_alloc_pbl(struct ecore_dev *p_dev,
434514b24e2bSVaishali Kulkarni 		      struct ecore_chain *p_chain,
434614b24e2bSVaishali Kulkarni 		      struct ecore_chain_ext_pbl *ext_pbl)
434714b24e2bSVaishali Kulkarni {
434814b24e2bSVaishali Kulkarni 	void *p_virt = OSAL_NULL;
434914b24e2bSVaishali Kulkarni 	u8 *p_pbl_virt = OSAL_NULL;
435014b24e2bSVaishali Kulkarni 	void **pp_virt_addr_tbl = OSAL_NULL;
435114b24e2bSVaishali Kulkarni 	dma_addr_t p_phys = 0, p_pbl_phys = 0;
435214b24e2bSVaishali Kulkarni 	u32 page_cnt = p_chain->page_cnt, size, i;
435314b24e2bSVaishali Kulkarni 
435414b24e2bSVaishali Kulkarni 	size = page_cnt * sizeof(*pp_virt_addr_tbl);
435514b24e2bSVaishali Kulkarni 	pp_virt_addr_tbl = (void **)OSAL_VZALLOC(p_dev, size);
435614b24e2bSVaishali Kulkarni 	if (!pp_virt_addr_tbl) {
435714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true,
435814b24e2bSVaishali Kulkarni 			  "Failed to allocate memory for the chain virtual addresses table\n");
435914b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
436014b24e2bSVaishali Kulkarni 	}
436114b24e2bSVaishali Kulkarni 
436214b24e2bSVaishali Kulkarni 	/* The allocation of the PBL table is done with its full size, since it
436314b24e2bSVaishali Kulkarni 	 * is expected to be successive.
436414b24e2bSVaishali Kulkarni 	 * ecore_chain_init_pbl_mem() is called even in a case of an allocation
436514b24e2bSVaishali Kulkarni 	 * failure, since pp_virt_addr_tbl was previously allocated, and it
436614b24e2bSVaishali Kulkarni 	 * should be saved to allow its freeing during the error flow.
436714b24e2bSVaishali Kulkarni 	 */
436814b24e2bSVaishali Kulkarni 	size = page_cnt * ECORE_CHAIN_PBL_ENTRY_SIZE;
436914b24e2bSVaishali Kulkarni 
437014b24e2bSVaishali Kulkarni 	if (ext_pbl == OSAL_NULL) {
437114b24e2bSVaishali Kulkarni 		p_pbl_virt = OSAL_DMA_ALLOC_COHERENT(p_dev, &p_pbl_phys, size);
437214b24e2bSVaishali Kulkarni 	} else {
437314b24e2bSVaishali Kulkarni 		p_pbl_virt = ext_pbl->p_pbl_virt;
437414b24e2bSVaishali Kulkarni 		p_pbl_phys = ext_pbl->p_pbl_phys;
437514b24e2bSVaishali Kulkarni 		p_chain->b_external_pbl = true;
437614b24e2bSVaishali Kulkarni 	}
437714b24e2bSVaishali Kulkarni 
437814b24e2bSVaishali Kulkarni 	ecore_chain_init_pbl_mem(p_chain, p_pbl_virt, p_pbl_phys,
437914b24e2bSVaishali Kulkarni 				 pp_virt_addr_tbl);
438014b24e2bSVaishali Kulkarni 	if (!p_pbl_virt) {
438114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true, "Failed to allocate chain pbl memory\n");
438214b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
438314b24e2bSVaishali Kulkarni 	}
438414b24e2bSVaishali Kulkarni 
438514b24e2bSVaishali Kulkarni 	for (i = 0; i < page_cnt; i++) {
438614b24e2bSVaishali Kulkarni 		p_virt = OSAL_DMA_ALLOC_COHERENT(p_dev, &p_phys,
438714b24e2bSVaishali Kulkarni 						 ECORE_CHAIN_PAGE_SIZE);
438814b24e2bSVaishali Kulkarni 		if (!p_virt) {
438914b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, true,
439014b24e2bSVaishali Kulkarni 				  "Failed to allocate chain memory\n");
439114b24e2bSVaishali Kulkarni 			return ECORE_NOMEM;
439214b24e2bSVaishali Kulkarni 		}
439314b24e2bSVaishali Kulkarni 
439414b24e2bSVaishali Kulkarni 		if (i == 0) {
439514b24e2bSVaishali Kulkarni 			ecore_chain_init_mem(p_chain, p_virt, p_phys);
439614b24e2bSVaishali Kulkarni 			ecore_chain_reset(p_chain);
439714b24e2bSVaishali Kulkarni 		}
439814b24e2bSVaishali Kulkarni 
439914b24e2bSVaishali Kulkarni 		/* Fill the PBL table with the physical address of the page */
440014b24e2bSVaishali Kulkarni 		*(dma_addr_t *)p_pbl_virt = p_phys;
440114b24e2bSVaishali Kulkarni 		/* Keep the virtual address of the page */
440214b24e2bSVaishali Kulkarni 		p_chain->pbl.pp_virt_addr_tbl[i] = p_virt;
440314b24e2bSVaishali Kulkarni 
440414b24e2bSVaishali Kulkarni 		p_pbl_virt += ECORE_CHAIN_PBL_ENTRY_SIZE;
440514b24e2bSVaishali Kulkarni 	}
440614b24e2bSVaishali Kulkarni 
440714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
440814b24e2bSVaishali Kulkarni }
440914b24e2bSVaishali Kulkarni 
ecore_chain_alloc(struct ecore_dev * p_dev,enum ecore_chain_use_mode intended_use,enum ecore_chain_mode mode,enum ecore_chain_cnt_type cnt_type,u32 num_elems,osal_size_t elem_size,struct ecore_chain * p_chain,struct ecore_chain_ext_pbl * ext_pbl)441014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_chain_alloc(struct ecore_dev *p_dev,
441114b24e2bSVaishali Kulkarni 				       enum ecore_chain_use_mode intended_use,
441214b24e2bSVaishali Kulkarni 				       enum ecore_chain_mode mode,
441314b24e2bSVaishali Kulkarni 				       enum ecore_chain_cnt_type cnt_type,
441414b24e2bSVaishali Kulkarni 				       u32 num_elems, osal_size_t elem_size,
441514b24e2bSVaishali Kulkarni 				       struct ecore_chain *p_chain,
441614b24e2bSVaishali Kulkarni 				       struct ecore_chain_ext_pbl *ext_pbl)
441714b24e2bSVaishali Kulkarni {
441814b24e2bSVaishali Kulkarni 	u32 page_cnt;
441914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
442014b24e2bSVaishali Kulkarni 
442114b24e2bSVaishali Kulkarni 	if (mode == ECORE_CHAIN_MODE_SINGLE)
442214b24e2bSVaishali Kulkarni 		page_cnt = 1;
442314b24e2bSVaishali Kulkarni 	else
442414b24e2bSVaishali Kulkarni 		page_cnt = ECORE_CHAIN_PAGE_CNT(num_elems, elem_size, mode);
442514b24e2bSVaishali Kulkarni 
442614b24e2bSVaishali Kulkarni 	rc = ecore_chain_alloc_sanity_check(p_dev, cnt_type, elem_size,
442714b24e2bSVaishali Kulkarni 					    page_cnt);
442814b24e2bSVaishali Kulkarni 	if (rc) {
442914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, true,
443014b24e2bSVaishali Kulkarni 			  "Cannot allocate a chain with the given arguments:\n"
443114b24e2bSVaishali Kulkarni 			  "[use_mode %d, mode %d, cnt_type %d, num_elems %d, elem_size %zu]\n",
443214b24e2bSVaishali Kulkarni 			  intended_use, mode, cnt_type, num_elems, elem_size);
443314b24e2bSVaishali Kulkarni 		return rc;
443414b24e2bSVaishali Kulkarni 	}
443514b24e2bSVaishali Kulkarni 
443614b24e2bSVaishali Kulkarni 	ecore_chain_init_params(p_chain, page_cnt, (u8)elem_size, intended_use,
443714b24e2bSVaishali Kulkarni 				mode, cnt_type, p_dev->dp_ctx);
443814b24e2bSVaishali Kulkarni 
443914b24e2bSVaishali Kulkarni 	switch (mode) {
444014b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_NEXT_PTR:
444114b24e2bSVaishali Kulkarni 		rc = ecore_chain_alloc_next_ptr(p_dev, p_chain);
444214b24e2bSVaishali Kulkarni 		break;
444314b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_SINGLE:
444414b24e2bSVaishali Kulkarni 		rc = ecore_chain_alloc_single(p_dev, p_chain);
444514b24e2bSVaishali Kulkarni 		break;
444614b24e2bSVaishali Kulkarni 	case ECORE_CHAIN_MODE_PBL:
444714b24e2bSVaishali Kulkarni 		rc = ecore_chain_alloc_pbl(p_dev, p_chain, ext_pbl);
444814b24e2bSVaishali Kulkarni 		break;
444914b24e2bSVaishali Kulkarni 	}
445014b24e2bSVaishali Kulkarni 	if (rc)
445114b24e2bSVaishali Kulkarni 		goto nomem;
445214b24e2bSVaishali Kulkarni 
445314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
445414b24e2bSVaishali Kulkarni 
445514b24e2bSVaishali Kulkarni nomem:
445614b24e2bSVaishali Kulkarni 	ecore_chain_free(p_dev, p_chain);
445714b24e2bSVaishali Kulkarni 	return rc;
445814b24e2bSVaishali Kulkarni }
445914b24e2bSVaishali Kulkarni 
ecore_fw_l2_queue(struct ecore_hwfn * p_hwfn,u16 src_id,u16 * dst_id)446014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_fw_l2_queue(struct ecore_hwfn *p_hwfn,
446114b24e2bSVaishali Kulkarni 				       u16 src_id, u16 *dst_id)
446214b24e2bSVaishali Kulkarni {
446314b24e2bSVaishali Kulkarni 	if (src_id >= RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
446414b24e2bSVaishali Kulkarni 		u16 min, max;
446514b24e2bSVaishali Kulkarni 
446614b24e2bSVaishali Kulkarni 		min = (u16)RESC_START(p_hwfn, ECORE_L2_QUEUE);
446714b24e2bSVaishali Kulkarni 		max = min + RESC_NUM(p_hwfn, ECORE_L2_QUEUE);
446814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "l2_queue id [%d] is not valid, available indices [%d - %d]\n",
446914b24e2bSVaishali Kulkarni 			  src_id, min, max);
447014b24e2bSVaishali Kulkarni 
447114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
447214b24e2bSVaishali Kulkarni 	}
447314b24e2bSVaishali Kulkarni 
447414b24e2bSVaishali Kulkarni 	*dst_id = RESC_START(p_hwfn, ECORE_L2_QUEUE) + src_id;
447514b24e2bSVaishali Kulkarni 
447614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
447714b24e2bSVaishali Kulkarni }
447814b24e2bSVaishali Kulkarni 
ecore_fw_vport(struct ecore_hwfn * p_hwfn,u8 src_id,u8 * dst_id)447914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_fw_vport(struct ecore_hwfn *p_hwfn,
448014b24e2bSVaishali Kulkarni 				    u8 src_id, u8 *dst_id)
448114b24e2bSVaishali Kulkarni {
448214b24e2bSVaishali Kulkarni 	if (src_id >= RESC_NUM(p_hwfn, ECORE_VPORT)) {
448314b24e2bSVaishali Kulkarni 		u8 min, max;
448414b24e2bSVaishali Kulkarni 
448514b24e2bSVaishali Kulkarni 		min = (u8)RESC_START(p_hwfn, ECORE_VPORT);
448614b24e2bSVaishali Kulkarni 		max = min + RESC_NUM(p_hwfn, ECORE_VPORT);
448714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "vport id [%d] is not valid, available indices [%d - %d]\n",
448814b24e2bSVaishali Kulkarni 			  src_id, min, max);
448914b24e2bSVaishali Kulkarni 
449014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
449114b24e2bSVaishali Kulkarni 	}
449214b24e2bSVaishali Kulkarni 
449314b24e2bSVaishali Kulkarni 	*dst_id = RESC_START(p_hwfn, ECORE_VPORT) + src_id;
449414b24e2bSVaishali Kulkarni 
449514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
449614b24e2bSVaishali Kulkarni }
449714b24e2bSVaishali Kulkarni 
ecore_fw_rss_eng(struct ecore_hwfn * p_hwfn,u8 src_id,u8 * dst_id)449814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_fw_rss_eng(struct ecore_hwfn *p_hwfn,
449914b24e2bSVaishali Kulkarni 				      u8 src_id, u8 *dst_id)
450014b24e2bSVaishali Kulkarni {
450114b24e2bSVaishali Kulkarni 	if (src_id >= RESC_NUM(p_hwfn, ECORE_RSS_ENG)) {
450214b24e2bSVaishali Kulkarni 		u8 min, max;
450314b24e2bSVaishali Kulkarni 
450414b24e2bSVaishali Kulkarni 		min = (u8)RESC_START(p_hwfn, ECORE_RSS_ENG);
450514b24e2bSVaishali Kulkarni 		max = min + RESC_NUM(p_hwfn, ECORE_RSS_ENG);
450614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "rss_eng id [%d] is not valid, available indices [%d - %d]\n",
450714b24e2bSVaishali Kulkarni 			  src_id, min, max);
450814b24e2bSVaishali Kulkarni 
450914b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
451014b24e2bSVaishali Kulkarni 	}
451114b24e2bSVaishali Kulkarni 
451214b24e2bSVaishali Kulkarni 	*dst_id = RESC_START(p_hwfn, ECORE_RSS_ENG) + src_id;
451314b24e2bSVaishali Kulkarni 
451414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
451514b24e2bSVaishali Kulkarni }
451614b24e2bSVaishali Kulkarni 
451714b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_add_mac_filter_bb_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 high,u32 low,u32 * p_entry_num)451814b24e2bSVaishali Kulkarni ecore_llh_add_mac_filter_bb_ah(struct ecore_hwfn *p_hwfn,
451914b24e2bSVaishali Kulkarni 			       struct ecore_ptt *p_ptt, u32 high, u32 low,
452014b24e2bSVaishali Kulkarni 			       u32 *p_entry_num)
452114b24e2bSVaishali Kulkarni {
452214b24e2bSVaishali Kulkarni 	u32 en;
452314b24e2bSVaishali Kulkarni 	int i;
452414b24e2bSVaishali Kulkarni 
452514b24e2bSVaishali Kulkarni 	/* Find a free entry and utilize it */
452614b24e2bSVaishali Kulkarni 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
452714b24e2bSVaishali Kulkarni 		en = ecore_rd(p_hwfn, p_ptt,
452814b24e2bSVaishali Kulkarni 			      NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
452914b24e2bSVaishali Kulkarni 			      i * sizeof(u32));
453014b24e2bSVaishali Kulkarni 		if (en)
453114b24e2bSVaishali Kulkarni 			continue;
453214b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
453314b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
453414b24e2bSVaishali Kulkarni 			 2 * i * sizeof(u32), low);
453514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
453614b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
453714b24e2bSVaishali Kulkarni 			 (2 * i + 1) * sizeof(u32), high);
453814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
453914b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
454014b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
454114b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
454214b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
454314b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
454414b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
454514b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
454614b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 1);
454714b24e2bSVaishali Kulkarni 		break;
454814b24e2bSVaishali Kulkarni 	}
454914b24e2bSVaishali Kulkarni 
455014b24e2bSVaishali Kulkarni 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
455114b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
455214b24e2bSVaishali Kulkarni 
455314b24e2bSVaishali Kulkarni 	*p_entry_num = i;
455414b24e2bSVaishali Kulkarni 
455514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
455614b24e2bSVaishali Kulkarni }
455714b24e2bSVaishali Kulkarni 
455814b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_add_mac_filter_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 high,u32 low,u32 * p_entry_num)455914b24e2bSVaishali Kulkarni ecore_llh_add_mac_filter_e5(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
456014b24e2bSVaishali Kulkarni 			    u32 high, u32 low, u32 *p_entry_num)
456114b24e2bSVaishali Kulkarni {
456214b24e2bSVaishali Kulkarni 	ECORE_E5_MISSING_CODE;
456314b24e2bSVaishali Kulkarni 
456414b24e2bSVaishali Kulkarni 	return ECORE_NOTIMPL;
456514b24e2bSVaishali Kulkarni }
456614b24e2bSVaishali Kulkarni 
ecore_llh_add_mac_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * p_filter)456714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_hwfn *p_hwfn,
456814b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt, u8 *p_filter)
456914b24e2bSVaishali Kulkarni {
457014b24e2bSVaishali Kulkarni 	u32 high, low, entry_num;
457114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
457214b24e2bSVaishali Kulkarni 
457314b24e2bSVaishali Kulkarni 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
457414b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
457514b24e2bSVaishali Kulkarni 
457614b24e2bSVaishali Kulkarni 	high = p_filter[1] | (p_filter[0] << 8);
457714b24e2bSVaishali Kulkarni 	low = p_filter[5] | (p_filter[4] << 8) |
457814b24e2bSVaishali Kulkarni 	      (p_filter[3] << 16) | (p_filter[2] << 24);
457914b24e2bSVaishali Kulkarni 
458014b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
458114b24e2bSVaishali Kulkarni 		rc = ecore_llh_add_mac_filter_bb_ah(p_hwfn, p_ptt, high, low,
458214b24e2bSVaishali Kulkarni 						    &entry_num);
458314b24e2bSVaishali Kulkarni 	else /* E5 */
458414b24e2bSVaishali Kulkarni 		rc = ecore_llh_add_mac_filter_e5(p_hwfn, p_ptt, high, low,
458514b24e2bSVaishali Kulkarni 						 &entry_num);
458614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
458714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
458814b24e2bSVaishali Kulkarni 			  "Failed to find an empty LLH filter to utilize\n");
458914b24e2bSVaishali Kulkarni 		return rc;
459014b24e2bSVaishali Kulkarni 	}
459114b24e2bSVaishali Kulkarni 
459214b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
459314b24e2bSVaishali Kulkarni 		   "MAC: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx is added at %d\n",
459414b24e2bSVaishali Kulkarni 		   p_filter[0], p_filter[1], p_filter[2], p_filter[3],
459514b24e2bSVaishali Kulkarni 		   p_filter[4], p_filter[5], entry_num);
459614b24e2bSVaishali Kulkarni 
459714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
459814b24e2bSVaishali Kulkarni }
459914b24e2bSVaishali Kulkarni 
460014b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_remove_mac_filter_bb_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 high,u32 low,u32 * p_entry_num)460114b24e2bSVaishali Kulkarni ecore_llh_remove_mac_filter_bb_ah(struct ecore_hwfn *p_hwfn,
460214b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt, u32 high, u32 low,
460314b24e2bSVaishali Kulkarni 				  u32 *p_entry_num)
460414b24e2bSVaishali Kulkarni {
460514b24e2bSVaishali Kulkarni 	int i;
460614b24e2bSVaishali Kulkarni 
460714b24e2bSVaishali Kulkarni 	/* Find the entry and clean it */
460814b24e2bSVaishali Kulkarni 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
460914b24e2bSVaishali Kulkarni 		if (ecore_rd(p_hwfn, p_ptt,
461014b24e2bSVaishali Kulkarni 			     NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
461114b24e2bSVaishali Kulkarni 			     2 * i * sizeof(u32)) != low)
461214b24e2bSVaishali Kulkarni 			continue;
461314b24e2bSVaishali Kulkarni 		if (ecore_rd(p_hwfn, p_ptt,
461414b24e2bSVaishali Kulkarni 			     NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
461514b24e2bSVaishali Kulkarni 			     (2 * i + 1) * sizeof(u32)) != high)
461614b24e2bSVaishali Kulkarni 			continue;
461714b24e2bSVaishali Kulkarni 
461814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
461914b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 0);
462014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
462114b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
462214b24e2bSVaishali Kulkarni 			 2 * i * sizeof(u32), 0);
462314b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
462414b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
462514b24e2bSVaishali Kulkarni 			 (2 * i + 1) * sizeof(u32), 0);
462614b24e2bSVaishali Kulkarni 		break;
462714b24e2bSVaishali Kulkarni 	}
462814b24e2bSVaishali Kulkarni 
462914b24e2bSVaishali Kulkarni 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
463014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
463114b24e2bSVaishali Kulkarni 
463214b24e2bSVaishali Kulkarni 	*p_entry_num = i;
463314b24e2bSVaishali Kulkarni 
463414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
463514b24e2bSVaishali Kulkarni }
463614b24e2bSVaishali Kulkarni 
463714b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_remove_mac_filter_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 high,u32 low,u32 * p_entry_num)463814b24e2bSVaishali Kulkarni ecore_llh_remove_mac_filter_e5(struct ecore_hwfn *p_hwfn,
463914b24e2bSVaishali Kulkarni 			       struct ecore_ptt *p_ptt, u32 high, u32 low,
464014b24e2bSVaishali Kulkarni 			       u32 *p_entry_num)
464114b24e2bSVaishali Kulkarni {
464214b24e2bSVaishali Kulkarni 	ECORE_E5_MISSING_CODE;
464314b24e2bSVaishali Kulkarni 
464414b24e2bSVaishali Kulkarni 	return ECORE_NOTIMPL;
464514b24e2bSVaishali Kulkarni }
464614b24e2bSVaishali Kulkarni 
ecore_llh_remove_mac_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * p_filter)464714b24e2bSVaishali Kulkarni void ecore_llh_remove_mac_filter(struct ecore_hwfn *p_hwfn,
464814b24e2bSVaishali Kulkarni 			     struct ecore_ptt *p_ptt, u8 *p_filter)
464914b24e2bSVaishali Kulkarni {
465014b24e2bSVaishali Kulkarni 	u32 high, low, entry_num;
465114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
465214b24e2bSVaishali Kulkarni 
465314b24e2bSVaishali Kulkarni 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
465414b24e2bSVaishali Kulkarni 		return;
465514b24e2bSVaishali Kulkarni 
465614b24e2bSVaishali Kulkarni 	high = p_filter[1] | (p_filter[0] << 8);
465714b24e2bSVaishali Kulkarni 	low = p_filter[5] | (p_filter[4] << 8) |
465814b24e2bSVaishali Kulkarni 	      (p_filter[3] << 16) | (p_filter[2] << 24);
465914b24e2bSVaishali Kulkarni 
466014b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
466114b24e2bSVaishali Kulkarni 		rc = ecore_llh_remove_mac_filter_bb_ah(p_hwfn, p_ptt, high,
466214b24e2bSVaishali Kulkarni 						       low, &entry_num);
466314b24e2bSVaishali Kulkarni 	else /* E5 */
466414b24e2bSVaishali Kulkarni 		rc = ecore_llh_remove_mac_filter_e5(p_hwfn, p_ptt, high, low,
466514b24e2bSVaishali Kulkarni 						    &entry_num);
466614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
466714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
466814b24e2bSVaishali Kulkarni 			  "Tried to remove a non-configured filter [MAC %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx]\n",
466914b24e2bSVaishali Kulkarni 			  p_filter[0], p_filter[1], p_filter[2], p_filter[3],
467014b24e2bSVaishali Kulkarni 			  p_filter[4], p_filter[5]);
467114b24e2bSVaishali Kulkarni 		return;
467214b24e2bSVaishali Kulkarni 	}
467314b24e2bSVaishali Kulkarni 
467414b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
467514b24e2bSVaishali Kulkarni 		   "MAC: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx was removed from %d\n",
467614b24e2bSVaishali Kulkarni 		   p_filter[0], p_filter[1], p_filter[2], p_filter[3],
467714b24e2bSVaishali Kulkarni 		   p_filter[4], p_filter[5], entry_num);
467814b24e2bSVaishali Kulkarni }
467914b24e2bSVaishali Kulkarni 
468014b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_add_protocol_filter_bb_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_llh_port_filter_type_t type,u32 high,u32 low,u32 * p_entry_num)468114b24e2bSVaishali Kulkarni ecore_llh_add_protocol_filter_bb_ah(struct ecore_hwfn *p_hwfn,
468214b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt,
468314b24e2bSVaishali Kulkarni 				    enum ecore_llh_port_filter_type_t type,
468414b24e2bSVaishali Kulkarni 				    u32 high, u32 low, u32 *p_entry_num)
468514b24e2bSVaishali Kulkarni {
468614b24e2bSVaishali Kulkarni 	u32 en;
468714b24e2bSVaishali Kulkarni 	int i;
468814b24e2bSVaishali Kulkarni 
468914b24e2bSVaishali Kulkarni 	/* Find a free entry and utilize it */
469014b24e2bSVaishali Kulkarni 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
469114b24e2bSVaishali Kulkarni 		en = ecore_rd(p_hwfn, p_ptt,
469214b24e2bSVaishali Kulkarni 			      NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
469314b24e2bSVaishali Kulkarni 			      i * sizeof(u32));
469414b24e2bSVaishali Kulkarni 		if (en)
469514b24e2bSVaishali Kulkarni 			continue;
469614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
469714b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
469814b24e2bSVaishali Kulkarni 			 2 * i * sizeof(u32), low);
469914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
470014b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
470114b24e2bSVaishali Kulkarni 			 (2 * i + 1) * sizeof(u32), high);
470214b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
470314b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
470414b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 1);
470514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
470614b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
470714b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 1 << type);
470814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
470914b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 1);
471014b24e2bSVaishali Kulkarni 		break;
471114b24e2bSVaishali Kulkarni 	}
471214b24e2bSVaishali Kulkarni 
471314b24e2bSVaishali Kulkarni 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
471414b24e2bSVaishali Kulkarni 		return ECORE_NORESOURCES;
471514b24e2bSVaishali Kulkarni 
471614b24e2bSVaishali Kulkarni 	*p_entry_num = i;
471714b24e2bSVaishali Kulkarni 
471814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
471914b24e2bSVaishali Kulkarni }
472014b24e2bSVaishali Kulkarni 
472114b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_add_protocol_filter_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_llh_port_filter_type_t type,u32 high,u32 low,u32 * p_entry_num)472214b24e2bSVaishali Kulkarni ecore_llh_add_protocol_filter_e5(struct ecore_hwfn *p_hwfn,
472314b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt,
472414b24e2bSVaishali Kulkarni 				 enum ecore_llh_port_filter_type_t type,
472514b24e2bSVaishali Kulkarni 				 u32 high, u32 low, u32 *p_entry_num)
472614b24e2bSVaishali Kulkarni {
472714b24e2bSVaishali Kulkarni 	ECORE_E5_MISSING_CODE;
472814b24e2bSVaishali Kulkarni 
472914b24e2bSVaishali Kulkarni 	return ECORE_NOTIMPL;
473014b24e2bSVaishali Kulkarni }
473114b24e2bSVaishali Kulkarni 
473214b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_llh_add_protocol_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 source_port_or_eth_type,u16 dest_port,enum ecore_llh_port_filter_type_t type)473314b24e2bSVaishali Kulkarni ecore_llh_add_protocol_filter(struct ecore_hwfn *p_hwfn,
473414b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt,
473514b24e2bSVaishali Kulkarni 			      u16 source_port_or_eth_type,
473614b24e2bSVaishali Kulkarni 			      u16 dest_port,
473714b24e2bSVaishali Kulkarni 			      enum ecore_llh_port_filter_type_t type)
473814b24e2bSVaishali Kulkarni {
473914b24e2bSVaishali Kulkarni 	u32 high, low, entry_num;
474014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
474114b24e2bSVaishali Kulkarni 
474214b24e2bSVaishali Kulkarni 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
474314b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
474414b24e2bSVaishali Kulkarni 
474514b24e2bSVaishali Kulkarni 	high = 0;
474614b24e2bSVaishali Kulkarni 	low = 0;
474714b24e2bSVaishali Kulkarni 	switch (type) {
474814b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_ETHERTYPE:
474914b24e2bSVaishali Kulkarni 		high = source_port_or_eth_type;
475014b24e2bSVaishali Kulkarni 		break;
475114b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_PORT:
475214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_PORT:
475314b24e2bSVaishali Kulkarni 		low = source_port_or_eth_type << 16;
475414b24e2bSVaishali Kulkarni 		break;
475514b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_DEST_PORT:
475614b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_DEST_PORT:
475714b24e2bSVaishali Kulkarni 		low = dest_port;
475814b24e2bSVaishali Kulkarni 		break;
475914b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
476014b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
476114b24e2bSVaishali Kulkarni 		low = (source_port_or_eth_type << 16) | dest_port;
476214b24e2bSVaishali Kulkarni 		break;
476314b24e2bSVaishali Kulkarni 	default:
476414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
476514b24e2bSVaishali Kulkarni 			  "Non valid LLH protocol filter type %d\n", type);
476614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
476714b24e2bSVaishali Kulkarni 	}
476814b24e2bSVaishali Kulkarni 
476914b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
477014b24e2bSVaishali Kulkarni 		rc = ecore_llh_add_protocol_filter_bb_ah(p_hwfn, p_ptt, type,
477114b24e2bSVaishali Kulkarni 							 high, low, &entry_num);
477214b24e2bSVaishali Kulkarni 	else /* E5 */
477314b24e2bSVaishali Kulkarni 		rc = ecore_llh_add_protocol_filter_e5(p_hwfn, p_ptt, type, high,
477414b24e2bSVaishali Kulkarni 						      low, &entry_num);
477514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
477614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
477714b24e2bSVaishali Kulkarni 			  "Failed to find an empty LLH filter to utilize\n");
477814b24e2bSVaishali Kulkarni 		return rc;
477914b24e2bSVaishali Kulkarni 	}
478014b24e2bSVaishali Kulkarni 
478114b24e2bSVaishali Kulkarni 	switch (type) {
478214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_ETHERTYPE:
478314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
478414b24e2bSVaishali Kulkarni 			   "ETH type %x is added at %d\n",
478514b24e2bSVaishali Kulkarni 			   source_port_or_eth_type, entry_num);
478614b24e2bSVaishali Kulkarni 		break;
478714b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_PORT:
478814b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
478914b24e2bSVaishali Kulkarni 			   "TCP src port %x is added at %d\n",
479014b24e2bSVaishali Kulkarni 			   source_port_or_eth_type, entry_num);
479114b24e2bSVaishali Kulkarni 		break;
479214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_PORT:
479314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
479414b24e2bSVaishali Kulkarni 			   "UDP src port %x is added at %d\n",
479514b24e2bSVaishali Kulkarni 			   source_port_or_eth_type, entry_num);
479614b24e2bSVaishali Kulkarni 		break;
479714b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_DEST_PORT:
479814b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
479914b24e2bSVaishali Kulkarni 			   "TCP dst port %x is added at %d\n",
480014b24e2bSVaishali Kulkarni 			   dest_port, entry_num);
480114b24e2bSVaishali Kulkarni 		break;
480214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_DEST_PORT:
480314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
480414b24e2bSVaishali Kulkarni 			   "UDP dst port %x is added at %d\n",
480514b24e2bSVaishali Kulkarni 			   dest_port, entry_num);
480614b24e2bSVaishali Kulkarni 		break;
480714b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
480814b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
480914b24e2bSVaishali Kulkarni 			   "TCP src/dst ports %x/%x are added at %d\n",
481014b24e2bSVaishali Kulkarni 			   source_port_or_eth_type, dest_port, entry_num);
481114b24e2bSVaishali Kulkarni 		break;
481214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
481314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
481414b24e2bSVaishali Kulkarni 			   "UDP src/dst ports %x/%x are added at %d\n",
481514b24e2bSVaishali Kulkarni 			   source_port_or_eth_type, dest_port, entry_num);
481614b24e2bSVaishali Kulkarni 			break;
481714b24e2bSVaishali Kulkarni 	}
481814b24e2bSVaishali Kulkarni 
481914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
482014b24e2bSVaishali Kulkarni }
482114b24e2bSVaishali Kulkarni 
482214b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_remove_protocol_filter_bb_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_llh_port_filter_type_t type,u32 high,u32 low,u32 * p_entry_num)482314b24e2bSVaishali Kulkarni ecore_llh_remove_protocol_filter_bb_ah(struct ecore_hwfn *p_hwfn,
482414b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
482514b24e2bSVaishali Kulkarni 				       enum ecore_llh_port_filter_type_t type,
482614b24e2bSVaishali Kulkarni 				       u32 high, u32 low, u32 *p_entry_num)
482714b24e2bSVaishali Kulkarni {
482814b24e2bSVaishali Kulkarni 	int i;
482914b24e2bSVaishali Kulkarni 
483014b24e2bSVaishali Kulkarni 	/* Find the entry and clean it */
483114b24e2bSVaishali Kulkarni 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
483214b24e2bSVaishali Kulkarni 		if (!ecore_rd(p_hwfn, p_ptt,
483314b24e2bSVaishali Kulkarni 			      NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
483414b24e2bSVaishali Kulkarni 			      i * sizeof(u32)))
483514b24e2bSVaishali Kulkarni 			continue;
483614b24e2bSVaishali Kulkarni 		if (!ecore_rd(p_hwfn, p_ptt,
483714b24e2bSVaishali Kulkarni 			      NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
483814b24e2bSVaishali Kulkarni 			      i * sizeof(u32)))
483914b24e2bSVaishali Kulkarni 			continue;
484014b24e2bSVaishali Kulkarni 		if (!(ecore_rd(p_hwfn, p_ptt,
484114b24e2bSVaishali Kulkarni 			       NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
484214b24e2bSVaishali Kulkarni 			       i * sizeof(u32)) & (1 << type)))
484314b24e2bSVaishali Kulkarni 			continue;
484414b24e2bSVaishali Kulkarni 		if (ecore_rd(p_hwfn, p_ptt,
484514b24e2bSVaishali Kulkarni 			     NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
484614b24e2bSVaishali Kulkarni 			     2 * i * sizeof(u32)) != low)
484714b24e2bSVaishali Kulkarni 			continue;
484814b24e2bSVaishali Kulkarni 		if (ecore_rd(p_hwfn, p_ptt,
484914b24e2bSVaishali Kulkarni 			     NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
485014b24e2bSVaishali Kulkarni 			     (2 * i + 1) * sizeof(u32)) != high)
485114b24e2bSVaishali Kulkarni 			continue;
485214b24e2bSVaishali Kulkarni 
485314b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
485414b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 0);
485514b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
485614b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
485714b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
485814b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
485914b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
486014b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
486114b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
486214b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
486314b24e2bSVaishali Kulkarni 			 2 * i * sizeof(u32), 0);
486414b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
486514b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
486614b24e2bSVaishali Kulkarni 			 (2 * i + 1) * sizeof(u32), 0);
486714b24e2bSVaishali Kulkarni 		break;
486814b24e2bSVaishali Kulkarni 	}
486914b24e2bSVaishali Kulkarni 
487014b24e2bSVaishali Kulkarni 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
487114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
487214b24e2bSVaishali Kulkarni 
487314b24e2bSVaishali Kulkarni 	*p_entry_num = i;
487414b24e2bSVaishali Kulkarni 
487514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
487614b24e2bSVaishali Kulkarni }
487714b24e2bSVaishali Kulkarni 
487814b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_llh_remove_protocol_filter_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_llh_port_filter_type_t type,u32 high,u32 low,u32 * p_entry_num)487914b24e2bSVaishali Kulkarni ecore_llh_remove_protocol_filter_e5(struct ecore_hwfn *p_hwfn,
488014b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt,
488114b24e2bSVaishali Kulkarni 				    enum ecore_llh_port_filter_type_t type,
488214b24e2bSVaishali Kulkarni 				    u32 high, u32 low, u32 *p_entry_num)
488314b24e2bSVaishali Kulkarni {
488414b24e2bSVaishali Kulkarni 	ECORE_E5_MISSING_CODE;
488514b24e2bSVaishali Kulkarni 
488614b24e2bSVaishali Kulkarni 	return ECORE_NOTIMPL;
488714b24e2bSVaishali Kulkarni }
488814b24e2bSVaishali Kulkarni 
488914b24e2bSVaishali Kulkarni void
ecore_llh_remove_protocol_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 source_port_or_eth_type,u16 dest_port,enum ecore_llh_port_filter_type_t type)489014b24e2bSVaishali Kulkarni ecore_llh_remove_protocol_filter(struct ecore_hwfn *p_hwfn,
489114b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt,
489214b24e2bSVaishali Kulkarni 				 u16 source_port_or_eth_type,
489314b24e2bSVaishali Kulkarni 				 u16 dest_port,
489414b24e2bSVaishali Kulkarni 				 enum ecore_llh_port_filter_type_t type)
489514b24e2bSVaishali Kulkarni {
489614b24e2bSVaishali Kulkarni 	u32 high, low, entry_num;
489714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
489814b24e2bSVaishali Kulkarni 
489914b24e2bSVaishali Kulkarni 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
490014b24e2bSVaishali Kulkarni 		return;
490114b24e2bSVaishali Kulkarni 
490214b24e2bSVaishali Kulkarni 	high = 0;
490314b24e2bSVaishali Kulkarni 	low = 0;
490414b24e2bSVaishali Kulkarni 	switch (type) {
490514b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_ETHERTYPE:
490614b24e2bSVaishali Kulkarni 		high = source_port_or_eth_type;
490714b24e2bSVaishali Kulkarni 		break;
490814b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_PORT:
490914b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_PORT:
491014b24e2bSVaishali Kulkarni 		low = source_port_or_eth_type << 16;
491114b24e2bSVaishali Kulkarni 		break;
491214b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_DEST_PORT:
491314b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_DEST_PORT:
491414b24e2bSVaishali Kulkarni 		low = dest_port;
491514b24e2bSVaishali Kulkarni 		break;
491614b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
491714b24e2bSVaishali Kulkarni 	case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
491814b24e2bSVaishali Kulkarni 		low = (source_port_or_eth_type << 16) | dest_port;
491914b24e2bSVaishali Kulkarni 		break;
492014b24e2bSVaishali Kulkarni 	default:
492114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
492214b24e2bSVaishali Kulkarni 			  "Non valid LLH protocol filter type %d\n", type);
492314b24e2bSVaishali Kulkarni 		return;
492414b24e2bSVaishali Kulkarni 	}
492514b24e2bSVaishali Kulkarni 
492614b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
492714b24e2bSVaishali Kulkarni 		rc = ecore_llh_remove_protocol_filter_bb_ah(p_hwfn, p_ptt, type,
492814b24e2bSVaishali Kulkarni 							    high, low,
492914b24e2bSVaishali Kulkarni 							    &entry_num);
493014b24e2bSVaishali Kulkarni 	else /* E5 */
493114b24e2bSVaishali Kulkarni 		rc = ecore_llh_remove_protocol_filter_e5(p_hwfn, p_ptt, type,
493214b24e2bSVaishali Kulkarni 							 high, low, &entry_num);
493314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
493414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
493514b24e2bSVaishali Kulkarni 			  "Tried to remove a non-configured filter [type %d, source_port_or_eth_type 0x%x, dest_port 0x%x]\n",
493614b24e2bSVaishali Kulkarni 			  type, source_port_or_eth_type, dest_port);
493714b24e2bSVaishali Kulkarni 		return;
493814b24e2bSVaishali Kulkarni 	}
493914b24e2bSVaishali Kulkarni 
494014b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
494114b24e2bSVaishali Kulkarni 		   "Protocol filter [type %d, source_port_or_eth_type 0x%x, dest_port 0x%x] was removed from %d\n",
494214b24e2bSVaishali Kulkarni 		   type, source_port_or_eth_type, dest_port, entry_num);
494314b24e2bSVaishali Kulkarni }
494414b24e2bSVaishali Kulkarni 
ecore_llh_clear_all_filters_bb_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)494514b24e2bSVaishali Kulkarni static void ecore_llh_clear_all_filters_bb_ah(struct ecore_hwfn *p_hwfn,
494614b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt)
494714b24e2bSVaishali Kulkarni {
494814b24e2bSVaishali Kulkarni 	int i;
494914b24e2bSVaishali Kulkarni 
495014b24e2bSVaishali Kulkarni 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
495114b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
495214b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_EN_BB_K2  +
495314b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
495414b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
495514b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
495614b24e2bSVaishali Kulkarni 			 2 * i * sizeof(u32), 0);
495714b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
495814b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
495914b24e2bSVaishali Kulkarni 			 (2 * i + 1) * sizeof(u32), 0);
496014b24e2bSVaishali Kulkarni 	}
496114b24e2bSVaishali Kulkarni }
496214b24e2bSVaishali Kulkarni 
ecore_llh_clear_all_filters_e5(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)496314b24e2bSVaishali Kulkarni static void ecore_llh_clear_all_filters_e5(struct ecore_hwfn *p_hwfn,
496414b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt)
496514b24e2bSVaishali Kulkarni {
496614b24e2bSVaishali Kulkarni 	ECORE_E5_MISSING_CODE;
496714b24e2bSVaishali Kulkarni }
496814b24e2bSVaishali Kulkarni 
ecore_llh_clear_all_filters(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)496914b24e2bSVaishali Kulkarni void ecore_llh_clear_all_filters(struct ecore_hwfn *p_hwfn,
497014b24e2bSVaishali Kulkarni 			     struct ecore_ptt *p_ptt)
497114b24e2bSVaishali Kulkarni {
497214b24e2bSVaishali Kulkarni 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
497314b24e2bSVaishali Kulkarni 		return;
497414b24e2bSVaishali Kulkarni 
497514b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
497614b24e2bSVaishali Kulkarni 		ecore_llh_clear_all_filters_bb_ah(p_hwfn, p_ptt);
497714b24e2bSVaishali Kulkarni 	else /* E5 */
497814b24e2bSVaishali Kulkarni 		ecore_llh_clear_all_filters_e5(p_hwfn, p_ptt);
497914b24e2bSVaishali Kulkarni }
498014b24e2bSVaishali Kulkarni 
498114b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_llh_set_function_as_default(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)498214b24e2bSVaishali Kulkarni ecore_llh_set_function_as_default(struct ecore_hwfn *p_hwfn,
498314b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt)
498414b24e2bSVaishali Kulkarni {
498514b24e2bSVaishali Kulkarni 	if (IS_MF_DEFAULT(p_hwfn) && ECORE_IS_BB(p_hwfn->p_dev)) {
498614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
498714b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_TAGMAC_DEF_PF_VECTOR,
498814b24e2bSVaishali Kulkarni 			 1 << p_hwfn->abs_pf_id / 2);
498914b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt, PRS_REG_MSG_INFO, 0);
499014b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
499114b24e2bSVaishali Kulkarni 	} else {
499214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
499314b24e2bSVaishali Kulkarni 			  "This function can't be set as default\n");
499414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
499514b24e2bSVaishali Kulkarni 	}
499614b24e2bSVaishali Kulkarni }
499714b24e2bSVaishali Kulkarni 
ecore_set_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 hw_addr,void * p_eth_qzone,osal_size_t eth_qzone_size,u8 timeset)499814b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_set_coalesce(struct ecore_hwfn *p_hwfn,
499914b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt,
500014b24e2bSVaishali Kulkarni 					       u32 hw_addr, void *p_eth_qzone,
500114b24e2bSVaishali Kulkarni 					       osal_size_t eth_qzone_size,
500214b24e2bSVaishali Kulkarni 					       u8 timeset)
500314b24e2bSVaishali Kulkarni {
500414b24e2bSVaishali Kulkarni 	struct coalescing_timeset *p_coal_timeset;
500514b24e2bSVaishali Kulkarni 
500614b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->int_coalescing_mode != ECORE_COAL_MODE_ENABLE) {
500714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
500814b24e2bSVaishali Kulkarni 			  "Coalescing configuration not enabled\n");
500914b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
501014b24e2bSVaishali Kulkarni 	}
501114b24e2bSVaishali Kulkarni 
501214b24e2bSVaishali Kulkarni 	p_coal_timeset = p_eth_qzone;
501314b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_eth_qzone, 0, eth_qzone_size);
501414b24e2bSVaishali Kulkarni 	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_TIMESET, timeset);
501514b24e2bSVaishali Kulkarni 	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_VALID, 1);
501614b24e2bSVaishali Kulkarni 	ecore_memcpy_to(p_hwfn, p_ptt, hw_addr, p_eth_qzone, eth_qzone_size);
501714b24e2bSVaishali Kulkarni 
501814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
501914b24e2bSVaishali Kulkarni }
502014b24e2bSVaishali Kulkarni 
ecore_set_queue_coalesce(struct ecore_hwfn * p_hwfn,u16 rx_coal,u16 tx_coal,void * p_handle)502114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_set_queue_coalesce(struct ecore_hwfn *p_hwfn,
502214b24e2bSVaishali Kulkarni 					      u16 rx_coal, u16 tx_coal,
502314b24e2bSVaishali Kulkarni 					      void *p_handle)
502414b24e2bSVaishali Kulkarni {
502514b24e2bSVaishali Kulkarni 	struct ecore_queue_cid *p_cid = (struct ecore_queue_cid *)p_handle;
502614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
502714b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
502814b24e2bSVaishali Kulkarni 
502914b24e2bSVaishali Kulkarni 	/* TODO - Configuring a single queue's coalescing but
503014b24e2bSVaishali Kulkarni 	 * claiming all queues are abiding same configuration
503114b24e2bSVaishali Kulkarni 	 * for PF and VF both.
503214b24e2bSVaishali Kulkarni 	 */
503314b24e2bSVaishali Kulkarni 
503414b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
503514b24e2bSVaishali Kulkarni 		return ecore_vf_pf_set_coalesce(p_hwfn, rx_coal,
503614b24e2bSVaishali Kulkarni 						tx_coal, p_cid);
503714b24e2bSVaishali Kulkarni 
503814b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
503914b24e2bSVaishali Kulkarni 	if (!p_ptt)
504014b24e2bSVaishali Kulkarni 		return ECORE_AGAIN;
504114b24e2bSVaishali Kulkarni 
504214b24e2bSVaishali Kulkarni 	if (rx_coal) {
504314b24e2bSVaishali Kulkarni 		rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
504414b24e2bSVaishali Kulkarni 		if (rc)
504514b24e2bSVaishali Kulkarni 			goto out;
504614b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->rx_coalesce_usecs = rx_coal;
504714b24e2bSVaishali Kulkarni 	}
504814b24e2bSVaishali Kulkarni 
504914b24e2bSVaishali Kulkarni 	if (tx_coal) {
505014b24e2bSVaishali Kulkarni 		rc = ecore_set_txq_coalesce(p_hwfn, p_ptt, tx_coal, p_cid);
505114b24e2bSVaishali Kulkarni 		if (rc)
505214b24e2bSVaishali Kulkarni 			goto out;
505314b24e2bSVaishali Kulkarni 		p_hwfn->p_dev->tx_coalesce_usecs = tx_coal;
505414b24e2bSVaishali Kulkarni 	}
505514b24e2bSVaishali Kulkarni out:
505614b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
505714b24e2bSVaishali Kulkarni 
505814b24e2bSVaishali Kulkarni 	return rc;
505914b24e2bSVaishali Kulkarni }
506014b24e2bSVaishali Kulkarni 
ecore_set_rxq_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 coalesce,struct ecore_queue_cid * p_cid)506114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_set_rxq_coalesce(struct ecore_hwfn *p_hwfn,
506214b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
506314b24e2bSVaishali Kulkarni 					    u16 coalesce,
506414b24e2bSVaishali Kulkarni 					    struct ecore_queue_cid *p_cid)
506514b24e2bSVaishali Kulkarni {
506614b24e2bSVaishali Kulkarni 	struct ustorm_eth_queue_zone eth_qzone;
506714b24e2bSVaishali Kulkarni 	u8 timeset, timer_res;
506814b24e2bSVaishali Kulkarni 	u32 address;
506914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
507014b24e2bSVaishali Kulkarni 
507114b24e2bSVaishali Kulkarni 	/* Coalesce = (timeset << timer-resolution), timeset is 7bit wide */
507214b24e2bSVaishali Kulkarni 	if (coalesce <= 0x7F)
507314b24e2bSVaishali Kulkarni 		timer_res = 0;
507414b24e2bSVaishali Kulkarni 	else if (coalesce <= 0xFF)
507514b24e2bSVaishali Kulkarni 		timer_res = 1;
507614b24e2bSVaishali Kulkarni 	else if (coalesce <= 0x1FF)
507714b24e2bSVaishali Kulkarni 		timer_res = 2;
507814b24e2bSVaishali Kulkarni 	else {
507914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid coalesce value - %d\n", coalesce);
508014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
508114b24e2bSVaishali Kulkarni 	}
508214b24e2bSVaishali Kulkarni 	timeset = (u8)(coalesce >> timer_res);
508314b24e2bSVaishali Kulkarni 
508414b24e2bSVaishali Kulkarni 	rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
508514b24e2bSVaishali Kulkarni 				     p_cid->sb_igu_id, false);
508614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
508714b24e2bSVaishali Kulkarni 		goto out;
508814b24e2bSVaishali Kulkarni 
508914b24e2bSVaishali Kulkarni 	address = BAR0_MAP_REG_USDM_RAM +
509014b24e2bSVaishali Kulkarni 		  USTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id);
509114b24e2bSVaishali Kulkarni 
509214b24e2bSVaishali Kulkarni 	rc = ecore_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
509314b24e2bSVaishali Kulkarni 				sizeof(struct ustorm_eth_queue_zone), timeset);
509414b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
509514b24e2bSVaishali Kulkarni 		goto out;
509614b24e2bSVaishali Kulkarni 
509714b24e2bSVaishali Kulkarni out:
509814b24e2bSVaishali Kulkarni 	return rc;
509914b24e2bSVaishali Kulkarni }
510014b24e2bSVaishali Kulkarni 
ecore_set_txq_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 coalesce,struct ecore_queue_cid * p_cid)510114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_set_txq_coalesce(struct ecore_hwfn *p_hwfn,
510214b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
510314b24e2bSVaishali Kulkarni 					    u16 coalesce,
510414b24e2bSVaishali Kulkarni 					    struct ecore_queue_cid *p_cid)
510514b24e2bSVaishali Kulkarni {
510614b24e2bSVaishali Kulkarni 	struct xstorm_eth_queue_zone eth_qzone;
510714b24e2bSVaishali Kulkarni 	u8 timeset, timer_res;
510814b24e2bSVaishali Kulkarni 	u32 address;
510914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
511014b24e2bSVaishali Kulkarni 
511114b24e2bSVaishali Kulkarni 	/* Coalesce = (timeset << timer-resolution), timeset is 7bit wide */
511214b24e2bSVaishali Kulkarni 	if (coalesce <= 0x7F)
511314b24e2bSVaishali Kulkarni 		timer_res = 0;
511414b24e2bSVaishali Kulkarni 	else if (coalesce <= 0xFF)
511514b24e2bSVaishali Kulkarni 		timer_res = 1;
511614b24e2bSVaishali Kulkarni 	else if (coalesce <= 0x1FF)
511714b24e2bSVaishali Kulkarni 		timer_res = 2;
511814b24e2bSVaishali Kulkarni 	else {
511914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid coalesce value - %d\n", coalesce);
512014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
512114b24e2bSVaishali Kulkarni 	}
512214b24e2bSVaishali Kulkarni 	timeset = (u8)(coalesce >> timer_res);
512314b24e2bSVaishali Kulkarni 
512414b24e2bSVaishali Kulkarni 	rc = ecore_int_set_timer_res(p_hwfn, p_ptt, timer_res,
512514b24e2bSVaishali Kulkarni 				     p_cid->sb_igu_id, true);
512614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
512714b24e2bSVaishali Kulkarni 		goto out;
512814b24e2bSVaishali Kulkarni 
512914b24e2bSVaishali Kulkarni 	address = BAR0_MAP_REG_XSDM_RAM +
513014b24e2bSVaishali Kulkarni 		  XSTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id);
513114b24e2bSVaishali Kulkarni 
513214b24e2bSVaishali Kulkarni 	rc = ecore_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
513314b24e2bSVaishali Kulkarni 				sizeof(struct xstorm_eth_queue_zone), timeset);
513414b24e2bSVaishali Kulkarni out:
513514b24e2bSVaishali Kulkarni 	return rc;
513614b24e2bSVaishali Kulkarni }
513714b24e2bSVaishali Kulkarni 
513814b24e2bSVaishali Kulkarni /* Calculate final WFQ values for all vports and configure it.
513914b24e2bSVaishali Kulkarni  * After this configuration each vport must have
514014b24e2bSVaishali Kulkarni  * approx min rate =  vport_wfq * min_pf_rate / ECORE_WFQ_UNIT
514114b24e2bSVaishali Kulkarni  */
ecore_configure_wfq_for_all_vports(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 min_pf_rate)514214b24e2bSVaishali Kulkarni static void ecore_configure_wfq_for_all_vports(struct ecore_hwfn *p_hwfn,
514314b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt,
514414b24e2bSVaishali Kulkarni 					       u32 min_pf_rate)
514514b24e2bSVaishali Kulkarni {
514614b24e2bSVaishali Kulkarni 	struct init_qm_vport_params *vport_params;
514714b24e2bSVaishali Kulkarni 	int i;
514814b24e2bSVaishali Kulkarni 
514914b24e2bSVaishali Kulkarni 	vport_params = p_hwfn->qm_info.qm_vport_params;
515014b24e2bSVaishali Kulkarni 
515114b24e2bSVaishali Kulkarni 	for (i = 0; i < p_hwfn->qm_info.num_vports; i++) {
515214b24e2bSVaishali Kulkarni 		u32 wfq_speed = p_hwfn->qm_info.wfq_data[i].min_speed;
515314b24e2bSVaishali Kulkarni 
515414b24e2bSVaishali Kulkarni 		vport_params[i].vport_wfq = (wfq_speed * ECORE_WFQ_UNIT) /
515514b24e2bSVaishali Kulkarni 					    min_pf_rate;
515614b24e2bSVaishali Kulkarni 		ecore_init_vport_wfq(p_hwfn, p_ptt,
515714b24e2bSVaishali Kulkarni 				     vport_params[i].first_tx_pq_id,
515814b24e2bSVaishali Kulkarni 				     vport_params[i].vport_wfq);
515914b24e2bSVaishali Kulkarni 	}
516014b24e2bSVaishali Kulkarni }
516114b24e2bSVaishali Kulkarni 
516214b24e2bSVaishali Kulkarni static void
ecore_init_wfq_default_param(struct ecore_hwfn * p_hwfn,u32 min_pf_rate)516314b24e2bSVaishali Kulkarni ecore_init_wfq_default_param(struct ecore_hwfn *p_hwfn, u32 min_pf_rate)
516414b24e2bSVaishali Kulkarni 
516514b24e2bSVaishali Kulkarni {
516614b24e2bSVaishali Kulkarni 	int i;
516714b24e2bSVaishali Kulkarni 
516814b24e2bSVaishali Kulkarni 	for (i = 0; i < p_hwfn->qm_info.num_vports; i++)
516914b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.qm_vport_params[i].vport_wfq = 1;
517014b24e2bSVaishali Kulkarni }
517114b24e2bSVaishali Kulkarni 
ecore_disable_wfq_for_all_vports(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 min_pf_rate)517214b24e2bSVaishali Kulkarni static void ecore_disable_wfq_for_all_vports(struct ecore_hwfn *p_hwfn,
517314b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
517414b24e2bSVaishali Kulkarni 					     u32 min_pf_rate)
517514b24e2bSVaishali Kulkarni {
517614b24e2bSVaishali Kulkarni 	struct init_qm_vport_params *vport_params;
517714b24e2bSVaishali Kulkarni 	int i;
517814b24e2bSVaishali Kulkarni 
517914b24e2bSVaishali Kulkarni 	vport_params = p_hwfn->qm_info.qm_vport_params;
518014b24e2bSVaishali Kulkarni 
518114b24e2bSVaishali Kulkarni 	for (i = 0; i < p_hwfn->qm_info.num_vports; i++) {
518214b24e2bSVaishali Kulkarni 		ecore_init_wfq_default_param(p_hwfn, min_pf_rate);
518314b24e2bSVaishali Kulkarni 		ecore_init_vport_wfq(p_hwfn, p_ptt,
518414b24e2bSVaishali Kulkarni 				     vport_params[i].first_tx_pq_id,
518514b24e2bSVaishali Kulkarni 				     vport_params[i].vport_wfq);
518614b24e2bSVaishali Kulkarni 	}
518714b24e2bSVaishali Kulkarni }
518814b24e2bSVaishali Kulkarni 
518914b24e2bSVaishali Kulkarni /* This function performs several validations for WFQ
519014b24e2bSVaishali Kulkarni  * configuration and required min rate for a given vport
519114b24e2bSVaishali Kulkarni  * 1. req_rate must be greater than one percent of min_pf_rate.
519214b24e2bSVaishali Kulkarni  * 2. req_rate should not cause other vports [not configured for WFQ explicitly]
519314b24e2bSVaishali Kulkarni  *    rates to get less than one percent of min_pf_rate.
519414b24e2bSVaishali Kulkarni  * 3. total_req_min_rate [all vports min rate sum] shouldn't exceed min_pf_rate.
519514b24e2bSVaishali Kulkarni  */
ecore_init_wfq_param(struct ecore_hwfn * p_hwfn,u16 vport_id,u32 req_rate,u32 min_pf_rate)519614b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_init_wfq_param(struct ecore_hwfn *p_hwfn,
519714b24e2bSVaishali Kulkarni 						 u16 vport_id, u32 req_rate,
519814b24e2bSVaishali Kulkarni 						 u32 min_pf_rate)
519914b24e2bSVaishali Kulkarni {
520014b24e2bSVaishali Kulkarni 	u32 total_req_min_rate = 0, total_left_rate = 0, left_rate_per_vp = 0;
520114b24e2bSVaishali Kulkarni 	int non_requested_count = 0, req_count = 0, i, num_vports;
520214b24e2bSVaishali Kulkarni 
520314b24e2bSVaishali Kulkarni 	num_vports = p_hwfn->qm_info.num_vports;
520414b24e2bSVaishali Kulkarni 
520514b24e2bSVaishali Kulkarni 	/* Accounting for the vports which are configured for WFQ explicitly */
520614b24e2bSVaishali Kulkarni 	for (i = 0; i < num_vports; i++) {
520714b24e2bSVaishali Kulkarni 		u32 tmp_speed;
520814b24e2bSVaishali Kulkarni 
520914b24e2bSVaishali Kulkarni 		if ((i != vport_id) && p_hwfn->qm_info.wfq_data[i].configured) {
521014b24e2bSVaishali Kulkarni 			req_count++;
521114b24e2bSVaishali Kulkarni 			tmp_speed = p_hwfn->qm_info.wfq_data[i].min_speed;
521214b24e2bSVaishali Kulkarni 			total_req_min_rate += tmp_speed;
521314b24e2bSVaishali Kulkarni 		}
521414b24e2bSVaishali Kulkarni 	}
521514b24e2bSVaishali Kulkarni 
521614b24e2bSVaishali Kulkarni 	/* Include current vport data as well */
521714b24e2bSVaishali Kulkarni 	req_count++;
521814b24e2bSVaishali Kulkarni 	total_req_min_rate += req_rate;
521914b24e2bSVaishali Kulkarni 	non_requested_count = num_vports - req_count;
522014b24e2bSVaishali Kulkarni 
522114b24e2bSVaishali Kulkarni 	/* validate possible error cases */
522214b24e2bSVaishali Kulkarni 	if (req_rate > min_pf_rate) {
522314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
522414b24e2bSVaishali Kulkarni 			   "Vport [%d] - Requested rate[%d Mbps] is greater than configured PF min rate[%d Mbps]\n",
522514b24e2bSVaishali Kulkarni 			   vport_id, req_rate, min_pf_rate);
522614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
522714b24e2bSVaishali Kulkarni 	}
522814b24e2bSVaishali Kulkarni 
522914b24e2bSVaishali Kulkarni 	if (req_rate < min_pf_rate / ECORE_WFQ_UNIT) {
523014b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
523114b24e2bSVaishali Kulkarni 			   "Vport [%d] - Requested rate[%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n",
523214b24e2bSVaishali Kulkarni 			   vport_id, req_rate, min_pf_rate);
523314b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
523414b24e2bSVaishali Kulkarni 	}
523514b24e2bSVaishali Kulkarni 
523614b24e2bSVaishali Kulkarni 	/* TBD - for number of vports greater than 100 */
523714b24e2bSVaishali Kulkarni 	if (num_vports > ECORE_WFQ_UNIT) {
523814b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
523914b24e2bSVaishali Kulkarni 			   "Number of vports is greater than %d\n",
524014b24e2bSVaishali Kulkarni 			   ECORE_WFQ_UNIT);
524114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
524214b24e2bSVaishali Kulkarni 	}
524314b24e2bSVaishali Kulkarni 
524414b24e2bSVaishali Kulkarni 	if (total_req_min_rate > min_pf_rate) {
524514b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
524614b24e2bSVaishali Kulkarni 			   "Total requested min rate for all vports[%d Mbps] is greater than configured PF min rate[%d Mbps]\n",
524714b24e2bSVaishali Kulkarni 			   total_req_min_rate, min_pf_rate);
524814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
524914b24e2bSVaishali Kulkarni 	}
525014b24e2bSVaishali Kulkarni 
525114b24e2bSVaishali Kulkarni 	/* Data left for non requested vports */
525214b24e2bSVaishali Kulkarni 	total_left_rate = min_pf_rate - total_req_min_rate;
525314b24e2bSVaishali Kulkarni 	left_rate_per_vp = total_left_rate / non_requested_count;
525414b24e2bSVaishali Kulkarni 
525514b24e2bSVaishali Kulkarni 	/* validate if non requested get < 1% of min bw */
525614b24e2bSVaishali Kulkarni 	if (left_rate_per_vp < min_pf_rate / ECORE_WFQ_UNIT) {
525714b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
525814b24e2bSVaishali Kulkarni 			   "Non WFQ configured vports rate [%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n",
525914b24e2bSVaishali Kulkarni 			   left_rate_per_vp, min_pf_rate);
526014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
526114b24e2bSVaishali Kulkarni 	}
526214b24e2bSVaishali Kulkarni 
526314b24e2bSVaishali Kulkarni 	/* now req_rate for given vport passes all scenarios.
526414b24e2bSVaishali Kulkarni 	 * assign final wfq rates to all vports.
526514b24e2bSVaishali Kulkarni 	 */
526614b24e2bSVaishali Kulkarni 	p_hwfn->qm_info.wfq_data[vport_id].min_speed = req_rate;
526714b24e2bSVaishali Kulkarni 	p_hwfn->qm_info.wfq_data[vport_id].configured = true;
526814b24e2bSVaishali Kulkarni 
526914b24e2bSVaishali Kulkarni 	for (i = 0; i < num_vports; i++) {
527014b24e2bSVaishali Kulkarni 		if (p_hwfn->qm_info.wfq_data[i].configured)
527114b24e2bSVaishali Kulkarni 			continue;
527214b24e2bSVaishali Kulkarni 
527314b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.wfq_data[i].min_speed = left_rate_per_vp;
527414b24e2bSVaishali Kulkarni 	}
527514b24e2bSVaishali Kulkarni 
527614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
527714b24e2bSVaishali Kulkarni }
527814b24e2bSVaishali Kulkarni 
__ecore_configure_vport_wfq(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 vp_id,u32 rate)527914b24e2bSVaishali Kulkarni static int __ecore_configure_vport_wfq(struct ecore_hwfn *p_hwfn,
528014b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
528114b24e2bSVaishali Kulkarni 				       u16 vp_id, u32 rate)
528214b24e2bSVaishali Kulkarni {
528314b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_state *p_link;
528414b24e2bSVaishali Kulkarni 	int rc = ECORE_SUCCESS;
528514b24e2bSVaishali Kulkarni 
528614b24e2bSVaishali Kulkarni 	p_link = &p_hwfn->p_dev->hwfns[0].mcp_info->link_output;
528714b24e2bSVaishali Kulkarni 
528814b24e2bSVaishali Kulkarni 	if (!p_link->min_pf_rate) {
528914b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.wfq_data[vp_id].min_speed = rate;
529014b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.wfq_data[vp_id].configured = true;
529114b24e2bSVaishali Kulkarni 		return rc;
529214b24e2bSVaishali Kulkarni 	}
529314b24e2bSVaishali Kulkarni 
529414b24e2bSVaishali Kulkarni 	rc = ecore_init_wfq_param(p_hwfn, vp_id, rate, p_link->min_pf_rate);
529514b24e2bSVaishali Kulkarni 
529614b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS)
529714b24e2bSVaishali Kulkarni 		ecore_configure_wfq_for_all_vports(p_hwfn, p_ptt,
529814b24e2bSVaishali Kulkarni 						   p_link->min_pf_rate);
529914b24e2bSVaishali Kulkarni 	else
530014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
530114b24e2bSVaishali Kulkarni 			  "Validation failed while configuring min rate\n");
530214b24e2bSVaishali Kulkarni 
530314b24e2bSVaishali Kulkarni 	return rc;
530414b24e2bSVaishali Kulkarni }
530514b24e2bSVaishali Kulkarni 
__ecore_configure_vp_wfq_on_link_change(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 min_pf_rate)530614b24e2bSVaishali Kulkarni static int __ecore_configure_vp_wfq_on_link_change(struct ecore_hwfn *p_hwfn,
530714b24e2bSVaishali Kulkarni 						   struct ecore_ptt *p_ptt,
530814b24e2bSVaishali Kulkarni 						   u32 min_pf_rate)
530914b24e2bSVaishali Kulkarni {
531014b24e2bSVaishali Kulkarni 	bool use_wfq = false;
531114b24e2bSVaishali Kulkarni 	int rc = ECORE_SUCCESS;
531214b24e2bSVaishali Kulkarni 	u16 i;
531314b24e2bSVaishali Kulkarni 
531414b24e2bSVaishali Kulkarni 	/* Validate all pre configured vports for wfq */
531514b24e2bSVaishali Kulkarni 	for (i = 0; i < p_hwfn->qm_info.num_vports; i++) {
531614b24e2bSVaishali Kulkarni 		u32 rate;
531714b24e2bSVaishali Kulkarni 
531814b24e2bSVaishali Kulkarni 		if (!p_hwfn->qm_info.wfq_data[i].configured)
531914b24e2bSVaishali Kulkarni 			continue;
532014b24e2bSVaishali Kulkarni 
532114b24e2bSVaishali Kulkarni 		rate = p_hwfn->qm_info.wfq_data[i].min_speed;
532214b24e2bSVaishali Kulkarni 		use_wfq = true;
532314b24e2bSVaishali Kulkarni 
532414b24e2bSVaishali Kulkarni 		rc = ecore_init_wfq_param(p_hwfn, i, rate, min_pf_rate);
532514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
532614b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
532714b24e2bSVaishali Kulkarni 				  "WFQ validation failed while configuring min rate\n");
532814b24e2bSVaishali Kulkarni 			break;
532914b24e2bSVaishali Kulkarni 		}
533014b24e2bSVaishali Kulkarni 	}
533114b24e2bSVaishali Kulkarni 
533214b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS && use_wfq)
533314b24e2bSVaishali Kulkarni 		ecore_configure_wfq_for_all_vports(p_hwfn, p_ptt, min_pf_rate);
533414b24e2bSVaishali Kulkarni 	else
533514b24e2bSVaishali Kulkarni 		ecore_disable_wfq_for_all_vports(p_hwfn, p_ptt, min_pf_rate);
533614b24e2bSVaishali Kulkarni 
533714b24e2bSVaishali Kulkarni 	return rc;
533814b24e2bSVaishali Kulkarni }
533914b24e2bSVaishali Kulkarni 
534014b24e2bSVaishali Kulkarni /* Main API for ecore clients to configure vport min rate.
534114b24e2bSVaishali Kulkarni  * vp_id - vport id in PF Range[0 - (total_num_vports_per_pf - 1)]
534214b24e2bSVaishali Kulkarni  * rate - Speed in Mbps needs to be assigned to a given vport.
534314b24e2bSVaishali Kulkarni  */
ecore_configure_vport_wfq(struct ecore_dev * p_dev,u16 vp_id,u32 rate)534414b24e2bSVaishali Kulkarni int ecore_configure_vport_wfq(struct ecore_dev *p_dev, u16 vp_id, u32 rate)
534514b24e2bSVaishali Kulkarni {
534614b24e2bSVaishali Kulkarni 	int i, rc = ECORE_INVAL;
534714b24e2bSVaishali Kulkarni 
534814b24e2bSVaishali Kulkarni 	/* TBD - for multiple hardware functions - that is 100 gig */
534914b24e2bSVaishali Kulkarni 	if (p_dev->num_hwfns > 1) {
535014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false,
535114b24e2bSVaishali Kulkarni 			  "WFQ configuration is not supported for this device\n");
535214b24e2bSVaishali Kulkarni 		return rc;
535314b24e2bSVaishali Kulkarni 	}
535414b24e2bSVaishali Kulkarni 
535514b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
535614b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
535714b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt;
535814b24e2bSVaishali Kulkarni 
535914b24e2bSVaishali Kulkarni 		p_ptt = ecore_ptt_acquire(p_hwfn);
536014b24e2bSVaishali Kulkarni 		if (!p_ptt)
536114b24e2bSVaishali Kulkarni 			return ECORE_TIMEOUT;
536214b24e2bSVaishali Kulkarni 
536314b24e2bSVaishali Kulkarni 		rc = __ecore_configure_vport_wfq(p_hwfn, p_ptt, vp_id, rate);
536414b24e2bSVaishali Kulkarni 
536514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
536614b24e2bSVaishali Kulkarni 			ecore_ptt_release(p_hwfn, p_ptt);
536714b24e2bSVaishali Kulkarni 			return rc;
536814b24e2bSVaishali Kulkarni 		}
536914b24e2bSVaishali Kulkarni 
537014b24e2bSVaishali Kulkarni 		ecore_ptt_release(p_hwfn, p_ptt);
537114b24e2bSVaishali Kulkarni 	}
537214b24e2bSVaishali Kulkarni 
537314b24e2bSVaishali Kulkarni 	return rc;
537414b24e2bSVaishali Kulkarni }
537514b24e2bSVaishali Kulkarni 
537614b24e2bSVaishali Kulkarni /* API to configure WFQ from mcp link change */
ecore_configure_vp_wfq_on_link_change(struct ecore_dev * p_dev,struct ecore_ptt * p_ptt,u32 min_pf_rate)537714b24e2bSVaishali Kulkarni void ecore_configure_vp_wfq_on_link_change(struct ecore_dev *p_dev,
537814b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
537914b24e2bSVaishali Kulkarni 					   u32 min_pf_rate)
538014b24e2bSVaishali Kulkarni {
538114b24e2bSVaishali Kulkarni 	int i;
538214b24e2bSVaishali Kulkarni 
538314b24e2bSVaishali Kulkarni 	/* TBD - for multiple hardware functions - that is 100 gig */
538414b24e2bSVaishali Kulkarni 	if (p_dev->num_hwfns > 1) {
538514b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_dev, ECORE_MSG_LINK,
538614b24e2bSVaishali Kulkarni 			   "WFQ configuration is not supported for this device\n");
538714b24e2bSVaishali Kulkarni 		return;
538814b24e2bSVaishali Kulkarni 	}
538914b24e2bSVaishali Kulkarni 
539014b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
539114b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
539214b24e2bSVaishali Kulkarni 
539314b24e2bSVaishali Kulkarni 		__ecore_configure_vp_wfq_on_link_change(p_hwfn, p_ptt,
539414b24e2bSVaishali Kulkarni 							min_pf_rate);
539514b24e2bSVaishali Kulkarni 	}
539614b24e2bSVaishali Kulkarni }
539714b24e2bSVaishali Kulkarni 
__ecore_configure_pf_max_bandwidth(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_link_state * p_link,u8 max_bw)539814b24e2bSVaishali Kulkarni int __ecore_configure_pf_max_bandwidth(struct ecore_hwfn *p_hwfn,
539914b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
540014b24e2bSVaishali Kulkarni 				       struct ecore_mcp_link_state *p_link,
540114b24e2bSVaishali Kulkarni 				       u8 max_bw)
540214b24e2bSVaishali Kulkarni {
540314b24e2bSVaishali Kulkarni 	int rc = ECORE_SUCCESS;
540414b24e2bSVaishali Kulkarni 
540514b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->func_info.bandwidth_max = max_bw;
540614b24e2bSVaishali Kulkarni 
540714b24e2bSVaishali Kulkarni 	if (!p_link->line_speed && (max_bw != 100))
540814b24e2bSVaishali Kulkarni 		return rc;
540914b24e2bSVaishali Kulkarni 
541014b24e2bSVaishali Kulkarni 	p_link->speed = (p_link->line_speed * max_bw) / 100;
541114b24e2bSVaishali Kulkarni 	p_hwfn->qm_info.pf_rl = p_link->speed;
541214b24e2bSVaishali Kulkarni 
541314b24e2bSVaishali Kulkarni 	/* Since the limiter also affects Tx-switched traffic, we don't want it
541414b24e2bSVaishali Kulkarni 	 * to limit such traffic in case there's no actual limit.
541514b24e2bSVaishali Kulkarni 	 * In that case, set limit to imaginary high boundary.
541614b24e2bSVaishali Kulkarni 	 */
541714b24e2bSVaishali Kulkarni 	if (max_bw == 100)
541814b24e2bSVaishali Kulkarni 		p_hwfn->qm_info.pf_rl = 100000;
541914b24e2bSVaishali Kulkarni 
542014b24e2bSVaishali Kulkarni 	rc = ecore_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
542114b24e2bSVaishali Kulkarni 			      p_hwfn->qm_info.pf_rl);
542214b24e2bSVaishali Kulkarni 
542314b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
542414b24e2bSVaishali Kulkarni 		   "Configured MAX bandwidth to be %08x Mb/sec\n",
542514b24e2bSVaishali Kulkarni 		   p_link->speed);
542614b24e2bSVaishali Kulkarni 
542714b24e2bSVaishali Kulkarni 	return rc;
542814b24e2bSVaishali Kulkarni }
542914b24e2bSVaishali Kulkarni 
543014b24e2bSVaishali Kulkarni /* Main API to configure PF max bandwidth where bw range is [1 - 100] */
ecore_configure_pf_max_bandwidth(struct ecore_dev * p_dev,u8 max_bw)543114b24e2bSVaishali Kulkarni int ecore_configure_pf_max_bandwidth(struct ecore_dev *p_dev, u8 max_bw)
543214b24e2bSVaishali Kulkarni {
543314b24e2bSVaishali Kulkarni 	int i, rc = ECORE_INVAL;
543414b24e2bSVaishali Kulkarni 
543514b24e2bSVaishali Kulkarni 	if (max_bw < 1 || max_bw > 100) {
543614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "PF max bw valid range is [1-100]\n");
543714b24e2bSVaishali Kulkarni 		return rc;
543814b24e2bSVaishali Kulkarni 	}
543914b24e2bSVaishali Kulkarni 
544014b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
544114b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
544214b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_lead = ECORE_LEADING_HWFN(p_dev);
544314b24e2bSVaishali Kulkarni 		struct ecore_mcp_link_state *p_link;
544414b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt;
544514b24e2bSVaishali Kulkarni 
544614b24e2bSVaishali Kulkarni 		p_link = &p_lead->mcp_info->link_output;
544714b24e2bSVaishali Kulkarni 
544814b24e2bSVaishali Kulkarni 		p_ptt = ecore_ptt_acquire(p_hwfn);
544914b24e2bSVaishali Kulkarni 		if (!p_ptt)
545014b24e2bSVaishali Kulkarni 			return ECORE_TIMEOUT;
545114b24e2bSVaishali Kulkarni 
545214b24e2bSVaishali Kulkarni 		rc = __ecore_configure_pf_max_bandwidth(p_hwfn, p_ptt,
545314b24e2bSVaishali Kulkarni 							p_link, max_bw);
545414b24e2bSVaishali Kulkarni 
545514b24e2bSVaishali Kulkarni 		ecore_ptt_release(p_hwfn, p_ptt);
545614b24e2bSVaishali Kulkarni 
545714b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
545814b24e2bSVaishali Kulkarni 			break;
545914b24e2bSVaishali Kulkarni 	}
546014b24e2bSVaishali Kulkarni 
546114b24e2bSVaishali Kulkarni 	return rc;
546214b24e2bSVaishali Kulkarni }
546314b24e2bSVaishali Kulkarni 
__ecore_configure_pf_min_bandwidth(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_link_state * p_link,u8 min_bw)546414b24e2bSVaishali Kulkarni int __ecore_configure_pf_min_bandwidth(struct ecore_hwfn *p_hwfn,
546514b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
546614b24e2bSVaishali Kulkarni 				       struct ecore_mcp_link_state *p_link,
546714b24e2bSVaishali Kulkarni 				       u8 min_bw)
546814b24e2bSVaishali Kulkarni {
546914b24e2bSVaishali Kulkarni 	int rc = ECORE_SUCCESS;
547014b24e2bSVaishali Kulkarni 
547114b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->func_info.bandwidth_min = min_bw;
547214b24e2bSVaishali Kulkarni 	p_hwfn->qm_info.pf_wfq = min_bw;
547314b24e2bSVaishali Kulkarni 
547414b24e2bSVaishali Kulkarni 	if (!p_link->line_speed)
547514b24e2bSVaishali Kulkarni 		return rc;
547614b24e2bSVaishali Kulkarni 
547714b24e2bSVaishali Kulkarni 	p_link->min_pf_rate = (p_link->line_speed * min_bw) / 100;
547814b24e2bSVaishali Kulkarni 
547914b24e2bSVaishali Kulkarni 	rc = ecore_init_pf_wfq(p_hwfn, p_ptt, p_hwfn->rel_pf_id, min_bw);
548014b24e2bSVaishali Kulkarni 
548114b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
548214b24e2bSVaishali Kulkarni 		   "Configured MIN bandwidth to be %d Mb/sec\n",
548314b24e2bSVaishali Kulkarni 		   p_link->min_pf_rate);
548414b24e2bSVaishali Kulkarni 
548514b24e2bSVaishali Kulkarni 	return rc;
548614b24e2bSVaishali Kulkarni }
548714b24e2bSVaishali Kulkarni 
548814b24e2bSVaishali Kulkarni /* Main API to configure PF min bandwidth where bw range is [1-100] */
ecore_configure_pf_min_bandwidth(struct ecore_dev * p_dev,u8 min_bw)548914b24e2bSVaishali Kulkarni int ecore_configure_pf_min_bandwidth(struct ecore_dev *p_dev, u8 min_bw)
549014b24e2bSVaishali Kulkarni {
549114b24e2bSVaishali Kulkarni 	int i, rc = ECORE_INVAL;
549214b24e2bSVaishali Kulkarni 
549314b24e2bSVaishali Kulkarni 	if (min_bw < 1 || min_bw > 100) {
549414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "PF min bw valid range is [1-100]\n");
549514b24e2bSVaishali Kulkarni 		return rc;
549614b24e2bSVaishali Kulkarni 	}
549714b24e2bSVaishali Kulkarni 
549814b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
549914b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
550014b24e2bSVaishali Kulkarni 		struct ecore_hwfn *p_lead = ECORE_LEADING_HWFN(p_dev);
550114b24e2bSVaishali Kulkarni 		struct ecore_mcp_link_state *p_link;
550214b24e2bSVaishali Kulkarni 		struct ecore_ptt *p_ptt;
550314b24e2bSVaishali Kulkarni 
550414b24e2bSVaishali Kulkarni 		p_link = &p_lead->mcp_info->link_output;
550514b24e2bSVaishali Kulkarni 
550614b24e2bSVaishali Kulkarni 		p_ptt = ecore_ptt_acquire(p_hwfn);
550714b24e2bSVaishali Kulkarni 		if (!p_ptt)
550814b24e2bSVaishali Kulkarni 			return ECORE_TIMEOUT;
550914b24e2bSVaishali Kulkarni 
551014b24e2bSVaishali Kulkarni 		rc = __ecore_configure_pf_min_bandwidth(p_hwfn, p_ptt,
551114b24e2bSVaishali Kulkarni 							p_link, min_bw);
551214b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
551314b24e2bSVaishali Kulkarni 			ecore_ptt_release(p_hwfn, p_ptt);
551414b24e2bSVaishali Kulkarni 			return rc;
551514b24e2bSVaishali Kulkarni 		}
551614b24e2bSVaishali Kulkarni 
551714b24e2bSVaishali Kulkarni 		if (p_link->min_pf_rate) {
551814b24e2bSVaishali Kulkarni 			u32 min_rate = p_link->min_pf_rate;
551914b24e2bSVaishali Kulkarni 
552014b24e2bSVaishali Kulkarni 			rc = __ecore_configure_vp_wfq_on_link_change(p_hwfn,
552114b24e2bSVaishali Kulkarni 								     p_ptt,
552214b24e2bSVaishali Kulkarni 								     min_rate);
552314b24e2bSVaishali Kulkarni 		}
552414b24e2bSVaishali Kulkarni 
552514b24e2bSVaishali Kulkarni 		ecore_ptt_release(p_hwfn, p_ptt);
552614b24e2bSVaishali Kulkarni 	}
552714b24e2bSVaishali Kulkarni 
552814b24e2bSVaishali Kulkarni 	return rc;
552914b24e2bSVaishali Kulkarni }
553014b24e2bSVaishali Kulkarni 
ecore_clean_wfq_db(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)553114b24e2bSVaishali Kulkarni void ecore_clean_wfq_db(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
553214b24e2bSVaishali Kulkarni {
553314b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_state *p_link;
553414b24e2bSVaishali Kulkarni 
553514b24e2bSVaishali Kulkarni 	p_link = &p_hwfn->mcp_info->link_output;
553614b24e2bSVaishali Kulkarni 
553714b24e2bSVaishali Kulkarni 	if (p_link->min_pf_rate)
553814b24e2bSVaishali Kulkarni 		ecore_disable_wfq_for_all_vports(p_hwfn, p_ptt,
553914b24e2bSVaishali Kulkarni 						 p_link->min_pf_rate);
554014b24e2bSVaishali Kulkarni 
554114b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_hwfn->qm_info.wfq_data, 0,
554214b24e2bSVaishali Kulkarni 		    sizeof(*p_hwfn->qm_info.wfq_data) *
554314b24e2bSVaishali Kulkarni 				p_hwfn->qm_info.num_vports);
554414b24e2bSVaishali Kulkarni }
554514b24e2bSVaishali Kulkarni 
ecore_device_num_engines(struct ecore_dev * p_dev)554614b24e2bSVaishali Kulkarni int ecore_device_num_engines(struct ecore_dev *p_dev)
554714b24e2bSVaishali Kulkarni {
554814b24e2bSVaishali Kulkarni 	return ECORE_IS_BB(p_dev) ? 2 : 1;
554914b24e2bSVaishali Kulkarni }
555014b24e2bSVaishali Kulkarni 
ecore_device_num_ports(struct ecore_dev * p_dev)555114b24e2bSVaishali Kulkarni int ecore_device_num_ports(struct ecore_dev *p_dev)
555214b24e2bSVaishali Kulkarni {
555314b24e2bSVaishali Kulkarni 	/* in CMT always only one port */
555414b24e2bSVaishali Kulkarni 	if (p_dev->num_hwfns > 1)
555514b24e2bSVaishali Kulkarni 		return 1;
555614b24e2bSVaishali Kulkarni 
555714b24e2bSVaishali Kulkarni 	return p_dev->num_ports_in_engine * ecore_device_num_engines(p_dev);
555814b24e2bSVaishali Kulkarni }
555914b24e2bSVaishali Kulkarni 
ecore_device_get_port_id(struct ecore_dev * p_dev)556014b24e2bSVaishali Kulkarni int ecore_device_get_port_id(struct ecore_dev *p_dev)
556114b24e2bSVaishali Kulkarni {
556214b24e2bSVaishali Kulkarni 	return (ECORE_LEADING_HWFN(p_dev)->abs_pf_id) %
556314b24e2bSVaishali Kulkarni 		ecore_device_num_ports(p_dev);
556414b24e2bSVaishali Kulkarni }
556514b24e2bSVaishali Kulkarni 
ecore_set_fw_mac_addr(__le16 * fw_msb,__le16 * fw_mid,__le16 * fw_lsb,u8 * mac)556614b24e2bSVaishali Kulkarni void ecore_set_fw_mac_addr(__le16 *fw_msb,
556714b24e2bSVaishali Kulkarni 			  __le16 *fw_mid,
556814b24e2bSVaishali Kulkarni 			  __le16 *fw_lsb,
556914b24e2bSVaishali Kulkarni 			  u8 *mac)
557014b24e2bSVaishali Kulkarni {
557114b24e2bSVaishali Kulkarni 	((u8 *)fw_msb)[0] = mac[1];
557214b24e2bSVaishali Kulkarni 	((u8 *)fw_msb)[1] = mac[0];
557314b24e2bSVaishali Kulkarni 	((u8 *)fw_mid)[0] = mac[3];
557414b24e2bSVaishali Kulkarni 	((u8 *)fw_mid)[1] = mac[2];
557514b24e2bSVaishali Kulkarni 	((u8 *)fw_lsb)[0] = mac[5];
557614b24e2bSVaishali Kulkarni 	((u8 *)fw_lsb)[1] = mac[4];
557714b24e2bSVaishali Kulkarni }
5578