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 
36b68ddc76SJohn Levon /*
37b68ddc76SJohn Levon  * Copyright 2018 Joyent, Inc.
38b68ddc76SJohn Levon  */
39b68ddc76SJohn Levon 
4014b24e2bSVaishali Kulkarni #include "bcm_osal.h"
4114b24e2bSVaishali Kulkarni #include "ecore.h"
4214b24e2bSVaishali Kulkarni #include "ecore_status.h"
4314b24e2bSVaishali Kulkarni #include "nvm_map.h"
4414b24e2bSVaishali Kulkarni #include "nvm_cfg.h"
4514b24e2bSVaishali Kulkarni #include "ecore_mcp.h"
4614b24e2bSVaishali Kulkarni #include "mcp_public.h"
4714b24e2bSVaishali Kulkarni #include "reg_addr.h"
4814b24e2bSVaishali Kulkarni #include "ecore_hw.h"
4914b24e2bSVaishali Kulkarni #include "ecore_init_fw_funcs.h"
5014b24e2bSVaishali Kulkarni #include "ecore_sriov.h"
5114b24e2bSVaishali Kulkarni #include "ecore_vf.h"
5214b24e2bSVaishali Kulkarni #include "ecore_iov_api.h"
5314b24e2bSVaishali Kulkarni #include "ecore_gtt_reg_addr.h"
5414b24e2bSVaishali Kulkarni #include "ecore_iro.h"
5514b24e2bSVaishali Kulkarni #include "ecore_dcbx.h"
5614b24e2bSVaishali Kulkarni #include "ecore_sp_commands.h"
5714b24e2bSVaishali Kulkarni 
5814b24e2bSVaishali Kulkarni #define CHIP_MCP_RESP_ITER_US 10
5914b24e2bSVaishali Kulkarni #define EMUL_MCP_RESP_ITER_US 1000 * 1000
6014b24e2bSVaishali Kulkarni 
6114b24e2bSVaishali Kulkarni #define ECORE_DRV_MB_MAX_RETRIES	(500 * 1000) /* Account for 5 sec */
6214b24e2bSVaishali Kulkarni #define ECORE_MCP_RESET_RETRIES		(50 * 1000) /* Account for 500 msec */
6314b24e2bSVaishali Kulkarni 
6414b24e2bSVaishali Kulkarni #define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \
6514b24e2bSVaishali Kulkarni 	ecore_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \
6614b24e2bSVaishali Kulkarni 		 _val)
6714b24e2bSVaishali Kulkarni 
6814b24e2bSVaishali Kulkarni #define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \
6914b24e2bSVaishali Kulkarni 	ecore_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset))
7014b24e2bSVaishali Kulkarni 
7114b24e2bSVaishali Kulkarni #define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \
7214b24e2bSVaishali Kulkarni 	DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \
73*04443fdeSToomas Soome 		     offsetof(struct public_drv_mb, _field), _val)
7414b24e2bSVaishali Kulkarni 
7514b24e2bSVaishali Kulkarni #define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \
7614b24e2bSVaishali Kulkarni 	DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \
77*04443fdeSToomas Soome 		     offsetof(struct public_drv_mb, _field))
7814b24e2bSVaishali Kulkarni 
7914b24e2bSVaishali Kulkarni #define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \
8014b24e2bSVaishali Kulkarni 	DRV_ID_PDA_COMP_VER_SHIFT)
8114b24e2bSVaishali Kulkarni 
8214b24e2bSVaishali Kulkarni #define MCP_BYTES_PER_MBIT_SHIFT 17
8314b24e2bSVaishali Kulkarni 
8414b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
8514b24e2bSVaishali Kulkarni static int loaded;
8614b24e2bSVaishali Kulkarni static int loaded_port[MAX_NUM_PORTS] = { 0 };
8714b24e2bSVaishali Kulkarni #endif
8814b24e2bSVaishali Kulkarni 
ecore_mcp_is_init(struct ecore_hwfn * p_hwfn)8914b24e2bSVaishali Kulkarni bool ecore_mcp_is_init(struct ecore_hwfn *p_hwfn)
9014b24e2bSVaishali Kulkarni {
9114b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base)
9214b24e2bSVaishali Kulkarni 		return false;
9314b24e2bSVaishali Kulkarni 	return true;
9414b24e2bSVaishali Kulkarni }
9514b24e2bSVaishali Kulkarni 
ecore_mcp_cmd_port_init(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)9614b24e2bSVaishali Kulkarni void ecore_mcp_cmd_port_init(struct ecore_hwfn *p_hwfn,
9714b24e2bSVaishali Kulkarni 			     struct ecore_ptt *p_ptt)
9814b24e2bSVaishali Kulkarni {
9914b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
10014b24e2bSVaishali Kulkarni 					PUBLIC_PORT);
10114b24e2bSVaishali Kulkarni 	u32 mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt, addr);
10214b24e2bSVaishali Kulkarni 
10314b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize,
10414b24e2bSVaishali Kulkarni 						   MFW_PORT(p_hwfn));
10514b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
10614b24e2bSVaishali Kulkarni 		   "port_addr = 0x%x, port_id 0x%02x\n",
10714b24e2bSVaishali Kulkarni 		   p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn));
10814b24e2bSVaishali Kulkarni }
10914b24e2bSVaishali Kulkarni 
ecore_mcp_read_mb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)11014b24e2bSVaishali Kulkarni void ecore_mcp_read_mb(struct ecore_hwfn *p_hwfn,
11114b24e2bSVaishali Kulkarni 		       struct ecore_ptt *p_ptt)
11214b24e2bSVaishali Kulkarni {
11314b24e2bSVaishali Kulkarni 	u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length);
11414b24e2bSVaishali Kulkarni 	OSAL_BE32 tmp;
11514b24e2bSVaishali Kulkarni 	u32 i;
11614b24e2bSVaishali Kulkarni 
11714b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
11814b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
11914b24e2bSVaishali Kulkarni 		return;
12014b24e2bSVaishali Kulkarni #endif
12114b24e2bSVaishali Kulkarni 
12214b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info->public_base)
12314b24e2bSVaishali Kulkarni 		return;
12414b24e2bSVaishali Kulkarni 
12514b24e2bSVaishali Kulkarni 	for (i = 0; i < length; i++) {
12614b24e2bSVaishali Kulkarni 		tmp = ecore_rd(p_hwfn, p_ptt,
12714b24e2bSVaishali Kulkarni 			       p_hwfn->mcp_info->mfw_mb_addr +
12814b24e2bSVaishali Kulkarni 			       (i << 2) + sizeof(u32));
12914b24e2bSVaishali Kulkarni 
13014b24e2bSVaishali Kulkarni 		((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] =
13114b24e2bSVaishali Kulkarni 						OSAL_BE32_TO_CPU(tmp);
13214b24e2bSVaishali Kulkarni 	}
13314b24e2bSVaishali Kulkarni }
13414b24e2bSVaishali Kulkarni 
ecore_mcp_free(struct ecore_hwfn * p_hwfn)13514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_free(struct ecore_hwfn *p_hwfn)
13614b24e2bSVaishali Kulkarni {
13714b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info) {
13814b24e2bSVaishali Kulkarni 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_cur);
13914b24e2bSVaishali Kulkarni 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_shadow);
14014b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LOCK_ALLOC
14114b24e2bSVaishali Kulkarni 		OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->lock);
14214b24e2bSVaishali Kulkarni 		OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->link_lock);
14314b24e2bSVaishali Kulkarni #endif
14414b24e2bSVaishali Kulkarni 	}
14514b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info);
14614b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info = OSAL_NULL;
14714b24e2bSVaishali Kulkarni 
14814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
14914b24e2bSVaishali Kulkarni }
15014b24e2bSVaishali Kulkarni 
ecore_load_mcp_offsets(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)15114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_load_mcp_offsets(struct ecore_hwfn *p_hwfn,
15214b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt)
15314b24e2bSVaishali Kulkarni {
15414b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *p_info = p_hwfn->mcp_info;
15514b24e2bSVaishali Kulkarni 	u32 drv_mb_offsize, mfw_mb_offsize;
15614b24e2bSVaishali Kulkarni 	u32 mcp_pf_id = MCP_PF_ID(p_hwfn);
15714b24e2bSVaishali Kulkarni 
15814b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
15914b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
16014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - assume no MFW\n");
16114b24e2bSVaishali Kulkarni 		p_info->public_base = 0;
16214b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
16314b24e2bSVaishali Kulkarni 	}
16414b24e2bSVaishali Kulkarni #endif
16514b24e2bSVaishali Kulkarni 
16614b24e2bSVaishali Kulkarni 	p_info->public_base = ecore_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR);
16714b24e2bSVaishali Kulkarni 	if (!p_info->public_base)
16814b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
16914b24e2bSVaishali Kulkarni 
17014b24e2bSVaishali Kulkarni 	p_info->public_base |= GRCBASE_MCP;
17114b24e2bSVaishali Kulkarni 
17214b24e2bSVaishali Kulkarni 	/* Calculate the driver and MFW mailbox address */
17314b24e2bSVaishali Kulkarni 	drv_mb_offsize = ecore_rd(p_hwfn, p_ptt,
17414b24e2bSVaishali Kulkarni 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
17514b24e2bSVaishali Kulkarni 						       PUBLIC_DRV_MB));
17614b24e2bSVaishali Kulkarni 	p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id);
17714b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
17814b24e2bSVaishali Kulkarni 		   "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n",
17914b24e2bSVaishali Kulkarni 		   drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id);
18014b24e2bSVaishali Kulkarni 
18114b24e2bSVaishali Kulkarni 	/* Set the MFW MB address */
18214b24e2bSVaishali Kulkarni 	mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt,
18314b24e2bSVaishali Kulkarni 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
18414b24e2bSVaishali Kulkarni 				  PUBLIC_MFW_MB));
18514b24e2bSVaishali Kulkarni 	p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id);
18614b24e2bSVaishali Kulkarni 	p_info->mfw_mb_length = (u16)ecore_rd(p_hwfn, p_ptt,
18714b24e2bSVaishali Kulkarni 					      p_info->mfw_mb_addr);
18814b24e2bSVaishali Kulkarni 
18914b24e2bSVaishali Kulkarni 	/* Get the current driver mailbox sequence before sending
19014b24e2bSVaishali Kulkarni 	 * the first command
19114b24e2bSVaishali Kulkarni 	 */
19214b24e2bSVaishali Kulkarni 	p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
19314b24e2bSVaishali Kulkarni 				       DRV_MSG_SEQ_NUMBER_MASK;
19414b24e2bSVaishali Kulkarni 
19514b24e2bSVaishali Kulkarni 	/* Get current FW pulse sequence */
19614b24e2bSVaishali Kulkarni 	p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) &
19714b24e2bSVaishali Kulkarni 				DRV_PULSE_SEQ_MASK;
19814b24e2bSVaishali Kulkarni 
19914b24e2bSVaishali Kulkarni 	p_info->mcp_hist = (u16)ecore_rd(p_hwfn, p_ptt,
20014b24e2bSVaishali Kulkarni 					 MISCS_REG_GENERIC_POR_0);
20114b24e2bSVaishali Kulkarni 
20214b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
20314b24e2bSVaishali Kulkarni }
20414b24e2bSVaishali Kulkarni 
ecore_mcp_cmd_init(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)20514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_cmd_init(struct ecore_hwfn *p_hwfn,
20614b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt)
20714b24e2bSVaishali Kulkarni {
20814b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *p_info;
20914b24e2bSVaishali Kulkarni 	u32 size;
21014b24e2bSVaishali Kulkarni 
21114b24e2bSVaishali Kulkarni 	/* Allocate mcp_info structure */
21214b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
21314b24e2bSVaishali Kulkarni 				       sizeof(*p_hwfn->mcp_info));
21414b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info)
21514b24e2bSVaishali Kulkarni 		goto err;
21614b24e2bSVaishali Kulkarni 	p_info = p_hwfn->mcp_info;
21714b24e2bSVaishali Kulkarni 
21814b24e2bSVaishali Kulkarni 	if (ecore_load_mcp_offsets(p_hwfn, p_ptt) != ECORE_SUCCESS) {
21914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "MCP is not initialized\n");
22014b24e2bSVaishali Kulkarni 		/* Do not free mcp_info here, since public_base indicate that
22114b24e2bSVaishali Kulkarni 		 * the MCP is not initialized
22214b24e2bSVaishali Kulkarni 		 */
22314b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
22414b24e2bSVaishali Kulkarni 	}
22514b24e2bSVaishali Kulkarni 
22614b24e2bSVaishali Kulkarni 	size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32);
22714b24e2bSVaishali Kulkarni 	p_info->mfw_mb_cur = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
22814b24e2bSVaishali Kulkarni 	p_info->mfw_mb_shadow = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
22914b24e2bSVaishali Kulkarni 	if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr)
23014b24e2bSVaishali Kulkarni 		goto err;
23114b24e2bSVaishali Kulkarni 
23214b24e2bSVaishali Kulkarni 	/* Initialize the MFW spinlock */
23314b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LOCK_ALLOC
23414b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->lock);
23514b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->link_lock);
23614b24e2bSVaishali Kulkarni #endif
23714b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_INIT(&p_info->lock);
23814b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_INIT(&p_info->link_lock);
23914b24e2bSVaishali Kulkarni 
24014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
24114b24e2bSVaishali Kulkarni 
24214b24e2bSVaishali Kulkarni err:
24314b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, true, "Failed to allocate mcp memory\n");
24414b24e2bSVaishali Kulkarni 	ecore_mcp_free(p_hwfn);
24514b24e2bSVaishali Kulkarni 	return ECORE_NOMEM;
24614b24e2bSVaishali Kulkarni 
24714b24e2bSVaishali Kulkarni }
24814b24e2bSVaishali Kulkarni 
24914b24e2bSVaishali Kulkarni /* Locks the MFW mailbox of a PF to ensure a single access.
25014b24e2bSVaishali Kulkarni  * The lock is achieved in most cases by holding a spinlock, causing other
25114b24e2bSVaishali Kulkarni  * threads to wait till a previous access is done.
25214b24e2bSVaishali Kulkarni  * In some cases (currently when a [UN]LOAD_REQ commands are sent), the single
25314b24e2bSVaishali Kulkarni  * access is achieved by setting a blocking flag, which will fail other
25414b24e2bSVaishali Kulkarni  * competing contexts to send their mailboxes.
25514b24e2bSVaishali Kulkarni  */
ecore_mcp_mb_lock(struct ecore_hwfn * p_hwfn,u32 cmd)25614b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_mb_lock(struct ecore_hwfn *p_hwfn,
25714b24e2bSVaishali Kulkarni 					      u32 cmd)
25814b24e2bSVaishali Kulkarni {
25914b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&p_hwfn->mcp_info->lock);
26014b24e2bSVaishali Kulkarni 
26114b24e2bSVaishali Kulkarni 	/* The spinlock shouldn't be acquired when the mailbox command is
26214b24e2bSVaishali Kulkarni 	 * [UN]LOAD_REQ, since the engine is locked by the MFW, and a parallel
26314b24e2bSVaishali Kulkarni 	 * pending [UN]LOAD_REQ command of another PF together with a spinlock
26414b24e2bSVaishali Kulkarni 	 * (i.e. interrupts are disabled) - can lead to a deadlock.
26514b24e2bSVaishali Kulkarni 	 * It is assumed that for a single PF, no other mailbox commands can be
26614b24e2bSVaishali Kulkarni 	 * sent from another context while sending LOAD_REQ, and that any
26714b24e2bSVaishali Kulkarni 	 * parallel commands to UNLOAD_REQ can be cancelled.
26814b24e2bSVaishali Kulkarni 	 */
26914b24e2bSVaishali Kulkarni 	if (cmd == DRV_MSG_CODE_LOAD_DONE || cmd == DRV_MSG_CODE_UNLOAD_DONE)
27014b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
27114b24e2bSVaishali Kulkarni 
27214b24e2bSVaishali Kulkarni 	/* There's at least a single command that is sent by ecore during the
27314b24e2bSVaishali Kulkarni 	 * load sequence [expectation of MFW].
27414b24e2bSVaishali Kulkarni 	 */
27514b24e2bSVaishali Kulkarni 	if ((p_hwfn->mcp_info->block_mb_sending) &&
27614b24e2bSVaishali Kulkarni 	    (cmd != DRV_MSG_CODE_FEATURE_SUPPORT)) {
27714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
27814b24e2bSVaishali Kulkarni 			  "Trying to send a MFW mailbox command [0x%x] in parallel to [UN]LOAD_REQ. Aborting.\n",
27914b24e2bSVaishali Kulkarni 			  cmd);
28014b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
28114b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
28214b24e2bSVaishali Kulkarni 	}
28314b24e2bSVaishali Kulkarni 
28414b24e2bSVaishali Kulkarni 	if (cmd == DRV_MSG_CODE_LOAD_REQ || cmd == DRV_MSG_CODE_UNLOAD_REQ) {
28514b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = true;
28614b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
28714b24e2bSVaishali Kulkarni 	}
28814b24e2bSVaishali Kulkarni 
28914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
29014b24e2bSVaishali Kulkarni }
29114b24e2bSVaishali Kulkarni 
ecore_mcp_mb_unlock(struct ecore_hwfn * p_hwfn,u32 cmd)29214b24e2bSVaishali Kulkarni static void ecore_mcp_mb_unlock(struct ecore_hwfn *p_hwfn, u32 cmd)
29314b24e2bSVaishali Kulkarni {
29414b24e2bSVaishali Kulkarni 	if (cmd != DRV_MSG_CODE_LOAD_REQ && cmd != DRV_MSG_CODE_UNLOAD_REQ)
29514b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
29614b24e2bSVaishali Kulkarni }
29714b24e2bSVaishali Kulkarni 
ecore_mcp_reset(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)29814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_reset(struct ecore_hwfn *p_hwfn,
29914b24e2bSVaishali Kulkarni 				     struct ecore_ptt *p_ptt)
30014b24e2bSVaishali Kulkarni {
30114b24e2bSVaishali Kulkarni 	u32 seq = ++p_hwfn->mcp_info->drv_mb_seq;
30214b24e2bSVaishali Kulkarni 	u32 delay = CHIP_MCP_RESP_ITER_US;
30314b24e2bSVaishali Kulkarni 	u32 org_mcp_reset_seq, cnt = 0;
30414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
30514b24e2bSVaishali Kulkarni 
30614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
30714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
30814b24e2bSVaishali Kulkarni 		delay = EMUL_MCP_RESP_ITER_US;
30914b24e2bSVaishali Kulkarni #endif
31014b24e2bSVaishali Kulkarni 
31114b24e2bSVaishali Kulkarni 	/* Ensure that only a single thread is accessing the mailbox at a
31214b24e2bSVaishali Kulkarni 	 * certain time.
31314b24e2bSVaishali Kulkarni 	 */
31414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mb_lock(p_hwfn, DRV_MSG_CODE_MCP_RESET);
31514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
31614b24e2bSVaishali Kulkarni 		return rc;
31714b24e2bSVaishali Kulkarni 
31814b24e2bSVaishali Kulkarni 	/* Set drv command along with the updated sequence */
31914b24e2bSVaishali Kulkarni 	org_mcp_reset_seq = ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
32014b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (DRV_MSG_CODE_MCP_RESET | seq));
32114b24e2bSVaishali Kulkarni 
32214b24e2bSVaishali Kulkarni 	do {
32314b24e2bSVaishali Kulkarni 		/* Wait for MFW response */
32414b24e2bSVaishali Kulkarni 		OSAL_UDELAY(delay);
32514b24e2bSVaishali Kulkarni 		/* Give the FW up to 500 second (50*1000*10usec) */
32614b24e2bSVaishali Kulkarni 	} while ((org_mcp_reset_seq == ecore_rd(p_hwfn, p_ptt,
32714b24e2bSVaishali Kulkarni 						MISCS_REG_GENERIC_POR_0)) &&
32814b24e2bSVaishali Kulkarni 		 (cnt++ < ECORE_MCP_RESET_RETRIES));
32914b24e2bSVaishali Kulkarni 
33014b24e2bSVaishali Kulkarni 	if (org_mcp_reset_seq !=
33114b24e2bSVaishali Kulkarni 	    ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
33214b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
33314b24e2bSVaishali Kulkarni 			   "MCP was reset after %d usec\n", cnt * delay);
33414b24e2bSVaishali Kulkarni 	} else {
33514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to reset MCP\n");
33614b24e2bSVaishali Kulkarni 		rc = ECORE_AGAIN;
33714b24e2bSVaishali Kulkarni 	}
33814b24e2bSVaishali Kulkarni 
33914b24e2bSVaishali Kulkarni 	ecore_mcp_mb_unlock(p_hwfn, DRV_MSG_CODE_MCP_RESET);
34014b24e2bSVaishali Kulkarni 
34114b24e2bSVaishali Kulkarni 	return rc;
34214b24e2bSVaishali Kulkarni }
34314b24e2bSVaishali Kulkarni 
ecore_mcp_print_cpu_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)34414b24e2bSVaishali Kulkarni void ecore_mcp_print_cpu_info(struct ecore_hwfn *p_hwfn,
34514b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt)
34614b24e2bSVaishali Kulkarni {
34714b24e2bSVaishali Kulkarni 	u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2;
34814b24e2bSVaishali Kulkarni 
34914b24e2bSVaishali Kulkarni 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
35014b24e2bSVaishali Kulkarni 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
35114b24e2bSVaishali Kulkarni 	cpu_pc_0 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
35214b24e2bSVaishali Kulkarni 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
35314b24e2bSVaishali Kulkarni 	cpu_pc_1 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
35414b24e2bSVaishali Kulkarni 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
35514b24e2bSVaishali Kulkarni 	cpu_pc_2 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
35614b24e2bSVaishali Kulkarni 
35714b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
35814b24e2bSVaishali Kulkarni 		  "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n",
35914b24e2bSVaishali Kulkarni 		  cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2);
36014b24e2bSVaishali Kulkarni }
36114b24e2bSVaishali Kulkarni 
ecore_do_mcp_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param)36214b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_do_mcp_cmd(struct ecore_hwfn *p_hwfn,
36314b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
36414b24e2bSVaishali Kulkarni 					     u32 cmd, u32 param,
36514b24e2bSVaishali Kulkarni 					     u32 *o_mcp_resp, u32 *o_mcp_param)
36614b24e2bSVaishali Kulkarni {
36714b24e2bSVaishali Kulkarni 	u32 delay = CHIP_MCP_RESP_ITER_US;
36814b24e2bSVaishali Kulkarni 	u32 max_retries = ECORE_DRV_MB_MAX_RETRIES;
369b68ddc76SJohn Levon 	u32 seq, cnt = 1, actual_mb_seq __unused;
37014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
37114b24e2bSVaishali Kulkarni 
37214b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
37314b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
37414b24e2bSVaishali Kulkarni 		delay = EMUL_MCP_RESP_ITER_US;
37514b24e2bSVaishali Kulkarni 	/* There is a built-in delay of 100usec in each MFW response read */
37614b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev))
37714b24e2bSVaishali Kulkarni 		max_retries /= 10;
37814b24e2bSVaishali Kulkarni #endif
37914b24e2bSVaishali Kulkarni 
38014b24e2bSVaishali Kulkarni 	/* Get actual driver mailbox sequence */
38114b24e2bSVaishali Kulkarni 	actual_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
38214b24e2bSVaishali Kulkarni 			DRV_MSG_SEQ_NUMBER_MASK;
38314b24e2bSVaishali Kulkarni 
38414b24e2bSVaishali Kulkarni 	/* Use MCP history register to check if MCP reset occurred between
38514b24e2bSVaishali Kulkarni 	 * init time and now.
38614b24e2bSVaishali Kulkarni 	 */
38714b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->mcp_hist !=
38814b24e2bSVaishali Kulkarni 	    ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
38914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Rereading MCP offsets\n");
39014b24e2bSVaishali Kulkarni 		ecore_load_mcp_offsets(p_hwfn, p_ptt);
39114b24e2bSVaishali Kulkarni 		ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
39214b24e2bSVaishali Kulkarni 	}
39314b24e2bSVaishali Kulkarni 	seq = ++p_hwfn->mcp_info->drv_mb_seq;
39414b24e2bSVaishali Kulkarni 
39514b24e2bSVaishali Kulkarni 	/* Set drv param */
39614b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, param);
39714b24e2bSVaishali Kulkarni 
39814b24e2bSVaishali Kulkarni 	/* Set drv command along with the updated sequence */
39914b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (cmd | seq));
40014b24e2bSVaishali Kulkarni 
40114b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
40214b24e2bSVaishali Kulkarni 		   "wrote command (%x) to MFW MB param 0x%08x\n",
40314b24e2bSVaishali Kulkarni 		   (cmd | seq), param);
40414b24e2bSVaishali Kulkarni 
40514b24e2bSVaishali Kulkarni 	do {
40614b24e2bSVaishali Kulkarni 		/* Wait for MFW response */
40714b24e2bSVaishali Kulkarni 		OSAL_UDELAY(delay);
40814b24e2bSVaishali Kulkarni 		*o_mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header);
40914b24e2bSVaishali Kulkarni 
41014b24e2bSVaishali Kulkarni 		/* Give the FW up to 5 second (500*10ms) */
41114b24e2bSVaishali Kulkarni 	} while ((seq != (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) &&
41214b24e2bSVaishali Kulkarni 		 (cnt++ < max_retries));
41314b24e2bSVaishali Kulkarni 
41414b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
41514b24e2bSVaishali Kulkarni 		   "[after %d ms] read (%x) seq is (%x) from FW MB\n",
41614b24e2bSVaishali Kulkarni 		   cnt * delay, *o_mcp_resp, seq);
41714b24e2bSVaishali Kulkarni 
41814b24e2bSVaishali Kulkarni 	/* Is this a reply to our command? */
41914b24e2bSVaishali Kulkarni 	if (seq == (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) {
42014b24e2bSVaishali Kulkarni 		*o_mcp_resp &= FW_MSG_CODE_MASK;
42114b24e2bSVaishali Kulkarni 		/* Get the MCP param */
42214b24e2bSVaishali Kulkarni 		*o_mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param);
42314b24e2bSVaishali Kulkarni 	} else {
42414b24e2bSVaishali Kulkarni 		/* FW BUG! */
42514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MFW failed to respond [cmd 0x%x param 0x%x]\n",
42614b24e2bSVaishali Kulkarni 		       cmd, param);
42714b24e2bSVaishali Kulkarni 		ecore_mcp_print_cpu_info(p_hwfn, p_ptt);
42814b24e2bSVaishali Kulkarni 		*o_mcp_resp = 0;
42914b24e2bSVaishali Kulkarni 		rc = ECORE_AGAIN;
43014b24e2bSVaishali Kulkarni 		ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_MFW_RESP_FAIL);
43114b24e2bSVaishali Kulkarni 	}
43214b24e2bSVaishali Kulkarni 	return rc;
43314b24e2bSVaishali Kulkarni }
43414b24e2bSVaishali Kulkarni 
ecore_mcp_cmd_and_union(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_mb_params * p_mb_params)43514b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn,
43614b24e2bSVaishali Kulkarni 						    struct ecore_ptt *p_ptt,
43714b24e2bSVaishali Kulkarni 						    struct ecore_mcp_mb_params *p_mb_params)
43814b24e2bSVaishali Kulkarni {
43914b24e2bSVaishali Kulkarni 	union drv_union_data union_data;
44014b24e2bSVaishali Kulkarni 	u32 union_data_addr;
44114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
44214b24e2bSVaishali Kulkarni 
44314b24e2bSVaishali Kulkarni 	/* MCP not initialized */
44414b24e2bSVaishali Kulkarni 	if (!ecore_mcp_is_init(p_hwfn)) {
44514b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW is not initialized!\n");
44614b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
44714b24e2bSVaishali Kulkarni 	}
44814b24e2bSVaishali Kulkarni 
44914b24e2bSVaishali Kulkarni 	if (p_mb_params->data_src_size > sizeof(union_data) ||
45014b24e2bSVaishali Kulkarni 	    p_mb_params->data_dst_size > sizeof(union_data)) {
45114b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
45214b24e2bSVaishali Kulkarni 		       "The provided size is larger than the union data size [src_size %u, dst_size %u, union_data_size %zu]\n",
45314b24e2bSVaishali Kulkarni 		       p_mb_params->data_src_size, p_mb_params->data_dst_size,
45414b24e2bSVaishali Kulkarni 		       sizeof(union_data));
45514b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
45614b24e2bSVaishali Kulkarni 	}
45714b24e2bSVaishali Kulkarni 
45814b24e2bSVaishali Kulkarni 	union_data_addr = p_hwfn->mcp_info->drv_mb_addr +
459*04443fdeSToomas Soome 			  offsetof(struct public_drv_mb, union_data);
46014b24e2bSVaishali Kulkarni 
46114b24e2bSVaishali Kulkarni 	/* Ensure that only a single thread is accessing the mailbox at a
46214b24e2bSVaishali Kulkarni 	 * certain time.
46314b24e2bSVaishali Kulkarni 	 */
46414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mb_lock(p_hwfn, p_mb_params->cmd);
46514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
46614b24e2bSVaishali Kulkarni 		return rc;
46714b24e2bSVaishali Kulkarni 
46814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&union_data, sizeof(union_data));
46914b24e2bSVaishali Kulkarni 	if (p_mb_params->p_data_src != OSAL_NULL && p_mb_params->data_src_size)
47014b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(&union_data, p_mb_params->p_data_src,
47114b24e2bSVaishali Kulkarni 			    p_mb_params->data_src_size);
47214b24e2bSVaishali Kulkarni 	ecore_memcpy_to(p_hwfn, p_ptt, union_data_addr, &union_data,
47314b24e2bSVaishali Kulkarni 			sizeof(union_data));
47414b24e2bSVaishali Kulkarni 
47514b24e2bSVaishali Kulkarni 	rc = ecore_do_mcp_cmd(p_hwfn, p_ptt, p_mb_params->cmd,
47614b24e2bSVaishali Kulkarni 			      p_mb_params->param, &p_mb_params->mcp_resp,
47714b24e2bSVaishali Kulkarni 			      &p_mb_params->mcp_param);
47814b24e2bSVaishali Kulkarni 
47914b24e2bSVaishali Kulkarni 	if (p_mb_params->p_data_dst != OSAL_NULL &&
48014b24e2bSVaishali Kulkarni 	    p_mb_params->data_dst_size)
48114b24e2bSVaishali Kulkarni 		ecore_memcpy_from(p_hwfn, p_ptt, p_mb_params->p_data_dst,
48214b24e2bSVaishali Kulkarni 				  union_data_addr, p_mb_params->data_dst_size);
48314b24e2bSVaishali Kulkarni 
48414b24e2bSVaishali Kulkarni 	ecore_mcp_mb_unlock(p_hwfn, p_mb_params->cmd);
48514b24e2bSVaishali Kulkarni 
48614b24e2bSVaishali Kulkarni 	return rc;
48714b24e2bSVaishali Kulkarni }
48814b24e2bSVaishali Kulkarni 
ecore_mcp_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param)48914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_cmd(struct ecore_hwfn *p_hwfn,
49014b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt, u32 cmd, u32 param,
49114b24e2bSVaishali Kulkarni 				   u32 *o_mcp_resp, u32 *o_mcp_param)
49214b24e2bSVaishali Kulkarni {
49314b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
49414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
49514b24e2bSVaishali Kulkarni 
49614b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
49714b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
49814b24e2bSVaishali Kulkarni 		if (cmd == DRV_MSG_CODE_UNLOAD_REQ) {
49914b24e2bSVaishali Kulkarni 			loaded--;
50014b24e2bSVaishali Kulkarni 			loaded_port[p_hwfn->port_id]--;
50114b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Unload cnt: 0x%x\n",
50214b24e2bSVaishali Kulkarni 				   loaded);
50314b24e2bSVaishali Kulkarni 		}
50414b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
50514b24e2bSVaishali Kulkarni 	}
50614b24e2bSVaishali Kulkarni #endif
50714b24e2bSVaishali Kulkarni 
50814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
50914b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
51014b24e2bSVaishali Kulkarni 	mb_params.param = param;
51114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
51214b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
51314b24e2bSVaishali Kulkarni 		return rc;
51414b24e2bSVaishali Kulkarni 
51514b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
51614b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
51714b24e2bSVaishali Kulkarni 
51814b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
51914b24e2bSVaishali Kulkarni }
52014b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_wr_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param,u32 i_txn_size,u32 * i_buf)52114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_wr_cmd(struct ecore_hwfn *p_hwfn,
52214b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
52314b24e2bSVaishali Kulkarni 					  u32 cmd,
52414b24e2bSVaishali Kulkarni 					  u32 param,
52514b24e2bSVaishali Kulkarni 					  u32 *o_mcp_resp,
52614b24e2bSVaishali Kulkarni 					  u32 *o_mcp_param,
52714b24e2bSVaishali Kulkarni 					  u32 i_txn_size,
52814b24e2bSVaishali Kulkarni 					  u32 *i_buf)
52914b24e2bSVaishali Kulkarni {
53014b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
53114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
53214b24e2bSVaishali Kulkarni 
53314b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
53414b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
53514b24e2bSVaishali Kulkarni 	mb_params.param = param;
53614b24e2bSVaishali Kulkarni 	mb_params.p_data_src = i_buf;
53714b24e2bSVaishali Kulkarni 	mb_params.data_src_size = (u8) i_txn_size;
53814b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
53914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
54014b24e2bSVaishali Kulkarni 		return rc;
54114b24e2bSVaishali Kulkarni 
54214b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
54314b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
54414b24e2bSVaishali Kulkarni 
54514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
54614b24e2bSVaishali Kulkarni }
54714b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_rd_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param,u32 * o_txn_size,u32 * o_buf)54814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_rd_cmd(struct ecore_hwfn *p_hwfn,
54914b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
55014b24e2bSVaishali Kulkarni 					  u32 cmd,
55114b24e2bSVaishali Kulkarni 					  u32 param,
55214b24e2bSVaishali Kulkarni 					  u32 *o_mcp_resp,
55314b24e2bSVaishali Kulkarni 					  u32 *o_mcp_param,
55414b24e2bSVaishali Kulkarni 					  u32 *o_txn_size,
55514b24e2bSVaishali Kulkarni 					  u32 *o_buf)
55614b24e2bSVaishali Kulkarni {
55714b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
55814b24e2bSVaishali Kulkarni 	u8 raw_data[MCP_DRV_NVM_BUF_LEN];
55914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
56014b24e2bSVaishali Kulkarni 
56114b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
56214b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
56314b24e2bSVaishali Kulkarni 	mb_params.param = param;
56414b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = raw_data;
56514b24e2bSVaishali Kulkarni 
56614b24e2bSVaishali Kulkarni 	/* Use the maximal value since the actual one is part of the response */
56714b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = MCP_DRV_NVM_BUF_LEN;
56814b24e2bSVaishali Kulkarni 
56914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
57014b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
57114b24e2bSVaishali Kulkarni 		return rc;
57214b24e2bSVaishali Kulkarni 
57314b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
57414b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
57514b24e2bSVaishali Kulkarni 
57614b24e2bSVaishali Kulkarni 	*o_txn_size = *o_mcp_param;
57714b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(o_buf, raw_data, *o_txn_size);
57814b24e2bSVaishali Kulkarni 
57914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
58014b24e2bSVaishali Kulkarni }
58114b24e2bSVaishali Kulkarni 
58214b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
ecore_mcp_mf_workaround(struct ecore_hwfn * p_hwfn,u32 * p_load_code)58314b24e2bSVaishali Kulkarni static void ecore_mcp_mf_workaround(struct ecore_hwfn *p_hwfn,
58414b24e2bSVaishali Kulkarni 				    u32 *p_load_code)
58514b24e2bSVaishali Kulkarni {
58614b24e2bSVaishali Kulkarni 	static int load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
58714b24e2bSVaishali Kulkarni 
58814b24e2bSVaishali Kulkarni 	if (!loaded) {
58914b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
59014b24e2bSVaishali Kulkarni 	} else if (!loaded_port[p_hwfn->port_id]) {
59114b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_PORT;
59214b24e2bSVaishali Kulkarni 	} else {
59314b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_FUNCTION;
59414b24e2bSVaishali Kulkarni 	}
59514b24e2bSVaishali Kulkarni 
59614b24e2bSVaishali Kulkarni 	/* On CMT, always tell that it's engine */
59714b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->num_hwfns > 1)
59814b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
59914b24e2bSVaishali Kulkarni 
60014b24e2bSVaishali Kulkarni 	*p_load_code = load_phase;
60114b24e2bSVaishali Kulkarni 	loaded++;
60214b24e2bSVaishali Kulkarni 	loaded_port[p_hwfn->port_id]++;
60314b24e2bSVaishali Kulkarni 
60414b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
60514b24e2bSVaishali Kulkarni 		   "Load phase: %x load cnt: 0x%x port id=%d port_load=%d\n",
60614b24e2bSVaishali Kulkarni 		   *p_load_code, loaded, p_hwfn->port_id,
60714b24e2bSVaishali Kulkarni 		   loaded_port[p_hwfn->port_id]);
60814b24e2bSVaishali Kulkarni }
60914b24e2bSVaishali Kulkarni #endif
61014b24e2bSVaishali Kulkarni 
61114b24e2bSVaishali Kulkarni static bool
ecore_mcp_can_force_load(u8 drv_role,u8 exist_drv_role,enum ecore_override_force_load override_force_load)61214b24e2bSVaishali Kulkarni ecore_mcp_can_force_load(u8 drv_role, u8 exist_drv_role,
61314b24e2bSVaishali Kulkarni 			 enum ecore_override_force_load override_force_load)
61414b24e2bSVaishali Kulkarni {
61514b24e2bSVaishali Kulkarni 	bool can_force_load = false;
61614b24e2bSVaishali Kulkarni 
61714b24e2bSVaishali Kulkarni 	switch (override_force_load) {
61814b24e2bSVaishali Kulkarni 	case ECORE_OVERRIDE_FORCE_LOAD_ALWAYS:
61914b24e2bSVaishali Kulkarni 		can_force_load = true;
62014b24e2bSVaishali Kulkarni 		break;
62114b24e2bSVaishali Kulkarni 	case ECORE_OVERRIDE_FORCE_LOAD_NEVER:
62214b24e2bSVaishali Kulkarni 		can_force_load = false;
62314b24e2bSVaishali Kulkarni 		break;
62414b24e2bSVaishali Kulkarni 	default:
62514b24e2bSVaishali Kulkarni 		can_force_load = (drv_role == DRV_ROLE_OS &&
62614b24e2bSVaishali Kulkarni 				  exist_drv_role == DRV_ROLE_PREBOOT) ||
62714b24e2bSVaishali Kulkarni 				 (drv_role == DRV_ROLE_KDUMP &&
62814b24e2bSVaishali Kulkarni 				  exist_drv_role == DRV_ROLE_OS);
62914b24e2bSVaishali Kulkarni 		break;
63014b24e2bSVaishali Kulkarni 	}
63114b24e2bSVaishali Kulkarni 
63214b24e2bSVaishali Kulkarni 	return can_force_load;
63314b24e2bSVaishali Kulkarni }
63414b24e2bSVaishali Kulkarni 
ecore_mcp_cancel_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)63514b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_cancel_load_req(struct ecore_hwfn *p_hwfn,
63614b24e2bSVaishali Kulkarni 						      struct ecore_ptt *p_ptt)
63714b24e2bSVaishali Kulkarni {
63814b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
63914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
64014b24e2bSVaishali Kulkarni 
64114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CANCEL_LOAD_REQ, 0,
64214b24e2bSVaishali Kulkarni 			   &resp, &param);
64314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
64414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
64514b24e2bSVaishali Kulkarni 			  "Failed to send cancel load request, rc = %d\n", rc);
64614b24e2bSVaishali Kulkarni 
64714b24e2bSVaishali Kulkarni 	return rc;
64814b24e2bSVaishali Kulkarni }
64914b24e2bSVaishali Kulkarni 
65014b24e2bSVaishali Kulkarni #define CONFIG_ECORE_L2_BITMAP_IDX	(0x1 << 0)
65114b24e2bSVaishali Kulkarni #define CONFIG_ECORE_SRIOV_BITMAP_IDX	(0x1 << 1)
65214b24e2bSVaishali Kulkarni #define CONFIG_ECORE_ROCE_BITMAP_IDX	(0x1 << 2)
65314b24e2bSVaishali Kulkarni #define CONFIG_ECORE_IWARP_BITMAP_IDX	(0x1 << 3)
65414b24e2bSVaishali Kulkarni #define CONFIG_ECORE_FCOE_BITMAP_IDX	(0x1 << 4)
65514b24e2bSVaishali Kulkarni #define CONFIG_ECORE_ISCSI_BITMAP_IDX	(0x1 << 5)
65614b24e2bSVaishali Kulkarni #define CONFIG_ECORE_LL2_BITMAP_IDX	(0x1 << 6)
65714b24e2bSVaishali Kulkarni 
ecore_get_config_bitmap(void)65814b24e2bSVaishali Kulkarni static u32 ecore_get_config_bitmap(void)
65914b24e2bSVaishali Kulkarni {
66014b24e2bSVaishali Kulkarni 	u32 config_bitmap = 0x0;
66114b24e2bSVaishali Kulkarni 
66214b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_L2
66314b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_L2_BITMAP_IDX;
66414b24e2bSVaishali Kulkarni #endif
66514b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_SRIOV
66614b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_SRIOV_BITMAP_IDX;
66714b24e2bSVaishali Kulkarni #endif
66814b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
66914b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_ROCE_BITMAP_IDX;
67014b24e2bSVaishali Kulkarni #endif
67114b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_IWARP
67214b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_IWARP_BITMAP_IDX;
67314b24e2bSVaishali Kulkarni #endif
67414b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_FCOE
67514b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_FCOE_BITMAP_IDX;
67614b24e2bSVaishali Kulkarni #endif
67714b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ISCSI
67814b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_ISCSI_BITMAP_IDX;
67914b24e2bSVaishali Kulkarni #endif
68014b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LL2
68114b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_LL2_BITMAP_IDX;
68214b24e2bSVaishali Kulkarni #endif
68314b24e2bSVaishali Kulkarni 
68414b24e2bSVaishali Kulkarni 	return config_bitmap;
68514b24e2bSVaishali Kulkarni }
68614b24e2bSVaishali Kulkarni 
68714b24e2bSVaishali Kulkarni struct ecore_load_req_in_params {
68814b24e2bSVaishali Kulkarni 	u8 hsi_ver;
68914b24e2bSVaishali Kulkarni #define ECORE_LOAD_REQ_HSI_VER_DEFAULT	0
69014b24e2bSVaishali Kulkarni #define ECORE_LOAD_REQ_HSI_VER_1	1
69114b24e2bSVaishali Kulkarni 	u32 drv_ver_0;
69214b24e2bSVaishali Kulkarni 	u32 drv_ver_1;
69314b24e2bSVaishali Kulkarni 	u32 fw_ver;
69414b24e2bSVaishali Kulkarni 	u8 drv_role;
69514b24e2bSVaishali Kulkarni 	u8 timeout_val;
69614b24e2bSVaishali Kulkarni 	u8 force_cmd;
69714b24e2bSVaishali Kulkarni 	bool avoid_eng_reset;
69814b24e2bSVaishali Kulkarni };
69914b24e2bSVaishali Kulkarni 
70014b24e2bSVaishali Kulkarni struct ecore_load_req_out_params {
70114b24e2bSVaishali Kulkarni 	u32 load_code;
70214b24e2bSVaishali Kulkarni 	u32 exist_drv_ver_0;
70314b24e2bSVaishali Kulkarni 	u32 exist_drv_ver_1;
70414b24e2bSVaishali Kulkarni 	u32 exist_fw_ver;
70514b24e2bSVaishali Kulkarni 	u8 exist_drv_role;
70614b24e2bSVaishali Kulkarni 	u8 mfw_hsi_ver;
70714b24e2bSVaishali Kulkarni 	bool drv_exists;
70814b24e2bSVaishali Kulkarni };
70914b24e2bSVaishali Kulkarni 
71014b24e2bSVaishali Kulkarni static enum _ecore_status_t
__ecore_mcp_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_load_req_in_params * p_in_params,struct ecore_load_req_out_params * p_out_params)71114b24e2bSVaishali Kulkarni __ecore_mcp_load_req(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
71214b24e2bSVaishali Kulkarni 		     struct ecore_load_req_in_params *p_in_params,
71314b24e2bSVaishali Kulkarni 		     struct ecore_load_req_out_params *p_out_params)
71414b24e2bSVaishali Kulkarni {
71514b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
71614b24e2bSVaishali Kulkarni 	struct load_req_stc load_req;
71714b24e2bSVaishali Kulkarni 	struct load_rsp_stc load_rsp;
71814b24e2bSVaishali Kulkarni 	u32 hsi_ver;
71914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
72014b24e2bSVaishali Kulkarni 
72114b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&load_req, sizeof(load_req));
72214b24e2bSVaishali Kulkarni 	load_req.drv_ver_0 = p_in_params->drv_ver_0;
72314b24e2bSVaishali Kulkarni 	load_req.drv_ver_1 = p_in_params->drv_ver_1;
72414b24e2bSVaishali Kulkarni 	load_req.fw_ver = p_in_params->fw_ver;
72514b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_ROLE,
72614b24e2bSVaishali Kulkarni 			    p_in_params->drv_role);
72714b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_LOCK_TO,
72814b24e2bSVaishali Kulkarni 			    p_in_params->timeout_val);
72914b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FORCE,
73014b24e2bSVaishali Kulkarni 			    p_in_params->force_cmd);
73114b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FLAGS0,
73214b24e2bSVaishali Kulkarni 			    p_in_params->avoid_eng_reset);
73314b24e2bSVaishali Kulkarni 
73414b24e2bSVaishali Kulkarni 	hsi_ver = (p_in_params->hsi_ver == ECORE_LOAD_REQ_HSI_VER_DEFAULT) ?
73514b24e2bSVaishali Kulkarni 		  DRV_ID_MCP_HSI_VER_CURRENT :
73614b24e2bSVaishali Kulkarni 		  (p_in_params->hsi_ver << DRV_ID_MCP_HSI_VER_SHIFT);
73714b24e2bSVaishali Kulkarni 
73814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
73914b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_LOAD_REQ;
74014b24e2bSVaishali Kulkarni 	mb_params.param = PDA_COMP | hsi_ver | p_hwfn->p_dev->drv_type;
74114b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &load_req;
74214b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(load_req);
74314b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &load_rsp;
74414b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(load_rsp);
74514b24e2bSVaishali Kulkarni 
74614b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
74714b24e2bSVaishali Kulkarni 		   "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n",
74814b24e2bSVaishali Kulkarni 		   mb_params.param,
74914b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_INIT_HW),
75014b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_TYPE),
75114b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_MCP_HSI_VER),
75214b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_PDA_COMP_VER));
75314b24e2bSVaishali Kulkarni 
75414b24e2bSVaishali Kulkarni 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1)
75514b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
75614b24e2bSVaishali Kulkarni 			   "Load Request: drv_ver 0x%08x_0x%08x, fw_ver 0x%08x, misc0 0x%08x [role %d, timeout %d, force %d, flags0 0x%x]\n",
75714b24e2bSVaishali Kulkarni 			   load_req.drv_ver_0, load_req.drv_ver_1,
75814b24e2bSVaishali Kulkarni 			   load_req.fw_ver, load_req.misc0,
75914b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_ROLE),
76014b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0,
76114b24e2bSVaishali Kulkarni 					       LOAD_REQ_LOCK_TO),
76214b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_FORCE),
76314b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0,
76414b24e2bSVaishali Kulkarni 					       LOAD_REQ_FLAGS0));
76514b24e2bSVaishali Kulkarni 
76614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
76714b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
76814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
76914b24e2bSVaishali Kulkarni 			  "Failed to send load request, rc = %d\n", rc);
77014b24e2bSVaishali Kulkarni 		return rc;
77114b24e2bSVaishali Kulkarni 	}
77214b24e2bSVaishali Kulkarni 
77314b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
77414b24e2bSVaishali Kulkarni 		   "Load Response: resp 0x%08x\n", mb_params.mcp_resp);
77514b24e2bSVaishali Kulkarni 	p_out_params->load_code = mb_params.mcp_resp;
77614b24e2bSVaishali Kulkarni 
77714b24e2bSVaishali Kulkarni 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
77814b24e2bSVaishali Kulkarni 	    p_out_params->load_code != FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
77914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
78014b24e2bSVaishali Kulkarni 			   "Load Response: exist_drv_ver 0x%08x_0x%08x, exist_fw_ver 0x%08x, misc0 0x%08x [exist_role %d, mfw_hsi %d, flags0 0x%x]\n",
78114b24e2bSVaishali Kulkarni 			   load_rsp.drv_ver_0, load_rsp.drv_ver_1,
78214b24e2bSVaishali Kulkarni 			   load_rsp.fw_ver, load_rsp.misc0,
78314b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE),
78414b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI),
78514b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0,
78614b24e2bSVaishali Kulkarni 					       LOAD_RSP_FLAGS0));
78714b24e2bSVaishali Kulkarni 
78814b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_ver_0 = load_rsp.drv_ver_0;
78914b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_ver_1 = load_rsp.drv_ver_1;
79014b24e2bSVaishali Kulkarni 		p_out_params->exist_fw_ver = load_rsp.fw_ver;
79114b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_role =
79214b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE);
79314b24e2bSVaishali Kulkarni 		p_out_params->mfw_hsi_ver =
79414b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI);
79514b24e2bSVaishali Kulkarni 		p_out_params->drv_exists =
79614b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0) &
79714b24e2bSVaishali Kulkarni 			LOAD_RSP_FLAGS0_DRV_EXISTS;
79814b24e2bSVaishali Kulkarni 	}
79914b24e2bSVaishali Kulkarni 
80014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
80114b24e2bSVaishali Kulkarni }
80214b24e2bSVaishali Kulkarni 
eocre_get_mfw_drv_role(struct ecore_hwfn * p_hwfn,enum ecore_drv_role drv_role,u8 * p_mfw_drv_role)80314b24e2bSVaishali Kulkarni static enum _ecore_status_t eocre_get_mfw_drv_role(struct ecore_hwfn *p_hwfn,
80414b24e2bSVaishali Kulkarni 						   enum ecore_drv_role drv_role,
80514b24e2bSVaishali Kulkarni 						   u8 *p_mfw_drv_role)
80614b24e2bSVaishali Kulkarni {
80714b24e2bSVaishali Kulkarni 	switch (drv_role)
80814b24e2bSVaishali Kulkarni 	{
80914b24e2bSVaishali Kulkarni 	case ECORE_DRV_ROLE_OS:
81014b24e2bSVaishali Kulkarni 		*p_mfw_drv_role = DRV_ROLE_OS;
81114b24e2bSVaishali Kulkarni 		break;
81214b24e2bSVaishali Kulkarni 	case ECORE_DRV_ROLE_KDUMP:
81314b24e2bSVaishali Kulkarni 		*p_mfw_drv_role = DRV_ROLE_KDUMP;
81414b24e2bSVaishali Kulkarni 		break;
81514b24e2bSVaishali Kulkarni 	default:
81614b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected driver role %d\n", drv_role);
81714b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
81814b24e2bSVaishali Kulkarni 	}
81914b24e2bSVaishali Kulkarni 
82014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
82114b24e2bSVaishali Kulkarni }
82214b24e2bSVaishali Kulkarni 
82314b24e2bSVaishali Kulkarni enum ecore_load_req_force {
82414b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_NONE,
82514b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_PF,
82614b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_ALL,
82714b24e2bSVaishali Kulkarni };
82814b24e2bSVaishali Kulkarni 
82914b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_get_mfw_force_cmd(struct ecore_hwfn * p_hwfn,enum ecore_load_req_force force_cmd,u8 * p_mfw_force_cmd)83014b24e2bSVaishali Kulkarni ecore_get_mfw_force_cmd(struct ecore_hwfn *p_hwfn,
83114b24e2bSVaishali Kulkarni 			enum ecore_load_req_force force_cmd,
83214b24e2bSVaishali Kulkarni 			u8 *p_mfw_force_cmd)
83314b24e2bSVaishali Kulkarni {
83414b24e2bSVaishali Kulkarni 	switch (force_cmd) {
83514b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_NONE:
83614b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_NONE;
83714b24e2bSVaishali Kulkarni 		break;
83814b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_PF:
83914b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_PF;
84014b24e2bSVaishali Kulkarni 		break;
84114b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_ALL:
84214b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_ALL;
84314b24e2bSVaishali Kulkarni 		break;
84414b24e2bSVaishali Kulkarni 	default:
84514b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected force value %d\n", force_cmd);
84614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
84714b24e2bSVaishali Kulkarni 	}
84814b24e2bSVaishali Kulkarni 
84914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
85014b24e2bSVaishali Kulkarni }
85114b24e2bSVaishali Kulkarni 
ecore_mcp_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_load_req_params * p_params)85214b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_load_req(struct ecore_hwfn *p_hwfn,
85314b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt,
85414b24e2bSVaishali Kulkarni 					struct ecore_load_req_params *p_params)
85514b24e2bSVaishali Kulkarni {
85614b24e2bSVaishali Kulkarni 	struct ecore_load_req_out_params out_params;
85714b24e2bSVaishali Kulkarni 	struct ecore_load_req_in_params in_params;
85814b24e2bSVaishali Kulkarni 	u8 mfw_drv_role, mfw_force_cmd;
85914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
86014b24e2bSVaishali Kulkarni 
86114b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
86214b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
86314b24e2bSVaishali Kulkarni 		ecore_mcp_mf_workaround(p_hwfn, &p_params->load_code);
86414b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
86514b24e2bSVaishali Kulkarni 	}
86614b24e2bSVaishali Kulkarni #endif
86714b24e2bSVaishali Kulkarni 
86814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
86914b24e2bSVaishali Kulkarni 	in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_DEFAULT;
87014b24e2bSVaishali Kulkarni 	in_params.drv_ver_0 = ECORE_VERSION;
87114b24e2bSVaishali Kulkarni 	in_params.drv_ver_1 = ecore_get_config_bitmap();
87214b24e2bSVaishali Kulkarni 	in_params.fw_ver = STORM_FW_VERSION;
87314b24e2bSVaishali Kulkarni 	rc = eocre_get_mfw_drv_role(p_hwfn, p_params->drv_role, &mfw_drv_role);
87414b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
87514b24e2bSVaishali Kulkarni 		return rc;
87614b24e2bSVaishali Kulkarni 
87714b24e2bSVaishali Kulkarni 	in_params.drv_role = mfw_drv_role;
87814b24e2bSVaishali Kulkarni 	in_params.timeout_val = p_params->timeout_val;
87914b24e2bSVaishali Kulkarni 	rc = ecore_get_mfw_force_cmd(p_hwfn, ECORE_LOAD_REQ_FORCE_NONE,
88014b24e2bSVaishali Kulkarni 				     &mfw_force_cmd);
88114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
88214b24e2bSVaishali Kulkarni 		return rc;
88314b24e2bSVaishali Kulkarni 
88414b24e2bSVaishali Kulkarni 	in_params.force_cmd = mfw_force_cmd;
88514b24e2bSVaishali Kulkarni 	in_params.avoid_eng_reset = p_params->avoid_eng_reset;
88614b24e2bSVaishali Kulkarni 
88714b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
88814b24e2bSVaishali Kulkarni 	rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params, &out_params);
88914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
89014b24e2bSVaishali Kulkarni 		return rc;
89114b24e2bSVaishali Kulkarni 
89214b24e2bSVaishali Kulkarni 	/* First handle cases where another load request should/might be sent:
89314b24e2bSVaishali Kulkarni 	 * - MFW expects the old interface [HSI version = 1]
89414b24e2bSVaishali Kulkarni 	 * - MFW responds that a force load request is required
89514b24e2bSVaishali Kulkarni 	 */
89614b24e2bSVaishali Kulkarni 	if (out_params.load_code == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
89714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
89814b24e2bSVaishali Kulkarni 			"MFW refused a load request due to HSI > 1. Resending with HSI = 1.\n");
89914b24e2bSVaishali Kulkarni 
90014b24e2bSVaishali Kulkarni 		/* The previous load request set the mailbox blocking */
90114b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
90214b24e2bSVaishali Kulkarni 
90314b24e2bSVaishali Kulkarni 		in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_1;
90414b24e2bSVaishali Kulkarni 		OSAL_MEM_ZERO(&out_params, sizeof(out_params));
90514b24e2bSVaishali Kulkarni 		rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
90614b24e2bSVaishali Kulkarni 					  &out_params);
90714b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
90814b24e2bSVaishali Kulkarni 			return rc;
90914b24e2bSVaishali Kulkarni 	} else if (out_params.load_code ==
91014b24e2bSVaishali Kulkarni 		   FW_MSG_CODE_DRV_LOAD_REFUSED_REQUIRES_FORCE) {
91114b24e2bSVaishali Kulkarni 		/* The previous load request set the mailbox blocking */
91214b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
91314b24e2bSVaishali Kulkarni 
91414b24e2bSVaishali Kulkarni 		if (ecore_mcp_can_force_load(in_params.drv_role,
91514b24e2bSVaishali Kulkarni 					     out_params.exist_drv_role,
91614b24e2bSVaishali Kulkarni 					     p_params->override_force_load)) {
91714b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn,
91814b24e2bSVaishali Kulkarni 				"A force load is required [{role, fw_ver, drv_ver}: loading={%d, 0x%08x, 0x%08x_%08x}, existing={%d, 0x%08x, 0x%08x_%08x}]\n",
91914b24e2bSVaishali Kulkarni 				in_params.drv_role, in_params.fw_ver,
92014b24e2bSVaishali Kulkarni 				in_params.drv_ver_1, in_params.drv_ver_0,
92114b24e2bSVaishali Kulkarni 				out_params.exist_drv_role,
92214b24e2bSVaishali Kulkarni 				out_params.exist_fw_ver,
92314b24e2bSVaishali Kulkarni 				out_params.exist_drv_ver_1,
92414b24e2bSVaishali Kulkarni 				out_params.exist_drv_ver_0);
92514b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Sending a force load request\n");
92614b24e2bSVaishali Kulkarni 
92714b24e2bSVaishali Kulkarni 			rc = ecore_get_mfw_force_cmd(p_hwfn,
92814b24e2bSVaishali Kulkarni 						     ECORE_LOAD_REQ_FORCE_ALL,
92914b24e2bSVaishali Kulkarni 						     &mfw_force_cmd);
93014b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
93114b24e2bSVaishali Kulkarni 				return rc;
93214b24e2bSVaishali Kulkarni 
93314b24e2bSVaishali Kulkarni 			in_params.force_cmd = mfw_force_cmd;
93414b24e2bSVaishali Kulkarni 			OSAL_MEM_ZERO(&out_params, sizeof(out_params));
93514b24e2bSVaishali Kulkarni 			rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
93614b24e2bSVaishali Kulkarni 						  &out_params);
93714b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
93814b24e2bSVaishali Kulkarni 				return rc;
93914b24e2bSVaishali Kulkarni 		} else {
94014b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
94114b24e2bSVaishali Kulkarni 				  "A force load is required [{role, fw_ver, drv_ver}: loading={%d, 0x%08x, x%08x_0x%08x}, existing={%d, 0x%08x, 0x%08x_0x%08x}]\n",
94214b24e2bSVaishali Kulkarni 				  in_params.drv_role, in_params.fw_ver,
94314b24e2bSVaishali Kulkarni 				  in_params.drv_ver_0, in_params.drv_ver_1,
94414b24e2bSVaishali Kulkarni 				  out_params.exist_drv_role,
94514b24e2bSVaishali Kulkarni 				  out_params.exist_fw_ver,
94614b24e2bSVaishali Kulkarni 				  out_params.exist_drv_ver_0,
94714b24e2bSVaishali Kulkarni 				  out_params.exist_drv_ver_1);
94814b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
94914b24e2bSVaishali Kulkarni 				  "Avoid sending a force load request to prevent disruption of active PFs\n");
95014b24e2bSVaishali Kulkarni 
95114b24e2bSVaishali Kulkarni 			ecore_mcp_cancel_load_req(p_hwfn, p_ptt);
95214b24e2bSVaishali Kulkarni 			return ECORE_BUSY;
95314b24e2bSVaishali Kulkarni 		}
95414b24e2bSVaishali Kulkarni 	}
95514b24e2bSVaishali Kulkarni 
95614b24e2bSVaishali Kulkarni 	/* Now handle the other types of responses.
95714b24e2bSVaishali Kulkarni 	 * The "REFUSED_HSI_1" and "REFUSED_REQUIRES_FORCE" responses are not
95814b24e2bSVaishali Kulkarni 	 * expected here after the additional revised load requests were sent.
95914b24e2bSVaishali Kulkarni 	 */
96014b24e2bSVaishali Kulkarni 	switch (out_params.load_code) {
96114b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_ENGINE:
96214b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_PORT:
96314b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
96414b24e2bSVaishali Kulkarni 		if (out_params.mfw_hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
96514b24e2bSVaishali Kulkarni 		    out_params.drv_exists) {
96614b24e2bSVaishali Kulkarni 			/* The role and fw/driver version match, but the PF is
96714b24e2bSVaishali Kulkarni 			 * already loaded and has not been unloaded gracefully.
96814b24e2bSVaishali Kulkarni 			 * This is unexpected since a quasi-FLR request was
96914b24e2bSVaishali Kulkarni 			 * previously sent as part of ecore_hw_prepare().
97014b24e2bSVaishali Kulkarni 			 */
97114b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
97214b24e2bSVaishali Kulkarni 				  "PF is already loaded - shouldn't have got here since a quasi-FLR request was previously sent!\n");
97314b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
97414b24e2bSVaishali Kulkarni 		}
97514b24e2bSVaishali Kulkarni 		break;
97614b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_PDA:
97714b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG:
97814b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_HSI:
97914b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_REJECT:
98014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
98114b24e2bSVaishali Kulkarni 			  "MFW refused a load request [resp 0x%08x]. Aborting.\n",
98214b24e2bSVaishali Kulkarni 			  out_params.load_code);
98314b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
98414b24e2bSVaishali Kulkarni 	default:
98514b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
98614b24e2bSVaishali Kulkarni 			  "Unexpected response to load request [resp 0x%08x]. Aborting.\n",
98714b24e2bSVaishali Kulkarni 			  out_params.load_code);
98814b24e2bSVaishali Kulkarni 		break;
98914b24e2bSVaishali Kulkarni 	}
99014b24e2bSVaishali Kulkarni 
99114b24e2bSVaishali Kulkarni 	p_params->load_code = out_params.load_code;
99214b24e2bSVaishali Kulkarni 
99314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
99414b24e2bSVaishali Kulkarni }
99514b24e2bSVaishali Kulkarni 
ecore_mcp_unload_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)99614b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_unload_req(struct ecore_hwfn *p_hwfn,
99714b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt)
99814b24e2bSVaishali Kulkarni {
99914b24e2bSVaishali Kulkarni 	u32 wol_param, mcp_resp, mcp_param;
100014b24e2bSVaishali Kulkarni 
100114b24e2bSVaishali Kulkarni 	switch (p_hwfn->p_dev->wol_config) {
100214b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DISABLED:
100314b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED;
100414b24e2bSVaishali Kulkarni 		break;
100514b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_ENABLED:
100614b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED;
100714b24e2bSVaishali Kulkarni 		break;
100814b24e2bSVaishali Kulkarni 	default:
100914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
101014b24e2bSVaishali Kulkarni 			  "Unknown WoL configuration %02x\n",
101114b24e2bSVaishali Kulkarni 			  p_hwfn->p_dev->wol_config);
101214b24e2bSVaishali Kulkarni 		/* Fallthrough */
101314b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DEFAULT:
101414b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
101514b24e2bSVaishali Kulkarni 	}
101614b24e2bSVaishali Kulkarni 
101714b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param,
101814b24e2bSVaishali Kulkarni 			     &mcp_resp, &mcp_param);
101914b24e2bSVaishali Kulkarni }
102014b24e2bSVaishali Kulkarni 
ecore_mcp_unload_done(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)102114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_unload_done(struct ecore_hwfn *p_hwfn,
102214b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt)
102314b24e2bSVaishali Kulkarni {
102414b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
102514b24e2bSVaishali Kulkarni 	struct mcp_mac wol_mac;
102614b24e2bSVaishali Kulkarni 
102714b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
102814b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_UNLOAD_DONE;
102914b24e2bSVaishali Kulkarni 
103014b24e2bSVaishali Kulkarni 	/* Set the primary MAC if WoL is enabled */
103114b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->wol_config == ECORE_OV_WOL_ENABLED) {
103214b24e2bSVaishali Kulkarni 		u8 *p_mac = p_hwfn->p_dev->wol_mac;
103314b24e2bSVaishali Kulkarni 
103414b24e2bSVaishali Kulkarni 		OSAL_MEM_ZERO(&wol_mac, sizeof(wol_mac));
103514b24e2bSVaishali Kulkarni 		wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1];
103614b24e2bSVaishali Kulkarni 		wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 |
103714b24e2bSVaishali Kulkarni 				    p_mac[4] << 8 | p_mac[5];
103814b24e2bSVaishali Kulkarni 
103914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFDOWN),
104014b24e2bSVaishali Kulkarni 			   "Setting WoL MAC: %02x:%02x:%02x:%02x:%02x:%02x --> [%08x,%08x]\n",
104114b24e2bSVaishali Kulkarni 			   p_mac[0], p_mac[1], p_mac[2], p_mac[3], p_mac[4],
104214b24e2bSVaishali Kulkarni 			   p_mac[5], wol_mac.mac_upper, wol_mac.mac_lower);
104314b24e2bSVaishali Kulkarni 
104414b24e2bSVaishali Kulkarni 		mb_params.p_data_src = &wol_mac;
104514b24e2bSVaishali Kulkarni 		mb_params.data_src_size = sizeof(wol_mac);
104614b24e2bSVaishali Kulkarni 	}
104714b24e2bSVaishali Kulkarni 
104814b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
104914b24e2bSVaishali Kulkarni }
105014b24e2bSVaishali Kulkarni 
ecore_mcp_handle_vf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)105114b24e2bSVaishali Kulkarni static void ecore_mcp_handle_vf_flr(struct ecore_hwfn *p_hwfn,
105214b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt)
105314b24e2bSVaishali Kulkarni {
105414b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
105514b24e2bSVaishali Kulkarni 					PUBLIC_PATH);
105614b24e2bSVaishali Kulkarni 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
105714b24e2bSVaishali Kulkarni 	u32 path_addr = SECTION_ADDR(mfw_path_offsize,
105814b24e2bSVaishali Kulkarni 				     ECORE_PATH_ID(p_hwfn));
105914b24e2bSVaishali Kulkarni 	u32 disabled_vfs[VF_MAX_STATIC / 32];
106014b24e2bSVaishali Kulkarni 	int i;
106114b24e2bSVaishali Kulkarni 
106214b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
106314b24e2bSVaishali Kulkarni 		   "Reading Disabled VF information from [offset %08x], path_addr %08x\n",
106414b24e2bSVaishali Kulkarni 		   mfw_path_offsize, path_addr);
106514b24e2bSVaishali Kulkarni 
106614b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++) {
106714b24e2bSVaishali Kulkarni 		disabled_vfs[i] = ecore_rd(p_hwfn, p_ptt,
106814b24e2bSVaishali Kulkarni 					   path_addr +
1069*04443fdeSToomas Soome 					   offsetof(struct public_path,
107014b24e2bSVaishali Kulkarni 						    mcp_vf_disabled) +
107114b24e2bSVaishali Kulkarni 					   sizeof(u32) * i);
107214b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
107314b24e2bSVaishali Kulkarni 			   "FLR-ed VFs [%08x,...,%08x] - %08x\n",
107414b24e2bSVaishali Kulkarni 			   i * 32, (i + 1) * 32 - 1, disabled_vfs[i]);
107514b24e2bSVaishali Kulkarni 	}
107614b24e2bSVaishali Kulkarni 
107714b24e2bSVaishali Kulkarni 	if (ecore_iov_mark_vf_flr(p_hwfn, disabled_vfs))
107814b24e2bSVaishali Kulkarni 		OSAL_VF_FLR_UPDATE(p_hwfn);
107914b24e2bSVaishali Kulkarni }
108014b24e2bSVaishali Kulkarni 
ecore_mcp_ack_vf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * vfs_to_ack)108114b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_ack_vf_flr(struct ecore_hwfn *p_hwfn,
108214b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
108314b24e2bSVaishali Kulkarni 					  u32 *vfs_to_ack)
108414b24e2bSVaishali Kulkarni {
108514b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
108614b24e2bSVaishali Kulkarni 					PUBLIC_FUNC);
108714b24e2bSVaishali Kulkarni 	u32 mfw_func_offsize = ecore_rd(p_hwfn, p_ptt, addr);
108814b24e2bSVaishali Kulkarni 	u32 func_addr = SECTION_ADDR(mfw_func_offsize,
108914b24e2bSVaishali Kulkarni 				     MCP_PF_ID(p_hwfn));
109014b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
109114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
109214b24e2bSVaishali Kulkarni 	int i;
109314b24e2bSVaishali Kulkarni 
109414b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
109514b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
109614b24e2bSVaishali Kulkarni 			   "Acking VFs [%08x,...,%08x] - %08x\n",
109714b24e2bSVaishali Kulkarni 			   i * 32, (i + 1) * 32 - 1, vfs_to_ack[i]);
109814b24e2bSVaishali Kulkarni 
109914b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
110014b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_VF_DISABLED_DONE;
110114b24e2bSVaishali Kulkarni 	mb_params.p_data_src = vfs_to_ack;
110214b24e2bSVaishali Kulkarni 	mb_params.data_src_size = VF_MAX_STATIC / 8;
110314b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
110414b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
110514b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
110614b24e2bSVaishali Kulkarni 			  "Failed to pass ACK for VF flr to MFW\n");
110714b24e2bSVaishali Kulkarni 		return ECORE_TIMEOUT;
110814b24e2bSVaishali Kulkarni 	}
110914b24e2bSVaishali Kulkarni 
111014b24e2bSVaishali Kulkarni 	/* TMP - clear the ACK bits; should be done by MFW */
111114b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
111214b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
111314b24e2bSVaishali Kulkarni 			 func_addr +
1114*04443fdeSToomas Soome 			 offsetof(struct public_func, drv_ack_vf_disabled) +
111514b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
111614b24e2bSVaishali Kulkarni 
111714b24e2bSVaishali Kulkarni 	return rc;
111814b24e2bSVaishali Kulkarni }
111914b24e2bSVaishali Kulkarni 
ecore_mcp_handle_transceiver_change(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)112014b24e2bSVaishali Kulkarni static void ecore_mcp_handle_transceiver_change(struct ecore_hwfn *p_hwfn,
112114b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
112214b24e2bSVaishali Kulkarni {
112314b24e2bSVaishali Kulkarni 	u32 transceiver_state;
112414b24e2bSVaishali Kulkarni 
112514b24e2bSVaishali Kulkarni 	transceiver_state = ecore_rd(p_hwfn, p_ptt,
112614b24e2bSVaishali Kulkarni 				     p_hwfn->mcp_info->port_addr +
1127*04443fdeSToomas Soome 				     offsetof(struct public_port,
112814b24e2bSVaishali Kulkarni 					      transceiver_data));
112914b24e2bSVaishali Kulkarni 
113014b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, (ECORE_MSG_HW | ECORE_MSG_SP),
113114b24e2bSVaishali Kulkarni 		   "Received transceiver state update [0x%08x] from mfw [Addr 0x%x]\n",
113214b24e2bSVaishali Kulkarni 		   transceiver_state, (u32)(p_hwfn->mcp_info->port_addr +
1133*04443fdeSToomas Soome 					    offsetof(struct public_port,
113414b24e2bSVaishali Kulkarni 						     transceiver_data)));
113514b24e2bSVaishali Kulkarni 
113614b24e2bSVaishali Kulkarni 	transceiver_state = GET_FIELD(transceiver_state, ETH_TRANSCEIVER_STATE);
113714b24e2bSVaishali Kulkarni 
113814b24e2bSVaishali Kulkarni 	if (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
113914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Transceiver is present.\n");
114014b24e2bSVaishali Kulkarni 	else
114114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Transceiver is unplugged.\n");
114214b24e2bSVaishali Kulkarni }
114314b24e2bSVaishali Kulkarni 
ecore_mcp_read_eee_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_link_state * p_link)114414b24e2bSVaishali Kulkarni static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
114514b24e2bSVaishali Kulkarni 				      struct ecore_ptt *p_ptt,
114614b24e2bSVaishali Kulkarni 				      struct ecore_mcp_link_state *p_link)
114714b24e2bSVaishali Kulkarni {
114814b24e2bSVaishali Kulkarni 	u32 eee_status, val;
114914b24e2bSVaishali Kulkarni 
115014b24e2bSVaishali Kulkarni 	p_link->eee_adv_caps = 0;
115114b24e2bSVaishali Kulkarni 	p_link->eee_lp_adv_caps = 0;
115214b24e2bSVaishali Kulkarni 	eee_status = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
1153*04443fdeSToomas Soome 				     offsetof(struct public_port, eee_status));
115414b24e2bSVaishali Kulkarni 	p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT);
115514b24e2bSVaishali Kulkarni 	val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_SHIFT;
115614b24e2bSVaishali Kulkarni 	if (val & EEE_1G_ADV)
115714b24e2bSVaishali Kulkarni 		p_link->eee_adv_caps |= ECORE_EEE_1G_ADV;
115814b24e2bSVaishali Kulkarni 	if (val & EEE_10G_ADV)
115914b24e2bSVaishali Kulkarni 		p_link->eee_adv_caps |= ECORE_EEE_10G_ADV;
116014b24e2bSVaishali Kulkarni 	val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_SHIFT;
116114b24e2bSVaishali Kulkarni 	if (val & EEE_1G_ADV)
116214b24e2bSVaishali Kulkarni 		p_link->eee_lp_adv_caps |= ECORE_EEE_1G_ADV;
116314b24e2bSVaishali Kulkarni 	if (val & EEE_10G_ADV)
116414b24e2bSVaishali Kulkarni 		p_link->eee_lp_adv_caps |= ECORE_EEE_10G_ADV;
116514b24e2bSVaishali Kulkarni }
116614b24e2bSVaishali Kulkarni 
ecore_mcp_handle_link_change(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,bool b_reset)116714b24e2bSVaishali Kulkarni static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
116814b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
116914b24e2bSVaishali Kulkarni 					 bool b_reset)
117014b24e2bSVaishali Kulkarni {
117114b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_state *p_link;
117214b24e2bSVaishali Kulkarni 	u8 max_bw, min_bw;
117314b24e2bSVaishali Kulkarni 	u32 status = 0;
117414b24e2bSVaishali Kulkarni 
117514b24e2bSVaishali Kulkarni 	/* Prevent SW/attentions from doing this at the same time */
117614b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&p_hwfn->mcp_info->link_lock);
117714b24e2bSVaishali Kulkarni 
117814b24e2bSVaishali Kulkarni 	p_link = &p_hwfn->mcp_info->link_output;
117914b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_link, 0, sizeof(*p_link));
118014b24e2bSVaishali Kulkarni 	if (!b_reset) {
118114b24e2bSVaishali Kulkarni 		status = ecore_rd(p_hwfn, p_ptt,
118214b24e2bSVaishali Kulkarni 				  p_hwfn->mcp_info->port_addr +
1183*04443fdeSToomas Soome 				  offsetof(struct public_port, link_status));
118414b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_LINK | ECORE_MSG_SP),
118514b24e2bSVaishali Kulkarni 			   "Received link update [0x%08x] from mfw [Addr 0x%x]\n",
118614b24e2bSVaishali Kulkarni 			   status, (u32)(p_hwfn->mcp_info->port_addr +
1187*04443fdeSToomas Soome 			   offsetof(struct public_port, link_status)));
118814b24e2bSVaishali Kulkarni 	} else {
118914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
119014b24e2bSVaishali Kulkarni 			   "Resetting link indications\n");
119114b24e2bSVaishali Kulkarni 		goto out;
119214b24e2bSVaishali Kulkarni 	}
119314b24e2bSVaishali Kulkarni 
119414b24e2bSVaishali Kulkarni 	if (p_hwfn->b_drv_link_init)
119514b24e2bSVaishali Kulkarni 		p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
119614b24e2bSVaishali Kulkarni 	else
119714b24e2bSVaishali Kulkarni 		p_link->link_up = false;
119814b24e2bSVaishali Kulkarni 
119914b24e2bSVaishali Kulkarni 	p_link->full_duplex = true;
120014b24e2bSVaishali Kulkarni 	switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) {
120114b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_100G:
120214b24e2bSVaishali Kulkarni 		p_link->speed = 100000;
120314b24e2bSVaishali Kulkarni 		break;
120414b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_50G:
120514b24e2bSVaishali Kulkarni 		p_link->speed = 50000;
120614b24e2bSVaishali Kulkarni 		break;
120714b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_40G:
120814b24e2bSVaishali Kulkarni 		p_link->speed = 40000;
120914b24e2bSVaishali Kulkarni 		break;
121014b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_25G:
121114b24e2bSVaishali Kulkarni 		p_link->speed = 25000;
121214b24e2bSVaishali Kulkarni 		break;
121314b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_20G:
121414b24e2bSVaishali Kulkarni 		p_link->speed = 20000;
121514b24e2bSVaishali Kulkarni 		break;
121614b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_10G:
121714b24e2bSVaishali Kulkarni 		p_link->speed = 10000;
121814b24e2bSVaishali Kulkarni 		break;
121914b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_1000THD:
122014b24e2bSVaishali Kulkarni 		p_link->full_duplex = false;
122114b24e2bSVaishali Kulkarni 		/* Fall-through */
122214b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD:
122314b24e2bSVaishali Kulkarni 		p_link->speed = 1000;
122414b24e2bSVaishali Kulkarni 		break;
122514b24e2bSVaishali Kulkarni 	default:
122614b24e2bSVaishali Kulkarni 		p_link->speed = 0;
122714b24e2bSVaishali Kulkarni 	}
122814b24e2bSVaishali Kulkarni 
122914b24e2bSVaishali Kulkarni 	/* We never store total line speed as p_link->speed is
123014b24e2bSVaishali Kulkarni 	 * again changes according to bandwidth allocation.
123114b24e2bSVaishali Kulkarni 	 */
123214b24e2bSVaishali Kulkarni 	if (p_link->link_up && p_link->speed)
123314b24e2bSVaishali Kulkarni 		p_link->line_speed = p_link->speed;
123414b24e2bSVaishali Kulkarni 	else
123514b24e2bSVaishali Kulkarni 		p_link->line_speed = 0;
123614b24e2bSVaishali Kulkarni 
123714b24e2bSVaishali Kulkarni 	max_bw = p_hwfn->mcp_info->func_info.bandwidth_max;
123814b24e2bSVaishali Kulkarni 	min_bw = p_hwfn->mcp_info->func_info.bandwidth_min;
123914b24e2bSVaishali Kulkarni 
124014b24e2bSVaishali Kulkarni 	/* Max bandwidth configuration */
124114b24e2bSVaishali Kulkarni 	__ecore_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw);
124214b24e2bSVaishali Kulkarni 
124314b24e2bSVaishali Kulkarni 	/* Mintz bandwidth configuration */
124414b24e2bSVaishali Kulkarni 	__ecore_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw);
124514b24e2bSVaishali Kulkarni 	ecore_configure_vp_wfq_on_link_change(p_hwfn->p_dev, p_ptt,
124614b24e2bSVaishali Kulkarni 					      p_link->min_pf_rate);
124714b24e2bSVaishali Kulkarni 
124814b24e2bSVaishali Kulkarni 	p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
124914b24e2bSVaishali Kulkarni 	p_link->an_complete = !!(status &
125014b24e2bSVaishali Kulkarni 				 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE);
125114b24e2bSVaishali Kulkarni 	p_link->parallel_detection = !!(status &
125214b24e2bSVaishali Kulkarni 					LINK_STATUS_PARALLEL_DETECTION_USED);
125314b24e2bSVaishali Kulkarni 	p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED);
125414b24e2bSVaishali Kulkarni 
125514b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
125614b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ?
125714b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_1G_FD : 0;
125814b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
125914b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ?
126014b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_1G_HD : 0;
126114b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
126214b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ?
126314b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_10G : 0;
126414b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
126514b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ?
126614b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_20G : 0;
126714b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
126814b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_25G_CAPABLE) ?
126914b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_25G : 0;
127014b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
127114b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ?
127214b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_40G : 0;
127314b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
127414b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ?
127514b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_50G : 0;
127614b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
127714b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ?
127814b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_100G : 0;
127914b24e2bSVaishali Kulkarni 
128014b24e2bSVaishali Kulkarni 	p_link->partner_tx_flow_ctrl_en =
128114b24e2bSVaishali Kulkarni 		!!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED);
128214b24e2bSVaishali Kulkarni 	p_link->partner_rx_flow_ctrl_en =
128314b24e2bSVaishali Kulkarni 		!!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
128414b24e2bSVaishali Kulkarni 
128514b24e2bSVaishali Kulkarni 	switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) {
128614b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE:
128714b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_SYMMETRIC_PAUSE;
128814b24e2bSVaishali Kulkarni 		break;
128914b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE:
129014b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE;
129114b24e2bSVaishali Kulkarni 		break;
129214b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE:
129314b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_BOTH_PAUSE;
129414b24e2bSVaishali Kulkarni 		break;
129514b24e2bSVaishali Kulkarni 	default:
129614b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = 0;
129714b24e2bSVaishali Kulkarni 	}
129814b24e2bSVaishali Kulkarni 
129914b24e2bSVaishali Kulkarni 	p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
130014b24e2bSVaishali Kulkarni 
130114b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
130214b24e2bSVaishali Kulkarni 		ecore_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
130314b24e2bSVaishali Kulkarni 
130414b24e2bSVaishali Kulkarni 	OSAL_LINK_UPDATE(p_hwfn);
130514b24e2bSVaishali Kulkarni out:
130614b24e2bSVaishali Kulkarni 	OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->link_lock);
130714b24e2bSVaishali Kulkarni }
130814b24e2bSVaishali Kulkarni 
ecore_mcp_set_link(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,bool b_up)130914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_link(struct ecore_hwfn *p_hwfn,
131014b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt,
131114b24e2bSVaishali Kulkarni 					bool b_up)
131214b24e2bSVaishali Kulkarni {
131314b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
131414b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
131514b24e2bSVaishali Kulkarni 	struct eth_phy_cfg phy_cfg;
131614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
131714b24e2bSVaishali Kulkarni 	u32 cmd;
131814b24e2bSVaishali Kulkarni 
131914b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
132014b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
132114b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
132214b24e2bSVaishali Kulkarni #endif
132314b24e2bSVaishali Kulkarni 
132414b24e2bSVaishali Kulkarni 	/* Set the shmem configuration according to params */
132514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&phy_cfg, sizeof(phy_cfg));
132614b24e2bSVaishali Kulkarni 	cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET;
132714b24e2bSVaishali Kulkarni 	if (!params->speed.autoneg)
132814b24e2bSVaishali Kulkarni 		phy_cfg.speed = params->speed.forced_speed;
132914b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.autoneg) ? ETH_PAUSE_AUTONEG : 0;
133014b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.forced_rx) ? ETH_PAUSE_RX : 0;
133114b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0;
133214b24e2bSVaishali Kulkarni 	phy_cfg.adv_speed = params->speed.advertised_speeds;
133314b24e2bSVaishali Kulkarni 	phy_cfg.loopback_mode = params->loopback_mode;
133414b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
133514b24e2bSVaishali Kulkarni 		if (params->eee.enable)
133614b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED;
133714b24e2bSVaishali Kulkarni 		if (params->eee.tx_lpi_enable)
133814b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_TX_LPI;
133914b24e2bSVaishali Kulkarni 		if (params->eee.adv_caps & ECORE_EEE_1G_ADV)
134014b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G;
134114b24e2bSVaishali Kulkarni 		if (params->eee.adv_caps & ECORE_EEE_10G_ADV)
134214b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G;
134314b24e2bSVaishali Kulkarni 		phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer <<
134414b24e2bSVaishali Kulkarni 				    EEE_TX_TIMER_USEC_SHIFT) &
134514b24e2bSVaishali Kulkarni 					EEE_TX_TIMER_USEC_MASK;
134614b24e2bSVaishali Kulkarni 	}
134714b24e2bSVaishali Kulkarni 
134814b24e2bSVaishali Kulkarni 	p_hwfn->b_drv_link_init = b_up;
134914b24e2bSVaishali Kulkarni 
135014b24e2bSVaishali Kulkarni 	if (b_up)
135114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
135214b24e2bSVaishali Kulkarni 			   "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x\n",
135314b24e2bSVaishali Kulkarni 			   phy_cfg.speed, phy_cfg.pause, phy_cfg.adv_speed,
135414b24e2bSVaishali Kulkarni 			   phy_cfg.loopback_mode);
135514b24e2bSVaishali Kulkarni 	else
135614b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK, "Resetting link\n");
135714b24e2bSVaishali Kulkarni 
135814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
135914b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
136014b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &phy_cfg;
136114b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(phy_cfg);
136214b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
136314b24e2bSVaishali Kulkarni 
136414b24e2bSVaishali Kulkarni 	/* if mcp fails to respond we must abort */
136514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
136614b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
136714b24e2bSVaishali Kulkarni 		return rc;
136814b24e2bSVaishali Kulkarni 	}
136914b24e2bSVaishali Kulkarni 
137014b24e2bSVaishali Kulkarni 	/* Mimic link-change attention, done for several reasons:
137114b24e2bSVaishali Kulkarni 	 *  - On reset, there's no guarantee MFW would trigger
137214b24e2bSVaishali Kulkarni 	 *    an attention.
137314b24e2bSVaishali Kulkarni 	 *  - On initialization, older MFWs might not indicate link change
137414b24e2bSVaishali Kulkarni 	 *    during LFA, so we'll never get an UP indication.
137514b24e2bSVaishali Kulkarni 	 */
137614b24e2bSVaishali Kulkarni 	ecore_mcp_handle_link_change(p_hwfn, p_ptt, !b_up);
137714b24e2bSVaishali Kulkarni 
137814b24e2bSVaishali Kulkarni 	return rc;
137914b24e2bSVaishali Kulkarni }
138014b24e2bSVaishali Kulkarni 
ecore_get_process_kill_counter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)138114b24e2bSVaishali Kulkarni u32 ecore_get_process_kill_counter(struct ecore_hwfn *p_hwfn,
138214b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt)
138314b24e2bSVaishali Kulkarni {
138414b24e2bSVaishali Kulkarni 	u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt;
138514b24e2bSVaishali Kulkarni 
138614b24e2bSVaishali Kulkarni 	/* TODO - Add support for VFs */
138714b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
138814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
138914b24e2bSVaishali Kulkarni 
139014b24e2bSVaishali Kulkarni 	path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
139114b24e2bSVaishali Kulkarni 						 PUBLIC_PATH);
139214b24e2bSVaishali Kulkarni 	path_offsize = ecore_rd(p_hwfn, p_ptt, path_offsize_addr);
139314b24e2bSVaishali Kulkarni 	path_addr = SECTION_ADDR(path_offsize, ECORE_PATH_ID(p_hwfn));
139414b24e2bSVaishali Kulkarni 
139514b24e2bSVaishali Kulkarni 	proc_kill_cnt = ecore_rd(p_hwfn, p_ptt,
139614b24e2bSVaishali Kulkarni 				 path_addr +
1397*04443fdeSToomas Soome 				 offsetof(struct public_path, process_kill)) &
139814b24e2bSVaishali Kulkarni 			PROCESS_KILL_COUNTER_MASK;
139914b24e2bSVaishali Kulkarni 
140014b24e2bSVaishali Kulkarni 	return proc_kill_cnt;
140114b24e2bSVaishali Kulkarni }
140214b24e2bSVaishali Kulkarni 
ecore_mcp_handle_process_kill(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)140314b24e2bSVaishali Kulkarni static void ecore_mcp_handle_process_kill(struct ecore_hwfn *p_hwfn,
140414b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt)
140514b24e2bSVaishali Kulkarni {
140614b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
140714b24e2bSVaishali Kulkarni 	u32 proc_kill_cnt;
140814b24e2bSVaishali Kulkarni 
140914b24e2bSVaishali Kulkarni 	/* Prevent possible attentions/interrupts during the recovery handling
141014b24e2bSVaishali Kulkarni 	 * and till its load phase, during which they will be re-enabled.
141114b24e2bSVaishali Kulkarni 	 */
141214b24e2bSVaishali Kulkarni 	ecore_int_igu_disable_int(p_hwfn, p_ptt);
141314b24e2bSVaishali Kulkarni 
141414b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Received a process kill indication\n");
141514b24e2bSVaishali Kulkarni 
141614b24e2bSVaishali Kulkarni 	/* The following operations should be done once, and thus in CMT mode
141714b24e2bSVaishali Kulkarni 	 * are carried out by only the first HW function.
141814b24e2bSVaishali Kulkarni 	 */
141914b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_dev))
142014b24e2bSVaishali Kulkarni 		return;
142114b24e2bSVaishali Kulkarni 
142214b24e2bSVaishali Kulkarni 	if (p_dev->recov_in_prog) {
142314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
142414b24e2bSVaishali Kulkarni 			  "Ignoring the indication since a recovery process is already in progress\n");
142514b24e2bSVaishali Kulkarni 		return;
142614b24e2bSVaishali Kulkarni 	}
142714b24e2bSVaishali Kulkarni 
142814b24e2bSVaishali Kulkarni 	p_dev->recov_in_prog = true;
142914b24e2bSVaishali Kulkarni 
143014b24e2bSVaishali Kulkarni 	proc_kill_cnt = ecore_get_process_kill_counter(p_hwfn, p_ptt);
143114b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Process kill counter: %d\n", proc_kill_cnt);
143214b24e2bSVaishali Kulkarni 
143314b24e2bSVaishali Kulkarni 	OSAL_SCHEDULE_RECOVERY_HANDLER(p_hwfn);
143414b24e2bSVaishali Kulkarni }
143514b24e2bSVaishali Kulkarni 
ecore_mcp_send_protocol_stats(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum MFW_DRV_MSG_TYPE type)143614b24e2bSVaishali Kulkarni static void ecore_mcp_send_protocol_stats(struct ecore_hwfn *p_hwfn,
143714b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
143814b24e2bSVaishali Kulkarni 					  enum MFW_DRV_MSG_TYPE type)
143914b24e2bSVaishali Kulkarni {
1440b68ddc76SJohn Levon 	enum ecore_mcp_protocol_type stats_type __unused;
144114b24e2bSVaishali Kulkarni 	union ecore_mcp_protocol_stats stats;
144214b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
144314b24e2bSVaishali Kulkarni 	u32 hsi_param;
144414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
144514b24e2bSVaishali Kulkarni 
144614b24e2bSVaishali Kulkarni 	switch (type) {
144714b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_LAN_STATS:
144814b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_LAN_STATS;
144914b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN;
145014b24e2bSVaishali Kulkarni 		break;
145114b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_FCOE_STATS:
145214b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_FCOE_STATS;
145314b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_FCOE;
145414b24e2bSVaishali Kulkarni 		break;
145514b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_ISCSI_STATS:
145614b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_ISCSI_STATS;
145714b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_ISCSI;
145814b24e2bSVaishali Kulkarni 		break;
145914b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_RDMA_STATS:
146014b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_RDMA_STATS;
146114b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_RDMA;
146214b24e2bSVaishali Kulkarni 		break;
146314b24e2bSVaishali Kulkarni 	default:
146414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Invalid protocol type %d\n", type);
146514b24e2bSVaishali Kulkarni 		return;
146614b24e2bSVaishali Kulkarni 	}
146714b24e2bSVaishali Kulkarni 
146814b24e2bSVaishali Kulkarni 	OSAL_GET_PROTOCOL_STATS(p_hwfn->p_dev, stats_type, &stats);
146914b24e2bSVaishali Kulkarni 
147014b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
147114b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_STATS;
147214b24e2bSVaishali Kulkarni 	mb_params.param = hsi_param;
147314b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &stats;
147414b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(stats);
147514b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
147614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
147714b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send protocol stats, rc = %d\n", rc);
147814b24e2bSVaishali Kulkarni }
147914b24e2bSVaishali Kulkarni 
ecore_read_pf_bandwidth(struct ecore_hwfn * p_hwfn,struct public_func * p_shmem_info)148014b24e2bSVaishali Kulkarni static void ecore_read_pf_bandwidth(struct ecore_hwfn *p_hwfn,
148114b24e2bSVaishali Kulkarni 				    struct public_func *p_shmem_info)
148214b24e2bSVaishali Kulkarni {
148314b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *p_info;
148414b24e2bSVaishali Kulkarni 
148514b24e2bSVaishali Kulkarni 	p_info = &p_hwfn->mcp_info->func_info;
148614b24e2bSVaishali Kulkarni 
148714b24e2bSVaishali Kulkarni 	/* TODO - bandwidth min/max should have valid values of 1-100,
148814b24e2bSVaishali Kulkarni 	 * as well as some indication that the feature is disabled.
148914b24e2bSVaishali Kulkarni 	 * Until MFW/qlediag enforce those limitations, Assume THERE IS ALWAYS
149014b24e2bSVaishali Kulkarni 	 * limit and correct value to min `1' and max `100' if limit isn't in
149114b24e2bSVaishali Kulkarni 	 * range.
149214b24e2bSVaishali Kulkarni 	 */
149314b24e2bSVaishali Kulkarni 	p_info->bandwidth_min = (p_shmem_info->config &
149414b24e2bSVaishali Kulkarni 				 FUNC_MF_CFG_MIN_BW_MASK) >>
149514b24e2bSVaishali Kulkarni 				FUNC_MF_CFG_MIN_BW_SHIFT;
149614b24e2bSVaishali Kulkarni 	if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) {
149714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
149814b24e2bSVaishali Kulkarni 			"bandwidth minimum out of bounds [%02x]. Set to 1\n",
149914b24e2bSVaishali Kulkarni 			p_info->bandwidth_min);
150014b24e2bSVaishali Kulkarni 		p_info->bandwidth_min = 1;
150114b24e2bSVaishali Kulkarni 	}
150214b24e2bSVaishali Kulkarni 
150314b24e2bSVaishali Kulkarni 	p_info->bandwidth_max = (p_shmem_info->config &
150414b24e2bSVaishali Kulkarni 				 FUNC_MF_CFG_MAX_BW_MASK) >>
150514b24e2bSVaishali Kulkarni 				FUNC_MF_CFG_MAX_BW_SHIFT;
150614b24e2bSVaishali Kulkarni 	if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) {
150714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
150814b24e2bSVaishali Kulkarni 			"bandwidth maximum out of bounds [%02x]. Set to 100\n",
150914b24e2bSVaishali Kulkarni 			p_info->bandwidth_max);
151014b24e2bSVaishali Kulkarni 		p_info->bandwidth_max = 100;
151114b24e2bSVaishali Kulkarni 	}
151214b24e2bSVaishali Kulkarni }
151314b24e2bSVaishali Kulkarni 
ecore_mcp_get_shmem_func(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct public_func * p_data,int pfid)151414b24e2bSVaishali Kulkarni static u32 ecore_mcp_get_shmem_func(struct ecore_hwfn *p_hwfn,
151514b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt,
151614b24e2bSVaishali Kulkarni 				    struct public_func *p_data,
151714b24e2bSVaishali Kulkarni 				    int pfid)
151814b24e2bSVaishali Kulkarni {
151914b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
152014b24e2bSVaishali Kulkarni 					PUBLIC_FUNC);
152114b24e2bSVaishali Kulkarni 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
152214b24e2bSVaishali Kulkarni 	u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
152314b24e2bSVaishali Kulkarni 	u32 i, size;
152414b24e2bSVaishali Kulkarni 
152514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(p_data, sizeof(*p_data));
152614b24e2bSVaishali Kulkarni 
152714b24e2bSVaishali Kulkarni 	size = OSAL_MIN_T(u32, sizeof(*p_data),
152814b24e2bSVaishali Kulkarni 			  SECTION_SIZE(mfw_path_offsize));
152914b24e2bSVaishali Kulkarni 	for (i = 0; i < size / sizeof(u32); i++)
153014b24e2bSVaishali Kulkarni 		((u32 *)p_data)[i] = ecore_rd(p_hwfn, p_ptt,
153114b24e2bSVaishali Kulkarni 					      func_addr + (i << 2));
153214b24e2bSVaishali Kulkarni 
153314b24e2bSVaishali Kulkarni 	return size;
153414b24e2bSVaishali Kulkarni }
153514b24e2bSVaishali Kulkarni #if 0
153614b24e2bSVaishali Kulkarni /* This was introduced with FW 8.10.5.0; Hopefully this is only temp. */
153714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_init_first_eth(struct ecore_hwfn *p_hwfn,
153814b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
153914b24e2bSVaishali Kulkarni 					     u8 *p_pf)
154014b24e2bSVaishali Kulkarni {
154114b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
154214b24e2bSVaishali Kulkarni 	int i;
154314b24e2bSVaishali Kulkarni 
154414b24e2bSVaishali Kulkarni 	/* Find first Ethernet interface in port */
154514b24e2bSVaishali Kulkarni 	for (i = 0; i < NUM_OF_ENG_PFS(p_hwfn->p_dev);
154614b24e2bSVaishali Kulkarni 	     i += p_hwfn->p_dev->num_ports_in_engine) {
154714b24e2bSVaishali Kulkarni 		ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
154814b24e2bSVaishali Kulkarni 					 MCP_PF_ID_BY_REL(p_hwfn, i));
154914b24e2bSVaishali Kulkarni 
155014b24e2bSVaishali Kulkarni 		if (shmem_info.config & FUNC_MF_CFG_FUNC_HIDE)
155114b24e2bSVaishali Kulkarni 			continue;
155214b24e2bSVaishali Kulkarni 
155314b24e2bSVaishali Kulkarni 		if ((shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK) ==
155414b24e2bSVaishali Kulkarni 		    FUNC_MF_CFG_PROTOCOL_ETHERNET) {
155514b24e2bSVaishali Kulkarni 			*p_pf = (u8)i;
155614b24e2bSVaishali Kulkarni 			return ECORE_SUCCESS;
155714b24e2bSVaishali Kulkarni 		}
155814b24e2bSVaishali Kulkarni 	}
155914b24e2bSVaishali Kulkarni 
156014b24e2bSVaishali Kulkarni 	/* This might actually be valid somewhere in the future but for now
156114b24e2bSVaishali Kulkarni 	 * it's highly unlikely.
156214b24e2bSVaishali Kulkarni 	 */
156314b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
156414b24e2bSVaishali Kulkarni 		  "Failed to find on port an ethernet interface in MF_SI mode\n");
156514b24e2bSVaishali Kulkarni 
156614b24e2bSVaishali Kulkarni 	return ECORE_INVAL;
156714b24e2bSVaishali Kulkarni }
156814b24e2bSVaishali Kulkarni #endif
156914b24e2bSVaishali Kulkarni static void
ecore_mcp_update_bw(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)157014b24e2bSVaishali Kulkarni ecore_mcp_update_bw(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
157114b24e2bSVaishali Kulkarni {
157214b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *p_info;
157314b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
157414b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
157514b24e2bSVaishali Kulkarni 
157614b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
157714b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
157814b24e2bSVaishali Kulkarni 
157914b24e2bSVaishali Kulkarni 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
158014b24e2bSVaishali Kulkarni 
158114b24e2bSVaishali Kulkarni 	p_info = &p_hwfn->mcp_info->func_info;
158214b24e2bSVaishali Kulkarni 
158314b24e2bSVaishali Kulkarni 	ecore_configure_pf_min_bandwidth(p_hwfn->p_dev, p_info->bandwidth_min);
158414b24e2bSVaishali Kulkarni 
158514b24e2bSVaishali Kulkarni 	ecore_configure_pf_max_bandwidth(p_hwfn->p_dev, p_info->bandwidth_max);
158614b24e2bSVaishali Kulkarni 
158714b24e2bSVaishali Kulkarni 	/* Acknowledge the MFW */
158814b24e2bSVaishali Kulkarni 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp,
158914b24e2bSVaishali Kulkarni 		      &param);
159014b24e2bSVaishali Kulkarni }
159114b24e2bSVaishali Kulkarni 
ecore_mcp_update_stag(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)159214b24e2bSVaishali Kulkarni static void ecore_mcp_update_stag(struct ecore_hwfn *p_hwfn,
159314b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt)
159414b24e2bSVaishali Kulkarni {
159514b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
159614b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
159714b24e2bSVaishali Kulkarni 
159814b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
159914b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
160014b24e2bSVaishali Kulkarni 
160114b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->func_info.ovlan = (u16)shmem_info.ovlan_stag &
160214b24e2bSVaishali Kulkarni 						 FUNC_MF_CFG_OV_STAG_MASK;
160314b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.ovlan = p_hwfn->mcp_info->func_info.ovlan;
160414b24e2bSVaishali Kulkarni 	if ((p_hwfn->hw_info.hw_mode & (1 << MODE_MF_SD)) &&
160514b24e2bSVaishali Kulkarni 	    (p_hwfn->hw_info.ovlan != ECORE_MCP_VLAN_UNSET)) {
160614b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
160714b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_TAG_VALUE,
160814b24e2bSVaishali Kulkarni 			 p_hwfn->hw_info.ovlan);
160914b24e2bSVaishali Kulkarni 		ecore_sp_pf_update_stag(p_hwfn);
161014b24e2bSVaishali Kulkarni 	}
161114b24e2bSVaishali Kulkarni 
161214b24e2bSVaishali Kulkarni 	OSAL_HW_INFO_CHANGE(p_hwfn, ECORE_HW_INFO_CHANGE_OVLAN);
161314b24e2bSVaishali Kulkarni 
161414b24e2bSVaishali Kulkarni 	/* Acknowledge the MFW */
161514b24e2bSVaishali Kulkarni 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_S_TAG_UPDATE_ACK, 0,
161614b24e2bSVaishali Kulkarni 		      &resp, &param);
161714b24e2bSVaishali Kulkarni }
161814b24e2bSVaishali Kulkarni 
ecore_mcp_handle_fan_failure(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)161914b24e2bSVaishali Kulkarni static void ecore_mcp_handle_fan_failure(struct ecore_hwfn *p_hwfn,
162014b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt)
162114b24e2bSVaishali Kulkarni {
162214b24e2bSVaishali Kulkarni 	/* A single notification should be sent to upper driver in CMT mode */
162314b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
162414b24e2bSVaishali Kulkarni 		return;
162514b24e2bSVaishali Kulkarni 
162614b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
162714b24e2bSVaishali Kulkarni 		  "Fan failure was detected on the network interface card and it's going to be shut down.\n");
162814b24e2bSVaishali Kulkarni 
162914b24e2bSVaishali Kulkarni 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_FAN_FAIL);
163014b24e2bSVaishali Kulkarni }
163114b24e2bSVaishali Kulkarni 
163214b24e2bSVaishali Kulkarni struct ecore_mdump_cmd_params {
163314b24e2bSVaishali Kulkarni 	u32 cmd;
163414b24e2bSVaishali Kulkarni 	void *p_data_src;
163514b24e2bSVaishali Kulkarni 	u8 data_src_size;
163614b24e2bSVaishali Kulkarni 	void *p_data_dst;
163714b24e2bSVaishali Kulkarni 	u8 data_dst_size;
163814b24e2bSVaishali Kulkarni 	u32 mcp_resp;
163914b24e2bSVaishali Kulkarni };
164014b24e2bSVaishali Kulkarni 
164114b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_mdump_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_cmd_params * p_mdump_cmd_params)164214b24e2bSVaishali Kulkarni ecore_mcp_mdump_cmd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
164314b24e2bSVaishali Kulkarni 		    struct ecore_mdump_cmd_params *p_mdump_cmd_params)
164414b24e2bSVaishali Kulkarni {
164514b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
164614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
164714b24e2bSVaishali Kulkarni 
164814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
164914b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_MDUMP_CMD;
165014b24e2bSVaishali Kulkarni 	mb_params.param = p_mdump_cmd_params->cmd;
165114b24e2bSVaishali Kulkarni 	mb_params.p_data_src = p_mdump_cmd_params->p_data_src;
165214b24e2bSVaishali Kulkarni 	mb_params.data_src_size = p_mdump_cmd_params->data_src_size;
165314b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = p_mdump_cmd_params->p_data_dst;
165414b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = p_mdump_cmd_params->data_dst_size;
165514b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
165614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
165714b24e2bSVaishali Kulkarni 		return rc;
165814b24e2bSVaishali Kulkarni 
165914b24e2bSVaishali Kulkarni 	p_mdump_cmd_params->mcp_resp = mb_params.mcp_resp;
166014b24e2bSVaishali Kulkarni 
166114b24e2bSVaishali Kulkarni 	if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_MDUMP_INVALID_CMD) {
166214b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
166314b24e2bSVaishali Kulkarni 			"The mdump sub command is unsupported by the MFW [mdump_cmd 0x%x]\n",
166414b24e2bSVaishali Kulkarni 			p_mdump_cmd_params->cmd);
166514b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
166614b24e2bSVaishali Kulkarni 	} else if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
166714b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
166814b24e2bSVaishali Kulkarni 			"The mdump command is not supported by the MFW\n");
166914b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
167014b24e2bSVaishali Kulkarni 	}
167114b24e2bSVaishali Kulkarni 
167214b24e2bSVaishali Kulkarni 	return rc;
167314b24e2bSVaishali Kulkarni }
167414b24e2bSVaishali Kulkarni 
ecore_mcp_mdump_ack(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)167514b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_mdump_ack(struct ecore_hwfn *p_hwfn,
167614b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
167714b24e2bSVaishali Kulkarni {
167814b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
167914b24e2bSVaishali Kulkarni 
168014b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
168114b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_ACK;
168214b24e2bSVaishali Kulkarni 
168314b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
168414b24e2bSVaishali Kulkarni }
168514b24e2bSVaishali Kulkarni 
ecore_mcp_mdump_set_values(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 epoch)168614b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_set_values(struct ecore_hwfn *p_hwfn,
168714b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt,
168814b24e2bSVaishali Kulkarni 						u32 epoch)
168914b24e2bSVaishali Kulkarni {
169014b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
169114b24e2bSVaishali Kulkarni 
169214b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
169314b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_SET_VALUES;
169414b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_src = &epoch;
169514b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_src_size = sizeof(epoch);
169614b24e2bSVaishali Kulkarni 
169714b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
169814b24e2bSVaishali Kulkarni }
169914b24e2bSVaishali Kulkarni 
ecore_mcp_mdump_trigger(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)170014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_trigger(struct ecore_hwfn *p_hwfn,
170114b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt)
170214b24e2bSVaishali Kulkarni {
170314b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
170414b24e2bSVaishali Kulkarni 
170514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
170614b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_TRIGGER;
170714b24e2bSVaishali Kulkarni 
170814b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
170914b24e2bSVaishali Kulkarni }
171014b24e2bSVaishali Kulkarni 
171114b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_mdump_get_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct mdump_config_stc * p_mdump_config)171214b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_config(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
171314b24e2bSVaishali Kulkarni 			   struct mdump_config_stc *p_mdump_config)
171414b24e2bSVaishali Kulkarni {
171514b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
171614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
171714b24e2bSVaishali Kulkarni 
171814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
171914b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_CONFIG;
172014b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_dst = p_mdump_config;
172114b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_dst_size = sizeof(*p_mdump_config);
172214b24e2bSVaishali Kulkarni 
172314b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
172414b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
172514b24e2bSVaishali Kulkarni 		return rc;
172614b24e2bSVaishali Kulkarni 
172714b24e2bSVaishali Kulkarni 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
172814b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
172914b24e2bSVaishali Kulkarni 			"Failed to get the mdump configuration and logs info [mcp_resp 0x%x]\n",
173014b24e2bSVaishali Kulkarni 			mdump_cmd_params.mcp_resp);
173114b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
173214b24e2bSVaishali Kulkarni 	}
173314b24e2bSVaishali Kulkarni 
173414b24e2bSVaishali Kulkarni 	return rc;
173514b24e2bSVaishali Kulkarni }
173614b24e2bSVaishali Kulkarni 
173714b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_mdump_get_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_info * p_mdump_info)173814b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
173914b24e2bSVaishali Kulkarni 			 struct ecore_mdump_info *p_mdump_info)
174014b24e2bSVaishali Kulkarni {
174114b24e2bSVaishali Kulkarni 	u32 addr, global_offsize, global_addr;
174214b24e2bSVaishali Kulkarni 	struct mdump_config_stc mdump_config;
174314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
174414b24e2bSVaishali Kulkarni 
174514b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_mdump_info, 0, sizeof(*p_mdump_info));
174614b24e2bSVaishali Kulkarni 
174714b24e2bSVaishali Kulkarni 	addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
174814b24e2bSVaishali Kulkarni 				    PUBLIC_GLOBAL);
174914b24e2bSVaishali Kulkarni 	global_offsize = ecore_rd(p_hwfn, p_ptt, addr);
175014b24e2bSVaishali Kulkarni 	global_addr = SECTION_ADDR(global_offsize, 0);
175114b24e2bSVaishali Kulkarni 	p_mdump_info->reason = ecore_rd(p_hwfn, p_ptt,
175214b24e2bSVaishali Kulkarni 					global_addr +
1753*04443fdeSToomas Soome 					offsetof(struct public_global,
175414b24e2bSVaishali Kulkarni 						 mdump_reason));
175514b24e2bSVaishali Kulkarni 
175614b24e2bSVaishali Kulkarni 	if (p_mdump_info->reason) {
175714b24e2bSVaishali Kulkarni 		rc = ecore_mcp_mdump_get_config(p_hwfn, p_ptt, &mdump_config);
175814b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
175914b24e2bSVaishali Kulkarni 			return rc;
176014b24e2bSVaishali Kulkarni 
176114b24e2bSVaishali Kulkarni 		p_mdump_info->version = mdump_config.version;
176214b24e2bSVaishali Kulkarni 		p_mdump_info->config = mdump_config.config;
176314b24e2bSVaishali Kulkarni 		p_mdump_info->epoch = mdump_config.epoc;
176414b24e2bSVaishali Kulkarni 		p_mdump_info->num_of_logs = mdump_config.num_of_logs;
176514b24e2bSVaishali Kulkarni 		p_mdump_info->valid_logs = mdump_config.valid_logs;
176614b24e2bSVaishali Kulkarni 
176714b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
176814b24e2bSVaishali Kulkarni 			   "MFW mdump info: reason %d, version 0x%x, config 0x%x, epoch 0x%x, num_of_logs 0x%x, valid_logs 0x%x\n",
176914b24e2bSVaishali Kulkarni 			   p_mdump_info->reason, p_mdump_info->version,
177014b24e2bSVaishali Kulkarni 			   p_mdump_info->config, p_mdump_info->epoch,
177114b24e2bSVaishali Kulkarni 			   p_mdump_info->num_of_logs, p_mdump_info->valid_logs);
177214b24e2bSVaishali Kulkarni 	} else {
177314b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
177414b24e2bSVaishali Kulkarni 			   "MFW mdump info: reason %d\n", p_mdump_info->reason);
177514b24e2bSVaishali Kulkarni 	}
177614b24e2bSVaishali Kulkarni 
177714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
177814b24e2bSVaishali Kulkarni }
177914b24e2bSVaishali Kulkarni 
ecore_mcp_mdump_clear_logs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)178014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_clear_logs(struct ecore_hwfn *p_hwfn,
178114b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
178214b24e2bSVaishali Kulkarni {
178314b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
178414b24e2bSVaishali Kulkarni 
178514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
178614b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLEAR_LOGS;
178714b24e2bSVaishali Kulkarni 
178814b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
178914b24e2bSVaishali Kulkarni }
179014b24e2bSVaishali Kulkarni 
179114b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_mdump_get_retain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_retain_data * p_mdump_retain)179214b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_retain(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
179314b24e2bSVaishali Kulkarni 			   struct ecore_mdump_retain_data *p_mdump_retain)
179414b24e2bSVaishali Kulkarni {
179514b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
179614b24e2bSVaishali Kulkarni 	struct mdump_retain_data_stc mfw_mdump_retain;
179714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
179814b24e2bSVaishali Kulkarni 
179914b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
180014b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_RETAIN;
180114b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_dst = &mfw_mdump_retain;
180214b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_dst_size = sizeof(mfw_mdump_retain);
180314b24e2bSVaishali Kulkarni 
180414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
180514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
180614b24e2bSVaishali Kulkarni 		return rc;
180714b24e2bSVaishali Kulkarni 
180814b24e2bSVaishali Kulkarni 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
180914b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
181014b24e2bSVaishali Kulkarni 			"Failed to get the mdump retained data [mcp_resp 0x%x]\n",
181114b24e2bSVaishali Kulkarni 			mdump_cmd_params.mcp_resp);
181214b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
181314b24e2bSVaishali Kulkarni 	}
181414b24e2bSVaishali Kulkarni 
181514b24e2bSVaishali Kulkarni 	p_mdump_retain->valid = mfw_mdump_retain.valid;
181614b24e2bSVaishali Kulkarni 	p_mdump_retain->epoch = mfw_mdump_retain.epoch;
181714b24e2bSVaishali Kulkarni 	p_mdump_retain->pf = mfw_mdump_retain.pf;
181814b24e2bSVaishali Kulkarni 	p_mdump_retain->status = mfw_mdump_retain.status;
181914b24e2bSVaishali Kulkarni 
182014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
182114b24e2bSVaishali Kulkarni }
182214b24e2bSVaishali Kulkarni 
ecore_mcp_mdump_clr_retain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)182314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_clr_retain(struct ecore_hwfn *p_hwfn,
182414b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
182514b24e2bSVaishali Kulkarni {
182614b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
182714b24e2bSVaishali Kulkarni 
182814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
182914b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLR_RETAIN;
183014b24e2bSVaishali Kulkarni 
183114b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
183214b24e2bSVaishali Kulkarni }
183314b24e2bSVaishali Kulkarni 
ecore_mcp_handle_critical_error(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)183414b24e2bSVaishali Kulkarni static void ecore_mcp_handle_critical_error(struct ecore_hwfn *p_hwfn,
183514b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt)
183614b24e2bSVaishali Kulkarni {
183714b24e2bSVaishali Kulkarni 	struct ecore_mdump_retain_data mdump_retain;
183814b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
183914b24e2bSVaishali Kulkarni 
184014b24e2bSVaishali Kulkarni 	/* In CMT mode - no need for more than a single acknowledgement to the
184114b24e2bSVaishali Kulkarni 	 * MFW, and no more than a single notification to the upper driver.
184214b24e2bSVaishali Kulkarni 	 */
184314b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
184414b24e2bSVaishali Kulkarni 		return;
184514b24e2bSVaishali Kulkarni 
184614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_get_retain(p_hwfn, p_ptt, &mdump_retain);
184714b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS && mdump_retain.valid) {
184814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
184914b24e2bSVaishali Kulkarni 			  "The MFW notified that a critical error occurred in the device [epoch 0x%08x, pf 0x%x, status 0x%08x]\n",
185014b24e2bSVaishali Kulkarni 			  mdump_retain.epoch, mdump_retain.pf,
185114b24e2bSVaishali Kulkarni 			  mdump_retain.status);
185214b24e2bSVaishali Kulkarni 	} else {
185314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
185414b24e2bSVaishali Kulkarni 			  "The MFW notified that a critical error occurred in the device\n");
185514b24e2bSVaishali Kulkarni 	}
185614b24e2bSVaishali Kulkarni 
185714b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->allow_mdump) {
185814b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
185914b24e2bSVaishali Kulkarni 			  "Not acknowledging the notification to allow the MFW crash dump\n");
186014b24e2bSVaishali Kulkarni 		return;
186114b24e2bSVaishali Kulkarni 	}
186214b24e2bSVaishali Kulkarni 
186314b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
186414b24e2bSVaishali Kulkarni 		  "Acknowledging the notification to not allow the MFW crash dump [driver debug data collection is preferable]\n");
186514b24e2bSVaishali Kulkarni 	ecore_mcp_mdump_ack(p_hwfn, p_ptt);
186614b24e2bSVaishali Kulkarni 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_HW_ATTN);
186714b24e2bSVaishali Kulkarni }
186814b24e2bSVaishali Kulkarni 
ecore_mcp_handle_events(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)186914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_handle_events(struct ecore_hwfn *p_hwfn,
187014b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt)
187114b24e2bSVaishali Kulkarni {
187214b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *info = p_hwfn->mcp_info;
187314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
187414b24e2bSVaishali Kulkarni 	bool found = false;
187514b24e2bSVaishali Kulkarni 	u16 i;
187614b24e2bSVaishali Kulkarni 
187714b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Received message from MFW\n");
187814b24e2bSVaishali Kulkarni 
187914b24e2bSVaishali Kulkarni 	/* Read Messages from MFW */
188014b24e2bSVaishali Kulkarni 	ecore_mcp_read_mb(p_hwfn, p_ptt);
188114b24e2bSVaishali Kulkarni 
188214b24e2bSVaishali Kulkarni 	/* Compare current messages to old ones */
188314b24e2bSVaishali Kulkarni 	for (i = 0; i < info->mfw_mb_length; i++) {
188414b24e2bSVaishali Kulkarni 		if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i])
188514b24e2bSVaishali Kulkarni 			continue;
188614b24e2bSVaishali Kulkarni 
188714b24e2bSVaishali Kulkarni 		found = true;
188814b24e2bSVaishali Kulkarni 
188914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
189014b24e2bSVaishali Kulkarni 			   "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n",
189114b24e2bSVaishali Kulkarni 			   i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]);
189214b24e2bSVaishali Kulkarni 
189314b24e2bSVaishali Kulkarni 		switch (i) {
189414b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_LINK_CHANGE:
189514b24e2bSVaishali Kulkarni 			ecore_mcp_handle_link_change(p_hwfn, p_ptt, false);
189614b24e2bSVaishali Kulkarni 			break;
189714b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_VF_DISABLED:
189814b24e2bSVaishali Kulkarni 			ecore_mcp_handle_vf_flr(p_hwfn, p_ptt);
189914b24e2bSVaishali Kulkarni 			break;
190014b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_LLDP_DATA_UPDATED:
190114b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
190214b24e2bSVaishali Kulkarni 						    ECORE_DCBX_REMOTE_LLDP_MIB);
190314b24e2bSVaishali Kulkarni 			break;
190414b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED:
190514b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
190614b24e2bSVaishali Kulkarni 						    ECORE_DCBX_REMOTE_MIB);
190714b24e2bSVaishali Kulkarni 			break;
190814b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED:
190914b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
191014b24e2bSVaishali Kulkarni 						    ECORE_DCBX_OPERATIONAL_MIB);
191114b24e2bSVaishali Kulkarni 			break;
191214b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
191314b24e2bSVaishali Kulkarni 			ecore_mcp_handle_transceiver_change(p_hwfn, p_ptt);
191414b24e2bSVaishali Kulkarni 			break;
191514b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_ERROR_RECOVERY:
191614b24e2bSVaishali Kulkarni 			ecore_mcp_handle_process_kill(p_hwfn, p_ptt);
191714b24e2bSVaishali Kulkarni 			break;
191814b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_LAN_STATS:
191914b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_FCOE_STATS:
192014b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_ISCSI_STATS:
192114b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_RDMA_STATS:
192214b24e2bSVaishali Kulkarni 			ecore_mcp_send_protocol_stats(p_hwfn, p_ptt, i);
192314b24e2bSVaishali Kulkarni 			break;
192414b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_BW_UPDATE:
192514b24e2bSVaishali Kulkarni 			ecore_mcp_update_bw(p_hwfn, p_ptt);
192614b24e2bSVaishali Kulkarni 			break;
192714b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_S_TAG_UPDATE:
192814b24e2bSVaishali Kulkarni 			ecore_mcp_update_stag(p_hwfn, p_ptt);
192914b24e2bSVaishali Kulkarni 			break;
193014b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_FAILURE_DETECTED:
193114b24e2bSVaishali Kulkarni 			ecore_mcp_handle_fan_failure(p_hwfn, p_ptt);
193214b24e2bSVaishali Kulkarni 			break;
193314b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_CRITICAL_ERROR_OCCURRED:
193414b24e2bSVaishali Kulkarni 			ecore_mcp_handle_critical_error(p_hwfn, p_ptt);
193514b24e2bSVaishali Kulkarni 			break;
193614b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_TLV_REQ:
193714b24e2bSVaishali Kulkarni 			OSAL_MFW_TLV_REQ(p_hwfn);
193814b24e2bSVaishali Kulkarni 			break;
193914b24e2bSVaishali Kulkarni 		default:
194014b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i);
194114b24e2bSVaishali Kulkarni 			rc = ECORE_INVAL;
194214b24e2bSVaishali Kulkarni 		}
194314b24e2bSVaishali Kulkarni 	}
194414b24e2bSVaishali Kulkarni 
194514b24e2bSVaishali Kulkarni 	/* ACK everything */
194614b24e2bSVaishali Kulkarni 	for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) {
194714b24e2bSVaishali Kulkarni 		OSAL_BE32 val = OSAL_CPU_TO_BE32(((u32 *)info->mfw_mb_cur)[i]);
194814b24e2bSVaishali Kulkarni 
194914b24e2bSVaishali Kulkarni 		/* MFW expect answer in BE, so we force write in that format */
195014b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
195114b24e2bSVaishali Kulkarni 			 info->mfw_mb_addr + sizeof(u32) +
195214b24e2bSVaishali Kulkarni 			 MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) *
195314b24e2bSVaishali Kulkarni 			 sizeof(u32) + i * sizeof(u32), val);
195414b24e2bSVaishali Kulkarni 	}
195514b24e2bSVaishali Kulkarni 
195614b24e2bSVaishali Kulkarni 	if (!found) {
195714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
195814b24e2bSVaishali Kulkarni 			  "Received an MFW message indication but no new message!\n");
195914b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
196014b24e2bSVaishali Kulkarni 	}
196114b24e2bSVaishali Kulkarni 
196214b24e2bSVaishali Kulkarni 	/* Copy the new mfw messages into the shadow */
196314b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length);
196414b24e2bSVaishali Kulkarni 
196514b24e2bSVaishali Kulkarni 	return rc;
196614b24e2bSVaishali Kulkarni }
196714b24e2bSVaishali Kulkarni 
ecore_mcp_get_mfw_ver(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_mfw_ver,u32 * p_running_bundle_id)196814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mfw_ver(struct ecore_hwfn *p_hwfn,
196914b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
197014b24e2bSVaishali Kulkarni 					   u32 *p_mfw_ver,
197114b24e2bSVaishali Kulkarni 					   u32 *p_running_bundle_id)
197214b24e2bSVaishali Kulkarni {
197314b24e2bSVaishali Kulkarni 	u32 global_offsize;
197414b24e2bSVaishali Kulkarni 
197514b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
197614b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
197714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MFW version\n");
197814b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
197914b24e2bSVaishali Kulkarni 	}
198014b24e2bSVaishali Kulkarni #endif
198114b24e2bSVaishali Kulkarni 
198214b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev)) {
198314b24e2bSVaishali Kulkarni 		if (p_hwfn->vf_iov_info) {
198414b24e2bSVaishali Kulkarni 			struct pfvf_acquire_resp_tlv *p_resp;
198514b24e2bSVaishali Kulkarni 
198614b24e2bSVaishali Kulkarni 			p_resp = &p_hwfn->vf_iov_info->acquire_resp;
198714b24e2bSVaishali Kulkarni 			*p_mfw_ver = p_resp->pfdev_info.mfw_ver;
198814b24e2bSVaishali Kulkarni 			return ECORE_SUCCESS;
198914b24e2bSVaishali Kulkarni 		} else {
199014b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
199114b24e2bSVaishali Kulkarni 				   "VF requested MFW version prior to ACQUIRE\n");
199214b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
199314b24e2bSVaishali Kulkarni 		}
199414b24e2bSVaishali Kulkarni 	}
199514b24e2bSVaishali Kulkarni 
199614b24e2bSVaishali Kulkarni 	global_offsize = ecore_rd(p_hwfn, p_ptt,
199714b24e2bSVaishali Kulkarni 			  SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
199814b24e2bSVaishali Kulkarni 					       PUBLIC_GLOBAL));
199914b24e2bSVaishali Kulkarni 	*p_mfw_ver = ecore_rd(p_hwfn, p_ptt,
200014b24e2bSVaishali Kulkarni 			SECTION_ADDR(global_offsize, 0) +
2001*04443fdeSToomas Soome 			offsetof(struct public_global, mfw_ver));
200214b24e2bSVaishali Kulkarni 
200314b24e2bSVaishali Kulkarni 	if (p_running_bundle_id != OSAL_NULL) {
200414b24e2bSVaishali Kulkarni 		*p_running_bundle_id = ecore_rd(p_hwfn, p_ptt,
200514b24e2bSVaishali Kulkarni 				SECTION_ADDR(global_offsize, 0) +
2006*04443fdeSToomas Soome 				offsetof(struct public_global,
200714b24e2bSVaishali Kulkarni 					 running_bundle_id));
200814b24e2bSVaishali Kulkarni 	}
200914b24e2bSVaishali Kulkarni 
201014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
201114b24e2bSVaishali Kulkarni }
201214b24e2bSVaishali Kulkarni 
ecore_mcp_get_mbi_ver(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_mbi_ver)201314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mbi_ver(struct ecore_hwfn *p_hwfn,
201414b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
201514b24e2bSVaishali Kulkarni 					   u32 *p_mbi_ver)
201614b24e2bSVaishali Kulkarni {
201714b24e2bSVaishali Kulkarni 	u32 nvm_cfg_addr, nvm_cfg1_offset, mbi_ver_addr;
201814b24e2bSVaishali Kulkarni 
201914b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
202014b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
202114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MBI version\n");
202214b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
202314b24e2bSVaishali Kulkarni 	}
202414b24e2bSVaishali Kulkarni #endif
202514b24e2bSVaishali Kulkarni 
202614b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
202714b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
202814b24e2bSVaishali Kulkarni 
202914b24e2bSVaishali Kulkarni 	/* Read the address of the nvm_cfg */
203014b24e2bSVaishali Kulkarni 	nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
203114b24e2bSVaishali Kulkarni 	if (!nvm_cfg_addr) {
203214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Shared memory not initialized\n");
203314b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
203414b24e2bSVaishali Kulkarni 	}
203514b24e2bSVaishali Kulkarni 
203614b24e2bSVaishali Kulkarni 	/* Read the offset of nvm_cfg1 */
203714b24e2bSVaishali Kulkarni 	nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
203814b24e2bSVaishali Kulkarni 
203914b24e2bSVaishali Kulkarni 	mbi_ver_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
2040*04443fdeSToomas Soome 		       offsetof(struct nvm_cfg1, glob) +
2041*04443fdeSToomas Soome 		       offsetof(struct nvm_cfg1_glob, mbi_version);
204214b24e2bSVaishali Kulkarni 	*p_mbi_ver = ecore_rd(p_hwfn, p_ptt, mbi_ver_addr) &
204314b24e2bSVaishali Kulkarni 		     (NVM_CFG1_GLOB_MBI_VERSION_0_MASK |
204414b24e2bSVaishali Kulkarni 		      NVM_CFG1_GLOB_MBI_VERSION_1_MASK |
204514b24e2bSVaishali Kulkarni 		      NVM_CFG1_GLOB_MBI_VERSION_2_MASK);
204614b24e2bSVaishali Kulkarni 
204714b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
204814b24e2bSVaishali Kulkarni }
204914b24e2bSVaishali Kulkarni 
ecore_mcp_get_media_type(struct ecore_dev * p_dev,u32 * p_media_type)205014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_media_type(struct ecore_dev *p_dev,
205114b24e2bSVaishali Kulkarni 					   u32 *p_media_type)
205214b24e2bSVaishali Kulkarni {
205314b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = &p_dev->hwfns[0];
205414b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
205514b24e2bSVaishali Kulkarni 
205614b24e2bSVaishali Kulkarni 	/* TODO - Add support for VFs */
205714b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev))
205814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
205914b24e2bSVaishali Kulkarni 
206014b24e2bSVaishali Kulkarni 	if (!ecore_mcp_is_init(p_hwfn)) {
206114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW is not initialized!\n");
206214b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
206314b24e2bSVaishali Kulkarni 	}
206414b24e2bSVaishali Kulkarni 
206514b24e2bSVaishali Kulkarni 	*p_media_type = MEDIA_UNSPECIFIED;
206614b24e2bSVaishali Kulkarni 
206714b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
206814b24e2bSVaishali Kulkarni 	if (!p_ptt)
206914b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
207014b24e2bSVaishali Kulkarni 
207114b24e2bSVaishali Kulkarni 	*p_media_type = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2072*04443fdeSToomas Soome 				 offsetof(struct public_port, media_type));
207314b24e2bSVaishali Kulkarni 
207414b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
207514b24e2bSVaishali Kulkarni 
207614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
207714b24e2bSVaishali Kulkarni }
207814b24e2bSVaishali Kulkarni 
207914b24e2bSVaishali Kulkarni /* Old MFW has a global configuration for all PFs regarding RDMA support */
208014b24e2bSVaishali Kulkarni static void
ecore_mcp_get_shmem_proto_legacy(struct ecore_hwfn * p_hwfn,enum ecore_pci_personality * p_proto)208114b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto_legacy(struct ecore_hwfn *p_hwfn,
208214b24e2bSVaishali Kulkarni 				 enum ecore_pci_personality *p_proto)
208314b24e2bSVaishali Kulkarni {
208414b24e2bSVaishali Kulkarni 	/* There wasn't ever a legacy MFW that published iwarp.
208514b24e2bSVaishali Kulkarni 	 * So at this point, this is either plain l2 or RoCE.
208614b24e2bSVaishali Kulkarni 	 */
208714b24e2bSVaishali Kulkarni 	if (OSAL_TEST_BIT(ECORE_DEV_CAP_ROCE,
208814b24e2bSVaishali Kulkarni 			  &p_hwfn->hw_info.device_capabilities))
208914b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_ROCE;
209014b24e2bSVaishali Kulkarni 	else
209114b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH;
209214b24e2bSVaishali Kulkarni 
209314b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
209414b24e2bSVaishali Kulkarni 		   "According to Legacy capabilities, L2 personality is %08x\n",
209514b24e2bSVaishali Kulkarni 		   (u32) *p_proto);
209614b24e2bSVaishali Kulkarni }
209714b24e2bSVaishali Kulkarni 
209814b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_get_shmem_proto_mfw(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_pci_personality * p_proto)209914b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto_mfw(struct ecore_hwfn *p_hwfn,
210014b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt,
210114b24e2bSVaishali Kulkarni 			      enum ecore_pci_personality *p_proto)
210214b24e2bSVaishali Kulkarni {
210314b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
210414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
210514b24e2bSVaishali Kulkarni 
210614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
210714b24e2bSVaishali Kulkarni 			 DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, &param);
210814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
210914b24e2bSVaishali Kulkarni 		return rc;
211014b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_OK) {
211114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
211214b24e2bSVaishali Kulkarni 			   "MFW lacks support for command; Returns %08x\n",
211314b24e2bSVaishali Kulkarni 			   resp);
211414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
211514b24e2bSVaishali Kulkarni 	}
211614b24e2bSVaishali Kulkarni 
211714b24e2bSVaishali Kulkarni 	switch (param) {
211814b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_NONE:
211914b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH;
212014b24e2bSVaishali Kulkarni 		break;
212114b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_ROCE:
212214b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_ROCE;
212314b24e2bSVaishali Kulkarni 		break;
212414b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_IWARP:
212514b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_IWARP;
212614b24e2bSVaishali Kulkarni 		break;
212714b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_BOTH:
212814b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_RDMA;
212914b24e2bSVaishali Kulkarni 		break;
213014b24e2bSVaishali Kulkarni 	default:
213114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
213214b24e2bSVaishali Kulkarni 			  "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n",
213314b24e2bSVaishali Kulkarni 			  param);
213414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
213514b24e2bSVaishali Kulkarni 	}
213614b24e2bSVaishali Kulkarni 
213714b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
213814b24e2bSVaishali Kulkarni 		   "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n",
213914b24e2bSVaishali Kulkarni 		   (u32) *p_proto, resp, param);
214014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
214114b24e2bSVaishali Kulkarni }
214214b24e2bSVaishali Kulkarni 
214314b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_get_shmem_proto(struct ecore_hwfn * p_hwfn,struct public_func * p_info,struct ecore_ptt * p_ptt,enum ecore_pci_personality * p_proto)214414b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto(struct ecore_hwfn *p_hwfn,
214514b24e2bSVaishali Kulkarni 			  struct public_func *p_info,
214614b24e2bSVaishali Kulkarni 			  struct ecore_ptt *p_ptt,
214714b24e2bSVaishali Kulkarni 			  enum ecore_pci_personality *p_proto)
214814b24e2bSVaishali Kulkarni {
214914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
215014b24e2bSVaishali Kulkarni 
215114b24e2bSVaishali Kulkarni 	switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
215214b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ETHERNET:
215314b24e2bSVaishali Kulkarni 		if (ecore_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto) !=
215414b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS)
215514b24e2bSVaishali Kulkarni 			ecore_mcp_get_shmem_proto_legacy(p_hwfn, p_proto);
215614b24e2bSVaishali Kulkarni 		break;
215714b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ISCSI:
215814b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ISCSI;
215914b24e2bSVaishali Kulkarni 		break;
216014b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_FCOE:
216114b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_FCOE;
216214b24e2bSVaishali Kulkarni 		break;
216314b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ROCE:
216414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "RoCE personality is not a valid value!\n");
216514b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
216614b24e2bSVaishali Kulkarni 		break;
216714b24e2bSVaishali Kulkarni 	default:
216814b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
216914b24e2bSVaishali Kulkarni 	}
217014b24e2bSVaishali Kulkarni 
217114b24e2bSVaishali Kulkarni 	return rc;
217214b24e2bSVaishali Kulkarni }
217314b24e2bSVaishali Kulkarni 
ecore_mcp_fill_shmem_func_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)217414b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_fill_shmem_func_info(struct ecore_hwfn *p_hwfn,
217514b24e2bSVaishali Kulkarni 						    struct ecore_ptt *p_ptt)
217614b24e2bSVaishali Kulkarni {
217714b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *info;
217814b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
217914b24e2bSVaishali Kulkarni 
218014b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
218114b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
218214b24e2bSVaishali Kulkarni 	info = &p_hwfn->mcp_info->func_info;
218314b24e2bSVaishali Kulkarni 
218414b24e2bSVaishali Kulkarni 	info->pause_on_host = (shmem_info.config &
218514b24e2bSVaishali Kulkarni 			       FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0;
218614b24e2bSVaishali Kulkarni 
218714b24e2bSVaishali Kulkarni 	if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
218814b24e2bSVaishali Kulkarni 				      &info->protocol)) {
218914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unknown personality %08x\n",
219014b24e2bSVaishali Kulkarni 		       (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
219114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
219214b24e2bSVaishali Kulkarni 	}
219314b24e2bSVaishali Kulkarni 
219414b24e2bSVaishali Kulkarni 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
219514b24e2bSVaishali Kulkarni 
219614b24e2bSVaishali Kulkarni 	if (shmem_info.mac_upper || shmem_info.mac_lower) {
219714b24e2bSVaishali Kulkarni 		info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
219814b24e2bSVaishali Kulkarni 		info->mac[1] = (u8)(shmem_info.mac_upper);
219914b24e2bSVaishali Kulkarni 		info->mac[2] = (u8)(shmem_info.mac_lower >> 24);
220014b24e2bSVaishali Kulkarni 		info->mac[3] = (u8)(shmem_info.mac_lower >> 16);
220114b24e2bSVaishali Kulkarni 		info->mac[4] = (u8)(shmem_info.mac_lower >> 8);
220214b24e2bSVaishali Kulkarni 		info->mac[5] = (u8)(shmem_info.mac_lower);
220314b24e2bSVaishali Kulkarni 
220414b24e2bSVaishali Kulkarni 		/* Store primary MAC for later possible WoL */
220514b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(&p_hwfn->p_dev->wol_mac, info->mac, ETH_ALEN);
220614b24e2bSVaishali Kulkarni 
220714b24e2bSVaishali Kulkarni 	} else {
220814b24e2bSVaishali Kulkarni 		/* TODO - are there protocols for which there's no MAC? */
220914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "MAC is 0 in shmem\n");
221014b24e2bSVaishali Kulkarni 	}
221114b24e2bSVaishali Kulkarni 
221214b24e2bSVaishali Kulkarni 	/* TODO - are these calculations true for BE machine? */
221314b24e2bSVaishali Kulkarni 	info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower |
221414b24e2bSVaishali Kulkarni 			 (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32);
221514b24e2bSVaishali Kulkarni 	info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower |
221614b24e2bSVaishali Kulkarni 			 (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32);
221714b24e2bSVaishali Kulkarni 
221814b24e2bSVaishali Kulkarni 	info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
221914b24e2bSVaishali Kulkarni 
222014b24e2bSVaishali Kulkarni 	info->mtu = (u16)shmem_info.mtu_size;
222114b24e2bSVaishali Kulkarni 
222214b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_NONE;
222314b24e2bSVaishali Kulkarni 	if (ecore_mcp_is_init(p_hwfn)) {
222414b24e2bSVaishali Kulkarni 		u32 resp = 0, param = 0;
222514b24e2bSVaishali Kulkarni 		enum _ecore_status_t rc;
222614b24e2bSVaishali Kulkarni 
222714b24e2bSVaishali Kulkarni 		rc = ecore_mcp_cmd(p_hwfn, p_ptt,
222814b24e2bSVaishali Kulkarni 				   DRV_MSG_CODE_OS_WOL, 0, &resp, &param);
222914b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
223014b24e2bSVaishali Kulkarni 			return rc;
223114b24e2bSVaishali Kulkarni 		if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED)
223214b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_PME;
223314b24e2bSVaishali Kulkarni 	}
223414b24e2bSVaishali Kulkarni 	p_hwfn->p_dev->wol_config = (u8)ECORE_OV_WOL_DEFAULT;
223514b24e2bSVaishali Kulkarni 
223614b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFUP),
223714b24e2bSVaishali Kulkarni 		   "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x wol %02x\n",
223814b24e2bSVaishali Kulkarni 		   info->pause_on_host, info->protocol,
223914b24e2bSVaishali Kulkarni 		   info->bandwidth_min, info->bandwidth_max,
224014b24e2bSVaishali Kulkarni 		   info->mac[0], info->mac[1], info->mac[2],
224114b24e2bSVaishali Kulkarni 		   info->mac[3], info->mac[4], info->mac[5],
224214b24e2bSVaishali Kulkarni 		   info->wwn_port, info->wwn_node, info->ovlan,
224314b24e2bSVaishali Kulkarni 		   (u8)p_hwfn->hw_info.b_wol_support);
224414b24e2bSVaishali Kulkarni 
224514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
224614b24e2bSVaishali Kulkarni }
224714b24e2bSVaishali Kulkarni 
224814b24e2bSVaishali Kulkarni struct ecore_mcp_link_params
ecore_mcp_get_link_params(struct ecore_hwfn * p_hwfn)224914b24e2bSVaishali Kulkarni *ecore_mcp_get_link_params(struct ecore_hwfn *p_hwfn)
225014b24e2bSVaishali Kulkarni {
225114b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
225214b24e2bSVaishali Kulkarni 		return OSAL_NULL;
225314b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_input;
225414b24e2bSVaishali Kulkarni }
225514b24e2bSVaishali Kulkarni 
225614b24e2bSVaishali Kulkarni struct ecore_mcp_link_state
ecore_mcp_get_link_state(struct ecore_hwfn * p_hwfn)225714b24e2bSVaishali Kulkarni *ecore_mcp_get_link_state(struct ecore_hwfn *p_hwfn)
225814b24e2bSVaishali Kulkarni {
225914b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
226014b24e2bSVaishali Kulkarni 		return OSAL_NULL;
226114b24e2bSVaishali Kulkarni 
226214b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
226314b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
226414b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn, "Non-ASIC - always notify that link is up\n");
226514b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->link_output.link_up = true;
226614b24e2bSVaishali Kulkarni 	}
226714b24e2bSVaishali Kulkarni #endif
226814b24e2bSVaishali Kulkarni 
226914b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_output;
227014b24e2bSVaishali Kulkarni }
227114b24e2bSVaishali Kulkarni 
227214b24e2bSVaishali Kulkarni struct ecore_mcp_link_capabilities
ecore_mcp_get_link_capabilities(struct ecore_hwfn * p_hwfn)227314b24e2bSVaishali Kulkarni *ecore_mcp_get_link_capabilities(struct ecore_hwfn *p_hwfn)
227414b24e2bSVaishali Kulkarni {
227514b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
227614b24e2bSVaishali Kulkarni 		return OSAL_NULL;
227714b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_capabilities;
227814b24e2bSVaishali Kulkarni }
227914b24e2bSVaishali Kulkarni 
ecore_mcp_drain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)228014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_drain(struct ecore_hwfn *p_hwfn,
228114b24e2bSVaishali Kulkarni 				     struct ecore_ptt *p_ptt)
228214b24e2bSVaishali Kulkarni {
228314b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
228414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
228514b24e2bSVaishali Kulkarni 
228614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
228714b24e2bSVaishali Kulkarni 			   DRV_MSG_CODE_NIG_DRAIN, 1000,
228814b24e2bSVaishali Kulkarni 			   &resp, &param);
228914b24e2bSVaishali Kulkarni 
229014b24e2bSVaishali Kulkarni 	/* Wait for the drain to complete before returning */
229114b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(1020);
229214b24e2bSVaishali Kulkarni 
229314b24e2bSVaishali Kulkarni 	return rc;
229414b24e2bSVaishali Kulkarni }
229514b24e2bSVaishali Kulkarni 
229614b24e2bSVaishali Kulkarni #ifndef LINUX_REMOVE
229714b24e2bSVaishali Kulkarni const struct ecore_mcp_function_info
ecore_mcp_get_function_info(struct ecore_hwfn * p_hwfn)229814b24e2bSVaishali Kulkarni *ecore_mcp_get_function_info(struct ecore_hwfn *p_hwfn)
229914b24e2bSVaishali Kulkarni {
230014b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
230114b24e2bSVaishali Kulkarni 		return OSAL_NULL;
230214b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->func_info;
230314b24e2bSVaishali Kulkarni }
230414b24e2bSVaishali Kulkarni #endif
230514b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_command(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_nvm_params * params)230614b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_command(struct ecore_hwfn *p_hwfn,
230714b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
230814b24e2bSVaishali Kulkarni 					   struct ecore_mcp_nvm_params *params)
230914b24e2bSVaishali Kulkarni {
231014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
231114b24e2bSVaishali Kulkarni 
231214b24e2bSVaishali Kulkarni 	switch (params->type) {
231314b24e2bSVaishali Kulkarni 	case ECORE_MCP_NVM_RD:
231414b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
231514b24e2bSVaishali Kulkarni 					  params->nvm_common.offset,
231614b24e2bSVaishali Kulkarni 					  &params->nvm_common.resp,
231714b24e2bSVaishali Kulkarni 					  &params->nvm_common.param,
231814b24e2bSVaishali Kulkarni 					  params->nvm_rd.buf_size,
231914b24e2bSVaishali Kulkarni 					  params->nvm_rd.buf);
232014b24e2bSVaishali Kulkarni 		break;
232114b24e2bSVaishali Kulkarni 	case ECORE_MCP_CMD:
232214b24e2bSVaishali Kulkarni 		rc = ecore_mcp_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
232314b24e2bSVaishali Kulkarni 				   params->nvm_common.offset,
232414b24e2bSVaishali Kulkarni 				   &params->nvm_common.resp,
232514b24e2bSVaishali Kulkarni 				   &params->nvm_common.param);
232614b24e2bSVaishali Kulkarni 		break;
232714b24e2bSVaishali Kulkarni 	case ECORE_MCP_NVM_WR:
232814b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
232914b24e2bSVaishali Kulkarni 					  params->nvm_common.offset,
233014b24e2bSVaishali Kulkarni 					  &params->nvm_common.resp,
233114b24e2bSVaishali Kulkarni 					  &params->nvm_common.param,
233214b24e2bSVaishali Kulkarni 					  params->nvm_wr.buf_size,
233314b24e2bSVaishali Kulkarni 					  params->nvm_wr.buf);
233414b24e2bSVaishali Kulkarni 		break;
233514b24e2bSVaishali Kulkarni 	default:
233614b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
233714b24e2bSVaishali Kulkarni 		break;
233814b24e2bSVaishali Kulkarni 	}
233914b24e2bSVaishali Kulkarni 	return rc;
234014b24e2bSVaishali Kulkarni }
234114b24e2bSVaishali Kulkarni 
234214b24e2bSVaishali Kulkarni #ifndef LINUX_REMOVE
ecore_mcp_get_personality_cnt(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 personalities)234314b24e2bSVaishali Kulkarni int ecore_mcp_get_personality_cnt(struct ecore_hwfn *p_hwfn,
234414b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt,
234514b24e2bSVaishali Kulkarni 				  u32 personalities)
234614b24e2bSVaishali Kulkarni {
234714b24e2bSVaishali Kulkarni 	enum ecore_pci_personality protocol = ECORE_PCI_DEFAULT;
234814b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
234914b24e2bSVaishali Kulkarni 	int i, count = 0, num_pfs;
235014b24e2bSVaishali Kulkarni 
235114b24e2bSVaishali Kulkarni 	num_pfs = NUM_OF_ENG_PFS(p_hwfn->p_dev);
235214b24e2bSVaishali Kulkarni 
235314b24e2bSVaishali Kulkarni 	for (i = 0; i < num_pfs; i++) {
235414b24e2bSVaishali Kulkarni 		ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
235514b24e2bSVaishali Kulkarni 					 MCP_PF_ID_BY_REL(p_hwfn, i));
235614b24e2bSVaishali Kulkarni 		if (shmem_info.config & FUNC_MF_CFG_FUNC_HIDE)
235714b24e2bSVaishali Kulkarni 			continue;
235814b24e2bSVaishali Kulkarni 
235914b24e2bSVaishali Kulkarni 		if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
236014b24e2bSVaishali Kulkarni 					      &protocol) !=
236114b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS)
236214b24e2bSVaishali Kulkarni 			continue;
236314b24e2bSVaishali Kulkarni 
236414b24e2bSVaishali Kulkarni 		if ((1 << ((u32)protocol)) & personalities)
236514b24e2bSVaishali Kulkarni 			count++;
236614b24e2bSVaishali Kulkarni 	}
236714b24e2bSVaishali Kulkarni 
236814b24e2bSVaishali Kulkarni 	return count;
236914b24e2bSVaishali Kulkarni }
237014b24e2bSVaishali Kulkarni #endif
237114b24e2bSVaishali Kulkarni 
ecore_mcp_get_flash_size(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_flash_size)237214b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_flash_size(struct ecore_hwfn *p_hwfn,
237314b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
237414b24e2bSVaishali Kulkarni 					      u32 *p_flash_size)
237514b24e2bSVaishali Kulkarni {
237614b24e2bSVaishali Kulkarni 	u32 flash_size;
237714b24e2bSVaishali Kulkarni 
237814b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
237914b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
238014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get flash size\n");
238114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
238214b24e2bSVaishali Kulkarni 	}
238314b24e2bSVaishali Kulkarni #endif
238414b24e2bSVaishali Kulkarni 
238514b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
238614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
238714b24e2bSVaishali Kulkarni 
238814b24e2bSVaishali Kulkarni 	flash_size = ecore_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4);
238914b24e2bSVaishali Kulkarni 	flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >>
239014b24e2bSVaishali Kulkarni 				MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT;
239114b24e2bSVaishali Kulkarni 	flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT));
239214b24e2bSVaishali Kulkarni 
239314b24e2bSVaishali Kulkarni 	*p_flash_size = flash_size;
239414b24e2bSVaishali Kulkarni 
239514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
239614b24e2bSVaishali Kulkarni }
239714b24e2bSVaishali Kulkarni 
ecore_start_recovery_process(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)239814b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_start_recovery_process(struct ecore_hwfn *p_hwfn,
239914b24e2bSVaishali Kulkarni 						  struct ecore_ptt *p_ptt)
240014b24e2bSVaishali Kulkarni {
240114b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
240214b24e2bSVaishali Kulkarni 
240314b24e2bSVaishali Kulkarni 	if (p_dev->recov_in_prog) {
240414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
240514b24e2bSVaishali Kulkarni 			  "Avoid triggering a recovery since such a process is already in progress\n");
240614b24e2bSVaishali Kulkarni 		return ECORE_AGAIN;
240714b24e2bSVaishali Kulkarni 	}
240814b24e2bSVaishali Kulkarni 
240914b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Triggering a recovery process\n");
241014b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1);
241114b24e2bSVaishali Kulkarni 
241214b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
241314b24e2bSVaishali Kulkarni }
241414b24e2bSVaishali Kulkarni 
241514b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_config_vf_msix_bb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 vf_id,u8 num)241614b24e2bSVaishali Kulkarni ecore_mcp_config_vf_msix_bb(struct ecore_hwfn *p_hwfn,
241714b24e2bSVaishali Kulkarni 			    struct ecore_ptt *p_ptt,
241814b24e2bSVaishali Kulkarni 			    u8 vf_id, u8 num)
241914b24e2bSVaishali Kulkarni {
242014b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, rc_param = 0;
242114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
242214b24e2bSVaishali Kulkarni 
242314b24e2bSVaishali Kulkarni 	/* Only Leader can configure MSIX, and need to take CMT into account */
242414b24e2bSVaishali Kulkarni 	if (!IS_LEAD_HWFN(p_hwfn))
242514b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
242614b24e2bSVaishali Kulkarni 	num *= p_hwfn->p_dev->num_hwfns;
242714b24e2bSVaishali Kulkarni 
242814b24e2bSVaishali Kulkarni 	param |= (vf_id << DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT) &
242914b24e2bSVaishali Kulkarni 		 DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK;
243014b24e2bSVaishali Kulkarni 	param |= (num << DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT) &
243114b24e2bSVaishali Kulkarni 		 DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK;
243214b24e2bSVaishali Kulkarni 
243314b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_VF_MSIX, param,
243414b24e2bSVaishali Kulkarni 			   &resp, &rc_param);
243514b24e2bSVaishali Kulkarni 
243614b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE) {
243714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "VF[%d]: MFW failed to set MSI-X\n",
243814b24e2bSVaishali Kulkarni 			  vf_id);
243914b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
244014b24e2bSVaishali Kulkarni 	} else {
244114b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
244214b24e2bSVaishali Kulkarni 			   "Requested 0x%02x MSI-x interrupts from VF 0x%02x\n",
244314b24e2bSVaishali Kulkarni 			    num, vf_id);
244414b24e2bSVaishali Kulkarni 	}
244514b24e2bSVaishali Kulkarni 
244614b24e2bSVaishali Kulkarni 	return rc;
244714b24e2bSVaishali Kulkarni }
244814b24e2bSVaishali Kulkarni 
244914b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_config_vf_msix_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 num)245014b24e2bSVaishali Kulkarni ecore_mcp_config_vf_msix_ah(struct ecore_hwfn *p_hwfn,
245114b24e2bSVaishali Kulkarni 			    struct ecore_ptt *p_ptt,
245214b24e2bSVaishali Kulkarni 			    u8 num)
245314b24e2bSVaishali Kulkarni {
245414b24e2bSVaishali Kulkarni 	u32 resp = 0, param = num, rc_param = 0;
245514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
245614b24e2bSVaishali Kulkarni 
245714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_PF_VFS_MSIX,
245814b24e2bSVaishali Kulkarni 			   param, &resp, &rc_param);
245914b24e2bSVaishali Kulkarni 
246014b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_DRV_CFG_PF_VFS_MSIX_DONE) {
246114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW failed to set MSI-X for VFs\n");
246214b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
246314b24e2bSVaishali Kulkarni 	} else {
246414b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
246514b24e2bSVaishali Kulkarni 			   "Requested 0x%02x MSI-x interrupts for VFs\n",
246614b24e2bSVaishali Kulkarni 			   num);
246714b24e2bSVaishali Kulkarni 	}
246814b24e2bSVaishali Kulkarni 
246914b24e2bSVaishali Kulkarni 	return rc;
247014b24e2bSVaishali Kulkarni }
247114b24e2bSVaishali Kulkarni 
ecore_mcp_config_vf_msix(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 vf_id,u8 num)247214b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_config_vf_msix(struct ecore_hwfn *p_hwfn,
247314b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
247414b24e2bSVaishali Kulkarni 					      u8 vf_id, u8 num)
247514b24e2bSVaishali Kulkarni {
247614b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev))
247714b24e2bSVaishali Kulkarni 		return ecore_mcp_config_vf_msix_bb(p_hwfn, p_ptt, vf_id, num);
247814b24e2bSVaishali Kulkarni 	else
247914b24e2bSVaishali Kulkarni 		return ecore_mcp_config_vf_msix_ah(p_hwfn, p_ptt, num);
248014b24e2bSVaishali Kulkarni }
248114b24e2bSVaishali Kulkarni 
248214b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_send_drv_version(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_drv_version * p_ver)248314b24e2bSVaishali Kulkarni ecore_mcp_send_drv_version(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
248414b24e2bSVaishali Kulkarni 			   struct ecore_mcp_drv_version *p_ver)
248514b24e2bSVaishali Kulkarni {
248614b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
248714b24e2bSVaishali Kulkarni 	struct drv_version_stc drv_version;
248814b24e2bSVaishali Kulkarni 	u32 num_words, i;
248914b24e2bSVaishali Kulkarni 	void *p_name;
249014b24e2bSVaishali Kulkarni 	OSAL_BE32 val;
249114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
249214b24e2bSVaishali Kulkarni 
249314b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
249414b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev))
249514b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
249614b24e2bSVaishali Kulkarni #endif
249714b24e2bSVaishali Kulkarni 
249814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&drv_version, sizeof(drv_version));
249914b24e2bSVaishali Kulkarni 	drv_version.version = p_ver->version;
250014b24e2bSVaishali Kulkarni 	num_words = (MCP_DRV_VER_STR_SIZE - 4) / 4;
250114b24e2bSVaishali Kulkarni 	for (i = 0; i < num_words; i++) {
250214b24e2bSVaishali Kulkarni 		/* The driver name is expected to be in a big-endian format */
250314b24e2bSVaishali Kulkarni 		p_name = &p_ver->name[i * sizeof(u32)];
250414b24e2bSVaishali Kulkarni 		val = OSAL_CPU_TO_BE32(*(u32 *)p_name);
250514b24e2bSVaishali Kulkarni 		*(u32 *)&drv_version.name[i * sizeof(u32)] = val;
250614b24e2bSVaishali Kulkarni 	}
250714b24e2bSVaishali Kulkarni 
250814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
250914b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_VERSION;
251014b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &drv_version;
251114b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(drv_version);
251214b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
251314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
251414b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
251514b24e2bSVaishali Kulkarni 
251614b24e2bSVaishali Kulkarni 	return rc;
251714b24e2bSVaishali Kulkarni }
251814b24e2bSVaishali Kulkarni 
251914b24e2bSVaishali Kulkarni /* A maximal 100 msec waiting time for the MCP to halt */
252014b24e2bSVaishali Kulkarni #define ECORE_MCP_HALT_SLEEP_MS		10
252114b24e2bSVaishali Kulkarni #define ECORE_MCP_HALT_MAX_RETRIES	10
252214b24e2bSVaishali Kulkarni 
ecore_mcp_halt(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)252314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_halt(struct ecore_hwfn *p_hwfn,
252414b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt)
252514b24e2bSVaishali Kulkarni {
252614b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, cpu_state, cnt = 0;
252714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
252814b24e2bSVaishali Kulkarni 
252914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp,
253014b24e2bSVaishali Kulkarni 			   &param);
253114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
253214b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
253314b24e2bSVaishali Kulkarni 		return rc;
253414b24e2bSVaishali Kulkarni 	}
253514b24e2bSVaishali Kulkarni 
253614b24e2bSVaishali Kulkarni 	do {
253714b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(ECORE_MCP_HALT_SLEEP_MS);
253814b24e2bSVaishali Kulkarni 		cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
253914b24e2bSVaishali Kulkarni 		if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED)
254014b24e2bSVaishali Kulkarni 			break;
254114b24e2bSVaishali Kulkarni 	} while (++cnt < ECORE_MCP_HALT_MAX_RETRIES);
254214b24e2bSVaishali Kulkarni 
254314b24e2bSVaishali Kulkarni 	if (cnt == ECORE_MCP_HALT_MAX_RETRIES) {
254414b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
254514b24e2bSVaishali Kulkarni 			  "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
254614b24e2bSVaishali Kulkarni 			  ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state);
254714b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
254814b24e2bSVaishali Kulkarni 	}
254914b24e2bSVaishali Kulkarni 
255014b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
255114b24e2bSVaishali Kulkarni }
255214b24e2bSVaishali Kulkarni 
255314b24e2bSVaishali Kulkarni #define ECORE_MCP_RESUME_SLEEP_MS	10
255414b24e2bSVaishali Kulkarni 
ecore_mcp_resume(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)255514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_resume(struct ecore_hwfn *p_hwfn,
255614b24e2bSVaishali Kulkarni 				      struct ecore_ptt *p_ptt)
255714b24e2bSVaishali Kulkarni {
255814b24e2bSVaishali Kulkarni 	u32 cpu_mode, cpu_state;
255914b24e2bSVaishali Kulkarni 
256014b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff);
256114b24e2bSVaishali Kulkarni 
256214b24e2bSVaishali Kulkarni 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
256314b24e2bSVaishali Kulkarni 	cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT;
256414b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode);
256514b24e2bSVaishali Kulkarni 
256614b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(ECORE_MCP_RESUME_SLEEP_MS);
256714b24e2bSVaishali Kulkarni 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
256814b24e2bSVaishali Kulkarni 
256914b24e2bSVaishali Kulkarni 	if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) {
257014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
257114b24e2bSVaishali Kulkarni 			  "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
257214b24e2bSVaishali Kulkarni 			  cpu_mode, cpu_state);
257314b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
257414b24e2bSVaishali Kulkarni 	}
257514b24e2bSVaishali Kulkarni 
257614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
257714b24e2bSVaishali Kulkarni }
257814b24e2bSVaishali Kulkarni 
257914b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_current_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_client client)258014b24e2bSVaishali Kulkarni ecore_mcp_ov_update_current_config(struct ecore_hwfn *p_hwfn,
258114b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt,
258214b24e2bSVaishali Kulkarni 				   enum ecore_ov_client client)
258314b24e2bSVaishali Kulkarni {
258414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
258514b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
258614b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
258714b24e2bSVaishali Kulkarni 
258814b24e2bSVaishali Kulkarni 	switch (client) {
258914b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_DRV:
259014b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS;
259114b24e2bSVaishali Kulkarni 		break;
259214b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_USER:
259314b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER;
259414b24e2bSVaishali Kulkarni 		break;
259514b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_VENDOR_SPEC:
259614b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC;
259714b24e2bSVaishali Kulkarni 		break;
259814b24e2bSVaishali Kulkarni 	default:
259914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
260014b24e2bSVaishali Kulkarni 			  "Invalid client type %d\n", client);
260114b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
260214b24e2bSVaishali Kulkarni 	}
260314b24e2bSVaishali Kulkarni 
260414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG,
260514b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
260614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
260714b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
260814b24e2bSVaishali Kulkarni 
260914b24e2bSVaishali Kulkarni 	return rc;
261014b24e2bSVaishali Kulkarni }
261114b24e2bSVaishali Kulkarni 
261214b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_driver_state(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_driver_state drv_state)261314b24e2bSVaishali Kulkarni ecore_mcp_ov_update_driver_state(struct ecore_hwfn *p_hwfn,
261414b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt,
261514b24e2bSVaishali Kulkarni 				 enum ecore_ov_driver_state drv_state)
261614b24e2bSVaishali Kulkarni {
261714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
261814b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
261914b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
262014b24e2bSVaishali Kulkarni 
262114b24e2bSVaishali Kulkarni 	switch (drv_state) {
262214b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_NOT_LOADED:
262314b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED;
262414b24e2bSVaishali Kulkarni 		break;
262514b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_DISABLED:
262614b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED;
262714b24e2bSVaishali Kulkarni 		break;
262814b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_ACTIVE:
262914b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE;
263014b24e2bSVaishali Kulkarni 		break;
263114b24e2bSVaishali Kulkarni 	default:
263214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
263314b24e2bSVaishali Kulkarni 			  "Invalid driver state %d\n", drv_state);
263414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
263514b24e2bSVaishali Kulkarni 	}
263614b24e2bSVaishali Kulkarni 
263714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE,
263814b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
263914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
264014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send driver state\n");
264114b24e2bSVaishali Kulkarni 
264214b24e2bSVaishali Kulkarni 	return rc;
264314b24e2bSVaishali Kulkarni }
264414b24e2bSVaishali Kulkarni 
264514b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_get_fc_npiv(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_fc_npiv_tbl * p_table)264614b24e2bSVaishali Kulkarni ecore_mcp_ov_get_fc_npiv(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
264714b24e2bSVaishali Kulkarni 			 struct ecore_fc_npiv_tbl *p_table)
264814b24e2bSVaishali Kulkarni {
264914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
265014b24e2bSVaishali Kulkarni 	struct dci_fc_npiv_tbl *p_npiv_table;
265114b24e2bSVaishali Kulkarni 	u8 *p_buf = OSAL_NULL;
265214b24e2bSVaishali Kulkarni 	u32 addr, size, i;
265314b24e2bSVaishali Kulkarni 
265414b24e2bSVaishali Kulkarni 	p_table->num_wwpn = 0;
265514b24e2bSVaishali Kulkarni 	p_table->num_wwnn = 0;
265614b24e2bSVaishali Kulkarni 	addr = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2657*04443fdeSToomas Soome 			offsetof(struct public_port, fc_npiv_nvram_tbl_addr));
265814b24e2bSVaishali Kulkarni 	if (addr == NPIV_TBL_INVALID_ADDR) {
265914b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table doesn't exist\n");
266014b24e2bSVaishali Kulkarni 		return rc;
266114b24e2bSVaishali Kulkarni 	}
266214b24e2bSVaishali Kulkarni 
266314b24e2bSVaishali Kulkarni 	size = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2664*04443fdeSToomas Soome 			offsetof(struct public_port, fc_npiv_nvram_tbl_size));
266514b24e2bSVaishali Kulkarni 	if (!size) {
266614b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table is empty\n");
266714b24e2bSVaishali Kulkarni 		return rc;
266814b24e2bSVaishali Kulkarni 	}
266914b24e2bSVaishali Kulkarni 
267014b24e2bSVaishali Kulkarni 	p_buf = OSAL_VZALLOC(p_hwfn->p_dev, size);
267114b24e2bSVaishali Kulkarni 	if (!p_buf) {
267214b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Buffer allocation failed\n");
267314b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
267414b24e2bSVaishali Kulkarni 	}
267514b24e2bSVaishali Kulkarni 
267614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_read(p_hwfn->p_dev, addr, p_buf, size);
267714b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
267814b24e2bSVaishali Kulkarni 		OSAL_VFREE(p_hwfn->p_dev, p_buf);
267914b24e2bSVaishali Kulkarni 		return rc;
268014b24e2bSVaishali Kulkarni 	}
268114b24e2bSVaishali Kulkarni 
268214b24e2bSVaishali Kulkarni 	p_npiv_table = (struct dci_fc_npiv_tbl *)p_buf;
268314b24e2bSVaishali Kulkarni 	p_table->num_wwpn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
268414b24e2bSVaishali Kulkarni 	p_table->num_wwnn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
268514b24e2bSVaishali Kulkarni 	for (i = 0; i < p_table->num_wwpn; i++) {
268614b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_table->wwpn, p_npiv_table->settings[i].npiv_wwpn,
268714b24e2bSVaishali Kulkarni 			    ECORE_WWN_SIZE);
268814b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_table->wwnn, p_npiv_table->settings[i].npiv_wwnn,
268914b24e2bSVaishali Kulkarni 			    ECORE_WWN_SIZE);
269014b24e2bSVaishali Kulkarni 	}
269114b24e2bSVaishali Kulkarni 
269214b24e2bSVaishali Kulkarni 	OSAL_VFREE(p_hwfn->p_dev, p_buf);
269314b24e2bSVaishali Kulkarni 
269414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
269514b24e2bSVaishali Kulkarni }
269614b24e2bSVaishali Kulkarni 
269714b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_mtu(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 mtu)269814b24e2bSVaishali Kulkarni ecore_mcp_ov_update_mtu(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
269914b24e2bSVaishali Kulkarni 			u16 mtu)
270014b24e2bSVaishali Kulkarni {
270114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
270214b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
270314b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
270414b24e2bSVaishali Kulkarni 
270514b24e2bSVaishali Kulkarni 	drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT;
270614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU,
270714b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
270814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
270914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc);
271014b24e2bSVaishali Kulkarni 
271114b24e2bSVaishali Kulkarni 	return rc;
271214b24e2bSVaishali Kulkarni }
271314b24e2bSVaishali Kulkarni 
271414b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * mac)271514b24e2bSVaishali Kulkarni ecore_mcp_ov_update_mac(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
271614b24e2bSVaishali Kulkarni 			u8 *mac)
271714b24e2bSVaishali Kulkarni {
271814b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
271914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
272014b24e2bSVaishali Kulkarni 	u32 mfw_mac[2];
272114b24e2bSVaishali Kulkarni 
272214b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
272314b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_VMAC;
272414b24e2bSVaishali Kulkarni 	mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC <<
272514b24e2bSVaishali Kulkarni 				DRV_MSG_CODE_VMAC_TYPE_SHIFT;
272614b24e2bSVaishali Kulkarni 	mb_params.param |= MCP_PF_ID(p_hwfn);
272714b24e2bSVaishali Kulkarni 
272814b24e2bSVaishali Kulkarni 	/* MCP is BE, and on LE platforms PCI would swap access to SHMEM
272914b24e2bSVaishali Kulkarni 	 * in 32-bit granularity.
273014b24e2bSVaishali Kulkarni 	 * So the MAC has to be set in native order [and not byte order],
273114b24e2bSVaishali Kulkarni 	 * otherwise it would be read incorrectly by MFW after swap.
273214b24e2bSVaishali Kulkarni 	 */
273314b24e2bSVaishali Kulkarni 	mfw_mac[0] = mac[0] << 24 | mac[1] << 16 | mac[2] << 8 | mac[3];
273414b24e2bSVaishali Kulkarni 	mfw_mac[1] = mac[4] << 24 | mac[5] << 16;
273514b24e2bSVaishali Kulkarni 
273614b24e2bSVaishali Kulkarni 	mb_params.p_data_src = (u8 *)mfw_mac;
273714b24e2bSVaishali Kulkarni 	mb_params.data_src_size = 8;
273814b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
273914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
274014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc);
274114b24e2bSVaishali Kulkarni 
274214b24e2bSVaishali Kulkarni 	/* Store primary MAC for later possible WoL */
274314b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_hwfn->p_dev->wol_mac, mac, ETH_ALEN);
274414b24e2bSVaishali Kulkarni 
274514b24e2bSVaishali Kulkarni 	return rc;
274614b24e2bSVaishali Kulkarni }
274714b24e2bSVaishali Kulkarni 
274814b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_wol(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_wol wol)274914b24e2bSVaishali Kulkarni ecore_mcp_ov_update_wol(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
275014b24e2bSVaishali Kulkarni 			enum ecore_ov_wol wol)
275114b24e2bSVaishali Kulkarni {
275214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
275314b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
275414b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
275514b24e2bSVaishali Kulkarni 
275614b24e2bSVaishali Kulkarni 	if (p_hwfn->hw_info.b_wol_support == ECORE_WOL_SUPPORT_NONE) {
275714b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
275814b24e2bSVaishali Kulkarni 			   "Can't change WoL configuration when WoL isn't supported\n");
275914b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
276014b24e2bSVaishali Kulkarni 	}
276114b24e2bSVaishali Kulkarni 
276214b24e2bSVaishali Kulkarni 	switch (wol) {
276314b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DEFAULT:
276414b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT;
276514b24e2bSVaishali Kulkarni 		break;
276614b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DISABLED:
276714b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_DISABLED;
276814b24e2bSVaishali Kulkarni 		break;
276914b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_ENABLED:
277014b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_ENABLED;
277114b24e2bSVaishali Kulkarni 		break;
277214b24e2bSVaishali Kulkarni 	default:
277314b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid wol state %d\n", wol);
277414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
277514b24e2bSVaishali Kulkarni 	}
277614b24e2bSVaishali Kulkarni 
277714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL,
277814b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
277914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
278014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc);
278114b24e2bSVaishali Kulkarni 
278214b24e2bSVaishali Kulkarni 	/* Store the WoL update for a future unload */
278314b24e2bSVaishali Kulkarni 	p_hwfn->p_dev->wol_config = (u8)wol;
278414b24e2bSVaishali Kulkarni 
278514b24e2bSVaishali Kulkarni 	return rc;
278614b24e2bSVaishali Kulkarni }
278714b24e2bSVaishali Kulkarni 
278814b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_ov_update_eswitch(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_eswitch eswitch)278914b24e2bSVaishali Kulkarni ecore_mcp_ov_update_eswitch(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
279014b24e2bSVaishali Kulkarni 			    enum ecore_ov_eswitch eswitch)
279114b24e2bSVaishali Kulkarni {
279214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
279314b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
279414b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
279514b24e2bSVaishali Kulkarni 
279614b24e2bSVaishali Kulkarni 	switch (eswitch) {
279714b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_NONE:
279814b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE;
279914b24e2bSVaishali Kulkarni 		break;
280014b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_VEB:
280114b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB;
280214b24e2bSVaishali Kulkarni 		break;
280314b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_VEPA:
280414b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA;
280514b24e2bSVaishali Kulkarni 		break;
280614b24e2bSVaishali Kulkarni 	default:
280714b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch);
280814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
280914b24e2bSVaishali Kulkarni 	}
281014b24e2bSVaishali Kulkarni 
281114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE,
281214b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
281314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
281414b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc);
281514b24e2bSVaishali Kulkarni 
281614b24e2bSVaishali Kulkarni 	return rc;
281714b24e2bSVaishali Kulkarni }
281814b24e2bSVaishali Kulkarni 
ecore_mcp_set_led(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_led_mode mode)281914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_led(struct ecore_hwfn *p_hwfn,
282014b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
282114b24e2bSVaishali Kulkarni 				       enum ecore_led_mode mode)
282214b24e2bSVaishali Kulkarni {
282314b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, drv_mb_param;
282414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
282514b24e2bSVaishali Kulkarni 
282614b24e2bSVaishali Kulkarni 	switch (mode) {
282714b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_ON:
282814b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON;
282914b24e2bSVaishali Kulkarni 		break;
283014b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_OFF:
283114b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF;
283214b24e2bSVaishali Kulkarni 		break;
283314b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_RESTORE:
283414b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER;
283514b24e2bSVaishali Kulkarni 		break;
283614b24e2bSVaishali Kulkarni 	default:
283714b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Invalid LED mode %d\n", mode);
283814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
283914b24e2bSVaishali Kulkarni 	}
284014b24e2bSVaishali Kulkarni 
284114b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE,
284214b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
284314b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
284414b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
284514b24e2bSVaishali Kulkarni 
284614b24e2bSVaishali Kulkarni 	return rc;
284714b24e2bSVaishali Kulkarni }
284814b24e2bSVaishali Kulkarni 
ecore_mcp_mask_parities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 mask_parities)284914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mask_parities(struct ecore_hwfn *p_hwfn,
285014b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
285114b24e2bSVaishali Kulkarni 					     u32 mask_parities)
285214b24e2bSVaishali Kulkarni {
285314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
285414b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
285514b24e2bSVaishali Kulkarni 
285614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MASK_PARITIES,
285714b24e2bSVaishali Kulkarni 			   mask_parities, &resp, &param);
285814b24e2bSVaishali Kulkarni 
285914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
286014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure for mask parities, aborting\n");
286114b24e2bSVaishali Kulkarni 	} else if (resp != FW_MSG_CODE_OK) {
286214b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP did not acknowledge mask parity request. Old MFW?\n");
286314b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
286414b24e2bSVaishali Kulkarni 	}
286514b24e2bSVaishali Kulkarni 
286614b24e2bSVaishali Kulkarni 	return rc;
286714b24e2bSVaishali Kulkarni }
286814b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_read(struct ecore_dev * p_dev,u32 addr,u8 * p_buf,u32 len)286914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
287014b24e2bSVaishali Kulkarni 			   u8 *p_buf, u32 len)
287114b24e2bSVaishali Kulkarni {
287214b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
287314b24e2bSVaishali Kulkarni 	u32 bytes_left, offset, bytes_to_copy, buf_size;
287414b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
287514b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
287614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
287714b24e2bSVaishali Kulkarni 
287814b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
287914b24e2bSVaishali Kulkarni 	if (!p_ptt)
288014b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
288114b24e2bSVaishali Kulkarni 
288214b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
288314b24e2bSVaishali Kulkarni 	bytes_left = len;
288414b24e2bSVaishali Kulkarni 	offset = 0;
288514b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
288614b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
288714b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_READ_NVRAM;
288814b24e2bSVaishali Kulkarni 	while (bytes_left > 0) {
288914b24e2bSVaishali Kulkarni 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
289014b24e2bSVaishali Kulkarni 					   MCP_DRV_NVM_BUF_LEN);
289114b24e2bSVaishali Kulkarni 		params.nvm_common.offset = (addr + offset) |
289214b24e2bSVaishali Kulkarni 					   (bytes_to_copy <<
289314b24e2bSVaishali Kulkarni 					    DRV_MB_PARAM_NVM_LEN_SHIFT);
289414b24e2bSVaishali Kulkarni 		params.nvm_rd.buf = (u32 *)(p_buf + offset);
289514b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
289614b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS || (params.nvm_common.resp !=
289714b24e2bSVaishali Kulkarni 					    FW_MSG_CODE_NVM_OK)) {
289814b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, false, "MCP command rc = %d\n",
289914b24e2bSVaishali Kulkarni 				  rc);
290014b24e2bSVaishali Kulkarni 			break;
290114b24e2bSVaishali Kulkarni 		}
290214b24e2bSVaishali Kulkarni 
290314b24e2bSVaishali Kulkarni 		/* This can be a lengthy process, and it's possible scheduler
290414b24e2bSVaishali Kulkarni 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
290514b24e2bSVaishali Kulkarni 		 */
290614b24e2bSVaishali Kulkarni 		if (bytes_left % 0x1000 <
290714b24e2bSVaishali Kulkarni 		    (bytes_left - *params.nvm_rd.buf_size) % 0x1000)
290814b24e2bSVaishali Kulkarni 			OSAL_MSLEEP(1);
290914b24e2bSVaishali Kulkarni 
291014b24e2bSVaishali Kulkarni 		offset += *params.nvm_rd.buf_size;
291114b24e2bSVaishali Kulkarni 		bytes_left -= *params.nvm_rd.buf_size;
291214b24e2bSVaishali Kulkarni 	}
291314b24e2bSVaishali Kulkarni 
291414b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
291514b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
291614b24e2bSVaishali Kulkarni 
291714b24e2bSVaishali Kulkarni 	return rc;
291814b24e2bSVaishali Kulkarni }
291914b24e2bSVaishali Kulkarni 
ecore_mcp_phy_read(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)292014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
292114b24e2bSVaishali Kulkarni 					u32 addr, u8 *p_buf, u32 len)
292214b24e2bSVaishali Kulkarni {
292314b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
292414b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
292514b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
292614b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
292714b24e2bSVaishali Kulkarni 
292814b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
292914b24e2bSVaishali Kulkarni 	if (!p_ptt)
293014b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
293114b24e2bSVaishali Kulkarni 
293214b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
293314b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
293414b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &len;
293514b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = (cmd == ECORE_PHY_CORE_READ) ?
293614b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_CORE_READ :
293714b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_RAW_READ;
293814b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
293914b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = (u32 *)p_buf;
294014b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
294114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
294214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
294314b24e2bSVaishali Kulkarni 
294414b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
294514b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
294614b24e2bSVaishali Kulkarni 
294714b24e2bSVaishali Kulkarni 	return rc;
294814b24e2bSVaishali Kulkarni }
294914b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_resp(struct ecore_dev * p_dev,u8 * p_buf)295014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_resp(struct ecore_dev *p_dev, u8 *p_buf)
295114b24e2bSVaishali Kulkarni {
295214b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
295314b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
295414b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
295514b24e2bSVaishali Kulkarni 
295614b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
295714b24e2bSVaishali Kulkarni 	if (!p_ptt)
295814b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
295914b24e2bSVaishali Kulkarni 
296014b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
296114b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_buf, &p_dev->mcp_nvm_resp, sizeof(p_dev->mcp_nvm_resp));
296214b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
296314b24e2bSVaishali Kulkarni 
296414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
296514b24e2bSVaishali Kulkarni }
296614b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_del_file(struct ecore_dev * p_dev,u32 addr)296714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_del_file(struct ecore_dev *p_dev,
296814b24e2bSVaishali Kulkarni 					    u32 addr)
296914b24e2bSVaishali Kulkarni {
297014b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
297114b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
297214b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
297314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
297414b24e2bSVaishali Kulkarni 
297514b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
297614b24e2bSVaishali Kulkarni 	if (!p_ptt)
297714b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
297814b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
297914b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
298014b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_DEL_FILE;
298114b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
298214b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
298314b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
298414b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
298514b24e2bSVaishali Kulkarni 
298614b24e2bSVaishali Kulkarni 	return rc;
298714b24e2bSVaishali Kulkarni }
298814b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_put_file_begin(struct ecore_dev * p_dev,u32 addr)298914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_put_file_begin(struct ecore_dev *p_dev,
299014b24e2bSVaishali Kulkarni 						  u32 addr)
299114b24e2bSVaishali Kulkarni {
299214b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
299314b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
299414b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
299514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
299614b24e2bSVaishali Kulkarni 
299714b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
299814b24e2bSVaishali Kulkarni 	if (!p_ptt)
299914b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
300014b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
300114b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
300214b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_PUT_FILE_BEGIN;
300314b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
300414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
300514b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
300614b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
300714b24e2bSVaishali Kulkarni 
300814b24e2bSVaishali Kulkarni 	return rc;
300914b24e2bSVaishali Kulkarni }
301014b24e2bSVaishali Kulkarni 
301114b24e2bSVaishali Kulkarni /* rc recieves ECORE_INVAL as default parameter because
301214b24e2bSVaishali Kulkarni  * it might not enter the while loop if the len is 0
301314b24e2bSVaishali Kulkarni  */
ecore_mcp_nvm_write(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)301414b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_write(struct ecore_dev *p_dev, u32 cmd,
301514b24e2bSVaishali Kulkarni 					 u32 addr, u8 *p_buf, u32 len)
301614b24e2bSVaishali Kulkarni {
301714b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
301814b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_INVAL;
301914b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
302014b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
302114b24e2bSVaishali Kulkarni 	u32 buf_idx, buf_size;
302214b24e2bSVaishali Kulkarni 
302314b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
302414b24e2bSVaishali Kulkarni 	if (!p_ptt)
302514b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
302614b24e2bSVaishali Kulkarni 
302714b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
302814b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
302914b24e2bSVaishali Kulkarni 	switch (cmd) {
303014b24e2bSVaishali Kulkarni 	case ECORE_PUT_FILE_DATA:
303114b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
303214b24e2bSVaishali Kulkarni 		break;
303314b24e2bSVaishali Kulkarni 	case ECORE_NVM_WRITE_NVRAM:
303414b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM;
303514b24e2bSVaishali Kulkarni 		break;
303614b24e2bSVaishali Kulkarni 	case ECORE_EXT_PHY_FW_UPGRADE:
303714b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_EXT_PHY_FW_UPGRADE;
303814b24e2bSVaishali Kulkarni 		break;
303914b24e2bSVaishali Kulkarni 	default:
304014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Invalid nvm write command 0x%x\n",
304114b24e2bSVaishali Kulkarni 			  cmd);
304214b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
304314b24e2bSVaishali Kulkarni 	}
304414b24e2bSVaishali Kulkarni 
304514b24e2bSVaishali Kulkarni 	buf_idx = 0;
304614b24e2bSVaishali Kulkarni 	while (buf_idx < len) {
304714b24e2bSVaishali Kulkarni 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
304814b24e2bSVaishali Kulkarni 				      MCP_DRV_NVM_BUF_LEN);
304914b24e2bSVaishali Kulkarni 		params.nvm_common.offset = ((buf_size <<
305014b24e2bSVaishali Kulkarni 					     DRV_MB_PARAM_NVM_LEN_SHIFT)
305114b24e2bSVaishali Kulkarni 					    | addr) + buf_idx;
305214b24e2bSVaishali Kulkarni 		params.nvm_wr.buf_size = buf_size;
305314b24e2bSVaishali Kulkarni 		params.nvm_wr.buf = (u32 *)&p_buf[buf_idx];
305414b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
305514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS ||
305614b24e2bSVaishali Kulkarni 		    ((params.nvm_common.resp != FW_MSG_CODE_NVM_OK) &&
305714b24e2bSVaishali Kulkarni 		     (params.nvm_common.resp !=
305814b24e2bSVaishali Kulkarni 		      FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK)))
305914b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
306014b24e2bSVaishali Kulkarni 
306114b24e2bSVaishali Kulkarni 		/* This can be a lengthy process, and it's possible scheduler
306214b24e2bSVaishali Kulkarni 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
306314b24e2bSVaishali Kulkarni 		 */
306414b24e2bSVaishali Kulkarni 		if (buf_idx % 0x1000 >
306514b24e2bSVaishali Kulkarni 		    (buf_idx + buf_size) % 0x1000)
306614b24e2bSVaishali Kulkarni 			OSAL_MSLEEP(1);
306714b24e2bSVaishali Kulkarni 
306814b24e2bSVaishali Kulkarni 		buf_idx += buf_size;
306914b24e2bSVaishali Kulkarni 	}
307014b24e2bSVaishali Kulkarni 
307114b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
307214b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
307314b24e2bSVaishali Kulkarni 
307414b24e2bSVaishali Kulkarni 	return rc;
307514b24e2bSVaishali Kulkarni }
307614b24e2bSVaishali Kulkarni 
ecore_mcp_phy_write(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)307714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_write(struct ecore_dev *p_dev, u32 cmd,
307814b24e2bSVaishali Kulkarni 					 u32 addr, u8 *p_buf, u32 len)
307914b24e2bSVaishali Kulkarni {
308014b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
308114b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
308214b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
308314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
308414b24e2bSVaishali Kulkarni 
308514b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
308614b24e2bSVaishali Kulkarni 	if (!p_ptt)
308714b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
308814b24e2bSVaishali Kulkarni 
308914b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
309014b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
309114b24e2bSVaishali Kulkarni 	params.nvm_wr.buf_size = len;
309214b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = (cmd == ECORE_PHY_CORE_WRITE) ?
309314b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_CORE_WRITE :
309414b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_RAW_WRITE;
309514b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
309614b24e2bSVaishali Kulkarni 	params.nvm_wr.buf = (u32 *)p_buf;
309714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
309814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
309914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
310014b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
310114b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
310214b24e2bSVaishali Kulkarni 
310314b24e2bSVaishali Kulkarni 	return rc;
310414b24e2bSVaishali Kulkarni }
310514b24e2bSVaishali Kulkarni 
ecore_mcp_nvm_set_secure_mode(struct ecore_dev * p_dev,u32 addr)310614b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_set_secure_mode(struct ecore_dev *p_dev,
310714b24e2bSVaishali Kulkarni 						   u32 addr)
310814b24e2bSVaishali Kulkarni {
310914b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
311014b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
311114b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
311214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
311314b24e2bSVaishali Kulkarni 
311414b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
311514b24e2bSVaishali Kulkarni 	if (!p_ptt)
311614b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
311714b24e2bSVaishali Kulkarni 
311814b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
311914b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
312014b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_SET_SECURE_MODE;
312114b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
312214b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
312314b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
312414b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
312514b24e2bSVaishali Kulkarni 
312614b24e2bSVaishali Kulkarni 	return rc;
312714b24e2bSVaishali Kulkarni }
312814b24e2bSVaishali Kulkarni 
ecore_mcp_phy_sfp_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 len,u8 * p_buf)312914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_sfp_read(struct ecore_hwfn *p_hwfn,
313014b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
313114b24e2bSVaishali Kulkarni 					    u32 port, u32 addr, u32 offset,
313214b24e2bSVaishali Kulkarni 					    u32 len, u8 *p_buf)
313314b24e2bSVaishali Kulkarni {
313414b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
313514b24e2bSVaishali Kulkarni 	u32 bytes_left, bytes_to_copy, buf_size;
313614b24e2bSVaishali Kulkarni 
313714b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
313814b24e2bSVaishali Kulkarni 	params.nvm_common.offset =
313914b24e2bSVaishali Kulkarni 		(port << DRV_MB_PARAM_TRANSCEIVER_PORT_SHIFT) |
314014b24e2bSVaishali Kulkarni 		(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_SHIFT);
314114b24e2bSVaishali Kulkarni 	addr = offset;
314214b24e2bSVaishali Kulkarni 	offset = 0;
314314b24e2bSVaishali Kulkarni 	bytes_left = len;
314414b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
314514b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
314614b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_TRANSCEIVER_READ;
314714b24e2bSVaishali Kulkarni 	while (bytes_left > 0) {
314814b24e2bSVaishali Kulkarni 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
314914b24e2bSVaishali Kulkarni 					   MAX_I2C_TRANSACTION_SIZE);
315014b24e2bSVaishali Kulkarni 		params.nvm_rd.buf = (u32 *)(p_buf + offset);
315114b24e2bSVaishali Kulkarni 		params.nvm_common.offset &=
315214b24e2bSVaishali Kulkarni 			(DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
315314b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
315414b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
315514b24e2bSVaishali Kulkarni 			((addr + offset) <<
315614b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_OFFSET_SHIFT);
315714b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
315814b24e2bSVaishali Kulkarni 			(bytes_to_copy << DRV_MB_PARAM_TRANSCEIVER_SIZE_SHIFT);
3159b68ddc76SJohn Levon 		(void) ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
316014b24e2bSVaishali Kulkarni 		if ((params.nvm_common.resp & FW_MSG_CODE_MASK) ==
316114b24e2bSVaishali Kulkarni 		    FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
316214b24e2bSVaishali Kulkarni 			return ECORE_NODEV;
316314b24e2bSVaishali Kulkarni 		} else if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
316414b24e2bSVaishali Kulkarni 			   FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
316514b24e2bSVaishali Kulkarni 			return ECORE_UNKNOWN_ERROR;
316614b24e2bSVaishali Kulkarni 
316714b24e2bSVaishali Kulkarni 		offset += *params.nvm_rd.buf_size;
316814b24e2bSVaishali Kulkarni 		bytes_left -= *params.nvm_rd.buf_size;
316914b24e2bSVaishali Kulkarni 	}
317014b24e2bSVaishali Kulkarni 
317114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
317214b24e2bSVaishali Kulkarni }
317314b24e2bSVaishali Kulkarni 
ecore_mcp_phy_sfp_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 len,u8 * p_buf)317414b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_sfp_write(struct ecore_hwfn *p_hwfn,
317514b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
317614b24e2bSVaishali Kulkarni 					     u32 port, u32 addr, u32 offset,
317714b24e2bSVaishali Kulkarni 					     u32 len, u8 *p_buf)
317814b24e2bSVaishali Kulkarni {
317914b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
318014b24e2bSVaishali Kulkarni 	u32 buf_idx, buf_size;
318114b24e2bSVaishali Kulkarni 
318214b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
318314b24e2bSVaishali Kulkarni 	params.nvm_common.offset =
318414b24e2bSVaishali Kulkarni 		(port << DRV_MB_PARAM_TRANSCEIVER_PORT_SHIFT) |
318514b24e2bSVaishali Kulkarni 		(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_SHIFT);
318614b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
318714b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_TRANSCEIVER_WRITE;
318814b24e2bSVaishali Kulkarni 	buf_idx = 0;
318914b24e2bSVaishali Kulkarni 	while (buf_idx < len) {
319014b24e2bSVaishali Kulkarni 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
319114b24e2bSVaishali Kulkarni 				      MAX_I2C_TRANSACTION_SIZE);
319214b24e2bSVaishali Kulkarni 		params.nvm_common.offset &=
319314b24e2bSVaishali Kulkarni 			(DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
319414b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
319514b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
319614b24e2bSVaishali Kulkarni 			((offset + buf_idx) <<
319714b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_OFFSET_SHIFT);
319814b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
319914b24e2bSVaishali Kulkarni 			(buf_size << DRV_MB_PARAM_TRANSCEIVER_SIZE_SHIFT);
320014b24e2bSVaishali Kulkarni 		params.nvm_wr.buf_size = buf_size;
320114b24e2bSVaishali Kulkarni 		params.nvm_wr.buf = (u32 *)&p_buf[buf_idx];
3202b68ddc76SJohn Levon 		(void) ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
320314b24e2bSVaishali Kulkarni 		if ((params.nvm_common.resp & FW_MSG_CODE_MASK) ==
320414b24e2bSVaishali Kulkarni 		    FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
320514b24e2bSVaishali Kulkarni 			return ECORE_NODEV;
320614b24e2bSVaishali Kulkarni 		} else if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
320714b24e2bSVaishali Kulkarni 			   FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
320814b24e2bSVaishali Kulkarni 			return ECORE_UNKNOWN_ERROR;
320914b24e2bSVaishali Kulkarni 
321014b24e2bSVaishali Kulkarni 		buf_idx += buf_size;
321114b24e2bSVaishali Kulkarni 	}
321214b24e2bSVaishali Kulkarni 
321314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
321414b24e2bSVaishali Kulkarni }
321514b24e2bSVaishali Kulkarni 
ecore_mcp_gpio_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u32 * gpio_val)321614b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_read(struct ecore_hwfn *p_hwfn,
321714b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
321814b24e2bSVaishali Kulkarni 					 u16 gpio, u32 *gpio_val)
321914b24e2bSVaishali Kulkarni {
322014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
322114b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp;
322214b24e2bSVaishali Kulkarni 
322314b24e2bSVaishali Kulkarni 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT);
322414b24e2bSVaishali Kulkarni 
322514b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_READ,
322614b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, gpio_val);
322714b24e2bSVaishali Kulkarni 
322814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
322914b24e2bSVaishali Kulkarni 		return rc;
323014b24e2bSVaishali Kulkarni 
323114b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
323214b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
323314b24e2bSVaishali Kulkarni 
323414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
323514b24e2bSVaishali Kulkarni }
323614b24e2bSVaishali Kulkarni 
ecore_mcp_gpio_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u16 gpio_val)323714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_write(struct ecore_hwfn *p_hwfn,
323814b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
323914b24e2bSVaishali Kulkarni 					  u16 gpio, u16 gpio_val)
324014b24e2bSVaishali Kulkarni {
324114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
324214b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, param, rsp;
324314b24e2bSVaishali Kulkarni 
324414b24e2bSVaishali Kulkarni 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT) |
324514b24e2bSVaishali Kulkarni 		(gpio_val << DRV_MB_PARAM_GPIO_VALUE_SHIFT);
324614b24e2bSVaishali Kulkarni 
324714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_WRITE,
324814b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
324914b24e2bSVaishali Kulkarni 
325014b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
325114b24e2bSVaishali Kulkarni 		return rc;
325214b24e2bSVaishali Kulkarni 
325314b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
325414b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
325514b24e2bSVaishali Kulkarni 
325614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
325714b24e2bSVaishali Kulkarni }
325814b24e2bSVaishali Kulkarni 
ecore_mcp_gpio_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u32 * gpio_direction,u32 * gpio_ctrl)325914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_info(struct ecore_hwfn *p_hwfn,
326014b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
326114b24e2bSVaishali Kulkarni 					 u16 gpio, u32 *gpio_direction,
326214b24e2bSVaishali Kulkarni 					 u32 *gpio_ctrl)
326314b24e2bSVaishali Kulkarni {
326414b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp, val = 0;
326514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
326614b24e2bSVaishali Kulkarni 
326714b24e2bSVaishali Kulkarni 	drv_mb_param = gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT;
326814b24e2bSVaishali Kulkarni 
326914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_INFO,
327014b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &val);
327114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
327214b24e2bSVaishali Kulkarni 		return rc;
327314b24e2bSVaishali Kulkarni 
327414b24e2bSVaishali Kulkarni 	*gpio_direction = (val & DRV_MB_PARAM_GPIO_DIRECTION_MASK) >>
327514b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_GPIO_DIRECTION_SHIFT;
327614b24e2bSVaishali Kulkarni 	*gpio_ctrl = (val & DRV_MB_PARAM_GPIO_CTRL_MASK) >>
327714b24e2bSVaishali Kulkarni 		      DRV_MB_PARAM_GPIO_CTRL_SHIFT;
327814b24e2bSVaishali Kulkarni 
327914b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
328014b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
328114b24e2bSVaishali Kulkarni 
328214b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
328314b24e2bSVaishali Kulkarni }
328414b24e2bSVaishali Kulkarni 
ecore_mcp_bist_register_test(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)328514b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_register_test(struct ecore_hwfn *p_hwfn,
328614b24e2bSVaishali Kulkarni 						  struct ecore_ptt *p_ptt)
328714b24e2bSVaishali Kulkarni {
328814b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp, param;
328914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
329014b24e2bSVaishali Kulkarni 
329114b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST <<
329214b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
329314b24e2bSVaishali Kulkarni 
329414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
329514b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
329614b24e2bSVaishali Kulkarni 
329714b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
329814b24e2bSVaishali Kulkarni 		return rc;
329914b24e2bSVaishali Kulkarni 
330014b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
330114b24e2bSVaishali Kulkarni 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
330214b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
330314b24e2bSVaishali Kulkarni 
330414b24e2bSVaishali Kulkarni 	return rc;
330514b24e2bSVaishali Kulkarni }
330614b24e2bSVaishali Kulkarni 
ecore_mcp_bist_clock_test(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)330714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_clock_test(struct ecore_hwfn *p_hwfn,
330814b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt)
330914b24e2bSVaishali Kulkarni {
331014b24e2bSVaishali Kulkarni 	u32 drv_mb_param, rsp, param;
331114b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
331214b24e2bSVaishali Kulkarni 
331314b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST <<
331414b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
331514b24e2bSVaishali Kulkarni 
331614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
331714b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
331814b24e2bSVaishali Kulkarni 
331914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
332014b24e2bSVaishali Kulkarni 		return rc;
332114b24e2bSVaishali Kulkarni 
332214b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
332314b24e2bSVaishali Kulkarni 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
332414b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
332514b24e2bSVaishali Kulkarni 
332614b24e2bSVaishali Kulkarni 	return rc;
332714b24e2bSVaishali Kulkarni }
332814b24e2bSVaishali Kulkarni 
ecore_mcp_bist_nvm_test_get_num_images(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * num_images)332914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_nvm_test_get_num_images(
333014b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, u32 *num_images)
333114b24e2bSVaishali Kulkarni {
333214b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp;
333314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
333414b24e2bSVaishali Kulkarni 
333514b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES <<
333614b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
333714b24e2bSVaishali Kulkarni 
333814b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
333914b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, num_images);
334014b24e2bSVaishali Kulkarni 
334114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
334214b24e2bSVaishali Kulkarni 		return rc;
334314b24e2bSVaishali Kulkarni 
334414b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
334514b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
334614b24e2bSVaishali Kulkarni 
334714b24e2bSVaishali Kulkarni 	return rc;
334814b24e2bSVaishali Kulkarni }
334914b24e2bSVaishali Kulkarni 
ecore_mcp_bist_nvm_test_get_image_att(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct bist_nvm_image_att * p_image_att,u32 image_index)335014b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
335114b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
335214b24e2bSVaishali Kulkarni 	struct bist_nvm_image_att *p_image_att, u32 image_index)
335314b24e2bSVaishali Kulkarni {
335414b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
335514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
335614b24e2bSVaishali Kulkarni 	u32 buf_size;
335714b24e2bSVaishali Kulkarni 
335814b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
335914b24e2bSVaishali Kulkarni 	params.nvm_common.offset = (DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX <<
336014b24e2bSVaishali Kulkarni 				    DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
336114b24e2bSVaishali Kulkarni 	params.nvm_common.offset |= (image_index <<
336214b24e2bSVaishali Kulkarni 				    DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT);
336314b24e2bSVaishali Kulkarni 
336414b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
336514b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
336614b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_BIST_TEST;
336714b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = (u32 *)p_image_att;
336814b24e2bSVaishali Kulkarni 
336914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
337014b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
337114b24e2bSVaishali Kulkarni 		return rc;
337214b24e2bSVaishali Kulkarni 
337314b24e2bSVaishali Kulkarni 	if (((params.nvm_common.resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
337414b24e2bSVaishali Kulkarni 	    (p_image_att->return_code != 1))
337514b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
337614b24e2bSVaishali Kulkarni 
337714b24e2bSVaishali Kulkarni 	return rc;
337814b24e2bSVaishali Kulkarni }
337914b24e2bSVaishali Kulkarni 
338014b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_get_nvm_image_att(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_nvm_images image_id,struct ecore_nvm_image_att * p_image_att)338114b24e2bSVaishali Kulkarni ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
338214b24e2bSVaishali Kulkarni 			    enum ecore_nvm_images image_id,
338314b24e2bSVaishali Kulkarni 			    struct ecore_nvm_image_att *p_image_att)
338414b24e2bSVaishali Kulkarni {
338514b24e2bSVaishali Kulkarni 	struct bist_nvm_image_att mfw_image_att;
338614b24e2bSVaishali Kulkarni 	enum nvm_image_type type;
338714b24e2bSVaishali Kulkarni 	u32 num_images, i;
338814b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
338914b24e2bSVaishali Kulkarni 
339014b24e2bSVaishali Kulkarni 	/* Translate image_id into MFW definitions */
339114b24e2bSVaishali Kulkarni 	switch (image_id) {
339214b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_ISCSI_CFG:
339314b24e2bSVaishali Kulkarni 		type = NVM_TYPE_ISCSI_CFG;
339414b24e2bSVaishali Kulkarni 		break;
339514b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_FCOE_CFG:
339614b24e2bSVaishali Kulkarni 		type = NVM_TYPE_FCOE_CFG;
339714b24e2bSVaishali Kulkarni 		break;
339814b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_MDUMP:
339914b24e2bSVaishali Kulkarni 		type = NVM_TYPE_MDUMP;
340014b24e2bSVaishali Kulkarni 		break;
340114b24e2bSVaishali Kulkarni 	default:
340214b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
340314b24e2bSVaishali Kulkarni 			  image_id);
340414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
340514b24e2bSVaishali Kulkarni 	}
340614b24e2bSVaishali Kulkarni 
340714b24e2bSVaishali Kulkarni 	/* Learn number of images, then traverse and see if one fits */
340814b24e2bSVaishali Kulkarni 	rc = ecore_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
340914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS || !num_images)
341014b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
341114b24e2bSVaishali Kulkarni 
341214b24e2bSVaishali Kulkarni 	for (i = 0; i < num_images; i++) {
341314b24e2bSVaishali Kulkarni 		rc = ecore_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
341414b24e2bSVaishali Kulkarni 							   &mfw_image_att, i);
341514b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
341614b24e2bSVaishali Kulkarni 			return rc;
341714b24e2bSVaishali Kulkarni 
341814b24e2bSVaishali Kulkarni 		if (type == mfw_image_att.image_type)
341914b24e2bSVaishali Kulkarni 			break;
342014b24e2bSVaishali Kulkarni 	}
342114b24e2bSVaishali Kulkarni 	if (i == num_images) {
342214b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
342314b24e2bSVaishali Kulkarni 			   "Failed to find nvram image of type %08x\n",
342414b24e2bSVaishali Kulkarni 			   image_id);
342514b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
342614b24e2bSVaishali Kulkarni 	}
342714b24e2bSVaishali Kulkarni 
342814b24e2bSVaishali Kulkarni 	p_image_att->start_addr = mfw_image_att.nvm_start_addr;
342914b24e2bSVaishali Kulkarni 	p_image_att->length = mfw_image_att.len;
343014b24e2bSVaishali Kulkarni 
343114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
343214b24e2bSVaishali Kulkarni }
343314b24e2bSVaishali Kulkarni 
ecore_mcp_get_nvm_image(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_nvm_images image_id,u8 * p_buffer,u32 buffer_len)343414b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
343514b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
343614b24e2bSVaishali Kulkarni 					     enum ecore_nvm_images image_id,
343714b24e2bSVaishali Kulkarni 					     u8 *p_buffer, u32 buffer_len)
343814b24e2bSVaishali Kulkarni {
343914b24e2bSVaishali Kulkarni 	struct ecore_nvm_image_att image_att;
344014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
344114b24e2bSVaishali Kulkarni 
344214b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(p_buffer, buffer_len);
344314b24e2bSVaishali Kulkarni 
344414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_get_nvm_image_att(p_hwfn, p_ptt, image_id, &image_att);
344514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
344614b24e2bSVaishali Kulkarni 		return rc;
344714b24e2bSVaishali Kulkarni 
344814b24e2bSVaishali Kulkarni 	/* Validate sizes - both the image's and the supplied buffer's */
344914b24e2bSVaishali Kulkarni 	if (image_att.length <= 4) {
345014b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
345114b24e2bSVaishali Kulkarni 			   "Image [%d] is too small - only %d bytes\n",
345214b24e2bSVaishali Kulkarni 			   image_id, image_att.length);
345314b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
345414b24e2bSVaishali Kulkarni 	}
345514b24e2bSVaishali Kulkarni 
345614b24e2bSVaishali Kulkarni 	/* Each NVM image is suffixed by CRC; Upper-layer has no need for it */
345714b24e2bSVaishali Kulkarni 	image_att.length -= 4;
345814b24e2bSVaishali Kulkarni 
345914b24e2bSVaishali Kulkarni 	if (image_att.length > buffer_len) {
346014b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
346114b24e2bSVaishali Kulkarni 			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
346214b24e2bSVaishali Kulkarni 			   image_id, image_att.length, buffer_len);
346314b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
346414b24e2bSVaishali Kulkarni 	}
346514b24e2bSVaishali Kulkarni 
346614b24e2bSVaishali Kulkarni 	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
346714b24e2bSVaishali Kulkarni 				  p_buffer, image_att.length);
346814b24e2bSVaishali Kulkarni }
346914b24e2bSVaishali Kulkarni 
347014b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_get_temperature_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_temperature_info * p_temp_info)347114b24e2bSVaishali Kulkarni ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
347214b24e2bSVaishali Kulkarni 			       struct ecore_ptt *p_ptt,
347314b24e2bSVaishali Kulkarni 			       struct ecore_temperature_info *p_temp_info)
347414b24e2bSVaishali Kulkarni {
347514b24e2bSVaishali Kulkarni 	struct ecore_temperature_sensor *p_temp_sensor;
347614b24e2bSVaishali Kulkarni 	struct temperature_status_stc mfw_temp_info;
347714b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
347814b24e2bSVaishali Kulkarni 	u32 val;
347914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
348014b24e2bSVaishali Kulkarni 	u8 i;
348114b24e2bSVaishali Kulkarni 
348214b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
348314b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_TEMPERATURE;
348414b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &mfw_temp_info;
348514b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(mfw_temp_info);
348614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
348714b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
348814b24e2bSVaishali Kulkarni 		return rc;
348914b24e2bSVaishali Kulkarni 
349014b24e2bSVaishali Kulkarni 	OSAL_BUILD_BUG_ON(ECORE_MAX_NUM_OF_SENSORS != MAX_NUM_OF_SENSORS);
349114b24e2bSVaishali Kulkarni 	p_temp_info->num_sensors = OSAL_MIN_T(u32, mfw_temp_info.num_of_sensors,
349214b24e2bSVaishali Kulkarni 					      ECORE_MAX_NUM_OF_SENSORS);
349314b24e2bSVaishali Kulkarni 	for (i = 0; i < p_temp_info->num_sensors; i++) {
349414b24e2bSVaishali Kulkarni 		val = mfw_temp_info.sensor[i];
349514b24e2bSVaishali Kulkarni 		p_temp_sensor = &p_temp_info->sensors[i];
349614b24e2bSVaishali Kulkarni 		p_temp_sensor->sensor_location = (val & SENSOR_LOCATION_MASK) >>
349714b24e2bSVaishali Kulkarni 						 SENSOR_LOCATION_SHIFT;
349814b24e2bSVaishali Kulkarni 		p_temp_sensor->threshold_high = (val & THRESHOLD_HIGH_MASK) >>
349914b24e2bSVaishali Kulkarni 						THRESHOLD_HIGH_SHIFT;
350014b24e2bSVaishali Kulkarni 		p_temp_sensor->critical = (val & CRITICAL_TEMPERATURE_MASK) >>
350114b24e2bSVaishali Kulkarni 					  CRITICAL_TEMPERATURE_SHIFT;
350214b24e2bSVaishali Kulkarni 		p_temp_sensor->current_temp = (val & CURRENT_TEMP_MASK) >>
350314b24e2bSVaishali Kulkarni 					      CURRENT_TEMP_SHIFT;
350414b24e2bSVaishali Kulkarni 	}
350514b24e2bSVaishali Kulkarni 
350614b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
350714b24e2bSVaishali Kulkarni }
350814b24e2bSVaishali Kulkarni 
ecore_mcp_get_mba_versions(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mba_vers * p_mba_vers)350914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mba_versions(
351014b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn,
351114b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt,
351214b24e2bSVaishali Kulkarni 	struct ecore_mba_vers *p_mba_vers)
351314b24e2bSVaishali Kulkarni {
351414b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
351514b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
351614b24e2bSVaishali Kulkarni 	u32 buf_size;
351714b24e2bSVaishali Kulkarni 
351814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&params, sizeof(params));
351914b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
352014b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_GET_MBA_VERSION;
352114b24e2bSVaishali Kulkarni 	params.nvm_common.offset = 0;
352214b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = &(p_mba_vers->mba_vers[0]);
352314b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
352414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
352514b24e2bSVaishali Kulkarni 
352614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
352714b24e2bSVaishali Kulkarni 		return rc;
352814b24e2bSVaishali Kulkarni 
352914b24e2bSVaishali Kulkarni 	if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
353014b24e2bSVaishali Kulkarni 	    FW_MSG_CODE_NVM_OK)
353114b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
353214b24e2bSVaishali Kulkarni 
353314b24e2bSVaishali Kulkarni 	if (buf_size != MCP_DRV_NVM_BUF_LEN)
353414b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
353514b24e2bSVaishali Kulkarni 
353614b24e2bSVaishali Kulkarni 	return rc;
353714b24e2bSVaishali Kulkarni }
353814b24e2bSVaishali Kulkarni 
ecore_mcp_mem_ecc_events(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u64 * num_events)353914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mem_ecc_events(struct ecore_hwfn *p_hwfn,
354014b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
354114b24e2bSVaishali Kulkarni 					      u64 *num_events)
354214b24e2bSVaishali Kulkarni {
354314b24e2bSVaishali Kulkarni 	u32 rsp;
354414b24e2bSVaishali Kulkarni 
354514b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MEM_ECC_EVENTS,
354614b24e2bSVaishali Kulkarni 			     0, &rsp, (u32 *)num_events);
354714b24e2bSVaishali Kulkarni }
354814b24e2bSVaishali Kulkarni 
354914b24e2bSVaishali Kulkarni static enum resource_id_enum
ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)355014b24e2bSVaishali Kulkarni ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)
355114b24e2bSVaishali Kulkarni {
355214b24e2bSVaishali Kulkarni 	enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
355314b24e2bSVaishali Kulkarni 
355414b24e2bSVaishali Kulkarni 	switch (res_id) {
355514b24e2bSVaishali Kulkarni 	case ECORE_SB:
355614b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_SB_E;
355714b24e2bSVaishali Kulkarni 		break;
355814b24e2bSVaishali Kulkarni 	case ECORE_L2_QUEUE:
355914b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
356014b24e2bSVaishali Kulkarni 		break;
356114b24e2bSVaishali Kulkarni 	case ECORE_VPORT:
356214b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_VPORT_E;
356314b24e2bSVaishali Kulkarni 		break;
356414b24e2bSVaishali Kulkarni 	case ECORE_RSS_ENG:
356514b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
356614b24e2bSVaishali Kulkarni 		break;
356714b24e2bSVaishali Kulkarni 	case ECORE_PQ:
356814b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_PQ_E;
356914b24e2bSVaishali Kulkarni 		break;
357014b24e2bSVaishali Kulkarni 	case ECORE_RL:
357114b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_RL_E;
357214b24e2bSVaishali Kulkarni 		break;
357314b24e2bSVaishali Kulkarni 	case ECORE_MAC:
357414b24e2bSVaishali Kulkarni 	case ECORE_VLAN:
357514b24e2bSVaishali Kulkarni 		/* Each VFC resource can accommodate both a MAC and a VLAN */
357614b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_VFC_FILTER_E;
357714b24e2bSVaishali Kulkarni 		break;
357814b24e2bSVaishali Kulkarni 	case ECORE_ILT:
357914b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_ILT_E;
358014b24e2bSVaishali Kulkarni 		break;
358114b24e2bSVaishali Kulkarni 	case ECORE_LL2_QUEUE:
358214b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_LL2_QUEUE_E;
358314b24e2bSVaishali Kulkarni 		break;
358414b24e2bSVaishali Kulkarni 	case ECORE_RDMA_CNQ_RAM:
358514b24e2bSVaishali Kulkarni 	case ECORE_CMDQS_CQS:
358614b24e2bSVaishali Kulkarni 		/* CNQ/CMDQS are the same resource */
358714b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_CQS_E;
358814b24e2bSVaishali Kulkarni 		break;
358914b24e2bSVaishali Kulkarni 	case ECORE_RDMA_STATS_QUEUE:
359014b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
359114b24e2bSVaishali Kulkarni 		break;
359214b24e2bSVaishali Kulkarni 	case ECORE_BDQ:
359314b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_BDQ_E;
359414b24e2bSVaishali Kulkarni 		break;
359514b24e2bSVaishali Kulkarni 	default:
359614b24e2bSVaishali Kulkarni 		break;
359714b24e2bSVaishali Kulkarni 	}
359814b24e2bSVaishali Kulkarni 
359914b24e2bSVaishali Kulkarni 	return mfw_res_id;
360014b24e2bSVaishali Kulkarni }
360114b24e2bSVaishali Kulkarni 
360214b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION_MAJOR	2
360314b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION_MINOR	0
360414b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION				\
360514b24e2bSVaishali Kulkarni 	((ECORE_RESC_ALLOC_VERSION_MAJOR <<			\
360614b24e2bSVaishali Kulkarni 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) |	\
360714b24e2bSVaishali Kulkarni 	 (ECORE_RESC_ALLOC_VERSION_MINOR <<			\
360814b24e2bSVaishali Kulkarni 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT))
360914b24e2bSVaishali Kulkarni 
361014b24e2bSVaishali Kulkarni struct ecore_resc_alloc_in_params {
361114b24e2bSVaishali Kulkarni 	u32 cmd;
361214b24e2bSVaishali Kulkarni 	enum ecore_resources res_id;
361314b24e2bSVaishali Kulkarni 	u32 resc_max_val;
361414b24e2bSVaishali Kulkarni };
361514b24e2bSVaishali Kulkarni 
361614b24e2bSVaishali Kulkarni struct ecore_resc_alloc_out_params {
361714b24e2bSVaishali Kulkarni 	u32 mcp_resp;
361814b24e2bSVaishali Kulkarni 	u32 mcp_param;
361914b24e2bSVaishali Kulkarni 	u32 resc_num;
362014b24e2bSVaishali Kulkarni 	u32 resc_start;
362114b24e2bSVaishali Kulkarni 	u32 vf_resc_num;
362214b24e2bSVaishali Kulkarni 	u32 vf_resc_start;
362314b24e2bSVaishali Kulkarni 	u32 flags;
362414b24e2bSVaishali Kulkarni };
362514b24e2bSVaishali Kulkarni 
362614b24e2bSVaishali Kulkarni static enum _ecore_status_t
ecore_mcp_resc_allocation_msg(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_alloc_in_params * p_in_params,struct ecore_resc_alloc_out_params * p_out_params)362714b24e2bSVaishali Kulkarni ecore_mcp_resc_allocation_msg(struct ecore_hwfn *p_hwfn,
362814b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt,
362914b24e2bSVaishali Kulkarni 			      struct ecore_resc_alloc_in_params *p_in_params,
363014b24e2bSVaishali Kulkarni 			      struct ecore_resc_alloc_out_params *p_out_params)
363114b24e2bSVaishali Kulkarni {
363214b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
363314b24e2bSVaishali Kulkarni 	struct resource_info mfw_resc_info;
363414b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
363514b24e2bSVaishali Kulkarni 
363614b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mfw_resc_info, sizeof(mfw_resc_info));
363714b24e2bSVaishali Kulkarni 
363814b24e2bSVaishali Kulkarni 	mfw_resc_info.res_id = ecore_mcp_get_mfw_res_id(p_in_params->res_id);
363914b24e2bSVaishali Kulkarni 	if (mfw_resc_info.res_id == RESOURCE_NUM_INVALID) {
364014b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
364114b24e2bSVaishali Kulkarni 		       "Failed to match resource %d [%s] with the MFW resources\n",
364214b24e2bSVaishali Kulkarni 		       p_in_params->res_id,
364314b24e2bSVaishali Kulkarni 		       ecore_hw_get_resc_name(p_in_params->res_id));
364414b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
364514b24e2bSVaishali Kulkarni 	}
364614b24e2bSVaishali Kulkarni 
364714b24e2bSVaishali Kulkarni 	switch (p_in_params->cmd) {
364814b24e2bSVaishali Kulkarni 	case DRV_MSG_SET_RESOURCE_VALUE_MSG:
364914b24e2bSVaishali Kulkarni 		mfw_resc_info.size = p_in_params->resc_max_val;
365014b24e2bSVaishali Kulkarni 		/* Fallthrough */
365114b24e2bSVaishali Kulkarni 	case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
365214b24e2bSVaishali Kulkarni 		break;
365314b24e2bSVaishali Kulkarni 	default:
365414b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected resource alloc command [0x%08x]\n",
365514b24e2bSVaishali Kulkarni 		       p_in_params->cmd);
365614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
365714b24e2bSVaishali Kulkarni 	}
365814b24e2bSVaishali Kulkarni 
365914b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
366014b24e2bSVaishali Kulkarni 	mb_params.cmd = p_in_params->cmd;
366114b24e2bSVaishali Kulkarni 	mb_params.param = ECORE_RESC_ALLOC_VERSION;
366214b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &mfw_resc_info;
366314b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(mfw_resc_info);
366414b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = mb_params.p_data_src;
366514b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = mb_params.data_src_size;
366614b24e2bSVaishali Kulkarni 
366714b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
366814b24e2bSVaishali Kulkarni 		   "Resource message request: cmd 0x%08x, res_id %d [%s], hsi_version %d.%d, val 0x%x\n",
366914b24e2bSVaishali Kulkarni 		   p_in_params->cmd, p_in_params->res_id,
367014b24e2bSVaishali Kulkarni 		   ecore_hw_get_resc_name(p_in_params->res_id),
367114b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param,
367214b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
367314b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param,
367414b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
367514b24e2bSVaishali Kulkarni 		   p_in_params->resc_max_val);
367614b24e2bSVaishali Kulkarni 
367714b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
367814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
367914b24e2bSVaishali Kulkarni 		return rc;
368014b24e2bSVaishali Kulkarni 
368114b24e2bSVaishali Kulkarni 	p_out_params->mcp_resp = mb_params.mcp_resp;
368214b24e2bSVaishali Kulkarni 	p_out_params->mcp_param = mb_params.mcp_param;
368314b24e2bSVaishali Kulkarni 	p_out_params->resc_num = mfw_resc_info.size;
368414b24e2bSVaishali Kulkarni 	p_out_params->resc_start = mfw_resc_info.offset;
368514b24e2bSVaishali Kulkarni 	p_out_params->vf_resc_num = mfw_resc_info.vf_size;
368614b24e2bSVaishali Kulkarni 	p_out_params->vf_resc_start = mfw_resc_info.vf_offset;
368714b24e2bSVaishali Kulkarni 	p_out_params->flags = mfw_resc_info.flags;
368814b24e2bSVaishali Kulkarni 
368914b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
369014b24e2bSVaishali Kulkarni 		   "Resource message response: mfw_hsi_version %d.%d, num 0x%x, start 0x%x, vf_num 0x%x, vf_start 0x%x, flags 0x%08x\n",
369114b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
369214b24e2bSVaishali Kulkarni 			   FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
369314b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
369414b24e2bSVaishali Kulkarni 			   FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
369514b24e2bSVaishali Kulkarni 		   p_out_params->resc_num, p_out_params->resc_start,
369614b24e2bSVaishali Kulkarni 		   p_out_params->vf_resc_num, p_out_params->vf_resc_start,
369714b24e2bSVaishali Kulkarni 		   p_out_params->flags);
369814b24e2bSVaishali Kulkarni 
369914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
370014b24e2bSVaishali Kulkarni }
370114b24e2bSVaishali Kulkarni 
370214b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_set_resc_max_val(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_resources res_id,u32 resc_max_val,u32 * p_mcp_resp)370314b24e2bSVaishali Kulkarni ecore_mcp_set_resc_max_val(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
370414b24e2bSVaishali Kulkarni 			   enum ecore_resources res_id, u32 resc_max_val,
370514b24e2bSVaishali Kulkarni 			   u32 *p_mcp_resp)
370614b24e2bSVaishali Kulkarni {
370714b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_out_params out_params;
370814b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_in_params in_params;
370914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
371014b24e2bSVaishali Kulkarni 
371114b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
371214b24e2bSVaishali Kulkarni 	in_params.cmd = DRV_MSG_SET_RESOURCE_VALUE_MSG;
371314b24e2bSVaishali Kulkarni 	in_params.res_id = res_id;
371414b24e2bSVaishali Kulkarni 	in_params.resc_max_val = resc_max_val;
371514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
371614b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
371714b24e2bSVaishali Kulkarni 					   &out_params);
371814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
371914b24e2bSVaishali Kulkarni 		return rc;
372014b24e2bSVaishali Kulkarni 
372114b24e2bSVaishali Kulkarni 	*p_mcp_resp = out_params.mcp_resp;
372214b24e2bSVaishali Kulkarni 
372314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
372414b24e2bSVaishali Kulkarni }
372514b24e2bSVaishali Kulkarni 
372614b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_get_resc_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_resources res_id,u32 * p_mcp_resp,u32 * p_resc_num,u32 * p_resc_start)372714b24e2bSVaishali Kulkarni ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
372814b24e2bSVaishali Kulkarni 			enum ecore_resources res_id, u32 *p_mcp_resp,
372914b24e2bSVaishali Kulkarni 			u32 *p_resc_num, u32 *p_resc_start)
373014b24e2bSVaishali Kulkarni {
373114b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_out_params out_params;
373214b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_in_params in_params;
373314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
373414b24e2bSVaishali Kulkarni 
373514b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
373614b24e2bSVaishali Kulkarni 	in_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
373714b24e2bSVaishali Kulkarni 	in_params.res_id = res_id;
373814b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
373914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
374014b24e2bSVaishali Kulkarni 					   &out_params);
374114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
374214b24e2bSVaishali Kulkarni 		return rc;
374314b24e2bSVaishali Kulkarni 
374414b24e2bSVaishali Kulkarni 	*p_mcp_resp = out_params.mcp_resp;
374514b24e2bSVaishali Kulkarni 
374614b24e2bSVaishali Kulkarni 	if (*p_mcp_resp == FW_MSG_CODE_RESOURCE_ALLOC_OK) {
374714b24e2bSVaishali Kulkarni 		*p_resc_num = out_params.resc_num;
374814b24e2bSVaishali Kulkarni 		*p_resc_start = out_params.resc_start;
374914b24e2bSVaishali Kulkarni 	}
375014b24e2bSVaishali Kulkarni 
375114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
375214b24e2bSVaishali Kulkarni }
375314b24e2bSVaishali Kulkarni 
ecore_mcp_initiate_pf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)375414b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_initiate_pf_flr(struct ecore_hwfn *p_hwfn,
375514b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt)
375614b24e2bSVaishali Kulkarni {
375714b24e2bSVaishali Kulkarni 	u32 mcp_resp, mcp_param;
375814b24e2bSVaishali Kulkarni 
375914b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_INITIATE_PF_FLR, 0,
376014b24e2bSVaishali Kulkarni 			     &mcp_resp, &mcp_param);
376114b24e2bSVaishali Kulkarni }
376214b24e2bSVaishali Kulkarni 
ecore_mcp_get_lldp_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 lldp_mac_addr[ETH_ALEN])376314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_lldp_mac(struct ecore_hwfn *p_hwfn,
376414b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
376514b24e2bSVaishali Kulkarni 					    u8 lldp_mac_addr[ETH_ALEN])
376614b24e2bSVaishali Kulkarni {
376714b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
376814b24e2bSVaishali Kulkarni 	struct mcp_mac lldp_mac;
376914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
377014b24e2bSVaishali Kulkarni 
377114b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
377214b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_LLDP_MAC;
377314b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &lldp_mac;
377414b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(lldp_mac);
377514b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
377614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
377714b24e2bSVaishali Kulkarni 		return rc;
377814b24e2bSVaishali Kulkarni 
377914b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
378014b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
378114b24e2bSVaishali Kulkarni 			  "MFW lacks support for the GET_LLDP_MAC command [resp 0x%08x]\n",
378214b24e2bSVaishali Kulkarni 			  mb_params.mcp_resp);
378314b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
378414b24e2bSVaishali Kulkarni 	}
378514b24e2bSVaishali Kulkarni 
378614b24e2bSVaishali Kulkarni 	*(u16 *)lldp_mac_addr = *(u16 *)&lldp_mac.mac_upper;
378714b24e2bSVaishali Kulkarni 	*(u32 *)(lldp_mac_addr + 2) = lldp_mac.mac_lower;
378814b24e2bSVaishali Kulkarni 
378914b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
379014b24e2bSVaishali Kulkarni 		   "LLDP MAC address is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
379114b24e2bSVaishali Kulkarni 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
379214b24e2bSVaishali Kulkarni 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
379314b24e2bSVaishali Kulkarni 
379414b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
379514b24e2bSVaishali Kulkarni }
379614b24e2bSVaishali Kulkarni 
ecore_mcp_set_lldp_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 lldp_mac_addr[ETH_ALEN])379714b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_lldp_mac(struct ecore_hwfn *p_hwfn,
379814b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
379914b24e2bSVaishali Kulkarni 					    u8 lldp_mac_addr[ETH_ALEN])
380014b24e2bSVaishali Kulkarni {
380114b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
380214b24e2bSVaishali Kulkarni 	struct mcp_mac lldp_mac;
380314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
380414b24e2bSVaishali Kulkarni 
380514b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
380614b24e2bSVaishali Kulkarni 		   "Configuring LLDP MAC address to %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
380714b24e2bSVaishali Kulkarni 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
380814b24e2bSVaishali Kulkarni 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
380914b24e2bSVaishali Kulkarni 
381014b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&lldp_mac, sizeof(lldp_mac));
381114b24e2bSVaishali Kulkarni 	lldp_mac.mac_upper = *(u16 *)lldp_mac_addr;
381214b24e2bSVaishali Kulkarni 	lldp_mac.mac_lower = *(u32 *)(lldp_mac_addr + 2);
381314b24e2bSVaishali Kulkarni 
381414b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
381514b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_LLDP_MAC;
381614b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &lldp_mac;
381714b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(lldp_mac);
381814b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
381914b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
382014b24e2bSVaishali Kulkarni 		return rc;
382114b24e2bSVaishali Kulkarni 
382214b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
382314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
382414b24e2bSVaishali Kulkarni 			  "MFW lacks support for the SET_LLDP_MAC command [resp 0x%08x]\n",
382514b24e2bSVaishali Kulkarni 			  mb_params.mcp_resp);
382614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
382714b24e2bSVaishali Kulkarni 	}
382814b24e2bSVaishali Kulkarni 
382914b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
383014b24e2bSVaishali Kulkarni }
383114b24e2bSVaishali Kulkarni 
ecore_mcp_resource_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 param,u32 * p_mcp_resp,u32 * p_mcp_param)383214b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn,
383314b24e2bSVaishali Kulkarni 						   struct ecore_ptt *p_ptt,
383414b24e2bSVaishali Kulkarni 						   u32 param, u32 *p_mcp_resp,
383514b24e2bSVaishali Kulkarni 						   u32 *p_mcp_param)
383614b24e2bSVaishali Kulkarni {
383714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
383814b24e2bSVaishali Kulkarni 
383914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_RESOURCE_CMD, param,
384014b24e2bSVaishali Kulkarni 			   p_mcp_resp, p_mcp_param);
384114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
384214b24e2bSVaishali Kulkarni 		return rc;
384314b24e2bSVaishali Kulkarni 
384414b24e2bSVaishali Kulkarni 	if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
384514b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
384614b24e2bSVaishali Kulkarni 			"The resource command is unsupported by the MFW\n");
384714b24e2bSVaishali Kulkarni 		return ECORE_NOTIMPL;
384814b24e2bSVaishali Kulkarni 	}
384914b24e2bSVaishali Kulkarni 
385014b24e2bSVaishali Kulkarni 	if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) {
385114b24e2bSVaishali Kulkarni 		u8 opcode = ECORE_MFW_GET_FIELD(param, RESOURCE_CMD_REQ_OPCODE);
385214b24e2bSVaishali Kulkarni 
385314b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
385414b24e2bSVaishali Kulkarni 			  "The resource command is unknown to the MFW [param 0x%08x, opcode %d]\n",
385514b24e2bSVaishali Kulkarni 			  param, opcode);
385614b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
385714b24e2bSVaishali Kulkarni 	}
385814b24e2bSVaishali Kulkarni 
385914b24e2bSVaishali Kulkarni 	return rc;
386014b24e2bSVaishali Kulkarni }
386114b24e2bSVaishali Kulkarni 
386214b24e2bSVaishali Kulkarni enum _ecore_status_t
__ecore_mcp_resc_lock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_lock_params * p_params)386314b24e2bSVaishali Kulkarni __ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
386414b24e2bSVaishali Kulkarni 		      struct ecore_resc_lock_params *p_params)
386514b24e2bSVaishali Kulkarni {
386614b24e2bSVaishali Kulkarni 	u32 param = 0, mcp_resp, mcp_param;
386714b24e2bSVaishali Kulkarni 	u8 opcode;
386814b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
386914b24e2bSVaishali Kulkarni 
387014b24e2bSVaishali Kulkarni 	switch (p_params->timeout) {
387114b24e2bSVaishali Kulkarni 	case ECORE_MCP_RESC_LOCK_TO_DEFAULT:
387214b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ;
387314b24e2bSVaishali Kulkarni 		p_params->timeout = 0;
387414b24e2bSVaishali Kulkarni 		break;
387514b24e2bSVaishali Kulkarni 	case ECORE_MCP_RESC_LOCK_TO_NONE:
387614b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ_WO_AGING;
387714b24e2bSVaishali Kulkarni 		p_params->timeout = 0;
387814b24e2bSVaishali Kulkarni 		break;
387914b24e2bSVaishali Kulkarni 	default:
388014b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ_W_AGING;
388114b24e2bSVaishali Kulkarni 		break;
388214b24e2bSVaishali Kulkarni 	}
388314b24e2bSVaishali Kulkarni 
388414b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
388514b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
388614b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, p_params->timeout);
388714b24e2bSVaishali Kulkarni 
388814b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
388914b24e2bSVaishali Kulkarni 		   "Resource lock request: param 0x%08x [age %d, opcode %d, resource %d]\n",
389014b24e2bSVaishali Kulkarni 		   param, p_params->timeout, opcode, p_params->resource);
389114b24e2bSVaishali Kulkarni 
389214b24e2bSVaishali Kulkarni 	/* Attempt to acquire the resource */
389314b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
389414b24e2bSVaishali Kulkarni 				    &mcp_param);
389514b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
389614b24e2bSVaishali Kulkarni 		return rc;
389714b24e2bSVaishali Kulkarni 
389814b24e2bSVaishali Kulkarni 	/* Analyze the response */
389914b24e2bSVaishali Kulkarni 	p_params->owner = ECORE_MFW_GET_FIELD(mcp_param,
390014b24e2bSVaishali Kulkarni 					     RESOURCE_CMD_RSP_OWNER);
390114b24e2bSVaishali Kulkarni 	opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
390214b24e2bSVaishali Kulkarni 
390314b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
390414b24e2bSVaishali Kulkarni 		   "Resource lock response: mcp_param 0x%08x [opcode %d, owner %d]\n",
390514b24e2bSVaishali Kulkarni 		   mcp_param, opcode, p_params->owner);
390614b24e2bSVaishali Kulkarni 
390714b24e2bSVaishali Kulkarni 	switch (opcode) {
390814b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_GNT:
390914b24e2bSVaishali Kulkarni 		p_params->b_granted = true;
391014b24e2bSVaishali Kulkarni 		break;
391114b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_BUSY:
391214b24e2bSVaishali Kulkarni 		p_params->b_granted = false;
391314b24e2bSVaishali Kulkarni 		break;
391414b24e2bSVaishali Kulkarni 	default:
391514b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
391614b24e2bSVaishali Kulkarni 			  "Unexpected opcode in resource lock response [mcp_param 0x%08x, opcode %d]\n",
391714b24e2bSVaishali Kulkarni 			  mcp_param, opcode);
391814b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
391914b24e2bSVaishali Kulkarni 	}
392014b24e2bSVaishali Kulkarni 
392114b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
392214b24e2bSVaishali Kulkarni }
392314b24e2bSVaishali Kulkarni 
392414b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_resc_lock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_lock_params * p_params)392514b24e2bSVaishali Kulkarni ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
392614b24e2bSVaishali Kulkarni 		    struct ecore_resc_lock_params *p_params)
392714b24e2bSVaishali Kulkarni {
392814b24e2bSVaishali Kulkarni 	u32 retry_cnt = 0;
392914b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
393014b24e2bSVaishali Kulkarni 
393114b24e2bSVaishali Kulkarni 	do {
393214b24e2bSVaishali Kulkarni 		/* No need for an interval before the first iteration */
393314b24e2bSVaishali Kulkarni 		if (retry_cnt) {
393414b24e2bSVaishali Kulkarni 			if (p_params->sleep_b4_retry) {
393514b24e2bSVaishali Kulkarni 				u16 retry_interval_in_ms =
393614b24e2bSVaishali Kulkarni 					DIV_ROUND_UP(p_params->retry_interval,
393714b24e2bSVaishali Kulkarni 						     1000);
393814b24e2bSVaishali Kulkarni 
393914b24e2bSVaishali Kulkarni 				OSAL_MSLEEP(retry_interval_in_ms);
394014b24e2bSVaishali Kulkarni 			} else {
394114b24e2bSVaishali Kulkarni 				OSAL_UDELAY(p_params->retry_interval);
394214b24e2bSVaishali Kulkarni 			}
394314b24e2bSVaishali Kulkarni 		}
394414b24e2bSVaishali Kulkarni 
394514b24e2bSVaishali Kulkarni 		rc = __ecore_mcp_resc_lock(p_hwfn, p_ptt, p_params);
394614b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
394714b24e2bSVaishali Kulkarni 			return rc;
394814b24e2bSVaishali Kulkarni 
394914b24e2bSVaishali Kulkarni 		if (p_params->b_granted)
395014b24e2bSVaishali Kulkarni 			break;
395114b24e2bSVaishali Kulkarni 	} while (retry_cnt++ < p_params->retry_num);
395214b24e2bSVaishali Kulkarni 
395314b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
395414b24e2bSVaishali Kulkarni }
395514b24e2bSVaishali Kulkarni 
395614b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_resc_unlock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_unlock_params * p_params)395714b24e2bSVaishali Kulkarni ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
395814b24e2bSVaishali Kulkarni 		      struct ecore_resc_unlock_params *p_params)
395914b24e2bSVaishali Kulkarni {
396014b24e2bSVaishali Kulkarni 	u32 param = 0, mcp_resp, mcp_param;
396114b24e2bSVaishali Kulkarni 	u8 opcode;
396214b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
396314b24e2bSVaishali Kulkarni 
396414b24e2bSVaishali Kulkarni 	opcode = p_params->b_force ? RESOURCE_OPCODE_FORCE_RELEASE
396514b24e2bSVaishali Kulkarni 				   : RESOURCE_OPCODE_RELEASE;
396614b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
396714b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
396814b24e2bSVaishali Kulkarni 
396914b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
397014b24e2bSVaishali Kulkarni 		   "Resource unlock request: param 0x%08x [opcode %d, resource %d]\n",
397114b24e2bSVaishali Kulkarni 		   param, opcode, p_params->resource);
397214b24e2bSVaishali Kulkarni 
397314b24e2bSVaishali Kulkarni 	/* Attempt to release the resource */
397414b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
397514b24e2bSVaishali Kulkarni 				    &mcp_param);
397614b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
397714b24e2bSVaishali Kulkarni 		return rc;
397814b24e2bSVaishali Kulkarni 
397914b24e2bSVaishali Kulkarni 	/* Analyze the response */
398014b24e2bSVaishali Kulkarni 	opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
398114b24e2bSVaishali Kulkarni 
398214b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
398314b24e2bSVaishali Kulkarni 		   "Resource unlock response: mcp_param 0x%08x [opcode %d]\n",
398414b24e2bSVaishali Kulkarni 		   mcp_param, opcode);
398514b24e2bSVaishali Kulkarni 
398614b24e2bSVaishali Kulkarni 	switch (opcode) {
398714b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_RELEASED_PREVIOUS:
398814b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
398914b24e2bSVaishali Kulkarni 			"Resource unlock request for an already released resource [%d]\n",
399014b24e2bSVaishali Kulkarni 			p_params->resource);
399114b24e2bSVaishali Kulkarni 		/* Fallthrough */
399214b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_RELEASED:
399314b24e2bSVaishali Kulkarni 		p_params->b_released = true;
399414b24e2bSVaishali Kulkarni 		break;
399514b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_WRONG_OWNER:
399614b24e2bSVaishali Kulkarni 		p_params->b_released = false;
399714b24e2bSVaishali Kulkarni 		break;
399814b24e2bSVaishali Kulkarni 	default:
399914b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
400014b24e2bSVaishali Kulkarni 			  "Unexpected opcode in resource unlock response [mcp_param 0x%08x, opcode %d]\n",
400114b24e2bSVaishali Kulkarni 			  mcp_param, opcode);
400214b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
400314b24e2bSVaishali Kulkarni 	}
400414b24e2bSVaishali Kulkarni 
400514b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
400614b24e2bSVaishali Kulkarni }
400714b24e2bSVaishali Kulkarni 
400814b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_update_fcoe_cvid(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 vlan)400914b24e2bSVaishali Kulkarni ecore_mcp_update_fcoe_cvid(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
401014b24e2bSVaishali Kulkarni 			   u16 vlan)
401114b24e2bSVaishali Kulkarni {
401214b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
401314b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
401414b24e2bSVaishali Kulkarni 
401514b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OEM_UPDATE_FCOE_CVID,
401614b24e2bSVaishali Kulkarni 			   (u32)vlan << DRV_MB_PARAM_FCOE_CVID_SHIFT,
401714b24e2bSVaishali Kulkarni 			   &resp, &param);
401814b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
401914b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to update fcoe vlan, rc = %d\n", rc);
402014b24e2bSVaishali Kulkarni 
402114b24e2bSVaishali Kulkarni 	return rc;
402214b24e2bSVaishali Kulkarni }
402314b24e2bSVaishali Kulkarni 
402414b24e2bSVaishali Kulkarni enum _ecore_status_t
ecore_mcp_update_fcoe_fabric_name(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * wwn)402514b24e2bSVaishali Kulkarni ecore_mcp_update_fcoe_fabric_name(struct ecore_hwfn *p_hwfn,
402614b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt, u8 *wwn)
402714b24e2bSVaishali Kulkarni {
402814b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
402914b24e2bSVaishali Kulkarni 	struct mcp_wwn fabric_name;
403014b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
403114b24e2bSVaishali Kulkarni 
403214b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&fabric_name, sizeof(fabric_name));
403314b24e2bSVaishali Kulkarni 	fabric_name.wwn_upper = *(u32 *)wwn;
403414b24e2bSVaishali Kulkarni 	fabric_name.wwn_lower = *(u32 *)(wwn + 4);
403514b24e2bSVaishali Kulkarni 
403614b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
403714b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_OEM_UPDATE_FCOE_FABRIC_NAME;
403814b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &fabric_name;
403914b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(fabric_name);
404014b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
404114b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
404214b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to update fcoe wwn, rc = %d\n", rc);
404314b24e2bSVaishali Kulkarni 
404414b24e2bSVaishali Kulkarni 	return rc;
404514b24e2bSVaishali Kulkarni }
404614b24e2bSVaishali Kulkarni 
ecore_mcp_wol_wr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 offset,u32 val)404714b24e2bSVaishali Kulkarni void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
404814b24e2bSVaishali Kulkarni 		      u32 offset, u32 val)
404914b24e2bSVaishali Kulkarni {
405014b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params = {0};
405114b24e2bSVaishali Kulkarni 	enum _ecore_status_t	   rc = ECORE_SUCCESS;
405214b24e2bSVaishali Kulkarni 	u32			   dword = val;
405314b24e2bSVaishali Kulkarni 
405414b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_WRITE_WOL_REG;
405514b24e2bSVaishali Kulkarni 	mb_params.param = offset;
405614b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &dword;
405714b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(dword);
405814b24e2bSVaishali Kulkarni 
405914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
406014b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
406114b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
406214b24e2bSVaishali Kulkarni 			  "Failed to wol write request, rc = %d\n", rc);
406314b24e2bSVaishali Kulkarni 	}
406414b24e2bSVaishali Kulkarni 
406514b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_WOL_READ_WRITE_OK) {
406614b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
406714b24e2bSVaishali Kulkarni 			  "Failed to write value 0x%x to offset 0x%x [mcp_resp 0x%x]\n",
406814b24e2bSVaishali Kulkarni 			  val, offset, mb_params.mcp_resp);
406914b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
407014b24e2bSVaishali Kulkarni 	}
407114b24e2bSVaishali Kulkarni }
407214b24e2bSVaishali Kulkarni 
ecore_mcp_get_capabilities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)407314b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_capabilities(struct ecore_hwfn *p_hwfn,
407414b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
407514b24e2bSVaishali Kulkarni {
407614b24e2bSVaishali Kulkarni 	u32 mcp_resp;
407714b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
407814b24e2bSVaishali Kulkarni 
407914b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT,
408014b24e2bSVaishali Kulkarni 			   0, &mcp_resp, &p_hwfn->mcp_info->capabilities);
408114b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS)
408214b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_PROBE),
408314b24e2bSVaishali Kulkarni 			   "MFW supported features: %08x\n",
408414b24e2bSVaishali Kulkarni 			   p_hwfn->mcp_info->capabilities);
408514b24e2bSVaishali Kulkarni 
408614b24e2bSVaishali Kulkarni 	return rc;
408714b24e2bSVaishali Kulkarni }
408814b24e2bSVaishali Kulkarni 
ecore_mcp_set_capabilities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)408914b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_capabilities(struct ecore_hwfn *p_hwfn,
409014b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
409114b24e2bSVaishali Kulkarni {
409214b24e2bSVaishali Kulkarni 	u32 mcp_resp, mcp_param, features;
409314b24e2bSVaishali Kulkarni 
409414b24e2bSVaishali Kulkarni 	features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ |
409514b24e2bSVaishali Kulkarni 		   DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE;
409614b24e2bSVaishali Kulkarni 
409714b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
409814b24e2bSVaishali Kulkarni 			     features, &mcp_resp, &mcp_param);
409914b24e2bSVaishali Kulkarni }
4100