1*14b24e2bSVaishali Kulkarni /*
2*14b24e2bSVaishali Kulkarni * CDDL HEADER START
3*14b24e2bSVaishali Kulkarni *
4*14b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the
5*14b24e2bSVaishali Kulkarni * Common Development and Distribution License, v.1,  (the "License").
6*14b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
7*14b24e2bSVaishali Kulkarni *
8*14b24e2bSVaishali Kulkarni * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*14b24e2bSVaishali Kulkarni * or http://opensource.org/licenses/CDDL-1.0.
10*14b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions
11*14b24e2bSVaishali Kulkarni * and limitations under the License.
12*14b24e2bSVaishali Kulkarni *
13*14b24e2bSVaishali Kulkarni * When distributing Covered Code, include this CDDL HEADER in each
14*14b24e2bSVaishali Kulkarni * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*14b24e2bSVaishali Kulkarni * If applicable, add the following below this CDDL HEADER, with the
16*14b24e2bSVaishali Kulkarni * fields enclosed by brackets "[]" replaced with your own identifying
17*14b24e2bSVaishali Kulkarni * information: Portions Copyright [yyyy] [name of copyright owner]
18*14b24e2bSVaishali Kulkarni *
19*14b24e2bSVaishali Kulkarni * CDDL HEADER END
20*14b24e2bSVaishali Kulkarni */
21*14b24e2bSVaishali Kulkarni 
22*14b24e2bSVaishali Kulkarni /*
23*14b24e2bSVaishali Kulkarni * Copyright 2014-2017 Cavium, Inc.
24*14b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the Common Development
25*14b24e2bSVaishali Kulkarni * and Distribution License, v.1,  (the "License").
26*14b24e2bSVaishali Kulkarni 
27*14b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
28*14b24e2bSVaishali Kulkarni 
29*14b24e2bSVaishali Kulkarni * You can obtain a copy of the License at available
30*14b24e2bSVaishali Kulkarni * at http://opensource.org/licenses/CDDL-1.0
31*14b24e2bSVaishali Kulkarni 
32*14b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions and
33*14b24e2bSVaishali Kulkarni * limitations under the License.
34*14b24e2bSVaishali Kulkarni */
35*14b24e2bSVaishali Kulkarni 
36*14b24e2bSVaishali Kulkarni #include "bcm_osal.h"
37*14b24e2bSVaishali Kulkarni #include "ecore.h"
38*14b24e2bSVaishali Kulkarni #include "ecore_status.h"
39*14b24e2bSVaishali Kulkarni #include "nvm_map.h"
40*14b24e2bSVaishali Kulkarni #include "nvm_cfg.h"
41*14b24e2bSVaishali Kulkarni #include "ecore_mcp.h"
42*14b24e2bSVaishali Kulkarni #include "mcp_public.h"
43*14b24e2bSVaishali Kulkarni #include "reg_addr.h"
44*14b24e2bSVaishali Kulkarni #include "ecore_hw.h"
45*14b24e2bSVaishali Kulkarni #include "ecore_init_fw_funcs.h"
46*14b24e2bSVaishali Kulkarni #include "ecore_sriov.h"
47*14b24e2bSVaishali Kulkarni #include "ecore_vf.h"
48*14b24e2bSVaishali Kulkarni #include "ecore_iov_api.h"
49*14b24e2bSVaishali Kulkarni #include "ecore_gtt_reg_addr.h"
50*14b24e2bSVaishali Kulkarni #include "ecore_iro.h"
51*14b24e2bSVaishali Kulkarni #include "ecore_dcbx.h"
52*14b24e2bSVaishali Kulkarni #include "ecore_sp_commands.h"
53*14b24e2bSVaishali Kulkarni 
54*14b24e2bSVaishali Kulkarni #define CHIP_MCP_RESP_ITER_US 10
55*14b24e2bSVaishali Kulkarni #define EMUL_MCP_RESP_ITER_US 1000 * 1000
56*14b24e2bSVaishali Kulkarni 
57*14b24e2bSVaishali Kulkarni #define ECORE_DRV_MB_MAX_RETRIES	(500 * 1000) /* Account for 5 sec */
58*14b24e2bSVaishali Kulkarni #define ECORE_MCP_RESET_RETRIES		(50 * 1000) /* Account for 500 msec */
59*14b24e2bSVaishali Kulkarni 
60*14b24e2bSVaishali Kulkarni #define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \
61*14b24e2bSVaishali Kulkarni 	ecore_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \
62*14b24e2bSVaishali Kulkarni 		 _val)
63*14b24e2bSVaishali Kulkarni 
64*14b24e2bSVaishali Kulkarni #define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \
65*14b24e2bSVaishali Kulkarni 	ecore_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset))
66*14b24e2bSVaishali Kulkarni 
67*14b24e2bSVaishali Kulkarni #define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \
68*14b24e2bSVaishali Kulkarni 	DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \
69*14b24e2bSVaishali Kulkarni 		     OFFSETOF(struct public_drv_mb, _field), _val)
70*14b24e2bSVaishali Kulkarni 
71*14b24e2bSVaishali Kulkarni #define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \
72*14b24e2bSVaishali Kulkarni 	DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \
73*14b24e2bSVaishali Kulkarni 		     OFFSETOF(struct public_drv_mb, _field))
74*14b24e2bSVaishali Kulkarni 
75*14b24e2bSVaishali Kulkarni #define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \
76*14b24e2bSVaishali Kulkarni 	DRV_ID_PDA_COMP_VER_SHIFT)
77*14b24e2bSVaishali Kulkarni 
78*14b24e2bSVaishali Kulkarni #define MCP_BYTES_PER_MBIT_SHIFT 17
79*14b24e2bSVaishali Kulkarni 
80*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
81*14b24e2bSVaishali Kulkarni static int loaded;
82*14b24e2bSVaishali Kulkarni static int loaded_port[MAX_NUM_PORTS] = { 0 };
83*14b24e2bSVaishali Kulkarni #endif
84*14b24e2bSVaishali Kulkarni 
85*14b24e2bSVaishali Kulkarni bool ecore_mcp_is_init(struct ecore_hwfn *p_hwfn)
86*14b24e2bSVaishali Kulkarni {
87*14b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base)
88*14b24e2bSVaishali Kulkarni 		return false;
89*14b24e2bSVaishali Kulkarni 	return true;
90*14b24e2bSVaishali Kulkarni }
91*14b24e2bSVaishali Kulkarni 
92*14b24e2bSVaishali Kulkarni void ecore_mcp_cmd_port_init(struct ecore_hwfn *p_hwfn,
93*14b24e2bSVaishali Kulkarni 			     struct ecore_ptt *p_ptt)
94*14b24e2bSVaishali Kulkarni {
95*14b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
96*14b24e2bSVaishali Kulkarni 					PUBLIC_PORT);
97*14b24e2bSVaishali Kulkarni 	u32 mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt, addr);
98*14b24e2bSVaishali Kulkarni 
99*14b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize,
100*14b24e2bSVaishali Kulkarni 						   MFW_PORT(p_hwfn));
101*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
102*14b24e2bSVaishali Kulkarni 		   "port_addr = 0x%x, port_id 0x%02x\n",
103*14b24e2bSVaishali Kulkarni 		   p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn));
104*14b24e2bSVaishali Kulkarni }
105*14b24e2bSVaishali Kulkarni 
106*14b24e2bSVaishali Kulkarni void ecore_mcp_read_mb(struct ecore_hwfn *p_hwfn,
107*14b24e2bSVaishali Kulkarni 		       struct ecore_ptt *p_ptt)
108*14b24e2bSVaishali Kulkarni {
109*14b24e2bSVaishali Kulkarni 	u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length);
110*14b24e2bSVaishali Kulkarni 	OSAL_BE32 tmp;
111*14b24e2bSVaishali Kulkarni 	u32 i;
112*14b24e2bSVaishali Kulkarni 
113*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
114*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
115*14b24e2bSVaishali Kulkarni 		return;
116*14b24e2bSVaishali Kulkarni #endif
117*14b24e2bSVaishali Kulkarni 
118*14b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info->public_base)
119*14b24e2bSVaishali Kulkarni 		return;
120*14b24e2bSVaishali Kulkarni 
121*14b24e2bSVaishali Kulkarni 	for (i = 0; i < length; i++) {
122*14b24e2bSVaishali Kulkarni 		tmp = ecore_rd(p_hwfn, p_ptt,
123*14b24e2bSVaishali Kulkarni 			       p_hwfn->mcp_info->mfw_mb_addr +
124*14b24e2bSVaishali Kulkarni 			       (i << 2) + sizeof(u32));
125*14b24e2bSVaishali Kulkarni 
126*14b24e2bSVaishali Kulkarni 		((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] =
127*14b24e2bSVaishali Kulkarni 						OSAL_BE32_TO_CPU(tmp);
128*14b24e2bSVaishali Kulkarni 	}
129*14b24e2bSVaishali Kulkarni }
130*14b24e2bSVaishali Kulkarni 
131*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_free(struct ecore_hwfn *p_hwfn)
132*14b24e2bSVaishali Kulkarni {
133*14b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info) {
134*14b24e2bSVaishali Kulkarni 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_cur);
135*14b24e2bSVaishali Kulkarni 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_shadow);
136*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LOCK_ALLOC
137*14b24e2bSVaishali Kulkarni 		OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->lock);
138*14b24e2bSVaishali Kulkarni 		OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->link_lock);
139*14b24e2bSVaishali Kulkarni #endif
140*14b24e2bSVaishali Kulkarni 	}
141*14b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info);
142*14b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info = OSAL_NULL;
143*14b24e2bSVaishali Kulkarni 
144*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
145*14b24e2bSVaishali Kulkarni }
146*14b24e2bSVaishali Kulkarni 
147*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_load_mcp_offsets(struct ecore_hwfn *p_hwfn,
148*14b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt)
149*14b24e2bSVaishali Kulkarni {
150*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *p_info = p_hwfn->mcp_info;
151*14b24e2bSVaishali Kulkarni 	u32 drv_mb_offsize, mfw_mb_offsize;
152*14b24e2bSVaishali Kulkarni 	u32 mcp_pf_id = MCP_PF_ID(p_hwfn);
153*14b24e2bSVaishali Kulkarni 
154*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
155*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
156*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - assume no MFW\n");
157*14b24e2bSVaishali Kulkarni 		p_info->public_base = 0;
158*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
159*14b24e2bSVaishali Kulkarni 	}
160*14b24e2bSVaishali Kulkarni #endif
161*14b24e2bSVaishali Kulkarni 
162*14b24e2bSVaishali Kulkarni 	p_info->public_base = ecore_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR);
163*14b24e2bSVaishali Kulkarni 	if (!p_info->public_base)
164*14b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
165*14b24e2bSVaishali Kulkarni 
166*14b24e2bSVaishali Kulkarni 	p_info->public_base |= GRCBASE_MCP;
167*14b24e2bSVaishali Kulkarni 
168*14b24e2bSVaishali Kulkarni 	/* Calculate the driver and MFW mailbox address */
169*14b24e2bSVaishali Kulkarni 	drv_mb_offsize = ecore_rd(p_hwfn, p_ptt,
170*14b24e2bSVaishali Kulkarni 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
171*14b24e2bSVaishali Kulkarni 						       PUBLIC_DRV_MB));
172*14b24e2bSVaishali Kulkarni 	p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id);
173*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
174*14b24e2bSVaishali Kulkarni 		   "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n",
175*14b24e2bSVaishali Kulkarni 		   drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id);
176*14b24e2bSVaishali Kulkarni 
177*14b24e2bSVaishali Kulkarni 	/* Set the MFW MB address */
178*14b24e2bSVaishali Kulkarni 	mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt,
179*14b24e2bSVaishali Kulkarni 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
180*14b24e2bSVaishali Kulkarni 				  PUBLIC_MFW_MB));
181*14b24e2bSVaishali Kulkarni 	p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id);
182*14b24e2bSVaishali Kulkarni 	p_info->mfw_mb_length = (u16)ecore_rd(p_hwfn, p_ptt,
183*14b24e2bSVaishali Kulkarni 					      p_info->mfw_mb_addr);
184*14b24e2bSVaishali Kulkarni 
185*14b24e2bSVaishali Kulkarni 	/* Get the current driver mailbox sequence before sending
186*14b24e2bSVaishali Kulkarni 	 * the first command
187*14b24e2bSVaishali Kulkarni 	 */
188*14b24e2bSVaishali Kulkarni 	p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
189*14b24e2bSVaishali Kulkarni 				       DRV_MSG_SEQ_NUMBER_MASK;
190*14b24e2bSVaishali Kulkarni 
191*14b24e2bSVaishali Kulkarni 	/* Get current FW pulse sequence */
192*14b24e2bSVaishali Kulkarni 	p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) &
193*14b24e2bSVaishali Kulkarni 				DRV_PULSE_SEQ_MASK;
194*14b24e2bSVaishali Kulkarni 
195*14b24e2bSVaishali Kulkarni 	p_info->mcp_hist = (u16)ecore_rd(p_hwfn, p_ptt,
196*14b24e2bSVaishali Kulkarni 					 MISCS_REG_GENERIC_POR_0);
197*14b24e2bSVaishali Kulkarni 
198*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
199*14b24e2bSVaishali Kulkarni }
200*14b24e2bSVaishali Kulkarni 
201*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_cmd_init(struct ecore_hwfn *p_hwfn,
202*14b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt)
203*14b24e2bSVaishali Kulkarni {
204*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *p_info;
205*14b24e2bSVaishali Kulkarni 	u32 size;
206*14b24e2bSVaishali Kulkarni 
207*14b24e2bSVaishali Kulkarni 	/* Allocate mcp_info structure */
208*14b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
209*14b24e2bSVaishali Kulkarni 				       sizeof(*p_hwfn->mcp_info));
210*14b24e2bSVaishali Kulkarni 	if (!p_hwfn->mcp_info)
211*14b24e2bSVaishali Kulkarni 		goto err;
212*14b24e2bSVaishali Kulkarni 	p_info = p_hwfn->mcp_info;
213*14b24e2bSVaishali Kulkarni 
214*14b24e2bSVaishali Kulkarni 	if (ecore_load_mcp_offsets(p_hwfn, p_ptt) != ECORE_SUCCESS) {
215*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "MCP is not initialized\n");
216*14b24e2bSVaishali Kulkarni 		/* Do not free mcp_info here, since public_base indicate that
217*14b24e2bSVaishali Kulkarni 		 * the MCP is not initialized
218*14b24e2bSVaishali Kulkarni 		 */
219*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
220*14b24e2bSVaishali Kulkarni 	}
221*14b24e2bSVaishali Kulkarni 
222*14b24e2bSVaishali Kulkarni 	size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32);
223*14b24e2bSVaishali Kulkarni 	p_info->mfw_mb_cur = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
224*14b24e2bSVaishali Kulkarni 	p_info->mfw_mb_shadow = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
225*14b24e2bSVaishali Kulkarni 	if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr)
226*14b24e2bSVaishali Kulkarni 		goto err;
227*14b24e2bSVaishali Kulkarni 
228*14b24e2bSVaishali Kulkarni 	/* Initialize the MFW spinlock */
229*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LOCK_ALLOC
230*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->lock);
231*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->link_lock);
232*14b24e2bSVaishali Kulkarni #endif
233*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_INIT(&p_info->lock);
234*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK_INIT(&p_info->link_lock);
235*14b24e2bSVaishali Kulkarni 
236*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
237*14b24e2bSVaishali Kulkarni 
238*14b24e2bSVaishali Kulkarni err:
239*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, true, "Failed to allocate mcp memory\n");
240*14b24e2bSVaishali Kulkarni 	ecore_mcp_free(p_hwfn);
241*14b24e2bSVaishali Kulkarni 	return ECORE_NOMEM;
242*14b24e2bSVaishali Kulkarni 
243*14b24e2bSVaishali Kulkarni }
244*14b24e2bSVaishali Kulkarni 
245*14b24e2bSVaishali Kulkarni /* Locks the MFW mailbox of a PF to ensure a single access.
246*14b24e2bSVaishali Kulkarni  * The lock is achieved in most cases by holding a spinlock, causing other
247*14b24e2bSVaishali Kulkarni  * threads to wait till a previous access is done.
248*14b24e2bSVaishali Kulkarni  * In some cases (currently when a [UN]LOAD_REQ commands are sent), the single
249*14b24e2bSVaishali Kulkarni  * access is achieved by setting a blocking flag, which will fail other
250*14b24e2bSVaishali Kulkarni  * competing contexts to send their mailboxes.
251*14b24e2bSVaishali Kulkarni  */
252*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_mb_lock(struct ecore_hwfn *p_hwfn,
253*14b24e2bSVaishali Kulkarni 					      u32 cmd)
254*14b24e2bSVaishali Kulkarni {
255*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&p_hwfn->mcp_info->lock);
256*14b24e2bSVaishali Kulkarni 
257*14b24e2bSVaishali Kulkarni 	/* The spinlock shouldn't be acquired when the mailbox command is
258*14b24e2bSVaishali Kulkarni 	 * [UN]LOAD_REQ, since the engine is locked by the MFW, and a parallel
259*14b24e2bSVaishali Kulkarni 	 * pending [UN]LOAD_REQ command of another PF together with a spinlock
260*14b24e2bSVaishali Kulkarni 	 * (i.e. interrupts are disabled) - can lead to a deadlock.
261*14b24e2bSVaishali Kulkarni 	 * It is assumed that for a single PF, no other mailbox commands can be
262*14b24e2bSVaishali Kulkarni 	 * sent from another context while sending LOAD_REQ, and that any
263*14b24e2bSVaishali Kulkarni 	 * parallel commands to UNLOAD_REQ can be cancelled.
264*14b24e2bSVaishali Kulkarni 	 */
265*14b24e2bSVaishali Kulkarni 	if (cmd == DRV_MSG_CODE_LOAD_DONE || cmd == DRV_MSG_CODE_UNLOAD_DONE)
266*14b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
267*14b24e2bSVaishali Kulkarni 
268*14b24e2bSVaishali Kulkarni 	/* There's at least a single command that is sent by ecore during the
269*14b24e2bSVaishali Kulkarni 	 * load sequence [expectation of MFW].
270*14b24e2bSVaishali Kulkarni 	 */
271*14b24e2bSVaishali Kulkarni 	if ((p_hwfn->mcp_info->block_mb_sending) &&
272*14b24e2bSVaishali Kulkarni 	    (cmd != DRV_MSG_CODE_FEATURE_SUPPORT)) {
273*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
274*14b24e2bSVaishali Kulkarni 			  "Trying to send a MFW mailbox command [0x%x] in parallel to [UN]LOAD_REQ. Aborting.\n",
275*14b24e2bSVaishali Kulkarni 			  cmd);
276*14b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
277*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
278*14b24e2bSVaishali Kulkarni 	}
279*14b24e2bSVaishali Kulkarni 
280*14b24e2bSVaishali Kulkarni 	if (cmd == DRV_MSG_CODE_LOAD_REQ || cmd == DRV_MSG_CODE_UNLOAD_REQ) {
281*14b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = true;
282*14b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
283*14b24e2bSVaishali Kulkarni 	}
284*14b24e2bSVaishali Kulkarni 
285*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
286*14b24e2bSVaishali Kulkarni }
287*14b24e2bSVaishali Kulkarni 
288*14b24e2bSVaishali Kulkarni static void ecore_mcp_mb_unlock(struct ecore_hwfn *p_hwfn, u32 cmd)
289*14b24e2bSVaishali Kulkarni {
290*14b24e2bSVaishali Kulkarni 	if (cmd != DRV_MSG_CODE_LOAD_REQ && cmd != DRV_MSG_CODE_UNLOAD_REQ)
291*14b24e2bSVaishali Kulkarni 		OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->lock);
292*14b24e2bSVaishali Kulkarni }
293*14b24e2bSVaishali Kulkarni 
294*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_reset(struct ecore_hwfn *p_hwfn,
295*14b24e2bSVaishali Kulkarni 				     struct ecore_ptt *p_ptt)
296*14b24e2bSVaishali Kulkarni {
297*14b24e2bSVaishali Kulkarni 	u32 seq = ++p_hwfn->mcp_info->drv_mb_seq;
298*14b24e2bSVaishali Kulkarni 	u32 delay = CHIP_MCP_RESP_ITER_US;
299*14b24e2bSVaishali Kulkarni 	u32 org_mcp_reset_seq, cnt = 0;
300*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
301*14b24e2bSVaishali Kulkarni 
302*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
303*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
304*14b24e2bSVaishali Kulkarni 		delay = EMUL_MCP_RESP_ITER_US;
305*14b24e2bSVaishali Kulkarni #endif
306*14b24e2bSVaishali Kulkarni 
307*14b24e2bSVaishali Kulkarni 	/* Ensure that only a single thread is accessing the mailbox at a
308*14b24e2bSVaishali Kulkarni 	 * certain time.
309*14b24e2bSVaishali Kulkarni 	 */
310*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mb_lock(p_hwfn, DRV_MSG_CODE_MCP_RESET);
311*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
312*14b24e2bSVaishali Kulkarni 		return rc;
313*14b24e2bSVaishali Kulkarni 
314*14b24e2bSVaishali Kulkarni 	/* Set drv command along with the updated sequence */
315*14b24e2bSVaishali Kulkarni 	org_mcp_reset_seq = ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
316*14b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (DRV_MSG_CODE_MCP_RESET | seq));
317*14b24e2bSVaishali Kulkarni 
318*14b24e2bSVaishali Kulkarni 	do {
319*14b24e2bSVaishali Kulkarni 		/* Wait for MFW response */
320*14b24e2bSVaishali Kulkarni 		OSAL_UDELAY(delay);
321*14b24e2bSVaishali Kulkarni 		/* Give the FW up to 500 second (50*1000*10usec) */
322*14b24e2bSVaishali Kulkarni 	} while ((org_mcp_reset_seq == ecore_rd(p_hwfn, p_ptt,
323*14b24e2bSVaishali Kulkarni 						MISCS_REG_GENERIC_POR_0)) &&
324*14b24e2bSVaishali Kulkarni 		 (cnt++ < ECORE_MCP_RESET_RETRIES));
325*14b24e2bSVaishali Kulkarni 
326*14b24e2bSVaishali Kulkarni 	if (org_mcp_reset_seq !=
327*14b24e2bSVaishali Kulkarni 	    ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
328*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
329*14b24e2bSVaishali Kulkarni 			   "MCP was reset after %d usec\n", cnt * delay);
330*14b24e2bSVaishali Kulkarni 	} else {
331*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to reset MCP\n");
332*14b24e2bSVaishali Kulkarni 		rc = ECORE_AGAIN;
333*14b24e2bSVaishali Kulkarni 	}
334*14b24e2bSVaishali Kulkarni 
335*14b24e2bSVaishali Kulkarni 	ecore_mcp_mb_unlock(p_hwfn, DRV_MSG_CODE_MCP_RESET);
336*14b24e2bSVaishali Kulkarni 
337*14b24e2bSVaishali Kulkarni 	return rc;
338*14b24e2bSVaishali Kulkarni }
339*14b24e2bSVaishali Kulkarni 
340*14b24e2bSVaishali Kulkarni void ecore_mcp_print_cpu_info(struct ecore_hwfn *p_hwfn,
341*14b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt)
342*14b24e2bSVaishali Kulkarni {
343*14b24e2bSVaishali Kulkarni 	u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2;
344*14b24e2bSVaishali Kulkarni 
345*14b24e2bSVaishali Kulkarni 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
346*14b24e2bSVaishali Kulkarni 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
347*14b24e2bSVaishali Kulkarni 	cpu_pc_0 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
348*14b24e2bSVaishali Kulkarni 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
349*14b24e2bSVaishali Kulkarni 	cpu_pc_1 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
350*14b24e2bSVaishali Kulkarni 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
351*14b24e2bSVaishali Kulkarni 	cpu_pc_2 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
352*14b24e2bSVaishali Kulkarni 
353*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
354*14b24e2bSVaishali Kulkarni 		  "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n",
355*14b24e2bSVaishali Kulkarni 		  cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2);
356*14b24e2bSVaishali Kulkarni }
357*14b24e2bSVaishali Kulkarni 
358*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_do_mcp_cmd(struct ecore_hwfn *p_hwfn,
359*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
360*14b24e2bSVaishali Kulkarni 					     u32 cmd, u32 param,
361*14b24e2bSVaishali Kulkarni 					     u32 *o_mcp_resp, u32 *o_mcp_param)
362*14b24e2bSVaishali Kulkarni {
363*14b24e2bSVaishali Kulkarni 	u32 delay = CHIP_MCP_RESP_ITER_US;
364*14b24e2bSVaishali Kulkarni 	u32 max_retries = ECORE_DRV_MB_MAX_RETRIES;
365*14b24e2bSVaishali Kulkarni 	u32 seq, cnt = 1, actual_mb_seq;
366*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
367*14b24e2bSVaishali Kulkarni 
368*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
369*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
370*14b24e2bSVaishali Kulkarni 		delay = EMUL_MCP_RESP_ITER_US;
371*14b24e2bSVaishali Kulkarni 	/* There is a built-in delay of 100usec in each MFW response read */
372*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev))
373*14b24e2bSVaishali Kulkarni 		max_retries /= 10;
374*14b24e2bSVaishali Kulkarni #endif
375*14b24e2bSVaishali Kulkarni 
376*14b24e2bSVaishali Kulkarni 	/* Get actual driver mailbox sequence */
377*14b24e2bSVaishali Kulkarni 	actual_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
378*14b24e2bSVaishali Kulkarni 			DRV_MSG_SEQ_NUMBER_MASK;
379*14b24e2bSVaishali Kulkarni 
380*14b24e2bSVaishali Kulkarni 	/* Use MCP history register to check if MCP reset occurred between
381*14b24e2bSVaishali Kulkarni 	 * init time and now.
382*14b24e2bSVaishali Kulkarni 	 */
383*14b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->mcp_hist !=
384*14b24e2bSVaishali Kulkarni 	    ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
385*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Rereading MCP offsets\n");
386*14b24e2bSVaishali Kulkarni 		ecore_load_mcp_offsets(p_hwfn, p_ptt);
387*14b24e2bSVaishali Kulkarni 		ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
388*14b24e2bSVaishali Kulkarni 	}
389*14b24e2bSVaishali Kulkarni 	seq = ++p_hwfn->mcp_info->drv_mb_seq;
390*14b24e2bSVaishali Kulkarni 
391*14b24e2bSVaishali Kulkarni 	/* Set drv param */
392*14b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, param);
393*14b24e2bSVaishali Kulkarni 
394*14b24e2bSVaishali Kulkarni 	/* Set drv command along with the updated sequence */
395*14b24e2bSVaishali Kulkarni 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (cmd | seq));
396*14b24e2bSVaishali Kulkarni 
397*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
398*14b24e2bSVaishali Kulkarni 		   "wrote command (%x) to MFW MB param 0x%08x\n",
399*14b24e2bSVaishali Kulkarni 		   (cmd | seq), param);
400*14b24e2bSVaishali Kulkarni 
401*14b24e2bSVaishali Kulkarni 	do {
402*14b24e2bSVaishali Kulkarni 		/* Wait for MFW response */
403*14b24e2bSVaishali Kulkarni 		OSAL_UDELAY(delay);
404*14b24e2bSVaishali Kulkarni 		*o_mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header);
405*14b24e2bSVaishali Kulkarni 
406*14b24e2bSVaishali Kulkarni 		/* Give the FW up to 5 second (500*10ms) */
407*14b24e2bSVaishali Kulkarni 	} while ((seq != (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) &&
408*14b24e2bSVaishali Kulkarni 		 (cnt++ < max_retries));
409*14b24e2bSVaishali Kulkarni 
410*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
411*14b24e2bSVaishali Kulkarni 		   "[after %d ms] read (%x) seq is (%x) from FW MB\n",
412*14b24e2bSVaishali Kulkarni 		   cnt * delay, *o_mcp_resp, seq);
413*14b24e2bSVaishali Kulkarni 
414*14b24e2bSVaishali Kulkarni 	/* Is this a reply to our command? */
415*14b24e2bSVaishali Kulkarni 	if (seq == (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) {
416*14b24e2bSVaishali Kulkarni 		*o_mcp_resp &= FW_MSG_CODE_MASK;
417*14b24e2bSVaishali Kulkarni 		/* Get the MCP param */
418*14b24e2bSVaishali Kulkarni 		*o_mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param);
419*14b24e2bSVaishali Kulkarni 	} else {
420*14b24e2bSVaishali Kulkarni 		/* FW BUG! */
421*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MFW failed to respond [cmd 0x%x param 0x%x]\n",
422*14b24e2bSVaishali Kulkarni 		       cmd, param);
423*14b24e2bSVaishali Kulkarni 		ecore_mcp_print_cpu_info(p_hwfn, p_ptt);
424*14b24e2bSVaishali Kulkarni 		*o_mcp_resp = 0;
425*14b24e2bSVaishali Kulkarni 		rc = ECORE_AGAIN;
426*14b24e2bSVaishali Kulkarni 		ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_MFW_RESP_FAIL);
427*14b24e2bSVaishali Kulkarni 	}
428*14b24e2bSVaishali Kulkarni 	return rc;
429*14b24e2bSVaishali Kulkarni }
430*14b24e2bSVaishali Kulkarni 
431*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn,
432*14b24e2bSVaishali Kulkarni 						    struct ecore_ptt *p_ptt,
433*14b24e2bSVaishali Kulkarni 						    struct ecore_mcp_mb_params *p_mb_params)
434*14b24e2bSVaishali Kulkarni {
435*14b24e2bSVaishali Kulkarni 	union drv_union_data union_data;
436*14b24e2bSVaishali Kulkarni 	u32 union_data_addr;
437*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
438*14b24e2bSVaishali Kulkarni 
439*14b24e2bSVaishali Kulkarni 	/* MCP not initialized */
440*14b24e2bSVaishali Kulkarni 	if (!ecore_mcp_is_init(p_hwfn)) {
441*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW is not initialized!\n");
442*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
443*14b24e2bSVaishali Kulkarni 	}
444*14b24e2bSVaishali Kulkarni 
445*14b24e2bSVaishali Kulkarni 	if (p_mb_params->data_src_size > sizeof(union_data) ||
446*14b24e2bSVaishali Kulkarni 	    p_mb_params->data_dst_size > sizeof(union_data)) {
447*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
448*14b24e2bSVaishali Kulkarni 		       "The provided size is larger than the union data size [src_size %u, dst_size %u, union_data_size %zu]\n",
449*14b24e2bSVaishali Kulkarni 		       p_mb_params->data_src_size, p_mb_params->data_dst_size,
450*14b24e2bSVaishali Kulkarni 		       sizeof(union_data));
451*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
452*14b24e2bSVaishali Kulkarni 	}
453*14b24e2bSVaishali Kulkarni 
454*14b24e2bSVaishali Kulkarni 	union_data_addr = p_hwfn->mcp_info->drv_mb_addr +
455*14b24e2bSVaishali Kulkarni 			  OFFSETOF(struct public_drv_mb, union_data);
456*14b24e2bSVaishali Kulkarni 
457*14b24e2bSVaishali Kulkarni 	/* Ensure that only a single thread is accessing the mailbox at a
458*14b24e2bSVaishali Kulkarni 	 * certain time.
459*14b24e2bSVaishali Kulkarni 	 */
460*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mb_lock(p_hwfn, p_mb_params->cmd);
461*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
462*14b24e2bSVaishali Kulkarni 		return rc;
463*14b24e2bSVaishali Kulkarni 
464*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&union_data, sizeof(union_data));
465*14b24e2bSVaishali Kulkarni 	if (p_mb_params->p_data_src != OSAL_NULL && p_mb_params->data_src_size)
466*14b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(&union_data, p_mb_params->p_data_src,
467*14b24e2bSVaishali Kulkarni 			    p_mb_params->data_src_size);
468*14b24e2bSVaishali Kulkarni 	ecore_memcpy_to(p_hwfn, p_ptt, union_data_addr, &union_data,
469*14b24e2bSVaishali Kulkarni 			sizeof(union_data));
470*14b24e2bSVaishali Kulkarni 
471*14b24e2bSVaishali Kulkarni 	rc = ecore_do_mcp_cmd(p_hwfn, p_ptt, p_mb_params->cmd,
472*14b24e2bSVaishali Kulkarni 			      p_mb_params->param, &p_mb_params->mcp_resp,
473*14b24e2bSVaishali Kulkarni 			      &p_mb_params->mcp_param);
474*14b24e2bSVaishali Kulkarni 
475*14b24e2bSVaishali Kulkarni 	if (p_mb_params->p_data_dst != OSAL_NULL &&
476*14b24e2bSVaishali Kulkarni 	    p_mb_params->data_dst_size)
477*14b24e2bSVaishali Kulkarni 		ecore_memcpy_from(p_hwfn, p_ptt, p_mb_params->p_data_dst,
478*14b24e2bSVaishali Kulkarni 				  union_data_addr, p_mb_params->data_dst_size);
479*14b24e2bSVaishali Kulkarni 
480*14b24e2bSVaishali Kulkarni 	ecore_mcp_mb_unlock(p_hwfn, p_mb_params->cmd);
481*14b24e2bSVaishali Kulkarni 
482*14b24e2bSVaishali Kulkarni 	return rc;
483*14b24e2bSVaishali Kulkarni }
484*14b24e2bSVaishali Kulkarni 
485*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_cmd(struct ecore_hwfn *p_hwfn,
486*14b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt, u32 cmd, u32 param,
487*14b24e2bSVaishali Kulkarni 				   u32 *o_mcp_resp, u32 *o_mcp_param)
488*14b24e2bSVaishali Kulkarni {
489*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
490*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
491*14b24e2bSVaishali Kulkarni 
492*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
493*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
494*14b24e2bSVaishali Kulkarni 		if (cmd == DRV_MSG_CODE_UNLOAD_REQ) {
495*14b24e2bSVaishali Kulkarni 			loaded--;
496*14b24e2bSVaishali Kulkarni 			loaded_port[p_hwfn->port_id]--;
497*14b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Unload cnt: 0x%x\n",
498*14b24e2bSVaishali Kulkarni 				   loaded);
499*14b24e2bSVaishali Kulkarni 		}
500*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
501*14b24e2bSVaishali Kulkarni 	}
502*14b24e2bSVaishali Kulkarni #endif
503*14b24e2bSVaishali Kulkarni 
504*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
505*14b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
506*14b24e2bSVaishali Kulkarni 	mb_params.param = param;
507*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
508*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
509*14b24e2bSVaishali Kulkarni 		return rc;
510*14b24e2bSVaishali Kulkarni 
511*14b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
512*14b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
513*14b24e2bSVaishali Kulkarni 
514*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
515*14b24e2bSVaishali Kulkarni }
516*14b24e2bSVaishali Kulkarni 
517*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_wr_cmd(struct ecore_hwfn *p_hwfn,
518*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
519*14b24e2bSVaishali Kulkarni 					  u32 cmd,
520*14b24e2bSVaishali Kulkarni 					  u32 param,
521*14b24e2bSVaishali Kulkarni 					  u32 *o_mcp_resp,
522*14b24e2bSVaishali Kulkarni 					  u32 *o_mcp_param,
523*14b24e2bSVaishali Kulkarni 					  u32 i_txn_size,
524*14b24e2bSVaishali Kulkarni 					  u32 *i_buf)
525*14b24e2bSVaishali Kulkarni {
526*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
527*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
528*14b24e2bSVaishali Kulkarni 
529*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
530*14b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
531*14b24e2bSVaishali Kulkarni 	mb_params.param = param;
532*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = i_buf;
533*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = (u8) i_txn_size;
534*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
535*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
536*14b24e2bSVaishali Kulkarni 		return rc;
537*14b24e2bSVaishali Kulkarni 
538*14b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
539*14b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
540*14b24e2bSVaishali Kulkarni 
541*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
542*14b24e2bSVaishali Kulkarni }
543*14b24e2bSVaishali Kulkarni 
544*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_rd_cmd(struct ecore_hwfn *p_hwfn,
545*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
546*14b24e2bSVaishali Kulkarni 					  u32 cmd,
547*14b24e2bSVaishali Kulkarni 					  u32 param,
548*14b24e2bSVaishali Kulkarni 					  u32 *o_mcp_resp,
549*14b24e2bSVaishali Kulkarni 					  u32 *o_mcp_param,
550*14b24e2bSVaishali Kulkarni 					  u32 *o_txn_size,
551*14b24e2bSVaishali Kulkarni 					  u32 *o_buf)
552*14b24e2bSVaishali Kulkarni {
553*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
554*14b24e2bSVaishali Kulkarni 	u8 raw_data[MCP_DRV_NVM_BUF_LEN];
555*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
556*14b24e2bSVaishali Kulkarni 
557*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
558*14b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
559*14b24e2bSVaishali Kulkarni 	mb_params.param = param;
560*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = raw_data;
561*14b24e2bSVaishali Kulkarni 
562*14b24e2bSVaishali Kulkarni 	/* Use the maximal value since the actual one is part of the response */
563*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = MCP_DRV_NVM_BUF_LEN;
564*14b24e2bSVaishali Kulkarni 
565*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
566*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
567*14b24e2bSVaishali Kulkarni 		return rc;
568*14b24e2bSVaishali Kulkarni 
569*14b24e2bSVaishali Kulkarni 	*o_mcp_resp = mb_params.mcp_resp;
570*14b24e2bSVaishali Kulkarni 	*o_mcp_param = mb_params.mcp_param;
571*14b24e2bSVaishali Kulkarni 
572*14b24e2bSVaishali Kulkarni 	*o_txn_size = *o_mcp_param;
573*14b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(o_buf, raw_data, *o_txn_size);
574*14b24e2bSVaishali Kulkarni 
575*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
576*14b24e2bSVaishali Kulkarni }
577*14b24e2bSVaishali Kulkarni 
578*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
579*14b24e2bSVaishali Kulkarni static void ecore_mcp_mf_workaround(struct ecore_hwfn *p_hwfn,
580*14b24e2bSVaishali Kulkarni 				    u32 *p_load_code)
581*14b24e2bSVaishali Kulkarni {
582*14b24e2bSVaishali Kulkarni 	static int load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
583*14b24e2bSVaishali Kulkarni 
584*14b24e2bSVaishali Kulkarni 	if (!loaded) {
585*14b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
586*14b24e2bSVaishali Kulkarni 	} else if (!loaded_port[p_hwfn->port_id]) {
587*14b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_PORT;
588*14b24e2bSVaishali Kulkarni 	} else {
589*14b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_FUNCTION;
590*14b24e2bSVaishali Kulkarni 	}
591*14b24e2bSVaishali Kulkarni 
592*14b24e2bSVaishali Kulkarni 	/* On CMT, always tell that it's engine */
593*14b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->num_hwfns > 1)
594*14b24e2bSVaishali Kulkarni 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
595*14b24e2bSVaishali Kulkarni 
596*14b24e2bSVaishali Kulkarni 	*p_load_code = load_phase;
597*14b24e2bSVaishali Kulkarni 	loaded++;
598*14b24e2bSVaishali Kulkarni 	loaded_port[p_hwfn->port_id]++;
599*14b24e2bSVaishali Kulkarni 
600*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
601*14b24e2bSVaishali Kulkarni 		   "Load phase: %x load cnt: 0x%x port id=%d port_load=%d\n",
602*14b24e2bSVaishali Kulkarni 		   *p_load_code, loaded, p_hwfn->port_id,
603*14b24e2bSVaishali Kulkarni 		   loaded_port[p_hwfn->port_id]);
604*14b24e2bSVaishali Kulkarni }
605*14b24e2bSVaishali Kulkarni #endif
606*14b24e2bSVaishali Kulkarni 
607*14b24e2bSVaishali Kulkarni static bool
608*14b24e2bSVaishali Kulkarni ecore_mcp_can_force_load(u8 drv_role, u8 exist_drv_role,
609*14b24e2bSVaishali Kulkarni 			 enum ecore_override_force_load override_force_load)
610*14b24e2bSVaishali Kulkarni {
611*14b24e2bSVaishali Kulkarni 	bool can_force_load = false;
612*14b24e2bSVaishali Kulkarni 
613*14b24e2bSVaishali Kulkarni 	switch (override_force_load) {
614*14b24e2bSVaishali Kulkarni 	case ECORE_OVERRIDE_FORCE_LOAD_ALWAYS:
615*14b24e2bSVaishali Kulkarni 		can_force_load = true;
616*14b24e2bSVaishali Kulkarni 		break;
617*14b24e2bSVaishali Kulkarni 	case ECORE_OVERRIDE_FORCE_LOAD_NEVER:
618*14b24e2bSVaishali Kulkarni 		can_force_load = false;
619*14b24e2bSVaishali Kulkarni 		break;
620*14b24e2bSVaishali Kulkarni 	default:
621*14b24e2bSVaishali Kulkarni 		can_force_load = (drv_role == DRV_ROLE_OS &&
622*14b24e2bSVaishali Kulkarni 				  exist_drv_role == DRV_ROLE_PREBOOT) ||
623*14b24e2bSVaishali Kulkarni 				 (drv_role == DRV_ROLE_KDUMP &&
624*14b24e2bSVaishali Kulkarni 				  exist_drv_role == DRV_ROLE_OS);
625*14b24e2bSVaishali Kulkarni 		break;
626*14b24e2bSVaishali Kulkarni 	}
627*14b24e2bSVaishali Kulkarni 
628*14b24e2bSVaishali Kulkarni 	return can_force_load;
629*14b24e2bSVaishali Kulkarni }
630*14b24e2bSVaishali Kulkarni 
631*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_cancel_load_req(struct ecore_hwfn *p_hwfn,
632*14b24e2bSVaishali Kulkarni 						      struct ecore_ptt *p_ptt)
633*14b24e2bSVaishali Kulkarni {
634*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
635*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
636*14b24e2bSVaishali Kulkarni 
637*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CANCEL_LOAD_REQ, 0,
638*14b24e2bSVaishali Kulkarni 			   &resp, &param);
639*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
640*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
641*14b24e2bSVaishali Kulkarni 			  "Failed to send cancel load request, rc = %d\n", rc);
642*14b24e2bSVaishali Kulkarni 
643*14b24e2bSVaishali Kulkarni 	return rc;
644*14b24e2bSVaishali Kulkarni }
645*14b24e2bSVaishali Kulkarni 
646*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_L2_BITMAP_IDX	(0x1 << 0)
647*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_SRIOV_BITMAP_IDX	(0x1 << 1)
648*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_ROCE_BITMAP_IDX	(0x1 << 2)
649*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_IWARP_BITMAP_IDX	(0x1 << 3)
650*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_FCOE_BITMAP_IDX	(0x1 << 4)
651*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_ISCSI_BITMAP_IDX	(0x1 << 5)
652*14b24e2bSVaishali Kulkarni #define CONFIG_ECORE_LL2_BITMAP_IDX	(0x1 << 6)
653*14b24e2bSVaishali Kulkarni 
654*14b24e2bSVaishali Kulkarni static u32 ecore_get_config_bitmap(void)
655*14b24e2bSVaishali Kulkarni {
656*14b24e2bSVaishali Kulkarni 	u32 config_bitmap = 0x0;
657*14b24e2bSVaishali Kulkarni 
658*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_L2
659*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_L2_BITMAP_IDX;
660*14b24e2bSVaishali Kulkarni #endif
661*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_SRIOV
662*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_SRIOV_BITMAP_IDX;
663*14b24e2bSVaishali Kulkarni #endif
664*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ROCE
665*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_ROCE_BITMAP_IDX;
666*14b24e2bSVaishali Kulkarni #endif
667*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_IWARP
668*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_IWARP_BITMAP_IDX;
669*14b24e2bSVaishali Kulkarni #endif
670*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_FCOE
671*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_FCOE_BITMAP_IDX;
672*14b24e2bSVaishali Kulkarni #endif
673*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_ISCSI
674*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_ISCSI_BITMAP_IDX;
675*14b24e2bSVaishali Kulkarni #endif
676*14b24e2bSVaishali Kulkarni #ifdef CONFIG_ECORE_LL2
677*14b24e2bSVaishali Kulkarni 	config_bitmap |= CONFIG_ECORE_LL2_BITMAP_IDX;
678*14b24e2bSVaishali Kulkarni #endif
679*14b24e2bSVaishali Kulkarni 
680*14b24e2bSVaishali Kulkarni 	return config_bitmap;
681*14b24e2bSVaishali Kulkarni }
682*14b24e2bSVaishali Kulkarni 
683*14b24e2bSVaishali Kulkarni struct ecore_load_req_in_params {
684*14b24e2bSVaishali Kulkarni 	u8 hsi_ver;
685*14b24e2bSVaishali Kulkarni #define ECORE_LOAD_REQ_HSI_VER_DEFAULT	0
686*14b24e2bSVaishali Kulkarni #define ECORE_LOAD_REQ_HSI_VER_1	1
687*14b24e2bSVaishali Kulkarni 	u32 drv_ver_0;
688*14b24e2bSVaishali Kulkarni 	u32 drv_ver_1;
689*14b24e2bSVaishali Kulkarni 	u32 fw_ver;
690*14b24e2bSVaishali Kulkarni 	u8 drv_role;
691*14b24e2bSVaishali Kulkarni 	u8 timeout_val;
692*14b24e2bSVaishali Kulkarni 	u8 force_cmd;
693*14b24e2bSVaishali Kulkarni 	bool avoid_eng_reset;
694*14b24e2bSVaishali Kulkarni };
695*14b24e2bSVaishali Kulkarni 
696*14b24e2bSVaishali Kulkarni struct ecore_load_req_out_params {
697*14b24e2bSVaishali Kulkarni 	u32 load_code;
698*14b24e2bSVaishali Kulkarni 	u32 exist_drv_ver_0;
699*14b24e2bSVaishali Kulkarni 	u32 exist_drv_ver_1;
700*14b24e2bSVaishali Kulkarni 	u32 exist_fw_ver;
701*14b24e2bSVaishali Kulkarni 	u8 exist_drv_role;
702*14b24e2bSVaishali Kulkarni 	u8 mfw_hsi_ver;
703*14b24e2bSVaishali Kulkarni 	bool drv_exists;
704*14b24e2bSVaishali Kulkarni };
705*14b24e2bSVaishali Kulkarni 
706*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
707*14b24e2bSVaishali Kulkarni __ecore_mcp_load_req(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
708*14b24e2bSVaishali Kulkarni 		     struct ecore_load_req_in_params *p_in_params,
709*14b24e2bSVaishali Kulkarni 		     struct ecore_load_req_out_params *p_out_params)
710*14b24e2bSVaishali Kulkarni {
711*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
712*14b24e2bSVaishali Kulkarni 	struct load_req_stc load_req;
713*14b24e2bSVaishali Kulkarni 	struct load_rsp_stc load_rsp;
714*14b24e2bSVaishali Kulkarni 	u32 hsi_ver;
715*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
716*14b24e2bSVaishali Kulkarni 
717*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&load_req, sizeof(load_req));
718*14b24e2bSVaishali Kulkarni 	load_req.drv_ver_0 = p_in_params->drv_ver_0;
719*14b24e2bSVaishali Kulkarni 	load_req.drv_ver_1 = p_in_params->drv_ver_1;
720*14b24e2bSVaishali Kulkarni 	load_req.fw_ver = p_in_params->fw_ver;
721*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_ROLE,
722*14b24e2bSVaishali Kulkarni 			    p_in_params->drv_role);
723*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_LOCK_TO,
724*14b24e2bSVaishali Kulkarni 			    p_in_params->timeout_val);
725*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FORCE,
726*14b24e2bSVaishali Kulkarni 			    p_in_params->force_cmd);
727*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FLAGS0,
728*14b24e2bSVaishali Kulkarni 			    p_in_params->avoid_eng_reset);
729*14b24e2bSVaishali Kulkarni 
730*14b24e2bSVaishali Kulkarni 	hsi_ver = (p_in_params->hsi_ver == ECORE_LOAD_REQ_HSI_VER_DEFAULT) ?
731*14b24e2bSVaishali Kulkarni 		  DRV_ID_MCP_HSI_VER_CURRENT :
732*14b24e2bSVaishali Kulkarni 		  (p_in_params->hsi_ver << DRV_ID_MCP_HSI_VER_SHIFT);
733*14b24e2bSVaishali Kulkarni 
734*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
735*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_LOAD_REQ;
736*14b24e2bSVaishali Kulkarni 	mb_params.param = PDA_COMP | hsi_ver | p_hwfn->p_dev->drv_type;
737*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &load_req;
738*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(load_req);
739*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &load_rsp;
740*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(load_rsp);
741*14b24e2bSVaishali Kulkarni 
742*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
743*14b24e2bSVaishali Kulkarni 		   "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n",
744*14b24e2bSVaishali Kulkarni 		   mb_params.param,
745*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_INIT_HW),
746*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_TYPE),
747*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_MCP_HSI_VER),
748*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param, DRV_ID_PDA_COMP_VER));
749*14b24e2bSVaishali Kulkarni 
750*14b24e2bSVaishali Kulkarni 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1)
751*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
752*14b24e2bSVaishali 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",
753*14b24e2bSVaishali Kulkarni 			   load_req.drv_ver_0, load_req.drv_ver_1,
754*14b24e2bSVaishali Kulkarni 			   load_req.fw_ver, load_req.misc0,
755*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_ROLE),
756*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0,
757*14b24e2bSVaishali Kulkarni 					       LOAD_REQ_LOCK_TO),
758*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_FORCE),
759*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_req.misc0,
760*14b24e2bSVaishali Kulkarni 					       LOAD_REQ_FLAGS0));
761*14b24e2bSVaishali Kulkarni 
762*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
763*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
764*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
765*14b24e2bSVaishali Kulkarni 			  "Failed to send load request, rc = %d\n", rc);
766*14b24e2bSVaishali Kulkarni 		return rc;
767*14b24e2bSVaishali Kulkarni 	}
768*14b24e2bSVaishali Kulkarni 
769*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
770*14b24e2bSVaishali Kulkarni 		   "Load Response: resp 0x%08x\n", mb_params.mcp_resp);
771*14b24e2bSVaishali Kulkarni 	p_out_params->load_code = mb_params.mcp_resp;
772*14b24e2bSVaishali Kulkarni 
773*14b24e2bSVaishali Kulkarni 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
774*14b24e2bSVaishali Kulkarni 	    p_out_params->load_code != FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
775*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
776*14b24e2bSVaishali 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",
777*14b24e2bSVaishali Kulkarni 			   load_rsp.drv_ver_0, load_rsp.drv_ver_1,
778*14b24e2bSVaishali Kulkarni 			   load_rsp.fw_ver, load_rsp.misc0,
779*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE),
780*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI),
781*14b24e2bSVaishali Kulkarni 			   ECORE_MFW_GET_FIELD(load_rsp.misc0,
782*14b24e2bSVaishali Kulkarni 					       LOAD_RSP_FLAGS0));
783*14b24e2bSVaishali Kulkarni 
784*14b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_ver_0 = load_rsp.drv_ver_0;
785*14b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_ver_1 = load_rsp.drv_ver_1;
786*14b24e2bSVaishali Kulkarni 		p_out_params->exist_fw_ver = load_rsp.fw_ver;
787*14b24e2bSVaishali Kulkarni 		p_out_params->exist_drv_role =
788*14b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE);
789*14b24e2bSVaishali Kulkarni 		p_out_params->mfw_hsi_ver =
790*14b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI);
791*14b24e2bSVaishali Kulkarni 		p_out_params->drv_exists =
792*14b24e2bSVaishali Kulkarni 			ECORE_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0) &
793*14b24e2bSVaishali Kulkarni 			LOAD_RSP_FLAGS0_DRV_EXISTS;
794*14b24e2bSVaishali Kulkarni 	}
795*14b24e2bSVaishali Kulkarni 
796*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
797*14b24e2bSVaishali Kulkarni }
798*14b24e2bSVaishali Kulkarni 
799*14b24e2bSVaishali Kulkarni static enum _ecore_status_t eocre_get_mfw_drv_role(struct ecore_hwfn *p_hwfn,
800*14b24e2bSVaishali Kulkarni 						   enum ecore_drv_role drv_role,
801*14b24e2bSVaishali Kulkarni 						   u8 *p_mfw_drv_role)
802*14b24e2bSVaishali Kulkarni {
803*14b24e2bSVaishali Kulkarni 	switch (drv_role)
804*14b24e2bSVaishali Kulkarni 	{
805*14b24e2bSVaishali Kulkarni 	case ECORE_DRV_ROLE_OS:
806*14b24e2bSVaishali Kulkarni 		*p_mfw_drv_role = DRV_ROLE_OS;
807*14b24e2bSVaishali Kulkarni 		break;
808*14b24e2bSVaishali Kulkarni 	case ECORE_DRV_ROLE_KDUMP:
809*14b24e2bSVaishali Kulkarni 		*p_mfw_drv_role = DRV_ROLE_KDUMP;
810*14b24e2bSVaishali Kulkarni 		break;
811*14b24e2bSVaishali Kulkarni 	default:
812*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected driver role %d\n", drv_role);
813*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
814*14b24e2bSVaishali Kulkarni 	}
815*14b24e2bSVaishali Kulkarni 
816*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
817*14b24e2bSVaishali Kulkarni }
818*14b24e2bSVaishali Kulkarni 
819*14b24e2bSVaishali Kulkarni enum ecore_load_req_force {
820*14b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_NONE,
821*14b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_PF,
822*14b24e2bSVaishali Kulkarni 	ECORE_LOAD_REQ_FORCE_ALL,
823*14b24e2bSVaishali Kulkarni };
824*14b24e2bSVaishali Kulkarni 
825*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
826*14b24e2bSVaishali Kulkarni ecore_get_mfw_force_cmd(struct ecore_hwfn *p_hwfn,
827*14b24e2bSVaishali Kulkarni 			enum ecore_load_req_force force_cmd,
828*14b24e2bSVaishali Kulkarni 			u8 *p_mfw_force_cmd)
829*14b24e2bSVaishali Kulkarni {
830*14b24e2bSVaishali Kulkarni 	switch (force_cmd) {
831*14b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_NONE:
832*14b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_NONE;
833*14b24e2bSVaishali Kulkarni 		break;
834*14b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_PF:
835*14b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_PF;
836*14b24e2bSVaishali Kulkarni 		break;
837*14b24e2bSVaishali Kulkarni 	case ECORE_LOAD_REQ_FORCE_ALL:
838*14b24e2bSVaishali Kulkarni 		*p_mfw_force_cmd = LOAD_REQ_FORCE_ALL;
839*14b24e2bSVaishali Kulkarni 		break;
840*14b24e2bSVaishali Kulkarni 	default:
841*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected force value %d\n", force_cmd);
842*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
843*14b24e2bSVaishali Kulkarni 	}
844*14b24e2bSVaishali Kulkarni 
845*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
846*14b24e2bSVaishali Kulkarni }
847*14b24e2bSVaishali Kulkarni 
848*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_load_req(struct ecore_hwfn *p_hwfn,
849*14b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt,
850*14b24e2bSVaishali Kulkarni 					struct ecore_load_req_params *p_params)
851*14b24e2bSVaishali Kulkarni {
852*14b24e2bSVaishali Kulkarni 	struct ecore_load_req_out_params out_params;
853*14b24e2bSVaishali Kulkarni 	struct ecore_load_req_in_params in_params;
854*14b24e2bSVaishali Kulkarni 	u8 mfw_drv_role, mfw_force_cmd;
855*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
856*14b24e2bSVaishali Kulkarni 
857*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
858*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
859*14b24e2bSVaishali Kulkarni 		ecore_mcp_mf_workaround(p_hwfn, &p_params->load_code);
860*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
861*14b24e2bSVaishali Kulkarni 	}
862*14b24e2bSVaishali Kulkarni #endif
863*14b24e2bSVaishali Kulkarni 
864*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
865*14b24e2bSVaishali Kulkarni 	in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_DEFAULT;
866*14b24e2bSVaishali Kulkarni 	in_params.drv_ver_0 = ECORE_VERSION;
867*14b24e2bSVaishali Kulkarni 	in_params.drv_ver_1 = ecore_get_config_bitmap();
868*14b24e2bSVaishali Kulkarni 	in_params.fw_ver = STORM_FW_VERSION;
869*14b24e2bSVaishali Kulkarni 	rc = eocre_get_mfw_drv_role(p_hwfn, p_params->drv_role, &mfw_drv_role);
870*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
871*14b24e2bSVaishali Kulkarni 		return rc;
872*14b24e2bSVaishali Kulkarni 
873*14b24e2bSVaishali Kulkarni 	in_params.drv_role = mfw_drv_role;
874*14b24e2bSVaishali Kulkarni 	in_params.timeout_val = p_params->timeout_val;
875*14b24e2bSVaishali Kulkarni 	rc = ecore_get_mfw_force_cmd(p_hwfn, ECORE_LOAD_REQ_FORCE_NONE,
876*14b24e2bSVaishali Kulkarni 				     &mfw_force_cmd);
877*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
878*14b24e2bSVaishali Kulkarni 		return rc;
879*14b24e2bSVaishali Kulkarni 
880*14b24e2bSVaishali Kulkarni 	in_params.force_cmd = mfw_force_cmd;
881*14b24e2bSVaishali Kulkarni 	in_params.avoid_eng_reset = p_params->avoid_eng_reset;
882*14b24e2bSVaishali Kulkarni 
883*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
884*14b24e2bSVaishali Kulkarni 	rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params, &out_params);
885*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
886*14b24e2bSVaishali Kulkarni 		return rc;
887*14b24e2bSVaishali Kulkarni 
888*14b24e2bSVaishali Kulkarni 	/* First handle cases where another load request should/might be sent:
889*14b24e2bSVaishali Kulkarni 	 * - MFW expects the old interface [HSI version = 1]
890*14b24e2bSVaishali Kulkarni 	 * - MFW responds that a force load request is required
891*14b24e2bSVaishali Kulkarni 	 */
892*14b24e2bSVaishali Kulkarni 	if (out_params.load_code == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
893*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
894*14b24e2bSVaishali Kulkarni 			"MFW refused a load request due to HSI > 1. Resending with HSI = 1.\n");
895*14b24e2bSVaishali Kulkarni 
896*14b24e2bSVaishali Kulkarni 		/* The previous load request set the mailbox blocking */
897*14b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
898*14b24e2bSVaishali Kulkarni 
899*14b24e2bSVaishali Kulkarni 		in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_1;
900*14b24e2bSVaishali Kulkarni 		OSAL_MEM_ZERO(&out_params, sizeof(out_params));
901*14b24e2bSVaishali Kulkarni 		rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
902*14b24e2bSVaishali Kulkarni 					  &out_params);
903*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
904*14b24e2bSVaishali Kulkarni 			return rc;
905*14b24e2bSVaishali Kulkarni 	} else if (out_params.load_code ==
906*14b24e2bSVaishali Kulkarni 		   FW_MSG_CODE_DRV_LOAD_REFUSED_REQUIRES_FORCE) {
907*14b24e2bSVaishali Kulkarni 		/* The previous load request set the mailbox blocking */
908*14b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->block_mb_sending = false;
909*14b24e2bSVaishali Kulkarni 
910*14b24e2bSVaishali Kulkarni 		if (ecore_mcp_can_force_load(in_params.drv_role,
911*14b24e2bSVaishali Kulkarni 					     out_params.exist_drv_role,
912*14b24e2bSVaishali Kulkarni 					     p_params->override_force_load)) {
913*14b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn,
914*14b24e2bSVaishali 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",
915*14b24e2bSVaishali Kulkarni 				in_params.drv_role, in_params.fw_ver,
916*14b24e2bSVaishali Kulkarni 				in_params.drv_ver_1, in_params.drv_ver_0,
917*14b24e2bSVaishali Kulkarni 				out_params.exist_drv_role,
918*14b24e2bSVaishali Kulkarni 				out_params.exist_fw_ver,
919*14b24e2bSVaishali Kulkarni 				out_params.exist_drv_ver_1,
920*14b24e2bSVaishali Kulkarni 				out_params.exist_drv_ver_0);
921*14b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Sending a force load request\n");
922*14b24e2bSVaishali Kulkarni 
923*14b24e2bSVaishali Kulkarni 			rc = ecore_get_mfw_force_cmd(p_hwfn,
924*14b24e2bSVaishali Kulkarni 						     ECORE_LOAD_REQ_FORCE_ALL,
925*14b24e2bSVaishali Kulkarni 						     &mfw_force_cmd);
926*14b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
927*14b24e2bSVaishali Kulkarni 				return rc;
928*14b24e2bSVaishali Kulkarni 
929*14b24e2bSVaishali Kulkarni 			in_params.force_cmd = mfw_force_cmd;
930*14b24e2bSVaishali Kulkarni 			OSAL_MEM_ZERO(&out_params, sizeof(out_params));
931*14b24e2bSVaishali Kulkarni 			rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
932*14b24e2bSVaishali Kulkarni 						  &out_params);
933*14b24e2bSVaishali Kulkarni 			if (rc != ECORE_SUCCESS)
934*14b24e2bSVaishali Kulkarni 				return rc;
935*14b24e2bSVaishali Kulkarni 		} else {
936*14b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
937*14b24e2bSVaishali 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",
938*14b24e2bSVaishali Kulkarni 				  in_params.drv_role, in_params.fw_ver,
939*14b24e2bSVaishali Kulkarni 				  in_params.drv_ver_0, in_params.drv_ver_1,
940*14b24e2bSVaishali Kulkarni 				  out_params.exist_drv_role,
941*14b24e2bSVaishali Kulkarni 				  out_params.exist_fw_ver,
942*14b24e2bSVaishali Kulkarni 				  out_params.exist_drv_ver_0,
943*14b24e2bSVaishali Kulkarni 				  out_params.exist_drv_ver_1);
944*14b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
945*14b24e2bSVaishali Kulkarni 				  "Avoid sending a force load request to prevent disruption of active PFs\n");
946*14b24e2bSVaishali Kulkarni 
947*14b24e2bSVaishali Kulkarni 			ecore_mcp_cancel_load_req(p_hwfn, p_ptt);
948*14b24e2bSVaishali Kulkarni 			return ECORE_BUSY;
949*14b24e2bSVaishali Kulkarni 		}
950*14b24e2bSVaishali Kulkarni 	}
951*14b24e2bSVaishali Kulkarni 
952*14b24e2bSVaishali Kulkarni 	/* Now handle the other types of responses.
953*14b24e2bSVaishali Kulkarni 	 * The "REFUSED_HSI_1" and "REFUSED_REQUIRES_FORCE" responses are not
954*14b24e2bSVaishali Kulkarni 	 * expected here after the additional revised load requests were sent.
955*14b24e2bSVaishali Kulkarni 	 */
956*14b24e2bSVaishali Kulkarni 	switch (out_params.load_code) {
957*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_ENGINE:
958*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_PORT:
959*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
960*14b24e2bSVaishali Kulkarni 		if (out_params.mfw_hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
961*14b24e2bSVaishali Kulkarni 		    out_params.drv_exists) {
962*14b24e2bSVaishali Kulkarni 			/* The role and fw/driver version match, but the PF is
963*14b24e2bSVaishali Kulkarni 			 * already loaded and has not been unloaded gracefully.
964*14b24e2bSVaishali Kulkarni 			 * This is unexpected since a quasi-FLR request was
965*14b24e2bSVaishali Kulkarni 			 * previously sent as part of ecore_hw_prepare().
966*14b24e2bSVaishali Kulkarni 			 */
967*14b24e2bSVaishali Kulkarni 			DP_NOTICE(p_hwfn, false,
968*14b24e2bSVaishali Kulkarni 				  "PF is already loaded - shouldn't have got here since a quasi-FLR request was previously sent!\n");
969*14b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
970*14b24e2bSVaishali Kulkarni 		}
971*14b24e2bSVaishali Kulkarni 		break;
972*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_PDA:
973*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG:
974*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_HSI:
975*14b24e2bSVaishali Kulkarni 	case FW_MSG_CODE_DRV_LOAD_REFUSED_REJECT:
976*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
977*14b24e2bSVaishali Kulkarni 			  "MFW refused a load request [resp 0x%08x]. Aborting.\n",
978*14b24e2bSVaishali Kulkarni 			  out_params.load_code);
979*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
980*14b24e2bSVaishali Kulkarni 	default:
981*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
982*14b24e2bSVaishali Kulkarni 			  "Unexpected response to load request [resp 0x%08x]. Aborting.\n",
983*14b24e2bSVaishali Kulkarni 			  out_params.load_code);
984*14b24e2bSVaishali Kulkarni 		break;
985*14b24e2bSVaishali Kulkarni 	}
986*14b24e2bSVaishali Kulkarni 
987*14b24e2bSVaishali Kulkarni 	p_params->load_code = out_params.load_code;
988*14b24e2bSVaishali Kulkarni 
989*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
990*14b24e2bSVaishali Kulkarni }
991*14b24e2bSVaishali Kulkarni 
992*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_unload_req(struct ecore_hwfn *p_hwfn,
993*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt)
994*14b24e2bSVaishali Kulkarni {
995*14b24e2bSVaishali Kulkarni 	u32 wol_param, mcp_resp, mcp_param;
996*14b24e2bSVaishali Kulkarni 
997*14b24e2bSVaishali Kulkarni 	switch (p_hwfn->p_dev->wol_config) {
998*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DISABLED:
999*14b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED;
1000*14b24e2bSVaishali Kulkarni 		break;
1001*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_ENABLED:
1002*14b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED;
1003*14b24e2bSVaishali Kulkarni 		break;
1004*14b24e2bSVaishali Kulkarni 	default:
1005*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
1006*14b24e2bSVaishali Kulkarni 			  "Unknown WoL configuration %02x\n",
1007*14b24e2bSVaishali Kulkarni 			  p_hwfn->p_dev->wol_config);
1008*14b24e2bSVaishali Kulkarni 		/* Fallthrough */
1009*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DEFAULT:
1010*14b24e2bSVaishali Kulkarni 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
1011*14b24e2bSVaishali Kulkarni 	}
1012*14b24e2bSVaishali Kulkarni 
1013*14b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param,
1014*14b24e2bSVaishali Kulkarni 			     &mcp_resp, &mcp_param);
1015*14b24e2bSVaishali Kulkarni }
1016*14b24e2bSVaishali Kulkarni 
1017*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_unload_done(struct ecore_hwfn *p_hwfn,
1018*14b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt)
1019*14b24e2bSVaishali Kulkarni {
1020*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
1021*14b24e2bSVaishali Kulkarni 	struct mcp_mac wol_mac;
1022*14b24e2bSVaishali Kulkarni 
1023*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1024*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_UNLOAD_DONE;
1025*14b24e2bSVaishali Kulkarni 
1026*14b24e2bSVaishali Kulkarni 	/* Set the primary MAC if WoL is enabled */
1027*14b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->wol_config == ECORE_OV_WOL_ENABLED) {
1028*14b24e2bSVaishali Kulkarni 		u8 *p_mac = p_hwfn->p_dev->wol_mac;
1029*14b24e2bSVaishali Kulkarni 
1030*14b24e2bSVaishali Kulkarni 		OSAL_MEM_ZERO(&wol_mac, sizeof(wol_mac));
1031*14b24e2bSVaishali Kulkarni 		wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1];
1032*14b24e2bSVaishali Kulkarni 		wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 |
1033*14b24e2bSVaishali Kulkarni 				    p_mac[4] << 8 | p_mac[5];
1034*14b24e2bSVaishali Kulkarni 
1035*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFDOWN),
1036*14b24e2bSVaishali Kulkarni 			   "Setting WoL MAC: %02x:%02x:%02x:%02x:%02x:%02x --> [%08x,%08x]\n",
1037*14b24e2bSVaishali Kulkarni 			   p_mac[0], p_mac[1], p_mac[2], p_mac[3], p_mac[4],
1038*14b24e2bSVaishali Kulkarni 			   p_mac[5], wol_mac.mac_upper, wol_mac.mac_lower);
1039*14b24e2bSVaishali Kulkarni 
1040*14b24e2bSVaishali Kulkarni 		mb_params.p_data_src = &wol_mac;
1041*14b24e2bSVaishali Kulkarni 		mb_params.data_src_size = sizeof(wol_mac);
1042*14b24e2bSVaishali Kulkarni 	}
1043*14b24e2bSVaishali Kulkarni 
1044*14b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
1045*14b24e2bSVaishali Kulkarni }
1046*14b24e2bSVaishali Kulkarni 
1047*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_vf_flr(struct ecore_hwfn *p_hwfn,
1048*14b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt)
1049*14b24e2bSVaishali Kulkarni {
1050*14b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1051*14b24e2bSVaishali Kulkarni 					PUBLIC_PATH);
1052*14b24e2bSVaishali Kulkarni 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
1053*14b24e2bSVaishali Kulkarni 	u32 path_addr = SECTION_ADDR(mfw_path_offsize,
1054*14b24e2bSVaishali Kulkarni 				     ECORE_PATH_ID(p_hwfn));
1055*14b24e2bSVaishali Kulkarni 	u32 disabled_vfs[VF_MAX_STATIC / 32];
1056*14b24e2bSVaishali Kulkarni 	int i;
1057*14b24e2bSVaishali Kulkarni 
1058*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
1059*14b24e2bSVaishali Kulkarni 		   "Reading Disabled VF information from [offset %08x], path_addr %08x\n",
1060*14b24e2bSVaishali Kulkarni 		   mfw_path_offsize, path_addr);
1061*14b24e2bSVaishali Kulkarni 
1062*14b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++) {
1063*14b24e2bSVaishali Kulkarni 		disabled_vfs[i] = ecore_rd(p_hwfn, p_ptt,
1064*14b24e2bSVaishali Kulkarni 					   path_addr +
1065*14b24e2bSVaishali Kulkarni 					   OFFSETOF(struct public_path,
1066*14b24e2bSVaishali Kulkarni 						    mcp_vf_disabled) +
1067*14b24e2bSVaishali Kulkarni 					   sizeof(u32) * i);
1068*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
1069*14b24e2bSVaishali Kulkarni 			   "FLR-ed VFs [%08x,...,%08x] - %08x\n",
1070*14b24e2bSVaishali Kulkarni 			   i * 32, (i + 1) * 32 - 1, disabled_vfs[i]);
1071*14b24e2bSVaishali Kulkarni 	}
1072*14b24e2bSVaishali Kulkarni 
1073*14b24e2bSVaishali Kulkarni 	if (ecore_iov_mark_vf_flr(p_hwfn, disabled_vfs))
1074*14b24e2bSVaishali Kulkarni 		OSAL_VF_FLR_UPDATE(p_hwfn);
1075*14b24e2bSVaishali Kulkarni }
1076*14b24e2bSVaishali Kulkarni 
1077*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_ack_vf_flr(struct ecore_hwfn *p_hwfn,
1078*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
1079*14b24e2bSVaishali Kulkarni 					  u32 *vfs_to_ack)
1080*14b24e2bSVaishali Kulkarni {
1081*14b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1082*14b24e2bSVaishali Kulkarni 					PUBLIC_FUNC);
1083*14b24e2bSVaishali Kulkarni 	u32 mfw_func_offsize = ecore_rd(p_hwfn, p_ptt, addr);
1084*14b24e2bSVaishali Kulkarni 	u32 func_addr = SECTION_ADDR(mfw_func_offsize,
1085*14b24e2bSVaishali Kulkarni 				     MCP_PF_ID(p_hwfn));
1086*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
1087*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1088*14b24e2bSVaishali Kulkarni 	int i;
1089*14b24e2bSVaishali Kulkarni 
1090*14b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
1091*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
1092*14b24e2bSVaishali Kulkarni 			   "Acking VFs [%08x,...,%08x] - %08x\n",
1093*14b24e2bSVaishali Kulkarni 			   i * 32, (i + 1) * 32 - 1, vfs_to_ack[i]);
1094*14b24e2bSVaishali Kulkarni 
1095*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1096*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_VF_DISABLED_DONE;
1097*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = vfs_to_ack;
1098*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = VF_MAX_STATIC / 8;
1099*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
1100*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
1101*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1102*14b24e2bSVaishali Kulkarni 			  "Failed to pass ACK for VF flr to MFW\n");
1103*14b24e2bSVaishali Kulkarni 		return ECORE_TIMEOUT;
1104*14b24e2bSVaishali Kulkarni 	}
1105*14b24e2bSVaishali Kulkarni 
1106*14b24e2bSVaishali Kulkarni 	/* TMP - clear the ACK bits; should be done by MFW */
1107*14b24e2bSVaishali Kulkarni 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
1108*14b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
1109*14b24e2bSVaishali Kulkarni 			 func_addr +
1110*14b24e2bSVaishali Kulkarni 			 OFFSETOF(struct public_func, drv_ack_vf_disabled) +
1111*14b24e2bSVaishali Kulkarni 			 i * sizeof(u32), 0);
1112*14b24e2bSVaishali Kulkarni 
1113*14b24e2bSVaishali Kulkarni 	return rc;
1114*14b24e2bSVaishali Kulkarni }
1115*14b24e2bSVaishali Kulkarni 
1116*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_transceiver_change(struct ecore_hwfn *p_hwfn,
1117*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
1118*14b24e2bSVaishali Kulkarni {
1119*14b24e2bSVaishali Kulkarni 	u32 transceiver_state;
1120*14b24e2bSVaishali Kulkarni 
1121*14b24e2bSVaishali Kulkarni 	transceiver_state = ecore_rd(p_hwfn, p_ptt,
1122*14b24e2bSVaishali Kulkarni 				     p_hwfn->mcp_info->port_addr +
1123*14b24e2bSVaishali Kulkarni 				     OFFSETOF(struct public_port,
1124*14b24e2bSVaishali Kulkarni 					      transceiver_data));
1125*14b24e2bSVaishali Kulkarni 
1126*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, (ECORE_MSG_HW | ECORE_MSG_SP),
1127*14b24e2bSVaishali Kulkarni 		   "Received transceiver state update [0x%08x] from mfw [Addr 0x%x]\n",
1128*14b24e2bSVaishali Kulkarni 		   transceiver_state, (u32)(p_hwfn->mcp_info->port_addr +
1129*14b24e2bSVaishali Kulkarni 					    OFFSETOF(struct public_port,
1130*14b24e2bSVaishali Kulkarni 						     transceiver_data)));
1131*14b24e2bSVaishali Kulkarni 
1132*14b24e2bSVaishali Kulkarni 	transceiver_state = GET_FIELD(transceiver_state, ETH_TRANSCEIVER_STATE);
1133*14b24e2bSVaishali Kulkarni 
1134*14b24e2bSVaishali Kulkarni 	if (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
1135*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Transceiver is present.\n");
1136*14b24e2bSVaishali Kulkarni 	else
1137*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Transceiver is unplugged.\n");
1138*14b24e2bSVaishali Kulkarni }
1139*14b24e2bSVaishali Kulkarni 
1140*14b24e2bSVaishali Kulkarni static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
1141*14b24e2bSVaishali Kulkarni 				      struct ecore_ptt *p_ptt,
1142*14b24e2bSVaishali Kulkarni 				      struct ecore_mcp_link_state *p_link)
1143*14b24e2bSVaishali Kulkarni {
1144*14b24e2bSVaishali Kulkarni 	u32 eee_status, val;
1145*14b24e2bSVaishali Kulkarni 
1146*14b24e2bSVaishali Kulkarni 	p_link->eee_adv_caps = 0;
1147*14b24e2bSVaishali Kulkarni 	p_link->eee_lp_adv_caps = 0;
1148*14b24e2bSVaishali Kulkarni 	eee_status = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
1149*14b24e2bSVaishali Kulkarni 				     OFFSETOF(struct public_port, eee_status));
1150*14b24e2bSVaishali Kulkarni 	p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT);
1151*14b24e2bSVaishali Kulkarni 	val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_SHIFT;
1152*14b24e2bSVaishali Kulkarni 	if (val & EEE_1G_ADV)
1153*14b24e2bSVaishali Kulkarni 		p_link->eee_adv_caps |= ECORE_EEE_1G_ADV;
1154*14b24e2bSVaishali Kulkarni 	if (val & EEE_10G_ADV)
1155*14b24e2bSVaishali Kulkarni 		p_link->eee_adv_caps |= ECORE_EEE_10G_ADV;
1156*14b24e2bSVaishali Kulkarni 	val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_SHIFT;
1157*14b24e2bSVaishali Kulkarni 	if (val & EEE_1G_ADV)
1158*14b24e2bSVaishali Kulkarni 		p_link->eee_lp_adv_caps |= ECORE_EEE_1G_ADV;
1159*14b24e2bSVaishali Kulkarni 	if (val & EEE_10G_ADV)
1160*14b24e2bSVaishali Kulkarni 		p_link->eee_lp_adv_caps |= ECORE_EEE_10G_ADV;
1161*14b24e2bSVaishali Kulkarni }
1162*14b24e2bSVaishali Kulkarni 
1163*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
1164*14b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
1165*14b24e2bSVaishali Kulkarni 					 bool b_reset)
1166*14b24e2bSVaishali Kulkarni {
1167*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_state *p_link;
1168*14b24e2bSVaishali Kulkarni 	u8 max_bw, min_bw;
1169*14b24e2bSVaishali Kulkarni 	u32 status = 0;
1170*14b24e2bSVaishali Kulkarni 
1171*14b24e2bSVaishali Kulkarni 	/* Prevent SW/attentions from doing this at the same time */
1172*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_LOCK(&p_hwfn->mcp_info->link_lock);
1173*14b24e2bSVaishali Kulkarni 
1174*14b24e2bSVaishali Kulkarni 	p_link = &p_hwfn->mcp_info->link_output;
1175*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_link, 0, sizeof(*p_link));
1176*14b24e2bSVaishali Kulkarni 	if (!b_reset) {
1177*14b24e2bSVaishali Kulkarni 		status = ecore_rd(p_hwfn, p_ptt,
1178*14b24e2bSVaishali Kulkarni 				  p_hwfn->mcp_info->port_addr +
1179*14b24e2bSVaishali Kulkarni 				  OFFSETOF(struct public_port, link_status));
1180*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_LINK | ECORE_MSG_SP),
1181*14b24e2bSVaishali Kulkarni 			   "Received link update [0x%08x] from mfw [Addr 0x%x]\n",
1182*14b24e2bSVaishali Kulkarni 			   status, (u32)(p_hwfn->mcp_info->port_addr +
1183*14b24e2bSVaishali Kulkarni 			   OFFSETOF(struct public_port, link_status)));
1184*14b24e2bSVaishali Kulkarni 	} else {
1185*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
1186*14b24e2bSVaishali Kulkarni 			   "Resetting link indications\n");
1187*14b24e2bSVaishali Kulkarni 		goto out;
1188*14b24e2bSVaishali Kulkarni 	}
1189*14b24e2bSVaishali Kulkarni 
1190*14b24e2bSVaishali Kulkarni 	if (p_hwfn->b_drv_link_init)
1191*14b24e2bSVaishali Kulkarni 		p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
1192*14b24e2bSVaishali Kulkarni 	else
1193*14b24e2bSVaishali Kulkarni 		p_link->link_up = false;
1194*14b24e2bSVaishali Kulkarni 
1195*14b24e2bSVaishali Kulkarni 	p_link->full_duplex = true;
1196*14b24e2bSVaishali Kulkarni 	switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) {
1197*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_100G:
1198*14b24e2bSVaishali Kulkarni 		p_link->speed = 100000;
1199*14b24e2bSVaishali Kulkarni 		break;
1200*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_50G:
1201*14b24e2bSVaishali Kulkarni 		p_link->speed = 50000;
1202*14b24e2bSVaishali Kulkarni 		break;
1203*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_40G:
1204*14b24e2bSVaishali Kulkarni 		p_link->speed = 40000;
1205*14b24e2bSVaishali Kulkarni 		break;
1206*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_25G:
1207*14b24e2bSVaishali Kulkarni 		p_link->speed = 25000;
1208*14b24e2bSVaishali Kulkarni 		break;
1209*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_20G:
1210*14b24e2bSVaishali Kulkarni 		p_link->speed = 20000;
1211*14b24e2bSVaishali Kulkarni 		break;
1212*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_10G:
1213*14b24e2bSVaishali Kulkarni 		p_link->speed = 10000;
1214*14b24e2bSVaishali Kulkarni 		break;
1215*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_1000THD:
1216*14b24e2bSVaishali Kulkarni 		p_link->full_duplex = false;
1217*14b24e2bSVaishali Kulkarni 		/* Fall-through */
1218*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD:
1219*14b24e2bSVaishali Kulkarni 		p_link->speed = 1000;
1220*14b24e2bSVaishali Kulkarni 		break;
1221*14b24e2bSVaishali Kulkarni 	default:
1222*14b24e2bSVaishali Kulkarni 		p_link->speed = 0;
1223*14b24e2bSVaishali Kulkarni 	}
1224*14b24e2bSVaishali Kulkarni 
1225*14b24e2bSVaishali Kulkarni 	/* We never store total line speed as p_link->speed is
1226*14b24e2bSVaishali Kulkarni 	 * again changes according to bandwidth allocation.
1227*14b24e2bSVaishali Kulkarni 	 */
1228*14b24e2bSVaishali Kulkarni 	if (p_link->link_up && p_link->speed)
1229*14b24e2bSVaishali Kulkarni 		p_link->line_speed = p_link->speed;
1230*14b24e2bSVaishali Kulkarni 	else
1231*14b24e2bSVaishali Kulkarni 		p_link->line_speed = 0;
1232*14b24e2bSVaishali Kulkarni 
1233*14b24e2bSVaishali Kulkarni 	max_bw = p_hwfn->mcp_info->func_info.bandwidth_max;
1234*14b24e2bSVaishali Kulkarni 	min_bw = p_hwfn->mcp_info->func_info.bandwidth_min;
1235*14b24e2bSVaishali Kulkarni 
1236*14b24e2bSVaishali Kulkarni 	/* Max bandwidth configuration */
1237*14b24e2bSVaishali Kulkarni 	__ecore_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw);
1238*14b24e2bSVaishali Kulkarni 
1239*14b24e2bSVaishali Kulkarni 	/* Mintz bandwidth configuration */
1240*14b24e2bSVaishali Kulkarni 	__ecore_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw);
1241*14b24e2bSVaishali Kulkarni 	ecore_configure_vp_wfq_on_link_change(p_hwfn->p_dev, p_ptt,
1242*14b24e2bSVaishali Kulkarni 					      p_link->min_pf_rate);
1243*14b24e2bSVaishali Kulkarni 
1244*14b24e2bSVaishali Kulkarni 	p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
1245*14b24e2bSVaishali Kulkarni 	p_link->an_complete = !!(status &
1246*14b24e2bSVaishali Kulkarni 				 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE);
1247*14b24e2bSVaishali Kulkarni 	p_link->parallel_detection = !!(status &
1248*14b24e2bSVaishali Kulkarni 					LINK_STATUS_PARALLEL_DETECTION_USED);
1249*14b24e2bSVaishali Kulkarni 	p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED);
1250*14b24e2bSVaishali Kulkarni 
1251*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1252*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ?
1253*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_1G_FD : 0;
1254*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1255*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ?
1256*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_1G_HD : 0;
1257*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1258*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ?
1259*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_10G : 0;
1260*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1261*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ?
1262*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_20G : 0;
1263*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1264*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_25G_CAPABLE) ?
1265*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_25G : 0;
1266*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1267*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ?
1268*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_40G : 0;
1269*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1270*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ?
1271*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_50G : 0;
1272*14b24e2bSVaishali Kulkarni 	p_link->partner_adv_speed |=
1273*14b24e2bSVaishali Kulkarni 		(status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ?
1274*14b24e2bSVaishali Kulkarni 		ECORE_LINK_PARTNER_SPEED_100G : 0;
1275*14b24e2bSVaishali Kulkarni 
1276*14b24e2bSVaishali Kulkarni 	p_link->partner_tx_flow_ctrl_en =
1277*14b24e2bSVaishali Kulkarni 		!!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED);
1278*14b24e2bSVaishali Kulkarni 	p_link->partner_rx_flow_ctrl_en =
1279*14b24e2bSVaishali Kulkarni 		!!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
1280*14b24e2bSVaishali Kulkarni 
1281*14b24e2bSVaishali Kulkarni 	switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) {
1282*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE:
1283*14b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_SYMMETRIC_PAUSE;
1284*14b24e2bSVaishali Kulkarni 		break;
1285*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE:
1286*14b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE;
1287*14b24e2bSVaishali Kulkarni 		break;
1288*14b24e2bSVaishali Kulkarni 	case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE:
1289*14b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_BOTH_PAUSE;
1290*14b24e2bSVaishali Kulkarni 		break;
1291*14b24e2bSVaishali Kulkarni 	default:
1292*14b24e2bSVaishali Kulkarni 		p_link->partner_adv_pause = 0;
1293*14b24e2bSVaishali Kulkarni 	}
1294*14b24e2bSVaishali Kulkarni 
1295*14b24e2bSVaishali Kulkarni 	p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
1296*14b24e2bSVaishali Kulkarni 
1297*14b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
1298*14b24e2bSVaishali Kulkarni 		ecore_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
1299*14b24e2bSVaishali Kulkarni 
1300*14b24e2bSVaishali Kulkarni 	OSAL_LINK_UPDATE(p_hwfn);
1301*14b24e2bSVaishali Kulkarni out:
1302*14b24e2bSVaishali Kulkarni 	OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->link_lock);
1303*14b24e2bSVaishali Kulkarni }
1304*14b24e2bSVaishali Kulkarni 
1305*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_link(struct ecore_hwfn *p_hwfn,
1306*14b24e2bSVaishali Kulkarni 					struct ecore_ptt *p_ptt,
1307*14b24e2bSVaishali Kulkarni 					bool b_up)
1308*14b24e2bSVaishali Kulkarni {
1309*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
1310*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
1311*14b24e2bSVaishali Kulkarni 	struct eth_phy_cfg phy_cfg;
1312*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
1313*14b24e2bSVaishali Kulkarni 	u32 cmd;
1314*14b24e2bSVaishali Kulkarni 
1315*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
1316*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
1317*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
1318*14b24e2bSVaishali Kulkarni #endif
1319*14b24e2bSVaishali Kulkarni 
1320*14b24e2bSVaishali Kulkarni 	/* Set the shmem configuration according to params */
1321*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&phy_cfg, sizeof(phy_cfg));
1322*14b24e2bSVaishali Kulkarni 	cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET;
1323*14b24e2bSVaishali Kulkarni 	if (!params->speed.autoneg)
1324*14b24e2bSVaishali Kulkarni 		phy_cfg.speed = params->speed.forced_speed;
1325*14b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.autoneg) ? ETH_PAUSE_AUTONEG : 0;
1326*14b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.forced_rx) ? ETH_PAUSE_RX : 0;
1327*14b24e2bSVaishali Kulkarni 	phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0;
1328*14b24e2bSVaishali Kulkarni 	phy_cfg.adv_speed = params->speed.advertised_speeds;
1329*14b24e2bSVaishali Kulkarni 	phy_cfg.loopback_mode = params->loopback_mode;
1330*14b24e2bSVaishali Kulkarni 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
1331*14b24e2bSVaishali Kulkarni 		if (params->eee.enable)
1332*14b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED;
1333*14b24e2bSVaishali Kulkarni 		if (params->eee.tx_lpi_enable)
1334*14b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_TX_LPI;
1335*14b24e2bSVaishali Kulkarni 		if (params->eee.adv_caps & ECORE_EEE_1G_ADV)
1336*14b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G;
1337*14b24e2bSVaishali Kulkarni 		if (params->eee.adv_caps & ECORE_EEE_10G_ADV)
1338*14b24e2bSVaishali Kulkarni 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G;
1339*14b24e2bSVaishali Kulkarni 		phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer <<
1340*14b24e2bSVaishali Kulkarni 				    EEE_TX_TIMER_USEC_SHIFT) &
1341*14b24e2bSVaishali Kulkarni 					EEE_TX_TIMER_USEC_MASK;
1342*14b24e2bSVaishali Kulkarni 	}
1343*14b24e2bSVaishali Kulkarni 
1344*14b24e2bSVaishali Kulkarni 	p_hwfn->b_drv_link_init = b_up;
1345*14b24e2bSVaishali Kulkarni 
1346*14b24e2bSVaishali Kulkarni 	if (b_up)
1347*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
1348*14b24e2bSVaishali Kulkarni 			   "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x\n",
1349*14b24e2bSVaishali Kulkarni 			   phy_cfg.speed, phy_cfg.pause, phy_cfg.adv_speed,
1350*14b24e2bSVaishali Kulkarni 			   phy_cfg.loopback_mode);
1351*14b24e2bSVaishali Kulkarni 	else
1352*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK, "Resetting link\n");
1353*14b24e2bSVaishali Kulkarni 
1354*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1355*14b24e2bSVaishali Kulkarni 	mb_params.cmd = cmd;
1356*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &phy_cfg;
1357*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(phy_cfg);
1358*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
1359*14b24e2bSVaishali Kulkarni 
1360*14b24e2bSVaishali Kulkarni 	/* if mcp fails to respond we must abort */
1361*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
1362*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
1363*14b24e2bSVaishali Kulkarni 		return rc;
1364*14b24e2bSVaishali Kulkarni 	}
1365*14b24e2bSVaishali Kulkarni 
1366*14b24e2bSVaishali Kulkarni 	/* Mimic link-change attention, done for several reasons:
1367*14b24e2bSVaishali Kulkarni 	 *  - On reset, there's no guarantee MFW would trigger
1368*14b24e2bSVaishali Kulkarni 	 *    an attention.
1369*14b24e2bSVaishali Kulkarni 	 *  - On initialization, older MFWs might not indicate link change
1370*14b24e2bSVaishali Kulkarni 	 *    during LFA, so we'll never get an UP indication.
1371*14b24e2bSVaishali Kulkarni 	 */
1372*14b24e2bSVaishali Kulkarni 	ecore_mcp_handle_link_change(p_hwfn, p_ptt, !b_up);
1373*14b24e2bSVaishali Kulkarni 
1374*14b24e2bSVaishali Kulkarni 	return rc;
1375*14b24e2bSVaishali Kulkarni }
1376*14b24e2bSVaishali Kulkarni 
1377*14b24e2bSVaishali Kulkarni u32 ecore_get_process_kill_counter(struct ecore_hwfn *p_hwfn,
1378*14b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt)
1379*14b24e2bSVaishali Kulkarni {
1380*14b24e2bSVaishali Kulkarni 	u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt;
1381*14b24e2bSVaishali Kulkarni 
1382*14b24e2bSVaishali Kulkarni 	/* TODO - Add support for VFs */
1383*14b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
1384*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
1385*14b24e2bSVaishali Kulkarni 
1386*14b24e2bSVaishali Kulkarni 	path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1387*14b24e2bSVaishali Kulkarni 						 PUBLIC_PATH);
1388*14b24e2bSVaishali Kulkarni 	path_offsize = ecore_rd(p_hwfn, p_ptt, path_offsize_addr);
1389*14b24e2bSVaishali Kulkarni 	path_addr = SECTION_ADDR(path_offsize, ECORE_PATH_ID(p_hwfn));
1390*14b24e2bSVaishali Kulkarni 
1391*14b24e2bSVaishali Kulkarni 	proc_kill_cnt = ecore_rd(p_hwfn, p_ptt,
1392*14b24e2bSVaishali Kulkarni 				 path_addr +
1393*14b24e2bSVaishali Kulkarni 				 OFFSETOF(struct public_path, process_kill)) &
1394*14b24e2bSVaishali Kulkarni 			PROCESS_KILL_COUNTER_MASK;
1395*14b24e2bSVaishali Kulkarni 
1396*14b24e2bSVaishali Kulkarni 	return proc_kill_cnt;
1397*14b24e2bSVaishali Kulkarni }
1398*14b24e2bSVaishali Kulkarni 
1399*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_process_kill(struct ecore_hwfn *p_hwfn,
1400*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt)
1401*14b24e2bSVaishali Kulkarni {
1402*14b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
1403*14b24e2bSVaishali Kulkarni 	u32 proc_kill_cnt;
1404*14b24e2bSVaishali Kulkarni 
1405*14b24e2bSVaishali Kulkarni 	/* Prevent possible attentions/interrupts during the recovery handling
1406*14b24e2bSVaishali Kulkarni 	 * and till its load phase, during which they will be re-enabled.
1407*14b24e2bSVaishali Kulkarni 	 */
1408*14b24e2bSVaishali Kulkarni 	ecore_int_igu_disable_int(p_hwfn, p_ptt);
1409*14b24e2bSVaishali Kulkarni 
1410*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Received a process kill indication\n");
1411*14b24e2bSVaishali Kulkarni 
1412*14b24e2bSVaishali Kulkarni 	/* The following operations should be done once, and thus in CMT mode
1413*14b24e2bSVaishali Kulkarni 	 * are carried out by only the first HW function.
1414*14b24e2bSVaishali Kulkarni 	 */
1415*14b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_dev))
1416*14b24e2bSVaishali Kulkarni 		return;
1417*14b24e2bSVaishali Kulkarni 
1418*14b24e2bSVaishali Kulkarni 	if (p_dev->recov_in_prog) {
1419*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1420*14b24e2bSVaishali Kulkarni 			  "Ignoring the indication since a recovery process is already in progress\n");
1421*14b24e2bSVaishali Kulkarni 		return;
1422*14b24e2bSVaishali Kulkarni 	}
1423*14b24e2bSVaishali Kulkarni 
1424*14b24e2bSVaishali Kulkarni 	p_dev->recov_in_prog = true;
1425*14b24e2bSVaishali Kulkarni 
1426*14b24e2bSVaishali Kulkarni 	proc_kill_cnt = ecore_get_process_kill_counter(p_hwfn, p_ptt);
1427*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Process kill counter: %d\n", proc_kill_cnt);
1428*14b24e2bSVaishali Kulkarni 
1429*14b24e2bSVaishali Kulkarni 	OSAL_SCHEDULE_RECOVERY_HANDLER(p_hwfn);
1430*14b24e2bSVaishali Kulkarni }
1431*14b24e2bSVaishali Kulkarni 
1432*14b24e2bSVaishali Kulkarni static void ecore_mcp_send_protocol_stats(struct ecore_hwfn *p_hwfn,
1433*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
1434*14b24e2bSVaishali Kulkarni 					  enum MFW_DRV_MSG_TYPE type)
1435*14b24e2bSVaishali Kulkarni {
1436*14b24e2bSVaishali Kulkarni 	enum ecore_mcp_protocol_type stats_type;
1437*14b24e2bSVaishali Kulkarni 	union ecore_mcp_protocol_stats stats;
1438*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
1439*14b24e2bSVaishali Kulkarni 	u32 hsi_param;
1440*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1441*14b24e2bSVaishali Kulkarni 
1442*14b24e2bSVaishali Kulkarni 	switch (type) {
1443*14b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_LAN_STATS:
1444*14b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_LAN_STATS;
1445*14b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN;
1446*14b24e2bSVaishali Kulkarni 		break;
1447*14b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_FCOE_STATS:
1448*14b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_FCOE_STATS;
1449*14b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_FCOE;
1450*14b24e2bSVaishali Kulkarni 		break;
1451*14b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_ISCSI_STATS:
1452*14b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_ISCSI_STATS;
1453*14b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_ISCSI;
1454*14b24e2bSVaishali Kulkarni 		break;
1455*14b24e2bSVaishali Kulkarni 	case MFW_DRV_MSG_GET_RDMA_STATS:
1456*14b24e2bSVaishali Kulkarni 		stats_type = ECORE_MCP_RDMA_STATS;
1457*14b24e2bSVaishali Kulkarni 		hsi_param = DRV_MSG_CODE_STATS_TYPE_RDMA;
1458*14b24e2bSVaishali Kulkarni 		break;
1459*14b24e2bSVaishali Kulkarni 	default:
1460*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Invalid protocol type %d\n", type);
1461*14b24e2bSVaishali Kulkarni 		return;
1462*14b24e2bSVaishali Kulkarni 	}
1463*14b24e2bSVaishali Kulkarni 
1464*14b24e2bSVaishali Kulkarni 	OSAL_GET_PROTOCOL_STATS(p_hwfn->p_dev, stats_type, &stats);
1465*14b24e2bSVaishali Kulkarni 
1466*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1467*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_STATS;
1468*14b24e2bSVaishali Kulkarni 	mb_params.param = hsi_param;
1469*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &stats;
1470*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(stats);
1471*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
1472*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
1473*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send protocol stats, rc = %d\n", rc);
1474*14b24e2bSVaishali Kulkarni }
1475*14b24e2bSVaishali Kulkarni 
1476*14b24e2bSVaishali Kulkarni static void ecore_read_pf_bandwidth(struct ecore_hwfn *p_hwfn,
1477*14b24e2bSVaishali Kulkarni 				    struct public_func *p_shmem_info)
1478*14b24e2bSVaishali Kulkarni {
1479*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *p_info;
1480*14b24e2bSVaishali Kulkarni 
1481*14b24e2bSVaishali Kulkarni 	p_info = &p_hwfn->mcp_info->func_info;
1482*14b24e2bSVaishali Kulkarni 
1483*14b24e2bSVaishali Kulkarni 	/* TODO - bandwidth min/max should have valid values of 1-100,
1484*14b24e2bSVaishali Kulkarni 	 * as well as some indication that the feature is disabled.
1485*14b24e2bSVaishali Kulkarni 	 * Until MFW/qlediag enforce those limitations, Assume THERE IS ALWAYS
1486*14b24e2bSVaishali Kulkarni 	 * limit and correct value to min `1' and max `100' if limit isn't in
1487*14b24e2bSVaishali Kulkarni 	 * range.
1488*14b24e2bSVaishali Kulkarni 	 */
1489*14b24e2bSVaishali Kulkarni 	p_info->bandwidth_min = (p_shmem_info->config &
1490*14b24e2bSVaishali Kulkarni 				 FUNC_MF_CFG_MIN_BW_MASK) >>
1491*14b24e2bSVaishali Kulkarni 				FUNC_MF_CFG_MIN_BW_SHIFT;
1492*14b24e2bSVaishali Kulkarni 	if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) {
1493*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1494*14b24e2bSVaishali Kulkarni 			"bandwidth minimum out of bounds [%02x]. Set to 1\n",
1495*14b24e2bSVaishali Kulkarni 			p_info->bandwidth_min);
1496*14b24e2bSVaishali Kulkarni 		p_info->bandwidth_min = 1;
1497*14b24e2bSVaishali Kulkarni 	}
1498*14b24e2bSVaishali Kulkarni 
1499*14b24e2bSVaishali Kulkarni 	p_info->bandwidth_max = (p_shmem_info->config &
1500*14b24e2bSVaishali Kulkarni 				 FUNC_MF_CFG_MAX_BW_MASK) >>
1501*14b24e2bSVaishali Kulkarni 				FUNC_MF_CFG_MAX_BW_SHIFT;
1502*14b24e2bSVaishali Kulkarni 	if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) {
1503*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1504*14b24e2bSVaishali Kulkarni 			"bandwidth maximum out of bounds [%02x]. Set to 100\n",
1505*14b24e2bSVaishali Kulkarni 			p_info->bandwidth_max);
1506*14b24e2bSVaishali Kulkarni 		p_info->bandwidth_max = 100;
1507*14b24e2bSVaishali Kulkarni 	}
1508*14b24e2bSVaishali Kulkarni }
1509*14b24e2bSVaishali Kulkarni 
1510*14b24e2bSVaishali Kulkarni static u32 ecore_mcp_get_shmem_func(struct ecore_hwfn *p_hwfn,
1511*14b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt,
1512*14b24e2bSVaishali Kulkarni 				    struct public_func *p_data,
1513*14b24e2bSVaishali Kulkarni 				    int pfid)
1514*14b24e2bSVaishali Kulkarni {
1515*14b24e2bSVaishali Kulkarni 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1516*14b24e2bSVaishali Kulkarni 					PUBLIC_FUNC);
1517*14b24e2bSVaishali Kulkarni 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
1518*14b24e2bSVaishali Kulkarni 	u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
1519*14b24e2bSVaishali Kulkarni 	u32 i, size;
1520*14b24e2bSVaishali Kulkarni 
1521*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(p_data, sizeof(*p_data));
1522*14b24e2bSVaishali Kulkarni 
1523*14b24e2bSVaishali Kulkarni 	size = OSAL_MIN_T(u32, sizeof(*p_data),
1524*14b24e2bSVaishali Kulkarni 			  SECTION_SIZE(mfw_path_offsize));
1525*14b24e2bSVaishali Kulkarni 	for (i = 0; i < size / sizeof(u32); i++)
1526*14b24e2bSVaishali Kulkarni 		((u32 *)p_data)[i] = ecore_rd(p_hwfn, p_ptt,
1527*14b24e2bSVaishali Kulkarni 					      func_addr + (i << 2));
1528*14b24e2bSVaishali Kulkarni 
1529*14b24e2bSVaishali Kulkarni 	return size;
1530*14b24e2bSVaishali Kulkarni }
1531*14b24e2bSVaishali Kulkarni #if 0
1532*14b24e2bSVaishali Kulkarni /* This was introduced with FW 8.10.5.0; Hopefully this is only temp. */
1533*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_hw_init_first_eth(struct ecore_hwfn *p_hwfn,
1534*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
1535*14b24e2bSVaishali Kulkarni 					     u8 *p_pf)
1536*14b24e2bSVaishali Kulkarni {
1537*14b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
1538*14b24e2bSVaishali Kulkarni 	int i;
1539*14b24e2bSVaishali Kulkarni 
1540*14b24e2bSVaishali Kulkarni 	/* Find first Ethernet interface in port */
1541*14b24e2bSVaishali Kulkarni 	for (i = 0; i < NUM_OF_ENG_PFS(p_hwfn->p_dev);
1542*14b24e2bSVaishali Kulkarni 	     i += p_hwfn->p_dev->num_ports_in_engine) {
1543*14b24e2bSVaishali Kulkarni 		ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
1544*14b24e2bSVaishali Kulkarni 					 MCP_PF_ID_BY_REL(p_hwfn, i));
1545*14b24e2bSVaishali Kulkarni 
1546*14b24e2bSVaishali Kulkarni 		if (shmem_info.config & FUNC_MF_CFG_FUNC_HIDE)
1547*14b24e2bSVaishali Kulkarni 			continue;
1548*14b24e2bSVaishali Kulkarni 
1549*14b24e2bSVaishali Kulkarni 		if ((shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK) ==
1550*14b24e2bSVaishali Kulkarni 		    FUNC_MF_CFG_PROTOCOL_ETHERNET) {
1551*14b24e2bSVaishali Kulkarni 			*p_pf = (u8)i;
1552*14b24e2bSVaishali Kulkarni 			return ECORE_SUCCESS;
1553*14b24e2bSVaishali Kulkarni 		}
1554*14b24e2bSVaishali Kulkarni 	}
1555*14b24e2bSVaishali Kulkarni 
1556*14b24e2bSVaishali Kulkarni 	/* This might actually be valid somewhere in the future but for now
1557*14b24e2bSVaishali Kulkarni 	 * it's highly unlikely.
1558*14b24e2bSVaishali Kulkarni 	 */
1559*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
1560*14b24e2bSVaishali Kulkarni 		  "Failed to find on port an ethernet interface in MF_SI mode\n");
1561*14b24e2bSVaishali Kulkarni 
1562*14b24e2bSVaishali Kulkarni 	return ECORE_INVAL;
1563*14b24e2bSVaishali Kulkarni }
1564*14b24e2bSVaishali Kulkarni #endif
1565*14b24e2bSVaishali Kulkarni static void
1566*14b24e2bSVaishali Kulkarni ecore_mcp_update_bw(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
1567*14b24e2bSVaishali Kulkarni {
1568*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *p_info;
1569*14b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
1570*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
1571*14b24e2bSVaishali Kulkarni 
1572*14b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
1573*14b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
1574*14b24e2bSVaishali Kulkarni 
1575*14b24e2bSVaishali Kulkarni 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
1576*14b24e2bSVaishali Kulkarni 
1577*14b24e2bSVaishali Kulkarni 	p_info = &p_hwfn->mcp_info->func_info;
1578*14b24e2bSVaishali Kulkarni 
1579*14b24e2bSVaishali Kulkarni 	ecore_configure_pf_min_bandwidth(p_hwfn->p_dev, p_info->bandwidth_min);
1580*14b24e2bSVaishali Kulkarni 
1581*14b24e2bSVaishali Kulkarni 	ecore_configure_pf_max_bandwidth(p_hwfn->p_dev, p_info->bandwidth_max);
1582*14b24e2bSVaishali Kulkarni 
1583*14b24e2bSVaishali Kulkarni 	/* Acknowledge the MFW */
1584*14b24e2bSVaishali Kulkarni 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp,
1585*14b24e2bSVaishali Kulkarni 		      &param);
1586*14b24e2bSVaishali Kulkarni }
1587*14b24e2bSVaishali Kulkarni 
1588*14b24e2bSVaishali Kulkarni static void ecore_mcp_update_stag(struct ecore_hwfn *p_hwfn,
1589*14b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt)
1590*14b24e2bSVaishali Kulkarni {
1591*14b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
1592*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
1593*14b24e2bSVaishali Kulkarni 
1594*14b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
1595*14b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
1596*14b24e2bSVaishali Kulkarni 
1597*14b24e2bSVaishali Kulkarni 	p_hwfn->mcp_info->func_info.ovlan = (u16)shmem_info.ovlan_stag &
1598*14b24e2bSVaishali Kulkarni 						 FUNC_MF_CFG_OV_STAG_MASK;
1599*14b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.ovlan = p_hwfn->mcp_info->func_info.ovlan;
1600*14b24e2bSVaishali Kulkarni 	if ((p_hwfn->hw_info.hw_mode & (1 << MODE_MF_SD)) &&
1601*14b24e2bSVaishali Kulkarni 	    (p_hwfn->hw_info.ovlan != ECORE_MCP_VLAN_UNSET)) {
1602*14b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
1603*14b24e2bSVaishali Kulkarni 			 NIG_REG_LLH_FUNC_TAG_VALUE,
1604*14b24e2bSVaishali Kulkarni 			 p_hwfn->hw_info.ovlan);
1605*14b24e2bSVaishali Kulkarni 		ecore_sp_pf_update_stag(p_hwfn);
1606*14b24e2bSVaishali Kulkarni 	}
1607*14b24e2bSVaishali Kulkarni 
1608*14b24e2bSVaishali Kulkarni 	OSAL_HW_INFO_CHANGE(p_hwfn, ECORE_HW_INFO_CHANGE_OVLAN);
1609*14b24e2bSVaishali Kulkarni 
1610*14b24e2bSVaishali Kulkarni 	/* Acknowledge the MFW */
1611*14b24e2bSVaishali Kulkarni 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_S_TAG_UPDATE_ACK, 0,
1612*14b24e2bSVaishali Kulkarni 		      &resp, &param);
1613*14b24e2bSVaishali Kulkarni }
1614*14b24e2bSVaishali Kulkarni 
1615*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_fan_failure(struct ecore_hwfn *p_hwfn,
1616*14b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt)
1617*14b24e2bSVaishali Kulkarni {
1618*14b24e2bSVaishali Kulkarni 	/* A single notification should be sent to upper driver in CMT mode */
1619*14b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
1620*14b24e2bSVaishali Kulkarni 		return;
1621*14b24e2bSVaishali Kulkarni 
1622*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
1623*14b24e2bSVaishali Kulkarni 		  "Fan failure was detected on the network interface card and it's going to be shut down.\n");
1624*14b24e2bSVaishali Kulkarni 
1625*14b24e2bSVaishali Kulkarni 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_FAN_FAIL);
1626*14b24e2bSVaishali Kulkarni }
1627*14b24e2bSVaishali Kulkarni 
1628*14b24e2bSVaishali Kulkarni struct ecore_mdump_cmd_params {
1629*14b24e2bSVaishali Kulkarni 	u32 cmd;
1630*14b24e2bSVaishali Kulkarni 	void *p_data_src;
1631*14b24e2bSVaishali Kulkarni 	u8 data_src_size;
1632*14b24e2bSVaishali Kulkarni 	void *p_data_dst;
1633*14b24e2bSVaishali Kulkarni 	u8 data_dst_size;
1634*14b24e2bSVaishali Kulkarni 	u32 mcp_resp;
1635*14b24e2bSVaishali Kulkarni };
1636*14b24e2bSVaishali Kulkarni 
1637*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
1638*14b24e2bSVaishali Kulkarni ecore_mcp_mdump_cmd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1639*14b24e2bSVaishali Kulkarni 		    struct ecore_mdump_cmd_params *p_mdump_cmd_params)
1640*14b24e2bSVaishali Kulkarni {
1641*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
1642*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1643*14b24e2bSVaishali Kulkarni 
1644*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1645*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_MDUMP_CMD;
1646*14b24e2bSVaishali Kulkarni 	mb_params.param = p_mdump_cmd_params->cmd;
1647*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = p_mdump_cmd_params->p_data_src;
1648*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = p_mdump_cmd_params->data_src_size;
1649*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = p_mdump_cmd_params->p_data_dst;
1650*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = p_mdump_cmd_params->data_dst_size;
1651*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
1652*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
1653*14b24e2bSVaishali Kulkarni 		return rc;
1654*14b24e2bSVaishali Kulkarni 
1655*14b24e2bSVaishali Kulkarni 	p_mdump_cmd_params->mcp_resp = mb_params.mcp_resp;
1656*14b24e2bSVaishali Kulkarni 
1657*14b24e2bSVaishali Kulkarni 	if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_MDUMP_INVALID_CMD) {
1658*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1659*14b24e2bSVaishali Kulkarni 			"The mdump sub command is unsupported by the MFW [mdump_cmd 0x%x]\n",
1660*14b24e2bSVaishali Kulkarni 			p_mdump_cmd_params->cmd);
1661*14b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
1662*14b24e2bSVaishali Kulkarni 	} else if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
1663*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1664*14b24e2bSVaishali Kulkarni 			"The mdump command is not supported by the MFW\n");
1665*14b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
1666*14b24e2bSVaishali Kulkarni 	}
1667*14b24e2bSVaishali Kulkarni 
1668*14b24e2bSVaishali Kulkarni 	return rc;
1669*14b24e2bSVaishali Kulkarni }
1670*14b24e2bSVaishali Kulkarni 
1671*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_mdump_ack(struct ecore_hwfn *p_hwfn,
1672*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
1673*14b24e2bSVaishali Kulkarni {
1674*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1675*14b24e2bSVaishali Kulkarni 
1676*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1677*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_ACK;
1678*14b24e2bSVaishali Kulkarni 
1679*14b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1680*14b24e2bSVaishali Kulkarni }
1681*14b24e2bSVaishali Kulkarni 
1682*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_set_values(struct ecore_hwfn *p_hwfn,
1683*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt,
1684*14b24e2bSVaishali Kulkarni 						u32 epoch)
1685*14b24e2bSVaishali Kulkarni {
1686*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1687*14b24e2bSVaishali Kulkarni 
1688*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1689*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_SET_VALUES;
1690*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_src = &epoch;
1691*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_src_size = sizeof(epoch);
1692*14b24e2bSVaishali Kulkarni 
1693*14b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1694*14b24e2bSVaishali Kulkarni }
1695*14b24e2bSVaishali Kulkarni 
1696*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_trigger(struct ecore_hwfn *p_hwfn,
1697*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt)
1698*14b24e2bSVaishali Kulkarni {
1699*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1700*14b24e2bSVaishali Kulkarni 
1701*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1702*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_TRIGGER;
1703*14b24e2bSVaishali Kulkarni 
1704*14b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1705*14b24e2bSVaishali Kulkarni }
1706*14b24e2bSVaishali Kulkarni 
1707*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
1708*14b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_config(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1709*14b24e2bSVaishali Kulkarni 			   struct mdump_config_stc *p_mdump_config)
1710*14b24e2bSVaishali Kulkarni {
1711*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1712*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1713*14b24e2bSVaishali Kulkarni 
1714*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1715*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_CONFIG;
1716*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_dst = p_mdump_config;
1717*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_dst_size = sizeof(*p_mdump_config);
1718*14b24e2bSVaishali Kulkarni 
1719*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1720*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
1721*14b24e2bSVaishali Kulkarni 		return rc;
1722*14b24e2bSVaishali Kulkarni 
1723*14b24e2bSVaishali Kulkarni 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
1724*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1725*14b24e2bSVaishali Kulkarni 			"Failed to get the mdump configuration and logs info [mcp_resp 0x%x]\n",
1726*14b24e2bSVaishali Kulkarni 			mdump_cmd_params.mcp_resp);
1727*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
1728*14b24e2bSVaishali Kulkarni 	}
1729*14b24e2bSVaishali Kulkarni 
1730*14b24e2bSVaishali Kulkarni 	return rc;
1731*14b24e2bSVaishali Kulkarni }
1732*14b24e2bSVaishali Kulkarni 
1733*14b24e2bSVaishali Kulkarni enum _ecore_status_t
1734*14b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1735*14b24e2bSVaishali Kulkarni 			 struct ecore_mdump_info *p_mdump_info)
1736*14b24e2bSVaishali Kulkarni {
1737*14b24e2bSVaishali Kulkarni 	u32 addr, global_offsize, global_addr;
1738*14b24e2bSVaishali Kulkarni 	struct mdump_config_stc mdump_config;
1739*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1740*14b24e2bSVaishali Kulkarni 
1741*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(p_mdump_info, 0, sizeof(*p_mdump_info));
1742*14b24e2bSVaishali Kulkarni 
1743*14b24e2bSVaishali Kulkarni 	addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1744*14b24e2bSVaishali Kulkarni 				    PUBLIC_GLOBAL);
1745*14b24e2bSVaishali Kulkarni 	global_offsize = ecore_rd(p_hwfn, p_ptt, addr);
1746*14b24e2bSVaishali Kulkarni 	global_addr = SECTION_ADDR(global_offsize, 0);
1747*14b24e2bSVaishali Kulkarni 	p_mdump_info->reason = ecore_rd(p_hwfn, p_ptt,
1748*14b24e2bSVaishali Kulkarni 					global_addr +
1749*14b24e2bSVaishali Kulkarni 					OFFSETOF(struct public_global,
1750*14b24e2bSVaishali Kulkarni 						 mdump_reason));
1751*14b24e2bSVaishali Kulkarni 
1752*14b24e2bSVaishali Kulkarni 	if (p_mdump_info->reason) {
1753*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_mdump_get_config(p_hwfn, p_ptt, &mdump_config);
1754*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
1755*14b24e2bSVaishali Kulkarni 			return rc;
1756*14b24e2bSVaishali Kulkarni 
1757*14b24e2bSVaishali Kulkarni 		p_mdump_info->version = mdump_config.version;
1758*14b24e2bSVaishali Kulkarni 		p_mdump_info->config = mdump_config.config;
1759*14b24e2bSVaishali Kulkarni 		p_mdump_info->epoch = mdump_config.epoc;
1760*14b24e2bSVaishali Kulkarni 		p_mdump_info->num_of_logs = mdump_config.num_of_logs;
1761*14b24e2bSVaishali Kulkarni 		p_mdump_info->valid_logs = mdump_config.valid_logs;
1762*14b24e2bSVaishali Kulkarni 
1763*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
1764*14b24e2bSVaishali 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",
1765*14b24e2bSVaishali Kulkarni 			   p_mdump_info->reason, p_mdump_info->version,
1766*14b24e2bSVaishali Kulkarni 			   p_mdump_info->config, p_mdump_info->epoch,
1767*14b24e2bSVaishali Kulkarni 			   p_mdump_info->num_of_logs, p_mdump_info->valid_logs);
1768*14b24e2bSVaishali Kulkarni 	} else {
1769*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
1770*14b24e2bSVaishali Kulkarni 			   "MFW mdump info: reason %d\n", p_mdump_info->reason);
1771*14b24e2bSVaishali Kulkarni 	}
1772*14b24e2bSVaishali Kulkarni 
1773*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
1774*14b24e2bSVaishali Kulkarni }
1775*14b24e2bSVaishali Kulkarni 
1776*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_clear_logs(struct ecore_hwfn *p_hwfn,
1777*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
1778*14b24e2bSVaishali Kulkarni {
1779*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1780*14b24e2bSVaishali Kulkarni 
1781*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1782*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLEAR_LOGS;
1783*14b24e2bSVaishali Kulkarni 
1784*14b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1785*14b24e2bSVaishali Kulkarni }
1786*14b24e2bSVaishali Kulkarni 
1787*14b24e2bSVaishali Kulkarni enum _ecore_status_t
1788*14b24e2bSVaishali Kulkarni ecore_mcp_mdump_get_retain(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1789*14b24e2bSVaishali Kulkarni 			   struct ecore_mdump_retain_data *p_mdump_retain)
1790*14b24e2bSVaishali Kulkarni {
1791*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1792*14b24e2bSVaishali Kulkarni 	struct mdump_retain_data_stc mfw_mdump_retain;
1793*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1794*14b24e2bSVaishali Kulkarni 
1795*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1796*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_RETAIN;
1797*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.p_data_dst = &mfw_mdump_retain;
1798*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.data_dst_size = sizeof(mfw_mdump_retain);
1799*14b24e2bSVaishali Kulkarni 
1800*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1801*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
1802*14b24e2bSVaishali Kulkarni 		return rc;
1803*14b24e2bSVaishali Kulkarni 
1804*14b24e2bSVaishali Kulkarni 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
1805*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
1806*14b24e2bSVaishali Kulkarni 			"Failed to get the mdump retained data [mcp_resp 0x%x]\n",
1807*14b24e2bSVaishali Kulkarni 			mdump_cmd_params.mcp_resp);
1808*14b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
1809*14b24e2bSVaishali Kulkarni 	}
1810*14b24e2bSVaishali Kulkarni 
1811*14b24e2bSVaishali Kulkarni 	p_mdump_retain->valid = mfw_mdump_retain.valid;
1812*14b24e2bSVaishali Kulkarni 	p_mdump_retain->epoch = mfw_mdump_retain.epoch;
1813*14b24e2bSVaishali Kulkarni 	p_mdump_retain->pf = mfw_mdump_retain.pf;
1814*14b24e2bSVaishali Kulkarni 	p_mdump_retain->status = mfw_mdump_retain.status;
1815*14b24e2bSVaishali Kulkarni 
1816*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
1817*14b24e2bSVaishali Kulkarni }
1818*14b24e2bSVaishali Kulkarni 
1819*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mdump_clr_retain(struct ecore_hwfn *p_hwfn,
1820*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
1821*14b24e2bSVaishali Kulkarni {
1822*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_cmd_params mdump_cmd_params;
1823*14b24e2bSVaishali Kulkarni 
1824*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
1825*14b24e2bSVaishali Kulkarni 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLR_RETAIN;
1826*14b24e2bSVaishali Kulkarni 
1827*14b24e2bSVaishali Kulkarni 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
1828*14b24e2bSVaishali Kulkarni }
1829*14b24e2bSVaishali Kulkarni 
1830*14b24e2bSVaishali Kulkarni static void ecore_mcp_handle_critical_error(struct ecore_hwfn *p_hwfn,
1831*14b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt)
1832*14b24e2bSVaishali Kulkarni {
1833*14b24e2bSVaishali Kulkarni 	struct ecore_mdump_retain_data mdump_retain;
1834*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
1835*14b24e2bSVaishali Kulkarni 
1836*14b24e2bSVaishali Kulkarni 	/* In CMT mode - no need for more than a single acknowledgement to the
1837*14b24e2bSVaishali Kulkarni 	 * MFW, and no more than a single notification to the upper driver.
1838*14b24e2bSVaishali Kulkarni 	 */
1839*14b24e2bSVaishali Kulkarni 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
1840*14b24e2bSVaishali Kulkarni 		return;
1841*14b24e2bSVaishali Kulkarni 
1842*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_mdump_get_retain(p_hwfn, p_ptt, &mdump_retain);
1843*14b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS && mdump_retain.valid) {
1844*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1845*14b24e2bSVaishali Kulkarni 			  "The MFW notified that a critical error occurred in the device [epoch 0x%08x, pf 0x%x, status 0x%08x]\n",
1846*14b24e2bSVaishali Kulkarni 			  mdump_retain.epoch, mdump_retain.pf,
1847*14b24e2bSVaishali Kulkarni 			  mdump_retain.status);
1848*14b24e2bSVaishali Kulkarni 	} else {
1849*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1850*14b24e2bSVaishali Kulkarni 			  "The MFW notified that a critical error occurred in the device\n");
1851*14b24e2bSVaishali Kulkarni 	}
1852*14b24e2bSVaishali Kulkarni 
1853*14b24e2bSVaishali Kulkarni 	if (p_hwfn->p_dev->allow_mdump) {
1854*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1855*14b24e2bSVaishali Kulkarni 			  "Not acknowledging the notification to allow the MFW crash dump\n");
1856*14b24e2bSVaishali Kulkarni 		return;
1857*14b24e2bSVaishali Kulkarni 	}
1858*14b24e2bSVaishali Kulkarni 
1859*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false,
1860*14b24e2bSVaishali Kulkarni 		  "Acknowledging the notification to not allow the MFW crash dump [driver debug data collection is preferable]\n");
1861*14b24e2bSVaishali Kulkarni 	ecore_mcp_mdump_ack(p_hwfn, p_ptt);
1862*14b24e2bSVaishali Kulkarni 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_HW_ATTN);
1863*14b24e2bSVaishali Kulkarni }
1864*14b24e2bSVaishali Kulkarni 
1865*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_handle_events(struct ecore_hwfn *p_hwfn,
1866*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt)
1867*14b24e2bSVaishali Kulkarni {
1868*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_info *info = p_hwfn->mcp_info;
1869*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
1870*14b24e2bSVaishali Kulkarni 	bool found = false;
1871*14b24e2bSVaishali Kulkarni 	u16 i;
1872*14b24e2bSVaishali Kulkarni 
1873*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Received message from MFW\n");
1874*14b24e2bSVaishali Kulkarni 
1875*14b24e2bSVaishali Kulkarni 	/* Read Messages from MFW */
1876*14b24e2bSVaishali Kulkarni 	ecore_mcp_read_mb(p_hwfn, p_ptt);
1877*14b24e2bSVaishali Kulkarni 
1878*14b24e2bSVaishali Kulkarni 	/* Compare current messages to old ones */
1879*14b24e2bSVaishali Kulkarni 	for (i = 0; i < info->mfw_mb_length; i++) {
1880*14b24e2bSVaishali Kulkarni 		if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i])
1881*14b24e2bSVaishali Kulkarni 			continue;
1882*14b24e2bSVaishali Kulkarni 
1883*14b24e2bSVaishali Kulkarni 		found = true;
1884*14b24e2bSVaishali Kulkarni 
1885*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
1886*14b24e2bSVaishali Kulkarni 			   "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n",
1887*14b24e2bSVaishali Kulkarni 			   i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]);
1888*14b24e2bSVaishali Kulkarni 
1889*14b24e2bSVaishali Kulkarni 		switch (i) {
1890*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_LINK_CHANGE:
1891*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_link_change(p_hwfn, p_ptt, false);
1892*14b24e2bSVaishali Kulkarni 			break;
1893*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_VF_DISABLED:
1894*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_vf_flr(p_hwfn, p_ptt);
1895*14b24e2bSVaishali Kulkarni 			break;
1896*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_LLDP_DATA_UPDATED:
1897*14b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
1898*14b24e2bSVaishali Kulkarni 						    ECORE_DCBX_REMOTE_LLDP_MIB);
1899*14b24e2bSVaishali Kulkarni 			break;
1900*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED:
1901*14b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
1902*14b24e2bSVaishali Kulkarni 						    ECORE_DCBX_REMOTE_MIB);
1903*14b24e2bSVaishali Kulkarni 			break;
1904*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED:
1905*14b24e2bSVaishali Kulkarni 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
1906*14b24e2bSVaishali Kulkarni 						    ECORE_DCBX_OPERATIONAL_MIB);
1907*14b24e2bSVaishali Kulkarni 			break;
1908*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
1909*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_transceiver_change(p_hwfn, p_ptt);
1910*14b24e2bSVaishali Kulkarni 			break;
1911*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_ERROR_RECOVERY:
1912*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_process_kill(p_hwfn, p_ptt);
1913*14b24e2bSVaishali Kulkarni 			break;
1914*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_LAN_STATS:
1915*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_FCOE_STATS:
1916*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_ISCSI_STATS:
1917*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_RDMA_STATS:
1918*14b24e2bSVaishali Kulkarni 			ecore_mcp_send_protocol_stats(p_hwfn, p_ptt, i);
1919*14b24e2bSVaishali Kulkarni 			break;
1920*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_BW_UPDATE:
1921*14b24e2bSVaishali Kulkarni 			ecore_mcp_update_bw(p_hwfn, p_ptt);
1922*14b24e2bSVaishali Kulkarni 			break;
1923*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_S_TAG_UPDATE:
1924*14b24e2bSVaishali Kulkarni 			ecore_mcp_update_stag(p_hwfn, p_ptt);
1925*14b24e2bSVaishali Kulkarni 			break;
1926*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_FAILURE_DETECTED:
1927*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_fan_failure(p_hwfn, p_ptt);
1928*14b24e2bSVaishali Kulkarni 			break;
1929*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_CRITICAL_ERROR_OCCURRED:
1930*14b24e2bSVaishali Kulkarni 			ecore_mcp_handle_critical_error(p_hwfn, p_ptt);
1931*14b24e2bSVaishali Kulkarni 			break;
1932*14b24e2bSVaishali Kulkarni 		case MFW_DRV_MSG_GET_TLV_REQ:
1933*14b24e2bSVaishali Kulkarni 			OSAL_MFW_TLV_REQ(p_hwfn);
1934*14b24e2bSVaishali Kulkarni 			break;
1935*14b24e2bSVaishali Kulkarni 		default:
1936*14b24e2bSVaishali Kulkarni 			DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i);
1937*14b24e2bSVaishali Kulkarni 			rc = ECORE_INVAL;
1938*14b24e2bSVaishali Kulkarni 		}
1939*14b24e2bSVaishali Kulkarni 	}
1940*14b24e2bSVaishali Kulkarni 
1941*14b24e2bSVaishali Kulkarni 	/* ACK everything */
1942*14b24e2bSVaishali Kulkarni 	for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) {
1943*14b24e2bSVaishali Kulkarni 		OSAL_BE32 val = OSAL_CPU_TO_BE32(((u32 *)info->mfw_mb_cur)[i]);
1944*14b24e2bSVaishali Kulkarni 
1945*14b24e2bSVaishali Kulkarni 		/* MFW expect answer in BE, so we force write in that format */
1946*14b24e2bSVaishali Kulkarni 		ecore_wr(p_hwfn, p_ptt,
1947*14b24e2bSVaishali Kulkarni 			 info->mfw_mb_addr + sizeof(u32) +
1948*14b24e2bSVaishali Kulkarni 			 MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) *
1949*14b24e2bSVaishali Kulkarni 			 sizeof(u32) + i * sizeof(u32), val);
1950*14b24e2bSVaishali Kulkarni 	}
1951*14b24e2bSVaishali Kulkarni 
1952*14b24e2bSVaishali Kulkarni 	if (!found) {
1953*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
1954*14b24e2bSVaishali Kulkarni 			  "Received an MFW message indication but no new message!\n");
1955*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
1956*14b24e2bSVaishali Kulkarni 	}
1957*14b24e2bSVaishali Kulkarni 
1958*14b24e2bSVaishali Kulkarni 	/* Copy the new mfw messages into the shadow */
1959*14b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length);
1960*14b24e2bSVaishali Kulkarni 
1961*14b24e2bSVaishali Kulkarni 	return rc;
1962*14b24e2bSVaishali Kulkarni }
1963*14b24e2bSVaishali Kulkarni 
1964*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mfw_ver(struct ecore_hwfn *p_hwfn,
1965*14b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
1966*14b24e2bSVaishali Kulkarni 					   u32 *p_mfw_ver,
1967*14b24e2bSVaishali Kulkarni 					   u32 *p_running_bundle_id)
1968*14b24e2bSVaishali Kulkarni {
1969*14b24e2bSVaishali Kulkarni 	u32 global_offsize;
1970*14b24e2bSVaishali Kulkarni 
1971*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
1972*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
1973*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MFW version\n");
1974*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
1975*14b24e2bSVaishali Kulkarni 	}
1976*14b24e2bSVaishali Kulkarni #endif
1977*14b24e2bSVaishali Kulkarni 
1978*14b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev)) {
1979*14b24e2bSVaishali Kulkarni 		if (p_hwfn->vf_iov_info) {
1980*14b24e2bSVaishali Kulkarni 			struct pfvf_acquire_resp_tlv *p_resp;
1981*14b24e2bSVaishali Kulkarni 
1982*14b24e2bSVaishali Kulkarni 			p_resp = &p_hwfn->vf_iov_info->acquire_resp;
1983*14b24e2bSVaishali Kulkarni 			*p_mfw_ver = p_resp->pfdev_info.mfw_ver;
1984*14b24e2bSVaishali Kulkarni 			return ECORE_SUCCESS;
1985*14b24e2bSVaishali Kulkarni 		} else {
1986*14b24e2bSVaishali Kulkarni 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1987*14b24e2bSVaishali Kulkarni 				   "VF requested MFW version prior to ACQUIRE\n");
1988*14b24e2bSVaishali Kulkarni 			return ECORE_INVAL;
1989*14b24e2bSVaishali Kulkarni 		}
1990*14b24e2bSVaishali Kulkarni 	}
1991*14b24e2bSVaishali Kulkarni 
1992*14b24e2bSVaishali Kulkarni 	global_offsize = ecore_rd(p_hwfn, p_ptt,
1993*14b24e2bSVaishali Kulkarni 			  SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1994*14b24e2bSVaishali Kulkarni 					       PUBLIC_GLOBAL));
1995*14b24e2bSVaishali Kulkarni 	*p_mfw_ver = ecore_rd(p_hwfn, p_ptt,
1996*14b24e2bSVaishali Kulkarni 			SECTION_ADDR(global_offsize, 0) +
1997*14b24e2bSVaishali Kulkarni 			OFFSETOF(struct public_global, mfw_ver));
1998*14b24e2bSVaishali Kulkarni 
1999*14b24e2bSVaishali Kulkarni 	if (p_running_bundle_id != OSAL_NULL) {
2000*14b24e2bSVaishali Kulkarni 		*p_running_bundle_id = ecore_rd(p_hwfn, p_ptt,
2001*14b24e2bSVaishali Kulkarni 				SECTION_ADDR(global_offsize, 0) +
2002*14b24e2bSVaishali Kulkarni 				OFFSETOF(struct public_global,
2003*14b24e2bSVaishali Kulkarni 					 running_bundle_id));
2004*14b24e2bSVaishali Kulkarni 	}
2005*14b24e2bSVaishali Kulkarni 
2006*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2007*14b24e2bSVaishali Kulkarni }
2008*14b24e2bSVaishali Kulkarni 
2009*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mbi_ver(struct ecore_hwfn *p_hwfn,
2010*14b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
2011*14b24e2bSVaishali Kulkarni 					   u32 *p_mbi_ver)
2012*14b24e2bSVaishali Kulkarni {
2013*14b24e2bSVaishali Kulkarni 	u32 nvm_cfg_addr, nvm_cfg1_offset, mbi_ver_addr;
2014*14b24e2bSVaishali Kulkarni 
2015*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
2016*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
2017*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MBI version\n");
2018*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
2019*14b24e2bSVaishali Kulkarni 	}
2020*14b24e2bSVaishali Kulkarni #endif
2021*14b24e2bSVaishali Kulkarni 
2022*14b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
2023*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2024*14b24e2bSVaishali Kulkarni 
2025*14b24e2bSVaishali Kulkarni 	/* Read the address of the nvm_cfg */
2026*14b24e2bSVaishali Kulkarni 	nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
2027*14b24e2bSVaishali Kulkarni 	if (!nvm_cfg_addr) {
2028*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Shared memory not initialized\n");
2029*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2030*14b24e2bSVaishali Kulkarni 	}
2031*14b24e2bSVaishali Kulkarni 
2032*14b24e2bSVaishali Kulkarni 	/* Read the offset of nvm_cfg1 */
2033*14b24e2bSVaishali Kulkarni 	nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
2034*14b24e2bSVaishali Kulkarni 
2035*14b24e2bSVaishali Kulkarni 	mbi_ver_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
2036*14b24e2bSVaishali Kulkarni 		       OFFSETOF(struct nvm_cfg1, glob) +
2037*14b24e2bSVaishali Kulkarni 		       OFFSETOF(struct nvm_cfg1_glob, mbi_version);
2038*14b24e2bSVaishali Kulkarni 	*p_mbi_ver = ecore_rd(p_hwfn, p_ptt, mbi_ver_addr) &
2039*14b24e2bSVaishali Kulkarni 		     (NVM_CFG1_GLOB_MBI_VERSION_0_MASK |
2040*14b24e2bSVaishali Kulkarni 		      NVM_CFG1_GLOB_MBI_VERSION_1_MASK |
2041*14b24e2bSVaishali Kulkarni 		      NVM_CFG1_GLOB_MBI_VERSION_2_MASK);
2042*14b24e2bSVaishali Kulkarni 
2043*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2044*14b24e2bSVaishali Kulkarni }
2045*14b24e2bSVaishali Kulkarni 
2046*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_media_type(struct ecore_dev *p_dev,
2047*14b24e2bSVaishali Kulkarni 					   u32 *p_media_type)
2048*14b24e2bSVaishali Kulkarni {
2049*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = &p_dev->hwfns[0];
2050*14b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
2051*14b24e2bSVaishali Kulkarni 
2052*14b24e2bSVaishali Kulkarni 	/* TODO - Add support for VFs */
2053*14b24e2bSVaishali Kulkarni 	if (IS_VF(p_dev))
2054*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2055*14b24e2bSVaishali Kulkarni 
2056*14b24e2bSVaishali Kulkarni 	if (!ecore_mcp_is_init(p_hwfn)) {
2057*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW is not initialized!\n");
2058*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2059*14b24e2bSVaishali Kulkarni 	}
2060*14b24e2bSVaishali Kulkarni 
2061*14b24e2bSVaishali Kulkarni 	*p_media_type = MEDIA_UNSPECIFIED;
2062*14b24e2bSVaishali Kulkarni 
2063*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2064*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2065*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2066*14b24e2bSVaishali Kulkarni 
2067*14b24e2bSVaishali Kulkarni 	*p_media_type = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2068*14b24e2bSVaishali Kulkarni 				 OFFSETOF(struct public_port, media_type));
2069*14b24e2bSVaishali Kulkarni 
2070*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
2071*14b24e2bSVaishali Kulkarni 
2072*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2073*14b24e2bSVaishali Kulkarni }
2074*14b24e2bSVaishali Kulkarni 
2075*14b24e2bSVaishali Kulkarni /* Old MFW has a global configuration for all PFs regarding RDMA support */
2076*14b24e2bSVaishali Kulkarni static void
2077*14b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto_legacy(struct ecore_hwfn *p_hwfn,
2078*14b24e2bSVaishali Kulkarni 				 enum ecore_pci_personality *p_proto)
2079*14b24e2bSVaishali Kulkarni {
2080*14b24e2bSVaishali Kulkarni 	/* There wasn't ever a legacy MFW that published iwarp.
2081*14b24e2bSVaishali Kulkarni 	 * So at this point, this is either plain l2 or RoCE.
2082*14b24e2bSVaishali Kulkarni 	 */
2083*14b24e2bSVaishali Kulkarni 	if (OSAL_TEST_BIT(ECORE_DEV_CAP_ROCE,
2084*14b24e2bSVaishali Kulkarni 			  &p_hwfn->hw_info.device_capabilities))
2085*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_ROCE;
2086*14b24e2bSVaishali Kulkarni 	else
2087*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH;
2088*14b24e2bSVaishali Kulkarni 
2089*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
2090*14b24e2bSVaishali Kulkarni 		   "According to Legacy capabilities, L2 personality is %08x\n",
2091*14b24e2bSVaishali Kulkarni 		   (u32) *p_proto);
2092*14b24e2bSVaishali Kulkarni }
2093*14b24e2bSVaishali Kulkarni 
2094*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
2095*14b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto_mfw(struct ecore_hwfn *p_hwfn,
2096*14b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt,
2097*14b24e2bSVaishali Kulkarni 			      enum ecore_pci_personality *p_proto)
2098*14b24e2bSVaishali Kulkarni {
2099*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2100*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2101*14b24e2bSVaishali Kulkarni 
2102*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
2103*14b24e2bSVaishali Kulkarni 			 DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, &param);
2104*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2105*14b24e2bSVaishali Kulkarni 		return rc;
2106*14b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_OK) {
2107*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
2108*14b24e2bSVaishali Kulkarni 			   "MFW lacks support for command; Returns %08x\n",
2109*14b24e2bSVaishali Kulkarni 			   resp);
2110*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2111*14b24e2bSVaishali Kulkarni 	}
2112*14b24e2bSVaishali Kulkarni 
2113*14b24e2bSVaishali Kulkarni 	switch (param) {
2114*14b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_NONE:
2115*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH;
2116*14b24e2bSVaishali Kulkarni 		break;
2117*14b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_ROCE:
2118*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_ROCE;
2119*14b24e2bSVaishali Kulkarni 		break;
2120*14b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_IWARP:
2121*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_IWARP;
2122*14b24e2bSVaishali Kulkarni 		break;
2123*14b24e2bSVaishali Kulkarni 	case FW_MB_PARAM_GET_PF_RDMA_BOTH:
2124*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ETH_RDMA;
2125*14b24e2bSVaishali Kulkarni 		break;
2126*14b24e2bSVaishali Kulkarni 	default:
2127*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
2128*14b24e2bSVaishali Kulkarni 			  "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n",
2129*14b24e2bSVaishali Kulkarni 			  param);
2130*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2131*14b24e2bSVaishali Kulkarni 	}
2132*14b24e2bSVaishali Kulkarni 
2133*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
2134*14b24e2bSVaishali Kulkarni 		   "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n",
2135*14b24e2bSVaishali Kulkarni 		   (u32) *p_proto, resp, param);
2136*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2137*14b24e2bSVaishali Kulkarni }
2138*14b24e2bSVaishali Kulkarni 
2139*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
2140*14b24e2bSVaishali Kulkarni ecore_mcp_get_shmem_proto(struct ecore_hwfn *p_hwfn,
2141*14b24e2bSVaishali Kulkarni 			  struct public_func *p_info,
2142*14b24e2bSVaishali Kulkarni 			  struct ecore_ptt *p_ptt,
2143*14b24e2bSVaishali Kulkarni 			  enum ecore_pci_personality *p_proto)
2144*14b24e2bSVaishali Kulkarni {
2145*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
2146*14b24e2bSVaishali Kulkarni 
2147*14b24e2bSVaishali Kulkarni 	switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
2148*14b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ETHERNET:
2149*14b24e2bSVaishali Kulkarni 		if (ecore_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto) !=
2150*14b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS)
2151*14b24e2bSVaishali Kulkarni 			ecore_mcp_get_shmem_proto_legacy(p_hwfn, p_proto);
2152*14b24e2bSVaishali Kulkarni 		break;
2153*14b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ISCSI:
2154*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_ISCSI;
2155*14b24e2bSVaishali Kulkarni 		break;
2156*14b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_FCOE:
2157*14b24e2bSVaishali Kulkarni 		*p_proto = ECORE_PCI_FCOE;
2158*14b24e2bSVaishali Kulkarni 		break;
2159*14b24e2bSVaishali Kulkarni 	case FUNC_MF_CFG_PROTOCOL_ROCE:
2160*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "RoCE personality is not a valid value!\n");
2161*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
2162*14b24e2bSVaishali Kulkarni 		break;
2163*14b24e2bSVaishali Kulkarni 	default:
2164*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
2165*14b24e2bSVaishali Kulkarni 	}
2166*14b24e2bSVaishali Kulkarni 
2167*14b24e2bSVaishali Kulkarni 	return rc;
2168*14b24e2bSVaishali Kulkarni }
2169*14b24e2bSVaishali Kulkarni 
2170*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_fill_shmem_func_info(struct ecore_hwfn *p_hwfn,
2171*14b24e2bSVaishali Kulkarni 						    struct ecore_ptt *p_ptt)
2172*14b24e2bSVaishali Kulkarni {
2173*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_function_info *info;
2174*14b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
2175*14b24e2bSVaishali Kulkarni 
2176*14b24e2bSVaishali Kulkarni 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
2177*14b24e2bSVaishali Kulkarni 				 MCP_PF_ID(p_hwfn));
2178*14b24e2bSVaishali Kulkarni 	info = &p_hwfn->mcp_info->func_info;
2179*14b24e2bSVaishali Kulkarni 
2180*14b24e2bSVaishali Kulkarni 	info->pause_on_host = (shmem_info.config &
2181*14b24e2bSVaishali Kulkarni 			       FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0;
2182*14b24e2bSVaishali Kulkarni 
2183*14b24e2bSVaishali Kulkarni 	if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
2184*14b24e2bSVaishali Kulkarni 				      &info->protocol)) {
2185*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unknown personality %08x\n",
2186*14b24e2bSVaishali Kulkarni 		       (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
2187*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2188*14b24e2bSVaishali Kulkarni 	}
2189*14b24e2bSVaishali Kulkarni 
2190*14b24e2bSVaishali Kulkarni 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
2191*14b24e2bSVaishali Kulkarni 
2192*14b24e2bSVaishali Kulkarni 	if (shmem_info.mac_upper || shmem_info.mac_lower) {
2193*14b24e2bSVaishali Kulkarni 		info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
2194*14b24e2bSVaishali Kulkarni 		info->mac[1] = (u8)(shmem_info.mac_upper);
2195*14b24e2bSVaishali Kulkarni 		info->mac[2] = (u8)(shmem_info.mac_lower >> 24);
2196*14b24e2bSVaishali Kulkarni 		info->mac[3] = (u8)(shmem_info.mac_lower >> 16);
2197*14b24e2bSVaishali Kulkarni 		info->mac[4] = (u8)(shmem_info.mac_lower >> 8);
2198*14b24e2bSVaishali Kulkarni 		info->mac[5] = (u8)(shmem_info.mac_lower);
2199*14b24e2bSVaishali Kulkarni 
2200*14b24e2bSVaishali Kulkarni 		/* Store primary MAC for later possible WoL */
2201*14b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(&p_hwfn->p_dev->wol_mac, info->mac, ETH_ALEN);
2202*14b24e2bSVaishali Kulkarni 
2203*14b24e2bSVaishali Kulkarni 	} else {
2204*14b24e2bSVaishali Kulkarni 		/* TODO - are there protocols for which there's no MAC? */
2205*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "MAC is 0 in shmem\n");
2206*14b24e2bSVaishali Kulkarni 	}
2207*14b24e2bSVaishali Kulkarni 
2208*14b24e2bSVaishali Kulkarni 	/* TODO - are these calculations true for BE machine? */
2209*14b24e2bSVaishali Kulkarni 	info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower |
2210*14b24e2bSVaishali Kulkarni 			 (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32);
2211*14b24e2bSVaishali Kulkarni 	info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower |
2212*14b24e2bSVaishali Kulkarni 			 (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32);
2213*14b24e2bSVaishali Kulkarni 
2214*14b24e2bSVaishali Kulkarni 	info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
2215*14b24e2bSVaishali Kulkarni 
2216*14b24e2bSVaishali Kulkarni 	info->mtu = (u16)shmem_info.mtu_size;
2217*14b24e2bSVaishali Kulkarni 
2218*14b24e2bSVaishali Kulkarni 	p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_NONE;
2219*14b24e2bSVaishali Kulkarni 	if (ecore_mcp_is_init(p_hwfn)) {
2220*14b24e2bSVaishali Kulkarni 		u32 resp = 0, param = 0;
2221*14b24e2bSVaishali Kulkarni 		enum _ecore_status_t rc;
2222*14b24e2bSVaishali Kulkarni 
2223*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_cmd(p_hwfn, p_ptt,
2224*14b24e2bSVaishali Kulkarni 				   DRV_MSG_CODE_OS_WOL, 0, &resp, &param);
2225*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
2226*14b24e2bSVaishali Kulkarni 			return rc;
2227*14b24e2bSVaishali Kulkarni 		if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED)
2228*14b24e2bSVaishali Kulkarni 			p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_PME;
2229*14b24e2bSVaishali Kulkarni 	}
2230*14b24e2bSVaishali Kulkarni 	p_hwfn->p_dev->wol_config = (u8)ECORE_OV_WOL_DEFAULT;
2231*14b24e2bSVaishali Kulkarni 
2232*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFUP),
2233*14b24e2bSVaishali 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",
2234*14b24e2bSVaishali Kulkarni 		   info->pause_on_host, info->protocol,
2235*14b24e2bSVaishali Kulkarni 		   info->bandwidth_min, info->bandwidth_max,
2236*14b24e2bSVaishali Kulkarni 		   info->mac[0], info->mac[1], info->mac[2],
2237*14b24e2bSVaishali Kulkarni 		   info->mac[3], info->mac[4], info->mac[5],
2238*14b24e2bSVaishali Kulkarni 		   info->wwn_port, info->wwn_node, info->ovlan,
2239*14b24e2bSVaishali Kulkarni 		   (u8)p_hwfn->hw_info.b_wol_support);
2240*14b24e2bSVaishali Kulkarni 
2241*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2242*14b24e2bSVaishali Kulkarni }
2243*14b24e2bSVaishali Kulkarni 
2244*14b24e2bSVaishali Kulkarni struct ecore_mcp_link_params
2245*14b24e2bSVaishali Kulkarni *ecore_mcp_get_link_params(struct ecore_hwfn *p_hwfn)
2246*14b24e2bSVaishali Kulkarni {
2247*14b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
2248*14b24e2bSVaishali Kulkarni 		return OSAL_NULL;
2249*14b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_input;
2250*14b24e2bSVaishali Kulkarni }
2251*14b24e2bSVaishali Kulkarni 
2252*14b24e2bSVaishali Kulkarni struct ecore_mcp_link_state
2253*14b24e2bSVaishali Kulkarni *ecore_mcp_get_link_state(struct ecore_hwfn *p_hwfn)
2254*14b24e2bSVaishali Kulkarni {
2255*14b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
2256*14b24e2bSVaishali Kulkarni 		return OSAL_NULL;
2257*14b24e2bSVaishali Kulkarni 
2258*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
2259*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
2260*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn, "Non-ASIC - always notify that link is up\n");
2261*14b24e2bSVaishali Kulkarni 		p_hwfn->mcp_info->link_output.link_up = true;
2262*14b24e2bSVaishali Kulkarni 	}
2263*14b24e2bSVaishali Kulkarni #endif
2264*14b24e2bSVaishali Kulkarni 
2265*14b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_output;
2266*14b24e2bSVaishali Kulkarni }
2267*14b24e2bSVaishali Kulkarni 
2268*14b24e2bSVaishali Kulkarni struct ecore_mcp_link_capabilities
2269*14b24e2bSVaishali Kulkarni *ecore_mcp_get_link_capabilities(struct ecore_hwfn *p_hwfn)
2270*14b24e2bSVaishali Kulkarni {
2271*14b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
2272*14b24e2bSVaishali Kulkarni 		return OSAL_NULL;
2273*14b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->link_capabilities;
2274*14b24e2bSVaishali Kulkarni }
2275*14b24e2bSVaishali Kulkarni 
2276*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_drain(struct ecore_hwfn *p_hwfn,
2277*14b24e2bSVaishali Kulkarni 				     struct ecore_ptt *p_ptt)
2278*14b24e2bSVaishali Kulkarni {
2279*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2280*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2281*14b24e2bSVaishali Kulkarni 
2282*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
2283*14b24e2bSVaishali Kulkarni 			   DRV_MSG_CODE_NIG_DRAIN, 1000,
2284*14b24e2bSVaishali Kulkarni 			   &resp, &param);
2285*14b24e2bSVaishali Kulkarni 
2286*14b24e2bSVaishali Kulkarni 	/* Wait for the drain to complete before returning */
2287*14b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(1020);
2288*14b24e2bSVaishali Kulkarni 
2289*14b24e2bSVaishali Kulkarni 	return rc;
2290*14b24e2bSVaishali Kulkarni }
2291*14b24e2bSVaishali Kulkarni 
2292*14b24e2bSVaishali Kulkarni #ifndef LINUX_REMOVE
2293*14b24e2bSVaishali Kulkarni const struct ecore_mcp_function_info
2294*14b24e2bSVaishali Kulkarni *ecore_mcp_get_function_info(struct ecore_hwfn *p_hwfn)
2295*14b24e2bSVaishali Kulkarni {
2296*14b24e2bSVaishali Kulkarni 	if (!p_hwfn || !p_hwfn->mcp_info)
2297*14b24e2bSVaishali Kulkarni 		return OSAL_NULL;
2298*14b24e2bSVaishali Kulkarni 	return &p_hwfn->mcp_info->func_info;
2299*14b24e2bSVaishali Kulkarni }
2300*14b24e2bSVaishali Kulkarni #endif
2301*14b24e2bSVaishali Kulkarni 
2302*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_command(struct ecore_hwfn *p_hwfn,
2303*14b24e2bSVaishali Kulkarni 					   struct ecore_ptt *p_ptt,
2304*14b24e2bSVaishali Kulkarni 					   struct ecore_mcp_nvm_params *params)
2305*14b24e2bSVaishali Kulkarni {
2306*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2307*14b24e2bSVaishali Kulkarni 
2308*14b24e2bSVaishali Kulkarni 	switch (params->type) {
2309*14b24e2bSVaishali Kulkarni 	case ECORE_MCP_NVM_RD:
2310*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
2311*14b24e2bSVaishali Kulkarni 					  params->nvm_common.offset,
2312*14b24e2bSVaishali Kulkarni 					  &params->nvm_common.resp,
2313*14b24e2bSVaishali Kulkarni 					  &params->nvm_common.param,
2314*14b24e2bSVaishali Kulkarni 					  params->nvm_rd.buf_size,
2315*14b24e2bSVaishali Kulkarni 					  params->nvm_rd.buf);
2316*14b24e2bSVaishali Kulkarni 		break;
2317*14b24e2bSVaishali Kulkarni 	case ECORE_MCP_CMD:
2318*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
2319*14b24e2bSVaishali Kulkarni 				   params->nvm_common.offset,
2320*14b24e2bSVaishali Kulkarni 				   &params->nvm_common.resp,
2321*14b24e2bSVaishali Kulkarni 				   &params->nvm_common.param);
2322*14b24e2bSVaishali Kulkarni 		break;
2323*14b24e2bSVaishali Kulkarni 	case ECORE_MCP_NVM_WR:
2324*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt, params->nvm_common.cmd,
2325*14b24e2bSVaishali Kulkarni 					  params->nvm_common.offset,
2326*14b24e2bSVaishali Kulkarni 					  &params->nvm_common.resp,
2327*14b24e2bSVaishali Kulkarni 					  &params->nvm_common.param,
2328*14b24e2bSVaishali Kulkarni 					  params->nvm_wr.buf_size,
2329*14b24e2bSVaishali Kulkarni 					  params->nvm_wr.buf);
2330*14b24e2bSVaishali Kulkarni 		break;
2331*14b24e2bSVaishali Kulkarni 	default:
2332*14b24e2bSVaishali Kulkarni 		rc = ECORE_NOTIMPL;
2333*14b24e2bSVaishali Kulkarni 		break;
2334*14b24e2bSVaishali Kulkarni 	}
2335*14b24e2bSVaishali Kulkarni 	return rc;
2336*14b24e2bSVaishali Kulkarni }
2337*14b24e2bSVaishali Kulkarni 
2338*14b24e2bSVaishali Kulkarni #ifndef LINUX_REMOVE
2339*14b24e2bSVaishali Kulkarni int ecore_mcp_get_personality_cnt(struct ecore_hwfn *p_hwfn,
2340*14b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt,
2341*14b24e2bSVaishali Kulkarni 				  u32 personalities)
2342*14b24e2bSVaishali Kulkarni {
2343*14b24e2bSVaishali Kulkarni 	enum ecore_pci_personality protocol = ECORE_PCI_DEFAULT;
2344*14b24e2bSVaishali Kulkarni 	struct public_func shmem_info;
2345*14b24e2bSVaishali Kulkarni 	int i, count = 0, num_pfs;
2346*14b24e2bSVaishali Kulkarni 
2347*14b24e2bSVaishali Kulkarni 	num_pfs = NUM_OF_ENG_PFS(p_hwfn->p_dev);
2348*14b24e2bSVaishali Kulkarni 
2349*14b24e2bSVaishali Kulkarni 	for (i = 0; i < num_pfs; i++) {
2350*14b24e2bSVaishali Kulkarni 		ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
2351*14b24e2bSVaishali Kulkarni 					 MCP_PF_ID_BY_REL(p_hwfn, i));
2352*14b24e2bSVaishali Kulkarni 		if (shmem_info.config & FUNC_MF_CFG_FUNC_HIDE)
2353*14b24e2bSVaishali Kulkarni 			continue;
2354*14b24e2bSVaishali Kulkarni 
2355*14b24e2bSVaishali Kulkarni 		if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
2356*14b24e2bSVaishali Kulkarni 					      &protocol) !=
2357*14b24e2bSVaishali Kulkarni 		    ECORE_SUCCESS)
2358*14b24e2bSVaishali Kulkarni 			continue;
2359*14b24e2bSVaishali Kulkarni 
2360*14b24e2bSVaishali Kulkarni 		if ((1 << ((u32)protocol)) & personalities)
2361*14b24e2bSVaishali Kulkarni 			count++;
2362*14b24e2bSVaishali Kulkarni 	}
2363*14b24e2bSVaishali Kulkarni 
2364*14b24e2bSVaishali Kulkarni 	return count;
2365*14b24e2bSVaishali Kulkarni }
2366*14b24e2bSVaishali Kulkarni #endif
2367*14b24e2bSVaishali Kulkarni 
2368*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_flash_size(struct ecore_hwfn *p_hwfn,
2369*14b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
2370*14b24e2bSVaishali Kulkarni 					      u32 *p_flash_size)
2371*14b24e2bSVaishali Kulkarni {
2372*14b24e2bSVaishali Kulkarni 	u32 flash_size;
2373*14b24e2bSVaishali Kulkarni 
2374*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
2375*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
2376*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Emulation - can't get flash size\n");
2377*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2378*14b24e2bSVaishali Kulkarni 	}
2379*14b24e2bSVaishali Kulkarni #endif
2380*14b24e2bSVaishali Kulkarni 
2381*14b24e2bSVaishali Kulkarni 	if (IS_VF(p_hwfn->p_dev))
2382*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2383*14b24e2bSVaishali Kulkarni 
2384*14b24e2bSVaishali Kulkarni 	flash_size = ecore_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4);
2385*14b24e2bSVaishali Kulkarni 	flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >>
2386*14b24e2bSVaishali Kulkarni 				MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT;
2387*14b24e2bSVaishali Kulkarni 	flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT));
2388*14b24e2bSVaishali Kulkarni 
2389*14b24e2bSVaishali Kulkarni 	*p_flash_size = flash_size;
2390*14b24e2bSVaishali Kulkarni 
2391*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2392*14b24e2bSVaishali Kulkarni }
2393*14b24e2bSVaishali Kulkarni 
2394*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_start_recovery_process(struct ecore_hwfn *p_hwfn,
2395*14b24e2bSVaishali Kulkarni 						  struct ecore_ptt *p_ptt)
2396*14b24e2bSVaishali Kulkarni {
2397*14b24e2bSVaishali Kulkarni 	struct ecore_dev *p_dev = p_hwfn->p_dev;
2398*14b24e2bSVaishali Kulkarni 
2399*14b24e2bSVaishali Kulkarni 	if (p_dev->recov_in_prog) {
2400*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
2401*14b24e2bSVaishali Kulkarni 			  "Avoid triggering a recovery since such a process is already in progress\n");
2402*14b24e2bSVaishali Kulkarni 		return ECORE_AGAIN;
2403*14b24e2bSVaishali Kulkarni 	}
2404*14b24e2bSVaishali Kulkarni 
2405*14b24e2bSVaishali Kulkarni 	DP_NOTICE(p_hwfn, false, "Triggering a recovery process\n");
2406*14b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1);
2407*14b24e2bSVaishali Kulkarni 
2408*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2409*14b24e2bSVaishali Kulkarni }
2410*14b24e2bSVaishali Kulkarni 
2411*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
2412*14b24e2bSVaishali Kulkarni ecore_mcp_config_vf_msix_bb(struct ecore_hwfn *p_hwfn,
2413*14b24e2bSVaishali Kulkarni 			    struct ecore_ptt *p_ptt,
2414*14b24e2bSVaishali Kulkarni 			    u8 vf_id, u8 num)
2415*14b24e2bSVaishali Kulkarni {
2416*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, rc_param = 0;
2417*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2418*14b24e2bSVaishali Kulkarni 
2419*14b24e2bSVaishali Kulkarni 	/* Only Leader can configure MSIX, and need to take CMT into account */
2420*14b24e2bSVaishali Kulkarni 	if (!IS_LEAD_HWFN(p_hwfn))
2421*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
2422*14b24e2bSVaishali Kulkarni 	num *= p_hwfn->p_dev->num_hwfns;
2423*14b24e2bSVaishali Kulkarni 
2424*14b24e2bSVaishali Kulkarni 	param |= (vf_id << DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT) &
2425*14b24e2bSVaishali Kulkarni 		 DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK;
2426*14b24e2bSVaishali Kulkarni 	param |= (num << DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT) &
2427*14b24e2bSVaishali Kulkarni 		 DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK;
2428*14b24e2bSVaishali Kulkarni 
2429*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_VF_MSIX, param,
2430*14b24e2bSVaishali Kulkarni 			   &resp, &rc_param);
2431*14b24e2bSVaishali Kulkarni 
2432*14b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE) {
2433*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "VF[%d]: MFW failed to set MSI-X\n",
2434*14b24e2bSVaishali Kulkarni 			  vf_id);
2435*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
2436*14b24e2bSVaishali Kulkarni 	} else {
2437*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2438*14b24e2bSVaishali Kulkarni 			   "Requested 0x%02x MSI-x interrupts from VF 0x%02x\n",
2439*14b24e2bSVaishali Kulkarni 			    num, vf_id);
2440*14b24e2bSVaishali Kulkarni 	}
2441*14b24e2bSVaishali Kulkarni 
2442*14b24e2bSVaishali Kulkarni 	return rc;
2443*14b24e2bSVaishali Kulkarni }
2444*14b24e2bSVaishali Kulkarni 
2445*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
2446*14b24e2bSVaishali Kulkarni ecore_mcp_config_vf_msix_ah(struct ecore_hwfn *p_hwfn,
2447*14b24e2bSVaishali Kulkarni 			    struct ecore_ptt *p_ptt,
2448*14b24e2bSVaishali Kulkarni 			    u8 num)
2449*14b24e2bSVaishali Kulkarni {
2450*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = num, rc_param = 0;
2451*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2452*14b24e2bSVaishali Kulkarni 
2453*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_PF_VFS_MSIX,
2454*14b24e2bSVaishali Kulkarni 			   param, &resp, &rc_param);
2455*14b24e2bSVaishali Kulkarni 
2456*14b24e2bSVaishali Kulkarni 	if (resp != FW_MSG_CODE_DRV_CFG_PF_VFS_MSIX_DONE) {
2457*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "MFW failed to set MSI-X for VFs\n");
2458*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
2459*14b24e2bSVaishali Kulkarni 	} else {
2460*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2461*14b24e2bSVaishali Kulkarni 			   "Requested 0x%02x MSI-x interrupts for VFs\n",
2462*14b24e2bSVaishali Kulkarni 			   num);
2463*14b24e2bSVaishali Kulkarni 	}
2464*14b24e2bSVaishali Kulkarni 
2465*14b24e2bSVaishali Kulkarni 	return rc;
2466*14b24e2bSVaishali Kulkarni }
2467*14b24e2bSVaishali Kulkarni 
2468*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_config_vf_msix(struct ecore_hwfn *p_hwfn,
2469*14b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
2470*14b24e2bSVaishali Kulkarni 					      u8 vf_id, u8 num)
2471*14b24e2bSVaishali Kulkarni {
2472*14b24e2bSVaishali Kulkarni 	if (ECORE_IS_BB(p_hwfn->p_dev))
2473*14b24e2bSVaishali Kulkarni 		return ecore_mcp_config_vf_msix_bb(p_hwfn, p_ptt, vf_id, num);
2474*14b24e2bSVaishali Kulkarni 	else
2475*14b24e2bSVaishali Kulkarni 		return ecore_mcp_config_vf_msix_ah(p_hwfn, p_ptt, num);
2476*14b24e2bSVaishali Kulkarni }
2477*14b24e2bSVaishali Kulkarni 
2478*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2479*14b24e2bSVaishali Kulkarni ecore_mcp_send_drv_version(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2480*14b24e2bSVaishali Kulkarni 			   struct ecore_mcp_drv_version *p_ver)
2481*14b24e2bSVaishali Kulkarni {
2482*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
2483*14b24e2bSVaishali Kulkarni 	struct drv_version_stc drv_version;
2484*14b24e2bSVaishali Kulkarni 	u32 num_words, i;
2485*14b24e2bSVaishali Kulkarni 	void *p_name;
2486*14b24e2bSVaishali Kulkarni 	OSAL_BE32 val;
2487*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2488*14b24e2bSVaishali Kulkarni 
2489*14b24e2bSVaishali Kulkarni #ifndef ASIC_ONLY
2490*14b24e2bSVaishali Kulkarni 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev))
2491*14b24e2bSVaishali Kulkarni 		return ECORE_SUCCESS;
2492*14b24e2bSVaishali Kulkarni #endif
2493*14b24e2bSVaishali Kulkarni 
2494*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&drv_version, sizeof(drv_version));
2495*14b24e2bSVaishali Kulkarni 	drv_version.version = p_ver->version;
2496*14b24e2bSVaishali Kulkarni 	num_words = (MCP_DRV_VER_STR_SIZE - 4) / 4;
2497*14b24e2bSVaishali Kulkarni 	for (i = 0; i < num_words; i++) {
2498*14b24e2bSVaishali Kulkarni 		/* The driver name is expected to be in a big-endian format */
2499*14b24e2bSVaishali Kulkarni 		p_name = &p_ver->name[i * sizeof(u32)];
2500*14b24e2bSVaishali Kulkarni 		val = OSAL_CPU_TO_BE32(*(u32 *)p_name);
2501*14b24e2bSVaishali Kulkarni 		*(u32 *)&drv_version.name[i * sizeof(u32)] = val;
2502*14b24e2bSVaishali Kulkarni 	}
2503*14b24e2bSVaishali Kulkarni 
2504*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
2505*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_VERSION;
2506*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &drv_version;
2507*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(drv_version);
2508*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
2509*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2510*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
2511*14b24e2bSVaishali Kulkarni 
2512*14b24e2bSVaishali Kulkarni 	return rc;
2513*14b24e2bSVaishali Kulkarni }
2514*14b24e2bSVaishali Kulkarni 
2515*14b24e2bSVaishali Kulkarni /* A maximal 100 msec waiting time for the MCP to halt */
2516*14b24e2bSVaishali Kulkarni #define ECORE_MCP_HALT_SLEEP_MS		10
2517*14b24e2bSVaishali Kulkarni #define ECORE_MCP_HALT_MAX_RETRIES	10
2518*14b24e2bSVaishali Kulkarni 
2519*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_halt(struct ecore_hwfn *p_hwfn,
2520*14b24e2bSVaishali Kulkarni 				    struct ecore_ptt *p_ptt)
2521*14b24e2bSVaishali Kulkarni {
2522*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, cpu_state, cnt = 0;
2523*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2524*14b24e2bSVaishali Kulkarni 
2525*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp,
2526*14b24e2bSVaishali Kulkarni 			   &param);
2527*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
2528*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
2529*14b24e2bSVaishali Kulkarni 		return rc;
2530*14b24e2bSVaishali Kulkarni 	}
2531*14b24e2bSVaishali Kulkarni 
2532*14b24e2bSVaishali Kulkarni 	do {
2533*14b24e2bSVaishali Kulkarni 		OSAL_MSLEEP(ECORE_MCP_HALT_SLEEP_MS);
2534*14b24e2bSVaishali Kulkarni 		cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
2535*14b24e2bSVaishali Kulkarni 		if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED)
2536*14b24e2bSVaishali Kulkarni 			break;
2537*14b24e2bSVaishali Kulkarni 	} while (++cnt < ECORE_MCP_HALT_MAX_RETRIES);
2538*14b24e2bSVaishali Kulkarni 
2539*14b24e2bSVaishali Kulkarni 	if (cnt == ECORE_MCP_HALT_MAX_RETRIES) {
2540*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
2541*14b24e2bSVaishali Kulkarni 			  "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
2542*14b24e2bSVaishali Kulkarni 			  ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state);
2543*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2544*14b24e2bSVaishali Kulkarni 	}
2545*14b24e2bSVaishali Kulkarni 
2546*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2547*14b24e2bSVaishali Kulkarni }
2548*14b24e2bSVaishali Kulkarni 
2549*14b24e2bSVaishali Kulkarni #define ECORE_MCP_RESUME_SLEEP_MS	10
2550*14b24e2bSVaishali Kulkarni 
2551*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_resume(struct ecore_hwfn *p_hwfn,
2552*14b24e2bSVaishali Kulkarni 				      struct ecore_ptt *p_ptt)
2553*14b24e2bSVaishali Kulkarni {
2554*14b24e2bSVaishali Kulkarni 	u32 cpu_mode, cpu_state;
2555*14b24e2bSVaishali Kulkarni 
2556*14b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff);
2557*14b24e2bSVaishali Kulkarni 
2558*14b24e2bSVaishali Kulkarni 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
2559*14b24e2bSVaishali Kulkarni 	cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT;
2560*14b24e2bSVaishali Kulkarni 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode);
2561*14b24e2bSVaishali Kulkarni 
2562*14b24e2bSVaishali Kulkarni 	OSAL_MSLEEP(ECORE_MCP_RESUME_SLEEP_MS);
2563*14b24e2bSVaishali Kulkarni 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
2564*14b24e2bSVaishali Kulkarni 
2565*14b24e2bSVaishali Kulkarni 	if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) {
2566*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
2567*14b24e2bSVaishali Kulkarni 			  "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
2568*14b24e2bSVaishali Kulkarni 			  cpu_mode, cpu_state);
2569*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2570*14b24e2bSVaishali Kulkarni 	}
2571*14b24e2bSVaishali Kulkarni 
2572*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2573*14b24e2bSVaishali Kulkarni }
2574*14b24e2bSVaishali Kulkarni 
2575*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2576*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_current_config(struct ecore_hwfn *p_hwfn,
2577*14b24e2bSVaishali Kulkarni 				   struct ecore_ptt *p_ptt,
2578*14b24e2bSVaishali Kulkarni 				   enum ecore_ov_client client)
2579*14b24e2bSVaishali Kulkarni {
2580*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2581*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2582*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
2583*14b24e2bSVaishali Kulkarni 
2584*14b24e2bSVaishali Kulkarni 	switch (client) {
2585*14b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_DRV:
2586*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS;
2587*14b24e2bSVaishali Kulkarni 		break;
2588*14b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_USER:
2589*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER;
2590*14b24e2bSVaishali Kulkarni 		break;
2591*14b24e2bSVaishali Kulkarni 	case ECORE_OV_CLIENT_VENDOR_SPEC:
2592*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC;
2593*14b24e2bSVaishali Kulkarni 		break;
2594*14b24e2bSVaishali Kulkarni 	default:
2595*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
2596*14b24e2bSVaishali Kulkarni 			  "Invalid client type %d\n", client);
2597*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2598*14b24e2bSVaishali Kulkarni 	}
2599*14b24e2bSVaishali Kulkarni 
2600*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG,
2601*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2602*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2603*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
2604*14b24e2bSVaishali Kulkarni 
2605*14b24e2bSVaishali Kulkarni 	return rc;
2606*14b24e2bSVaishali Kulkarni }
2607*14b24e2bSVaishali Kulkarni 
2608*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2609*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_driver_state(struct ecore_hwfn *p_hwfn,
2610*14b24e2bSVaishali Kulkarni 				 struct ecore_ptt *p_ptt,
2611*14b24e2bSVaishali Kulkarni 				 enum ecore_ov_driver_state drv_state)
2612*14b24e2bSVaishali Kulkarni {
2613*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2614*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2615*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
2616*14b24e2bSVaishali Kulkarni 
2617*14b24e2bSVaishali Kulkarni 	switch (drv_state) {
2618*14b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_NOT_LOADED:
2619*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED;
2620*14b24e2bSVaishali Kulkarni 		break;
2621*14b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_DISABLED:
2622*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED;
2623*14b24e2bSVaishali Kulkarni 		break;
2624*14b24e2bSVaishali Kulkarni 	case ECORE_OV_DRIVER_STATE_ACTIVE:
2625*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE;
2626*14b24e2bSVaishali Kulkarni 		break;
2627*14b24e2bSVaishali Kulkarni 	default:
2628*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true,
2629*14b24e2bSVaishali Kulkarni 			  "Invalid driver state %d\n", drv_state);
2630*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2631*14b24e2bSVaishali Kulkarni 	}
2632*14b24e2bSVaishali Kulkarni 
2633*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE,
2634*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2635*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2636*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send driver state\n");
2637*14b24e2bSVaishali Kulkarni 
2638*14b24e2bSVaishali Kulkarni 	return rc;
2639*14b24e2bSVaishali Kulkarni }
2640*14b24e2bSVaishali Kulkarni 
2641*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2642*14b24e2bSVaishali Kulkarni ecore_mcp_ov_get_fc_npiv(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2643*14b24e2bSVaishali Kulkarni 			 struct ecore_fc_npiv_tbl *p_table)
2644*14b24e2bSVaishali Kulkarni {
2645*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
2646*14b24e2bSVaishali Kulkarni 	struct dci_fc_npiv_tbl *p_npiv_table;
2647*14b24e2bSVaishali Kulkarni 	u8 *p_buf = OSAL_NULL;
2648*14b24e2bSVaishali Kulkarni 	u32 addr, size, i;
2649*14b24e2bSVaishali Kulkarni 
2650*14b24e2bSVaishali Kulkarni 	p_table->num_wwpn = 0;
2651*14b24e2bSVaishali Kulkarni 	p_table->num_wwnn = 0;
2652*14b24e2bSVaishali Kulkarni 	addr = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2653*14b24e2bSVaishali Kulkarni 			OFFSETOF(struct public_port, fc_npiv_nvram_tbl_addr));
2654*14b24e2bSVaishali Kulkarni 	if (addr == NPIV_TBL_INVALID_ADDR) {
2655*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table doesn't exist\n");
2656*14b24e2bSVaishali Kulkarni 		return rc;
2657*14b24e2bSVaishali Kulkarni 	}
2658*14b24e2bSVaishali Kulkarni 
2659*14b24e2bSVaishali Kulkarni 	size = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2660*14b24e2bSVaishali Kulkarni 			OFFSETOF(struct public_port, fc_npiv_nvram_tbl_size));
2661*14b24e2bSVaishali Kulkarni 	if (!size) {
2662*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table is empty\n");
2663*14b24e2bSVaishali Kulkarni 		return rc;
2664*14b24e2bSVaishali Kulkarni 	}
2665*14b24e2bSVaishali Kulkarni 
2666*14b24e2bSVaishali Kulkarni 	p_buf = OSAL_VZALLOC(p_hwfn->p_dev, size);
2667*14b24e2bSVaishali Kulkarni 	if (!p_buf) {
2668*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Buffer allocation failed\n");
2669*14b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
2670*14b24e2bSVaishali Kulkarni 	}
2671*14b24e2bSVaishali Kulkarni 
2672*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_read(p_hwfn->p_dev, addr, p_buf, size);
2673*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
2674*14b24e2bSVaishali Kulkarni 		OSAL_VFREE(p_hwfn->p_dev, p_buf);
2675*14b24e2bSVaishali Kulkarni 		return rc;
2676*14b24e2bSVaishali Kulkarni 	}
2677*14b24e2bSVaishali Kulkarni 
2678*14b24e2bSVaishali Kulkarni 	p_npiv_table = (struct dci_fc_npiv_tbl *)p_buf;
2679*14b24e2bSVaishali Kulkarni 	p_table->num_wwpn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
2680*14b24e2bSVaishali Kulkarni 	p_table->num_wwnn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
2681*14b24e2bSVaishali Kulkarni 	for (i = 0; i < p_table->num_wwpn; i++) {
2682*14b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_table->wwpn, p_npiv_table->settings[i].npiv_wwpn,
2683*14b24e2bSVaishali Kulkarni 			    ECORE_WWN_SIZE);
2684*14b24e2bSVaishali Kulkarni 		OSAL_MEMCPY(p_table->wwnn, p_npiv_table->settings[i].npiv_wwnn,
2685*14b24e2bSVaishali Kulkarni 			    ECORE_WWN_SIZE);
2686*14b24e2bSVaishali Kulkarni 	}
2687*14b24e2bSVaishali Kulkarni 
2688*14b24e2bSVaishali Kulkarni 	OSAL_VFREE(p_hwfn->p_dev, p_buf);
2689*14b24e2bSVaishali Kulkarni 
2690*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2691*14b24e2bSVaishali Kulkarni }
2692*14b24e2bSVaishali Kulkarni 
2693*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2694*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_mtu(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2695*14b24e2bSVaishali Kulkarni 			u16 mtu)
2696*14b24e2bSVaishali Kulkarni {
2697*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2698*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2699*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
2700*14b24e2bSVaishali Kulkarni 
2701*14b24e2bSVaishali Kulkarni 	drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT;
2702*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU,
2703*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2704*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2705*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc);
2706*14b24e2bSVaishali Kulkarni 
2707*14b24e2bSVaishali Kulkarni 	return rc;
2708*14b24e2bSVaishali Kulkarni }
2709*14b24e2bSVaishali Kulkarni 
2710*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2711*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_mac(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2712*14b24e2bSVaishali Kulkarni 			u8 *mac)
2713*14b24e2bSVaishali Kulkarni {
2714*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
2715*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2716*14b24e2bSVaishali Kulkarni 	u32 mfw_mac[2];
2717*14b24e2bSVaishali Kulkarni 
2718*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
2719*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_VMAC;
2720*14b24e2bSVaishali Kulkarni 	mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC <<
2721*14b24e2bSVaishali Kulkarni 				DRV_MSG_CODE_VMAC_TYPE_SHIFT;
2722*14b24e2bSVaishali Kulkarni 	mb_params.param |= MCP_PF_ID(p_hwfn);
2723*14b24e2bSVaishali Kulkarni 
2724*14b24e2bSVaishali Kulkarni 	/* MCP is BE, and on LE platforms PCI would swap access to SHMEM
2725*14b24e2bSVaishali Kulkarni 	 * in 32-bit granularity.
2726*14b24e2bSVaishali Kulkarni 	 * So the MAC has to be set in native order [and not byte order],
2727*14b24e2bSVaishali Kulkarni 	 * otherwise it would be read incorrectly by MFW after swap.
2728*14b24e2bSVaishali Kulkarni 	 */
2729*14b24e2bSVaishali Kulkarni 	mfw_mac[0] = mac[0] << 24 | mac[1] << 16 | mac[2] << 8 | mac[3];
2730*14b24e2bSVaishali Kulkarni 	mfw_mac[1] = mac[4] << 24 | mac[5] << 16;
2731*14b24e2bSVaishali Kulkarni 
2732*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = (u8 *)mfw_mac;
2733*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = 8;
2734*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
2735*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2736*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc);
2737*14b24e2bSVaishali Kulkarni 
2738*14b24e2bSVaishali Kulkarni 	/* Store primary MAC for later possible WoL */
2739*14b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_hwfn->p_dev->wol_mac, mac, ETH_ALEN);
2740*14b24e2bSVaishali Kulkarni 
2741*14b24e2bSVaishali Kulkarni 	return rc;
2742*14b24e2bSVaishali Kulkarni }
2743*14b24e2bSVaishali Kulkarni 
2744*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2745*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_wol(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2746*14b24e2bSVaishali Kulkarni 			enum ecore_ov_wol wol)
2747*14b24e2bSVaishali Kulkarni {
2748*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2749*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2750*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
2751*14b24e2bSVaishali Kulkarni 
2752*14b24e2bSVaishali Kulkarni 	if (p_hwfn->hw_info.b_wol_support == ECORE_WOL_SUPPORT_NONE) {
2753*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
2754*14b24e2bSVaishali Kulkarni 			   "Can't change WoL configuration when WoL isn't supported\n");
2755*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2756*14b24e2bSVaishali Kulkarni 	}
2757*14b24e2bSVaishali Kulkarni 
2758*14b24e2bSVaishali Kulkarni 	switch (wol) {
2759*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DEFAULT:
2760*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT;
2761*14b24e2bSVaishali Kulkarni 		break;
2762*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_DISABLED:
2763*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_DISABLED;
2764*14b24e2bSVaishali Kulkarni 		break;
2765*14b24e2bSVaishali Kulkarni 	case ECORE_OV_WOL_ENABLED:
2766*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_WOL_ENABLED;
2767*14b24e2bSVaishali Kulkarni 		break;
2768*14b24e2bSVaishali Kulkarni 	default:
2769*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid wol state %d\n", wol);
2770*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2771*14b24e2bSVaishali Kulkarni 	}
2772*14b24e2bSVaishali Kulkarni 
2773*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL,
2774*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2775*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2776*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc);
2777*14b24e2bSVaishali Kulkarni 
2778*14b24e2bSVaishali Kulkarni 	/* Store the WoL update for a future unload */
2779*14b24e2bSVaishali Kulkarni 	p_hwfn->p_dev->wol_config = (u8)wol;
2780*14b24e2bSVaishali Kulkarni 
2781*14b24e2bSVaishali Kulkarni 	return rc;
2782*14b24e2bSVaishali Kulkarni }
2783*14b24e2bSVaishali Kulkarni 
2784*14b24e2bSVaishali Kulkarni enum _ecore_status_t
2785*14b24e2bSVaishali Kulkarni ecore_mcp_ov_update_eswitch(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
2786*14b24e2bSVaishali Kulkarni 			    enum ecore_ov_eswitch eswitch)
2787*14b24e2bSVaishali Kulkarni {
2788*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2789*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2790*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param;
2791*14b24e2bSVaishali Kulkarni 
2792*14b24e2bSVaishali Kulkarni 	switch (eswitch) {
2793*14b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_NONE:
2794*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE;
2795*14b24e2bSVaishali Kulkarni 		break;
2796*14b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_VEB:
2797*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB;
2798*14b24e2bSVaishali Kulkarni 		break;
2799*14b24e2bSVaishali Kulkarni 	case ECORE_OV_ESWITCH_VEPA:
2800*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA;
2801*14b24e2bSVaishali Kulkarni 		break;
2802*14b24e2bSVaishali Kulkarni 	default:
2803*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch);
2804*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2805*14b24e2bSVaishali Kulkarni 	}
2806*14b24e2bSVaishali Kulkarni 
2807*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE,
2808*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2809*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2810*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc);
2811*14b24e2bSVaishali Kulkarni 
2812*14b24e2bSVaishali Kulkarni 	return rc;
2813*14b24e2bSVaishali Kulkarni }
2814*14b24e2bSVaishali Kulkarni 
2815*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_led(struct ecore_hwfn *p_hwfn,
2816*14b24e2bSVaishali Kulkarni 				       struct ecore_ptt *p_ptt,
2817*14b24e2bSVaishali Kulkarni 				       enum ecore_led_mode mode)
2818*14b24e2bSVaishali Kulkarni {
2819*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0, drv_mb_param;
2820*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2821*14b24e2bSVaishali Kulkarni 
2822*14b24e2bSVaishali Kulkarni 	switch (mode) {
2823*14b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_ON:
2824*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON;
2825*14b24e2bSVaishali Kulkarni 		break;
2826*14b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_OFF:
2827*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF;
2828*14b24e2bSVaishali Kulkarni 		break;
2829*14b24e2bSVaishali Kulkarni 	case ECORE_LED_MODE_RESTORE:
2830*14b24e2bSVaishali Kulkarni 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER;
2831*14b24e2bSVaishali Kulkarni 		break;
2832*14b24e2bSVaishali Kulkarni 	default:
2833*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Invalid LED mode %d\n", mode);
2834*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
2835*14b24e2bSVaishali Kulkarni 	}
2836*14b24e2bSVaishali Kulkarni 
2837*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE,
2838*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &resp, &param);
2839*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2840*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
2841*14b24e2bSVaishali Kulkarni 
2842*14b24e2bSVaishali Kulkarni 	return rc;
2843*14b24e2bSVaishali Kulkarni }
2844*14b24e2bSVaishali Kulkarni 
2845*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mask_parities(struct ecore_hwfn *p_hwfn,
2846*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
2847*14b24e2bSVaishali Kulkarni 					     u32 mask_parities)
2848*14b24e2bSVaishali Kulkarni {
2849*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2850*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
2851*14b24e2bSVaishali Kulkarni 
2852*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MASK_PARITIES,
2853*14b24e2bSVaishali Kulkarni 			   mask_parities, &resp, &param);
2854*14b24e2bSVaishali Kulkarni 
2855*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
2856*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP response failure for mask parities, aborting\n");
2857*14b24e2bSVaishali Kulkarni 	} else if (resp != FW_MSG_CODE_OK) {
2858*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "MCP did not acknowledge mask parity request. Old MFW?\n");
2859*14b24e2bSVaishali Kulkarni 		rc = ECORE_INVAL;
2860*14b24e2bSVaishali Kulkarni 	}
2861*14b24e2bSVaishali Kulkarni 
2862*14b24e2bSVaishali Kulkarni 	return rc;
2863*14b24e2bSVaishali Kulkarni }
2864*14b24e2bSVaishali Kulkarni 
2865*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
2866*14b24e2bSVaishali Kulkarni 			   u8 *p_buf, u32 len)
2867*14b24e2bSVaishali Kulkarni {
2868*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2869*14b24e2bSVaishali Kulkarni 	u32 bytes_left, offset, bytes_to_copy, buf_size;
2870*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
2871*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
2872*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
2873*14b24e2bSVaishali Kulkarni 
2874*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2875*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2876*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2877*14b24e2bSVaishali Kulkarni 
2878*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
2879*14b24e2bSVaishali Kulkarni 	bytes_left = len;
2880*14b24e2bSVaishali Kulkarni 	offset = 0;
2881*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
2882*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
2883*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_READ_NVRAM;
2884*14b24e2bSVaishali Kulkarni 	while (bytes_left > 0) {
2885*14b24e2bSVaishali Kulkarni 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
2886*14b24e2bSVaishali Kulkarni 					   MCP_DRV_NVM_BUF_LEN);
2887*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset = (addr + offset) |
2888*14b24e2bSVaishali Kulkarni 					   (bytes_to_copy <<
2889*14b24e2bSVaishali Kulkarni 					    DRV_MB_PARAM_NVM_LEN_SHIFT);
2890*14b24e2bSVaishali Kulkarni 		params.nvm_rd.buf = (u32 *)(p_buf + offset);
2891*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
2892*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS || (params.nvm_common.resp !=
2893*14b24e2bSVaishali Kulkarni 					    FW_MSG_CODE_NVM_OK)) {
2894*14b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, false, "MCP command rc = %d\n",
2895*14b24e2bSVaishali Kulkarni 				  rc);
2896*14b24e2bSVaishali Kulkarni 			break;
2897*14b24e2bSVaishali Kulkarni 		}
2898*14b24e2bSVaishali Kulkarni 
2899*14b24e2bSVaishali Kulkarni 		/* This can be a lengthy process, and it's possible scheduler
2900*14b24e2bSVaishali Kulkarni 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
2901*14b24e2bSVaishali Kulkarni 		 */
2902*14b24e2bSVaishali Kulkarni 		if (bytes_left % 0x1000 <
2903*14b24e2bSVaishali Kulkarni 		    (bytes_left - *params.nvm_rd.buf_size) % 0x1000)
2904*14b24e2bSVaishali Kulkarni 			OSAL_MSLEEP(1);
2905*14b24e2bSVaishali Kulkarni 
2906*14b24e2bSVaishali Kulkarni 		offset += *params.nvm_rd.buf_size;
2907*14b24e2bSVaishali Kulkarni 		bytes_left -= *params.nvm_rd.buf_size;
2908*14b24e2bSVaishali Kulkarni 	}
2909*14b24e2bSVaishali Kulkarni 
2910*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
2911*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
2912*14b24e2bSVaishali Kulkarni 
2913*14b24e2bSVaishali Kulkarni 	return rc;
2914*14b24e2bSVaishali Kulkarni }
2915*14b24e2bSVaishali Kulkarni 
2916*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
2917*14b24e2bSVaishali Kulkarni 					u32 addr, u8 *p_buf, u32 len)
2918*14b24e2bSVaishali Kulkarni {
2919*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2920*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
2921*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
2922*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2923*14b24e2bSVaishali Kulkarni 
2924*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2925*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2926*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2927*14b24e2bSVaishali Kulkarni 
2928*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
2929*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
2930*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &len;
2931*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = (cmd == ECORE_PHY_CORE_READ) ?
2932*14b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_CORE_READ :
2933*14b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_RAW_READ;
2934*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
2935*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = (u32 *)p_buf;
2936*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
2937*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
2938*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
2939*14b24e2bSVaishali Kulkarni 
2940*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
2941*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
2942*14b24e2bSVaishali Kulkarni 
2943*14b24e2bSVaishali Kulkarni 	return rc;
2944*14b24e2bSVaishali Kulkarni }
2945*14b24e2bSVaishali Kulkarni 
2946*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_resp(struct ecore_dev *p_dev, u8 *p_buf)
2947*14b24e2bSVaishali Kulkarni {
2948*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2949*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
2950*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
2951*14b24e2bSVaishali Kulkarni 
2952*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2953*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2954*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2955*14b24e2bSVaishali Kulkarni 
2956*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
2957*14b24e2bSVaishali Kulkarni 	OSAL_MEMCPY(p_buf, &p_dev->mcp_nvm_resp, sizeof(p_dev->mcp_nvm_resp));
2958*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
2959*14b24e2bSVaishali Kulkarni 
2960*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
2961*14b24e2bSVaishali Kulkarni }
2962*14b24e2bSVaishali Kulkarni 
2963*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_del_file(struct ecore_dev *p_dev,
2964*14b24e2bSVaishali Kulkarni 					    u32 addr)
2965*14b24e2bSVaishali Kulkarni {
2966*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2967*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
2968*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
2969*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2970*14b24e2bSVaishali Kulkarni 
2971*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2972*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2973*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2974*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
2975*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
2976*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_DEL_FILE;
2977*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
2978*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
2979*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
2980*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
2981*14b24e2bSVaishali Kulkarni 
2982*14b24e2bSVaishali Kulkarni 	return rc;
2983*14b24e2bSVaishali Kulkarni }
2984*14b24e2bSVaishali Kulkarni 
2985*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_put_file_begin(struct ecore_dev *p_dev,
2986*14b24e2bSVaishali Kulkarni 						  u32 addr)
2987*14b24e2bSVaishali Kulkarni {
2988*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2989*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
2990*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
2991*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
2992*14b24e2bSVaishali Kulkarni 
2993*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
2994*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
2995*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
2996*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
2997*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
2998*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_NVM_PUT_FILE_BEGIN;
2999*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
3000*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3001*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
3002*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
3003*14b24e2bSVaishali Kulkarni 
3004*14b24e2bSVaishali Kulkarni 	return rc;
3005*14b24e2bSVaishali Kulkarni }
3006*14b24e2bSVaishali Kulkarni 
3007*14b24e2bSVaishali Kulkarni /* rc recieves ECORE_INVAL as default parameter because
3008*14b24e2bSVaishali Kulkarni  * it might not enter the while loop if the len is 0
3009*14b24e2bSVaishali Kulkarni  */
3010*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_write(struct ecore_dev *p_dev, u32 cmd,
3011*14b24e2bSVaishali Kulkarni 					 u32 addr, u8 *p_buf, u32 len)
3012*14b24e2bSVaishali Kulkarni {
3013*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
3014*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_INVAL;
3015*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3016*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
3017*14b24e2bSVaishali Kulkarni 	u32 buf_idx, buf_size;
3018*14b24e2bSVaishali Kulkarni 
3019*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
3020*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
3021*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
3022*14b24e2bSVaishali Kulkarni 
3023*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3024*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
3025*14b24e2bSVaishali Kulkarni 	switch (cmd) {
3026*14b24e2bSVaishali Kulkarni 	case ECORE_PUT_FILE_DATA:
3027*14b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
3028*14b24e2bSVaishali Kulkarni 		break;
3029*14b24e2bSVaishali Kulkarni 	case ECORE_NVM_WRITE_NVRAM:
3030*14b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM;
3031*14b24e2bSVaishali Kulkarni 		break;
3032*14b24e2bSVaishali Kulkarni 	case ECORE_EXT_PHY_FW_UPGRADE:
3033*14b24e2bSVaishali Kulkarni 		params.nvm_common.cmd = DRV_MSG_CODE_EXT_PHY_FW_UPGRADE;
3034*14b24e2bSVaishali Kulkarni 		break;
3035*14b24e2bSVaishali Kulkarni 	default:
3036*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, true, "Invalid nvm write command 0x%x\n",
3037*14b24e2bSVaishali Kulkarni 			  cmd);
3038*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3039*14b24e2bSVaishali Kulkarni 	}
3040*14b24e2bSVaishali Kulkarni 
3041*14b24e2bSVaishali Kulkarni 	buf_idx = 0;
3042*14b24e2bSVaishali Kulkarni 	while (buf_idx < len) {
3043*14b24e2bSVaishali Kulkarni 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
3044*14b24e2bSVaishali Kulkarni 				      MCP_DRV_NVM_BUF_LEN);
3045*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset = ((buf_size <<
3046*14b24e2bSVaishali Kulkarni 					     DRV_MB_PARAM_NVM_LEN_SHIFT)
3047*14b24e2bSVaishali Kulkarni 					    | addr) + buf_idx;
3048*14b24e2bSVaishali Kulkarni 		params.nvm_wr.buf_size = buf_size;
3049*14b24e2bSVaishali Kulkarni 		params.nvm_wr.buf = (u32 *)&p_buf[buf_idx];
3050*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3051*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS ||
3052*14b24e2bSVaishali Kulkarni 		    ((params.nvm_common.resp != FW_MSG_CODE_NVM_OK) &&
3053*14b24e2bSVaishali Kulkarni 		     (params.nvm_common.resp !=
3054*14b24e2bSVaishali Kulkarni 		      FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK)))
3055*14b24e2bSVaishali Kulkarni 			DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
3056*14b24e2bSVaishali Kulkarni 
3057*14b24e2bSVaishali Kulkarni 		/* This can be a lengthy process, and it's possible scheduler
3058*14b24e2bSVaishali Kulkarni 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
3059*14b24e2bSVaishali Kulkarni 		 */
3060*14b24e2bSVaishali Kulkarni 		if (buf_idx % 0x1000 >
3061*14b24e2bSVaishali Kulkarni 		    (buf_idx + buf_size) % 0x1000)
3062*14b24e2bSVaishali Kulkarni 			OSAL_MSLEEP(1);
3063*14b24e2bSVaishali Kulkarni 
3064*14b24e2bSVaishali Kulkarni 		buf_idx += buf_size;
3065*14b24e2bSVaishali Kulkarni 	}
3066*14b24e2bSVaishali Kulkarni 
3067*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
3068*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
3069*14b24e2bSVaishali Kulkarni 
3070*14b24e2bSVaishali Kulkarni 	return rc;
3071*14b24e2bSVaishali Kulkarni }
3072*14b24e2bSVaishali Kulkarni 
3073*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_write(struct ecore_dev *p_dev, u32 cmd,
3074*14b24e2bSVaishali Kulkarni 					 u32 addr, u8 *p_buf, u32 len)
3075*14b24e2bSVaishali Kulkarni {
3076*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
3077*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3078*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
3079*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3080*14b24e2bSVaishali Kulkarni 
3081*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
3082*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
3083*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
3084*14b24e2bSVaishali Kulkarni 
3085*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3086*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
3087*14b24e2bSVaishali Kulkarni 	params.nvm_wr.buf_size = len;
3088*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = (cmd == ECORE_PHY_CORE_WRITE) ?
3089*14b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_CORE_WRITE :
3090*14b24e2bSVaishali Kulkarni 					DRV_MSG_CODE_PHY_RAW_WRITE;
3091*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
3092*14b24e2bSVaishali Kulkarni 	params.nvm_wr.buf = (u32 *)p_buf;
3093*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3094*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3095*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
3096*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
3097*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
3098*14b24e2bSVaishali Kulkarni 
3099*14b24e2bSVaishali Kulkarni 	return rc;
3100*14b24e2bSVaishali Kulkarni }
3101*14b24e2bSVaishali Kulkarni 
3102*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_nvm_set_secure_mode(struct ecore_dev *p_dev,
3103*14b24e2bSVaishali Kulkarni 						   u32 addr)
3104*14b24e2bSVaishali Kulkarni {
3105*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
3106*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3107*14b24e2bSVaishali Kulkarni 	struct ecore_ptt  *p_ptt;
3108*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3109*14b24e2bSVaishali Kulkarni 
3110*14b24e2bSVaishali Kulkarni 	p_ptt = ecore_ptt_acquire(p_hwfn);
3111*14b24e2bSVaishali Kulkarni 	if (!p_ptt)
3112*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
3113*14b24e2bSVaishali Kulkarni 
3114*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3115*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_CMD;
3116*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_SET_SECURE_MODE;
3117*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = addr;
3118*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3119*14b24e2bSVaishali Kulkarni 	p_dev->mcp_nvm_resp = params.nvm_common.resp;
3120*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
3121*14b24e2bSVaishali Kulkarni 
3122*14b24e2bSVaishali Kulkarni 	return rc;
3123*14b24e2bSVaishali Kulkarni }
3124*14b24e2bSVaishali Kulkarni 
3125*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_sfp_read(struct ecore_hwfn *p_hwfn,
3126*14b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
3127*14b24e2bSVaishali Kulkarni 					    u32 port, u32 addr, u32 offset,
3128*14b24e2bSVaishali Kulkarni 					    u32 len, u8 *p_buf)
3129*14b24e2bSVaishali Kulkarni {
3130*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3131*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3132*14b24e2bSVaishali Kulkarni 	u32 bytes_left, bytes_to_copy, buf_size;
3133*14b24e2bSVaishali Kulkarni 
3134*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3135*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset =
3136*14b24e2bSVaishali Kulkarni 		(port << DRV_MB_PARAM_TRANSCEIVER_PORT_SHIFT) |
3137*14b24e2bSVaishali Kulkarni 		(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_SHIFT);
3138*14b24e2bSVaishali Kulkarni 	addr = offset;
3139*14b24e2bSVaishali Kulkarni 	offset = 0;
3140*14b24e2bSVaishali Kulkarni 	bytes_left = len;
3141*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
3142*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
3143*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_TRANSCEIVER_READ;
3144*14b24e2bSVaishali Kulkarni 	while (bytes_left > 0) {
3145*14b24e2bSVaishali Kulkarni 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
3146*14b24e2bSVaishali Kulkarni 					   MAX_I2C_TRANSACTION_SIZE);
3147*14b24e2bSVaishali Kulkarni 		params.nvm_rd.buf = (u32 *)(p_buf + offset);
3148*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset &=
3149*14b24e2bSVaishali Kulkarni 			(DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
3150*14b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
3151*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
3152*14b24e2bSVaishali Kulkarni 			((addr + offset) <<
3153*14b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_OFFSET_SHIFT);
3154*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
3155*14b24e2bSVaishali Kulkarni 			(bytes_to_copy << DRV_MB_PARAM_TRANSCEIVER_SIZE_SHIFT);
3156*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3157*14b24e2bSVaishali Kulkarni 		if ((params.nvm_common.resp & FW_MSG_CODE_MASK) ==
3158*14b24e2bSVaishali Kulkarni 		    FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
3159*14b24e2bSVaishali Kulkarni 			return ECORE_NODEV;
3160*14b24e2bSVaishali Kulkarni 		} else if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
3161*14b24e2bSVaishali Kulkarni 			   FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
3162*14b24e2bSVaishali Kulkarni 			return ECORE_UNKNOWN_ERROR;
3163*14b24e2bSVaishali Kulkarni 
3164*14b24e2bSVaishali Kulkarni 		offset += *params.nvm_rd.buf_size;
3165*14b24e2bSVaishali Kulkarni 		bytes_left -= *params.nvm_rd.buf_size;
3166*14b24e2bSVaishali Kulkarni 	}
3167*14b24e2bSVaishali Kulkarni 
3168*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3169*14b24e2bSVaishali Kulkarni }
3170*14b24e2bSVaishali Kulkarni 
3171*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_phy_sfp_write(struct ecore_hwfn *p_hwfn,
3172*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
3173*14b24e2bSVaishali Kulkarni 					     u32 port, u32 addr, u32 offset,
3174*14b24e2bSVaishali Kulkarni 					     u32 len, u8 *p_buf)
3175*14b24e2bSVaishali Kulkarni {
3176*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3177*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3178*14b24e2bSVaishali Kulkarni 	u32 buf_idx, buf_size;
3179*14b24e2bSVaishali Kulkarni 
3180*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3181*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset =
3182*14b24e2bSVaishali Kulkarni 		(port << DRV_MB_PARAM_TRANSCEIVER_PORT_SHIFT) |
3183*14b24e2bSVaishali Kulkarni 		(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_SHIFT);
3184*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_WR;
3185*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_TRANSCEIVER_WRITE;
3186*14b24e2bSVaishali Kulkarni 	buf_idx = 0;
3187*14b24e2bSVaishali Kulkarni 	while (buf_idx < len) {
3188*14b24e2bSVaishali Kulkarni 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
3189*14b24e2bSVaishali Kulkarni 				      MAX_I2C_TRANSACTION_SIZE);
3190*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset &=
3191*14b24e2bSVaishali Kulkarni 			(DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
3192*14b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
3193*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
3194*14b24e2bSVaishali Kulkarni 			((offset + buf_idx) <<
3195*14b24e2bSVaishali Kulkarni 			 DRV_MB_PARAM_TRANSCEIVER_OFFSET_SHIFT);
3196*14b24e2bSVaishali Kulkarni 		params.nvm_common.offset |=
3197*14b24e2bSVaishali Kulkarni 			(buf_size << DRV_MB_PARAM_TRANSCEIVER_SIZE_SHIFT);
3198*14b24e2bSVaishali Kulkarni 		params.nvm_wr.buf_size = buf_size;
3199*14b24e2bSVaishali Kulkarni 		params.nvm_wr.buf = (u32 *)&p_buf[buf_idx];
3200*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3201*14b24e2bSVaishali Kulkarni 		if ((params.nvm_common.resp & FW_MSG_CODE_MASK) ==
3202*14b24e2bSVaishali Kulkarni 		    FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
3203*14b24e2bSVaishali Kulkarni 			return ECORE_NODEV;
3204*14b24e2bSVaishali Kulkarni 		} else if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
3205*14b24e2bSVaishali Kulkarni 			   FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
3206*14b24e2bSVaishali Kulkarni 			return ECORE_UNKNOWN_ERROR;
3207*14b24e2bSVaishali Kulkarni 
3208*14b24e2bSVaishali Kulkarni 		buf_idx += buf_size;
3209*14b24e2bSVaishali Kulkarni 	}
3210*14b24e2bSVaishali Kulkarni 
3211*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3212*14b24e2bSVaishali Kulkarni }
3213*14b24e2bSVaishali Kulkarni 
3214*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_read(struct ecore_hwfn *p_hwfn,
3215*14b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
3216*14b24e2bSVaishali Kulkarni 					 u16 gpio, u32 *gpio_val)
3217*14b24e2bSVaishali Kulkarni {
3218*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3219*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp;
3220*14b24e2bSVaishali Kulkarni 
3221*14b24e2bSVaishali Kulkarni 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT);
3222*14b24e2bSVaishali Kulkarni 
3223*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_READ,
3224*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, gpio_val);
3225*14b24e2bSVaishali Kulkarni 
3226*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3227*14b24e2bSVaishali Kulkarni 		return rc;
3228*14b24e2bSVaishali Kulkarni 
3229*14b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
3230*14b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
3231*14b24e2bSVaishali Kulkarni 
3232*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3233*14b24e2bSVaishali Kulkarni }
3234*14b24e2bSVaishali Kulkarni 
3235*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_write(struct ecore_hwfn *p_hwfn,
3236*14b24e2bSVaishali Kulkarni 					  struct ecore_ptt *p_ptt,
3237*14b24e2bSVaishali Kulkarni 					  u16 gpio, u16 gpio_val)
3238*14b24e2bSVaishali Kulkarni {
3239*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3240*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, param, rsp;
3241*14b24e2bSVaishali Kulkarni 
3242*14b24e2bSVaishali Kulkarni 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT) |
3243*14b24e2bSVaishali Kulkarni 		(gpio_val << DRV_MB_PARAM_GPIO_VALUE_SHIFT);
3244*14b24e2bSVaishali Kulkarni 
3245*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_WRITE,
3246*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
3247*14b24e2bSVaishali Kulkarni 
3248*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3249*14b24e2bSVaishali Kulkarni 		return rc;
3250*14b24e2bSVaishali Kulkarni 
3251*14b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
3252*14b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
3253*14b24e2bSVaishali Kulkarni 
3254*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3255*14b24e2bSVaishali Kulkarni }
3256*14b24e2bSVaishali Kulkarni 
3257*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_gpio_info(struct ecore_hwfn *p_hwfn,
3258*14b24e2bSVaishali Kulkarni 					 struct ecore_ptt *p_ptt,
3259*14b24e2bSVaishali Kulkarni 					 u16 gpio, u32 *gpio_direction,
3260*14b24e2bSVaishali Kulkarni 					 u32 *gpio_ctrl)
3261*14b24e2bSVaishali Kulkarni {
3262*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp, val = 0;
3263*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3264*14b24e2bSVaishali Kulkarni 
3265*14b24e2bSVaishali Kulkarni 	drv_mb_param = gpio << DRV_MB_PARAM_GPIO_NUMBER_SHIFT;
3266*14b24e2bSVaishali Kulkarni 
3267*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_INFO,
3268*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &val);
3269*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3270*14b24e2bSVaishali Kulkarni 		return rc;
3271*14b24e2bSVaishali Kulkarni 
3272*14b24e2bSVaishali Kulkarni 	*gpio_direction = (val & DRV_MB_PARAM_GPIO_DIRECTION_MASK) >>
3273*14b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_GPIO_DIRECTION_SHIFT;
3274*14b24e2bSVaishali Kulkarni 	*gpio_ctrl = (val & DRV_MB_PARAM_GPIO_CTRL_MASK) >>
3275*14b24e2bSVaishali Kulkarni 		      DRV_MB_PARAM_GPIO_CTRL_SHIFT;
3276*14b24e2bSVaishali Kulkarni 
3277*14b24e2bSVaishali Kulkarni 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
3278*14b24e2bSVaishali Kulkarni 		return ECORE_UNKNOWN_ERROR;
3279*14b24e2bSVaishali Kulkarni 
3280*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3281*14b24e2bSVaishali Kulkarni }
3282*14b24e2bSVaishali Kulkarni 
3283*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_register_test(struct ecore_hwfn *p_hwfn,
3284*14b24e2bSVaishali Kulkarni 						  struct ecore_ptt *p_ptt)
3285*14b24e2bSVaishali Kulkarni {
3286*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp, param;
3287*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3288*14b24e2bSVaishali Kulkarni 
3289*14b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST <<
3290*14b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
3291*14b24e2bSVaishali Kulkarni 
3292*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
3293*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
3294*14b24e2bSVaishali Kulkarni 
3295*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3296*14b24e2bSVaishali Kulkarni 		return rc;
3297*14b24e2bSVaishali Kulkarni 
3298*14b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
3299*14b24e2bSVaishali Kulkarni 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
3300*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3301*14b24e2bSVaishali Kulkarni 
3302*14b24e2bSVaishali Kulkarni 	return rc;
3303*14b24e2bSVaishali Kulkarni }
3304*14b24e2bSVaishali Kulkarni 
3305*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_clock_test(struct ecore_hwfn *p_hwfn,
3306*14b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt)
3307*14b24e2bSVaishali Kulkarni {
3308*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param, rsp, param;
3309*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3310*14b24e2bSVaishali Kulkarni 
3311*14b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST <<
3312*14b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
3313*14b24e2bSVaishali Kulkarni 
3314*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
3315*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, &param);
3316*14b24e2bSVaishali Kulkarni 
3317*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3318*14b24e2bSVaishali Kulkarni 		return rc;
3319*14b24e2bSVaishali Kulkarni 
3320*14b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
3321*14b24e2bSVaishali Kulkarni 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
3322*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3323*14b24e2bSVaishali Kulkarni 
3324*14b24e2bSVaishali Kulkarni 	return rc;
3325*14b24e2bSVaishali Kulkarni }
3326*14b24e2bSVaishali Kulkarni 
3327*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_nvm_test_get_num_images(
3328*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, u32 *num_images)
3329*14b24e2bSVaishali Kulkarni {
3330*14b24e2bSVaishali Kulkarni 	u32 drv_mb_param = 0, rsp;
3331*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
3332*14b24e2bSVaishali Kulkarni 
3333*14b24e2bSVaishali Kulkarni 	drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES <<
3334*14b24e2bSVaishali Kulkarni 			DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
3335*14b24e2bSVaishali Kulkarni 
3336*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
3337*14b24e2bSVaishali Kulkarni 			   drv_mb_param, &rsp, num_images);
3338*14b24e2bSVaishali Kulkarni 
3339*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3340*14b24e2bSVaishali Kulkarni 		return rc;
3341*14b24e2bSVaishali Kulkarni 
3342*14b24e2bSVaishali Kulkarni 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
3343*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3344*14b24e2bSVaishali Kulkarni 
3345*14b24e2bSVaishali Kulkarni 	return rc;
3346*14b24e2bSVaishali Kulkarni }
3347*14b24e2bSVaishali Kulkarni 
3348*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
3349*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3350*14b24e2bSVaishali Kulkarni 	struct bist_nvm_image_att *p_image_att, u32 image_index)
3351*14b24e2bSVaishali Kulkarni {
3352*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3353*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3354*14b24e2bSVaishali Kulkarni 	u32 buf_size;
3355*14b24e2bSVaishali Kulkarni 
3356*14b24e2bSVaishali Kulkarni 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_mcp_nvm_params));
3357*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = (DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX <<
3358*14b24e2bSVaishali Kulkarni 				    DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
3359*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset |= (image_index <<
3360*14b24e2bSVaishali Kulkarni 				    DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT);
3361*14b24e2bSVaishali Kulkarni 
3362*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
3363*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
3364*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_BIST_TEST;
3365*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = (u32 *)p_image_att;
3366*14b24e2bSVaishali Kulkarni 
3367*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3368*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3369*14b24e2bSVaishali Kulkarni 		return rc;
3370*14b24e2bSVaishali Kulkarni 
3371*14b24e2bSVaishali Kulkarni 	if (((params.nvm_common.resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
3372*14b24e2bSVaishali Kulkarni 	    (p_image_att->return_code != 1))
3373*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3374*14b24e2bSVaishali Kulkarni 
3375*14b24e2bSVaishali Kulkarni 	return rc;
3376*14b24e2bSVaishali Kulkarni }
3377*14b24e2bSVaishali Kulkarni 
3378*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3379*14b24e2bSVaishali Kulkarni ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3380*14b24e2bSVaishali Kulkarni 			    enum ecore_nvm_images image_id,
3381*14b24e2bSVaishali Kulkarni 			    struct ecore_nvm_image_att *p_image_att)
3382*14b24e2bSVaishali Kulkarni {
3383*14b24e2bSVaishali Kulkarni 	struct bist_nvm_image_att mfw_image_att;
3384*14b24e2bSVaishali Kulkarni 	enum nvm_image_type type;
3385*14b24e2bSVaishali Kulkarni 	u32 num_images, i;
3386*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3387*14b24e2bSVaishali Kulkarni 
3388*14b24e2bSVaishali Kulkarni 	/* Translate image_id into MFW definitions */
3389*14b24e2bSVaishali Kulkarni 	switch (image_id) {
3390*14b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_ISCSI_CFG:
3391*14b24e2bSVaishali Kulkarni 		type = NVM_TYPE_ISCSI_CFG;
3392*14b24e2bSVaishali Kulkarni 		break;
3393*14b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_FCOE_CFG:
3394*14b24e2bSVaishali Kulkarni 		type = NVM_TYPE_FCOE_CFG;
3395*14b24e2bSVaishali Kulkarni 		break;
3396*14b24e2bSVaishali Kulkarni 	case ECORE_NVM_IMAGE_MDUMP:
3397*14b24e2bSVaishali Kulkarni 		type = NVM_TYPE_MDUMP;
3398*14b24e2bSVaishali Kulkarni 		break;
3399*14b24e2bSVaishali Kulkarni 	default:
3400*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
3401*14b24e2bSVaishali Kulkarni 			  image_id);
3402*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3403*14b24e2bSVaishali Kulkarni 	}
3404*14b24e2bSVaishali Kulkarni 
3405*14b24e2bSVaishali Kulkarni 	/* Learn number of images, then traverse and see if one fits */
3406*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
3407*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS || !num_images)
3408*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3409*14b24e2bSVaishali Kulkarni 
3410*14b24e2bSVaishali Kulkarni 	for (i = 0; i < num_images; i++) {
3411*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
3412*14b24e2bSVaishali Kulkarni 							   &mfw_image_att, i);
3413*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
3414*14b24e2bSVaishali Kulkarni 			return rc;
3415*14b24e2bSVaishali Kulkarni 
3416*14b24e2bSVaishali Kulkarni 		if (type == mfw_image_att.image_type)
3417*14b24e2bSVaishali Kulkarni 			break;
3418*14b24e2bSVaishali Kulkarni 	}
3419*14b24e2bSVaishali Kulkarni 	if (i == num_images) {
3420*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
3421*14b24e2bSVaishali Kulkarni 			   "Failed to find nvram image of type %08x\n",
3422*14b24e2bSVaishali Kulkarni 			   image_id);
3423*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3424*14b24e2bSVaishali Kulkarni 	}
3425*14b24e2bSVaishali Kulkarni 
3426*14b24e2bSVaishali Kulkarni 	p_image_att->start_addr = mfw_image_att.nvm_start_addr;
3427*14b24e2bSVaishali Kulkarni 	p_image_att->length = mfw_image_att.len;
3428*14b24e2bSVaishali Kulkarni 
3429*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3430*14b24e2bSVaishali Kulkarni }
3431*14b24e2bSVaishali Kulkarni 
3432*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
3433*14b24e2bSVaishali Kulkarni 					     struct ecore_ptt *p_ptt,
3434*14b24e2bSVaishali Kulkarni 					     enum ecore_nvm_images image_id,
3435*14b24e2bSVaishali Kulkarni 					     u8 *p_buffer, u32 buffer_len)
3436*14b24e2bSVaishali Kulkarni {
3437*14b24e2bSVaishali Kulkarni 	struct ecore_nvm_image_att image_att;
3438*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3439*14b24e2bSVaishali Kulkarni 
3440*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(p_buffer, buffer_len);
3441*14b24e2bSVaishali Kulkarni 
3442*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_get_nvm_image_att(p_hwfn, p_ptt, image_id, &image_att);
3443*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3444*14b24e2bSVaishali Kulkarni 		return rc;
3445*14b24e2bSVaishali Kulkarni 
3446*14b24e2bSVaishali Kulkarni 	/* Validate sizes - both the image's and the supplied buffer's */
3447*14b24e2bSVaishali Kulkarni 	if (image_att.length <= 4) {
3448*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
3449*14b24e2bSVaishali Kulkarni 			   "Image [%d] is too small - only %d bytes\n",
3450*14b24e2bSVaishali Kulkarni 			   image_id, image_att.length);
3451*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3452*14b24e2bSVaishali Kulkarni 	}
3453*14b24e2bSVaishali Kulkarni 
3454*14b24e2bSVaishali Kulkarni 	/* Each NVM image is suffixed by CRC; Upper-layer has no need for it */
3455*14b24e2bSVaishali Kulkarni 	image_att.length -= 4;
3456*14b24e2bSVaishali Kulkarni 
3457*14b24e2bSVaishali Kulkarni 	if (image_att.length > buffer_len) {
3458*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
3459*14b24e2bSVaishali Kulkarni 			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
3460*14b24e2bSVaishali Kulkarni 			   image_id, image_att.length, buffer_len);
3461*14b24e2bSVaishali Kulkarni 		return ECORE_NOMEM;
3462*14b24e2bSVaishali Kulkarni 	}
3463*14b24e2bSVaishali Kulkarni 
3464*14b24e2bSVaishali Kulkarni 	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
3465*14b24e2bSVaishali Kulkarni 				  p_buffer, image_att.length);
3466*14b24e2bSVaishali Kulkarni }
3467*14b24e2bSVaishali Kulkarni 
3468*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3469*14b24e2bSVaishali Kulkarni ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
3470*14b24e2bSVaishali Kulkarni 			       struct ecore_ptt *p_ptt,
3471*14b24e2bSVaishali Kulkarni 			       struct ecore_temperature_info *p_temp_info)
3472*14b24e2bSVaishali Kulkarni {
3473*14b24e2bSVaishali Kulkarni 	struct ecore_temperature_sensor *p_temp_sensor;
3474*14b24e2bSVaishali Kulkarni 	struct temperature_status_stc mfw_temp_info;
3475*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
3476*14b24e2bSVaishali Kulkarni 	u32 val;
3477*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3478*14b24e2bSVaishali Kulkarni 	u8 i;
3479*14b24e2bSVaishali Kulkarni 
3480*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
3481*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_TEMPERATURE;
3482*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &mfw_temp_info;
3483*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(mfw_temp_info);
3484*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
3485*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3486*14b24e2bSVaishali Kulkarni 		return rc;
3487*14b24e2bSVaishali Kulkarni 
3488*14b24e2bSVaishali Kulkarni 	OSAL_BUILD_BUG_ON(ECORE_MAX_NUM_OF_SENSORS != MAX_NUM_OF_SENSORS);
3489*14b24e2bSVaishali Kulkarni 	p_temp_info->num_sensors = OSAL_MIN_T(u32, mfw_temp_info.num_of_sensors,
3490*14b24e2bSVaishali Kulkarni 					      ECORE_MAX_NUM_OF_SENSORS);
3491*14b24e2bSVaishali Kulkarni 	for (i = 0; i < p_temp_info->num_sensors; i++) {
3492*14b24e2bSVaishali Kulkarni 		val = mfw_temp_info.sensor[i];
3493*14b24e2bSVaishali Kulkarni 		p_temp_sensor = &p_temp_info->sensors[i];
3494*14b24e2bSVaishali Kulkarni 		p_temp_sensor->sensor_location = (val & SENSOR_LOCATION_MASK) >>
3495*14b24e2bSVaishali Kulkarni 						 SENSOR_LOCATION_SHIFT;
3496*14b24e2bSVaishali Kulkarni 		p_temp_sensor->threshold_high = (val & THRESHOLD_HIGH_MASK) >>
3497*14b24e2bSVaishali Kulkarni 						THRESHOLD_HIGH_SHIFT;
3498*14b24e2bSVaishali Kulkarni 		p_temp_sensor->critical = (val & CRITICAL_TEMPERATURE_MASK) >>
3499*14b24e2bSVaishali Kulkarni 					  CRITICAL_TEMPERATURE_SHIFT;
3500*14b24e2bSVaishali Kulkarni 		p_temp_sensor->current_temp = (val & CURRENT_TEMP_MASK) >>
3501*14b24e2bSVaishali Kulkarni 					      CURRENT_TEMP_SHIFT;
3502*14b24e2bSVaishali Kulkarni 	}
3503*14b24e2bSVaishali Kulkarni 
3504*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3505*14b24e2bSVaishali Kulkarni }
3506*14b24e2bSVaishali Kulkarni 
3507*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_mba_versions(
3508*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn,
3509*14b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt,
3510*14b24e2bSVaishali Kulkarni 	struct ecore_mba_vers *p_mba_vers)
3511*14b24e2bSVaishali Kulkarni {
3512*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_nvm_params params;
3513*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3514*14b24e2bSVaishali Kulkarni 	u32 buf_size;
3515*14b24e2bSVaishali Kulkarni 
3516*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&params, sizeof(params));
3517*14b24e2bSVaishali Kulkarni 	params.type = ECORE_MCP_NVM_RD;
3518*14b24e2bSVaishali Kulkarni 	params.nvm_common.cmd = DRV_MSG_CODE_GET_MBA_VERSION;
3519*14b24e2bSVaishali Kulkarni 	params.nvm_common.offset = 0;
3520*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf = &(p_mba_vers->mba_vers[0]);
3521*14b24e2bSVaishali Kulkarni 	params.nvm_rd.buf_size = &buf_size;
3522*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_nvm_command(p_hwfn, p_ptt, &params);
3523*14b24e2bSVaishali Kulkarni 
3524*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3525*14b24e2bSVaishali Kulkarni 		return rc;
3526*14b24e2bSVaishali Kulkarni 
3527*14b24e2bSVaishali Kulkarni 	if ((params.nvm_common.resp & FW_MSG_CODE_MASK) !=
3528*14b24e2bSVaishali Kulkarni 	    FW_MSG_CODE_NVM_OK)
3529*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3530*14b24e2bSVaishali Kulkarni 
3531*14b24e2bSVaishali Kulkarni 	if (buf_size != MCP_DRV_NVM_BUF_LEN)
3532*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
3533*14b24e2bSVaishali Kulkarni 
3534*14b24e2bSVaishali Kulkarni 	return rc;
3535*14b24e2bSVaishali Kulkarni }
3536*14b24e2bSVaishali Kulkarni 
3537*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_mem_ecc_events(struct ecore_hwfn *p_hwfn,
3538*14b24e2bSVaishali Kulkarni 					      struct ecore_ptt *p_ptt,
3539*14b24e2bSVaishali Kulkarni 					      u64 *num_events)
3540*14b24e2bSVaishali Kulkarni {
3541*14b24e2bSVaishali Kulkarni 	u32 rsp;
3542*14b24e2bSVaishali Kulkarni 
3543*14b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MEM_ECC_EVENTS,
3544*14b24e2bSVaishali Kulkarni 			     0, &rsp, (u32 *)num_events);
3545*14b24e2bSVaishali Kulkarni }
3546*14b24e2bSVaishali Kulkarni 
3547*14b24e2bSVaishali Kulkarni static enum resource_id_enum
3548*14b24e2bSVaishali Kulkarni ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)
3549*14b24e2bSVaishali Kulkarni {
3550*14b24e2bSVaishali Kulkarni 	enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
3551*14b24e2bSVaishali Kulkarni 
3552*14b24e2bSVaishali Kulkarni 	switch (res_id) {
3553*14b24e2bSVaishali Kulkarni 	case ECORE_SB:
3554*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_SB_E;
3555*14b24e2bSVaishali Kulkarni 		break;
3556*14b24e2bSVaishali Kulkarni 	case ECORE_L2_QUEUE:
3557*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
3558*14b24e2bSVaishali Kulkarni 		break;
3559*14b24e2bSVaishali Kulkarni 	case ECORE_VPORT:
3560*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_VPORT_E;
3561*14b24e2bSVaishali Kulkarni 		break;
3562*14b24e2bSVaishali Kulkarni 	case ECORE_RSS_ENG:
3563*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
3564*14b24e2bSVaishali Kulkarni 		break;
3565*14b24e2bSVaishali Kulkarni 	case ECORE_PQ:
3566*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_PQ_E;
3567*14b24e2bSVaishali Kulkarni 		break;
3568*14b24e2bSVaishali Kulkarni 	case ECORE_RL:
3569*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_NUM_RL_E;
3570*14b24e2bSVaishali Kulkarni 		break;
3571*14b24e2bSVaishali Kulkarni 	case ECORE_MAC:
3572*14b24e2bSVaishali Kulkarni 	case ECORE_VLAN:
3573*14b24e2bSVaishali Kulkarni 		/* Each VFC resource can accommodate both a MAC and a VLAN */
3574*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_VFC_FILTER_E;
3575*14b24e2bSVaishali Kulkarni 		break;
3576*14b24e2bSVaishali Kulkarni 	case ECORE_ILT:
3577*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_ILT_E;
3578*14b24e2bSVaishali Kulkarni 		break;
3579*14b24e2bSVaishali Kulkarni 	case ECORE_LL2_QUEUE:
3580*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_LL2_QUEUE_E;
3581*14b24e2bSVaishali Kulkarni 		break;
3582*14b24e2bSVaishali Kulkarni 	case ECORE_RDMA_CNQ_RAM:
3583*14b24e2bSVaishali Kulkarni 	case ECORE_CMDQS_CQS:
3584*14b24e2bSVaishali Kulkarni 		/* CNQ/CMDQS are the same resource */
3585*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_CQS_E;
3586*14b24e2bSVaishali Kulkarni 		break;
3587*14b24e2bSVaishali Kulkarni 	case ECORE_RDMA_STATS_QUEUE:
3588*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
3589*14b24e2bSVaishali Kulkarni 		break;
3590*14b24e2bSVaishali Kulkarni 	case ECORE_BDQ:
3591*14b24e2bSVaishali Kulkarni 		mfw_res_id = RESOURCE_BDQ_E;
3592*14b24e2bSVaishali Kulkarni 		break;
3593*14b24e2bSVaishali Kulkarni 	default:
3594*14b24e2bSVaishali Kulkarni 		break;
3595*14b24e2bSVaishali Kulkarni 	}
3596*14b24e2bSVaishali Kulkarni 
3597*14b24e2bSVaishali Kulkarni 	return mfw_res_id;
3598*14b24e2bSVaishali Kulkarni }
3599*14b24e2bSVaishali Kulkarni 
3600*14b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION_MAJOR	2
3601*14b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION_MINOR	0
3602*14b24e2bSVaishali Kulkarni #define ECORE_RESC_ALLOC_VERSION				\
3603*14b24e2bSVaishali Kulkarni 	((ECORE_RESC_ALLOC_VERSION_MAJOR <<			\
3604*14b24e2bSVaishali Kulkarni 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) |	\
3605*14b24e2bSVaishali Kulkarni 	 (ECORE_RESC_ALLOC_VERSION_MINOR <<			\
3606*14b24e2bSVaishali Kulkarni 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT))
3607*14b24e2bSVaishali Kulkarni 
3608*14b24e2bSVaishali Kulkarni struct ecore_resc_alloc_in_params {
3609*14b24e2bSVaishali Kulkarni 	u32 cmd;
3610*14b24e2bSVaishali Kulkarni 	enum ecore_resources res_id;
3611*14b24e2bSVaishali Kulkarni 	u32 resc_max_val;
3612*14b24e2bSVaishali Kulkarni };
3613*14b24e2bSVaishali Kulkarni 
3614*14b24e2bSVaishali Kulkarni struct ecore_resc_alloc_out_params {
3615*14b24e2bSVaishali Kulkarni 	u32 mcp_resp;
3616*14b24e2bSVaishali Kulkarni 	u32 mcp_param;
3617*14b24e2bSVaishali Kulkarni 	u32 resc_num;
3618*14b24e2bSVaishali Kulkarni 	u32 resc_start;
3619*14b24e2bSVaishali Kulkarni 	u32 vf_resc_num;
3620*14b24e2bSVaishali Kulkarni 	u32 vf_resc_start;
3621*14b24e2bSVaishali Kulkarni 	u32 flags;
3622*14b24e2bSVaishali Kulkarni };
3623*14b24e2bSVaishali Kulkarni 
3624*14b24e2bSVaishali Kulkarni static enum _ecore_status_t
3625*14b24e2bSVaishali Kulkarni ecore_mcp_resc_allocation_msg(struct ecore_hwfn *p_hwfn,
3626*14b24e2bSVaishali Kulkarni 			      struct ecore_ptt *p_ptt,
3627*14b24e2bSVaishali Kulkarni 			      struct ecore_resc_alloc_in_params *p_in_params,
3628*14b24e2bSVaishali Kulkarni 			      struct ecore_resc_alloc_out_params *p_out_params)
3629*14b24e2bSVaishali Kulkarni {
3630*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
3631*14b24e2bSVaishali Kulkarni 	struct resource_info mfw_resc_info;
3632*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3633*14b24e2bSVaishali Kulkarni 
3634*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mfw_resc_info, sizeof(mfw_resc_info));
3635*14b24e2bSVaishali Kulkarni 
3636*14b24e2bSVaishali Kulkarni 	mfw_resc_info.res_id = ecore_mcp_get_mfw_res_id(p_in_params->res_id);
3637*14b24e2bSVaishali Kulkarni 	if (mfw_resc_info.res_id == RESOURCE_NUM_INVALID) {
3638*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn,
3639*14b24e2bSVaishali Kulkarni 		       "Failed to match resource %d [%s] with the MFW resources\n",
3640*14b24e2bSVaishali Kulkarni 		       p_in_params->res_id,
3641*14b24e2bSVaishali Kulkarni 		       ecore_hw_get_resc_name(p_in_params->res_id));
3642*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3643*14b24e2bSVaishali Kulkarni 	}
3644*14b24e2bSVaishali Kulkarni 
3645*14b24e2bSVaishali Kulkarni 	switch (p_in_params->cmd) {
3646*14b24e2bSVaishali Kulkarni 	case DRV_MSG_SET_RESOURCE_VALUE_MSG:
3647*14b24e2bSVaishali Kulkarni 		mfw_resc_info.size = p_in_params->resc_max_val;
3648*14b24e2bSVaishali Kulkarni 		/* Fallthrough */
3649*14b24e2bSVaishali Kulkarni 	case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
3650*14b24e2bSVaishali Kulkarni 		break;
3651*14b24e2bSVaishali Kulkarni 	default:
3652*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Unexpected resource alloc command [0x%08x]\n",
3653*14b24e2bSVaishali Kulkarni 		       p_in_params->cmd);
3654*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3655*14b24e2bSVaishali Kulkarni 	}
3656*14b24e2bSVaishali Kulkarni 
3657*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
3658*14b24e2bSVaishali Kulkarni 	mb_params.cmd = p_in_params->cmd;
3659*14b24e2bSVaishali Kulkarni 	mb_params.param = ECORE_RESC_ALLOC_VERSION;
3660*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &mfw_resc_info;
3661*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(mfw_resc_info);
3662*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = mb_params.p_data_src;
3663*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = mb_params.data_src_size;
3664*14b24e2bSVaishali Kulkarni 
3665*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3666*14b24e2bSVaishali Kulkarni 		   "Resource message request: cmd 0x%08x, res_id %d [%s], hsi_version %d.%d, val 0x%x\n",
3667*14b24e2bSVaishali Kulkarni 		   p_in_params->cmd, p_in_params->res_id,
3668*14b24e2bSVaishali Kulkarni 		   ecore_hw_get_resc_name(p_in_params->res_id),
3669*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param,
3670*14b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
3671*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(mb_params.param,
3672*14b24e2bSVaishali Kulkarni 			   DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
3673*14b24e2bSVaishali Kulkarni 		   p_in_params->resc_max_val);
3674*14b24e2bSVaishali Kulkarni 
3675*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
3676*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3677*14b24e2bSVaishali Kulkarni 		return rc;
3678*14b24e2bSVaishali Kulkarni 
3679*14b24e2bSVaishali Kulkarni 	p_out_params->mcp_resp = mb_params.mcp_resp;
3680*14b24e2bSVaishali Kulkarni 	p_out_params->mcp_param = mb_params.mcp_param;
3681*14b24e2bSVaishali Kulkarni 	p_out_params->resc_num = mfw_resc_info.size;
3682*14b24e2bSVaishali Kulkarni 	p_out_params->resc_start = mfw_resc_info.offset;
3683*14b24e2bSVaishali Kulkarni 	p_out_params->vf_resc_num = mfw_resc_info.vf_size;
3684*14b24e2bSVaishali Kulkarni 	p_out_params->vf_resc_start = mfw_resc_info.vf_offset;
3685*14b24e2bSVaishali Kulkarni 	p_out_params->flags = mfw_resc_info.flags;
3686*14b24e2bSVaishali Kulkarni 
3687*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3688*14b24e2bSVaishali 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",
3689*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
3690*14b24e2bSVaishali Kulkarni 			   FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
3691*14b24e2bSVaishali Kulkarni 		   ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
3692*14b24e2bSVaishali Kulkarni 			   FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
3693*14b24e2bSVaishali Kulkarni 		   p_out_params->resc_num, p_out_params->resc_start,
3694*14b24e2bSVaishali Kulkarni 		   p_out_params->vf_resc_num, p_out_params->vf_resc_start,
3695*14b24e2bSVaishali Kulkarni 		   p_out_params->flags);
3696*14b24e2bSVaishali Kulkarni 
3697*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3698*14b24e2bSVaishali Kulkarni }
3699*14b24e2bSVaishali Kulkarni 
3700*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3701*14b24e2bSVaishali Kulkarni ecore_mcp_set_resc_max_val(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3702*14b24e2bSVaishali Kulkarni 			   enum ecore_resources res_id, u32 resc_max_val,
3703*14b24e2bSVaishali Kulkarni 			   u32 *p_mcp_resp)
3704*14b24e2bSVaishali Kulkarni {
3705*14b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_out_params out_params;
3706*14b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_in_params in_params;
3707*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3708*14b24e2bSVaishali Kulkarni 
3709*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
3710*14b24e2bSVaishali Kulkarni 	in_params.cmd = DRV_MSG_SET_RESOURCE_VALUE_MSG;
3711*14b24e2bSVaishali Kulkarni 	in_params.res_id = res_id;
3712*14b24e2bSVaishali Kulkarni 	in_params.resc_max_val = resc_max_val;
3713*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
3714*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
3715*14b24e2bSVaishali Kulkarni 					   &out_params);
3716*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3717*14b24e2bSVaishali Kulkarni 		return rc;
3718*14b24e2bSVaishali Kulkarni 
3719*14b24e2bSVaishali Kulkarni 	*p_mcp_resp = out_params.mcp_resp;
3720*14b24e2bSVaishali Kulkarni 
3721*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3722*14b24e2bSVaishali Kulkarni }
3723*14b24e2bSVaishali Kulkarni 
3724*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3725*14b24e2bSVaishali Kulkarni ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3726*14b24e2bSVaishali Kulkarni 			enum ecore_resources res_id, u32 *p_mcp_resp,
3727*14b24e2bSVaishali Kulkarni 			u32 *p_resc_num, u32 *p_resc_start)
3728*14b24e2bSVaishali Kulkarni {
3729*14b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_out_params out_params;
3730*14b24e2bSVaishali Kulkarni 	struct ecore_resc_alloc_in_params in_params;
3731*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3732*14b24e2bSVaishali Kulkarni 
3733*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
3734*14b24e2bSVaishali Kulkarni 	in_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
3735*14b24e2bSVaishali Kulkarni 	in_params.res_id = res_id;
3736*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
3737*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
3738*14b24e2bSVaishali Kulkarni 					   &out_params);
3739*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3740*14b24e2bSVaishali Kulkarni 		return rc;
3741*14b24e2bSVaishali Kulkarni 
3742*14b24e2bSVaishali Kulkarni 	*p_mcp_resp = out_params.mcp_resp;
3743*14b24e2bSVaishali Kulkarni 
3744*14b24e2bSVaishali Kulkarni 	if (*p_mcp_resp == FW_MSG_CODE_RESOURCE_ALLOC_OK) {
3745*14b24e2bSVaishali Kulkarni 		*p_resc_num = out_params.resc_num;
3746*14b24e2bSVaishali Kulkarni 		*p_resc_start = out_params.resc_start;
3747*14b24e2bSVaishali Kulkarni 	}
3748*14b24e2bSVaishali Kulkarni 
3749*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3750*14b24e2bSVaishali Kulkarni }
3751*14b24e2bSVaishali Kulkarni 
3752*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_initiate_pf_flr(struct ecore_hwfn *p_hwfn,
3753*14b24e2bSVaishali Kulkarni 					       struct ecore_ptt *p_ptt)
3754*14b24e2bSVaishali Kulkarni {
3755*14b24e2bSVaishali Kulkarni 	u32 mcp_resp, mcp_param;
3756*14b24e2bSVaishali Kulkarni 
3757*14b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_INITIATE_PF_FLR, 0,
3758*14b24e2bSVaishali Kulkarni 			     &mcp_resp, &mcp_param);
3759*14b24e2bSVaishali Kulkarni }
3760*14b24e2bSVaishali Kulkarni 
3761*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_lldp_mac(struct ecore_hwfn *p_hwfn,
3762*14b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
3763*14b24e2bSVaishali Kulkarni 					    u8 lldp_mac_addr[ETH_ALEN])
3764*14b24e2bSVaishali Kulkarni {
3765*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
3766*14b24e2bSVaishali Kulkarni 	struct mcp_mac lldp_mac;
3767*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3768*14b24e2bSVaishali Kulkarni 
3769*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
3770*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_GET_LLDP_MAC;
3771*14b24e2bSVaishali Kulkarni 	mb_params.p_data_dst = &lldp_mac;
3772*14b24e2bSVaishali Kulkarni 	mb_params.data_dst_size = sizeof(lldp_mac);
3773*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
3774*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3775*14b24e2bSVaishali Kulkarni 		return rc;
3776*14b24e2bSVaishali Kulkarni 
3777*14b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
3778*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
3779*14b24e2bSVaishali Kulkarni 			  "MFW lacks support for the GET_LLDP_MAC command [resp 0x%08x]\n",
3780*14b24e2bSVaishali Kulkarni 			  mb_params.mcp_resp);
3781*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3782*14b24e2bSVaishali Kulkarni 	}
3783*14b24e2bSVaishali Kulkarni 
3784*14b24e2bSVaishali Kulkarni 	*(u16 *)lldp_mac_addr = *(u16 *)&lldp_mac.mac_upper;
3785*14b24e2bSVaishali Kulkarni 	*(u32 *)(lldp_mac_addr + 2) = lldp_mac.mac_lower;
3786*14b24e2bSVaishali Kulkarni 
3787*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3788*14b24e2bSVaishali Kulkarni 		   "LLDP MAC address is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
3789*14b24e2bSVaishali Kulkarni 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
3790*14b24e2bSVaishali Kulkarni 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
3791*14b24e2bSVaishali Kulkarni 
3792*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3793*14b24e2bSVaishali Kulkarni }
3794*14b24e2bSVaishali Kulkarni 
3795*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_lldp_mac(struct ecore_hwfn *p_hwfn,
3796*14b24e2bSVaishali Kulkarni 					    struct ecore_ptt *p_ptt,
3797*14b24e2bSVaishali Kulkarni 					    u8 lldp_mac_addr[ETH_ALEN])
3798*14b24e2bSVaishali Kulkarni {
3799*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
3800*14b24e2bSVaishali Kulkarni 	struct mcp_mac lldp_mac;
3801*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3802*14b24e2bSVaishali Kulkarni 
3803*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3804*14b24e2bSVaishali Kulkarni 		   "Configuring LLDP MAC address to %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
3805*14b24e2bSVaishali Kulkarni 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
3806*14b24e2bSVaishali Kulkarni 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
3807*14b24e2bSVaishali Kulkarni 
3808*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&lldp_mac, sizeof(lldp_mac));
3809*14b24e2bSVaishali Kulkarni 	lldp_mac.mac_upper = *(u16 *)lldp_mac_addr;
3810*14b24e2bSVaishali Kulkarni 	lldp_mac.mac_lower = *(u32 *)(lldp_mac_addr + 2);
3811*14b24e2bSVaishali Kulkarni 
3812*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
3813*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_SET_LLDP_MAC;
3814*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &lldp_mac;
3815*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(lldp_mac);
3816*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
3817*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3818*14b24e2bSVaishali Kulkarni 		return rc;
3819*14b24e2bSVaishali Kulkarni 
3820*14b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
3821*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
3822*14b24e2bSVaishali Kulkarni 			  "MFW lacks support for the SET_LLDP_MAC command [resp 0x%08x]\n",
3823*14b24e2bSVaishali Kulkarni 			  mb_params.mcp_resp);
3824*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3825*14b24e2bSVaishali Kulkarni 	}
3826*14b24e2bSVaishali Kulkarni 
3827*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3828*14b24e2bSVaishali Kulkarni }
3829*14b24e2bSVaishali Kulkarni 
3830*14b24e2bSVaishali Kulkarni static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn,
3831*14b24e2bSVaishali Kulkarni 						   struct ecore_ptt *p_ptt,
3832*14b24e2bSVaishali Kulkarni 						   u32 param, u32 *p_mcp_resp,
3833*14b24e2bSVaishali Kulkarni 						   u32 *p_mcp_param)
3834*14b24e2bSVaishali Kulkarni {
3835*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3836*14b24e2bSVaishali Kulkarni 
3837*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_RESOURCE_CMD, param,
3838*14b24e2bSVaishali Kulkarni 			   p_mcp_resp, p_mcp_param);
3839*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3840*14b24e2bSVaishali Kulkarni 		return rc;
3841*14b24e2bSVaishali Kulkarni 
3842*14b24e2bSVaishali Kulkarni 	if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
3843*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
3844*14b24e2bSVaishali Kulkarni 			"The resource command is unsupported by the MFW\n");
3845*14b24e2bSVaishali Kulkarni 		return ECORE_NOTIMPL;
3846*14b24e2bSVaishali Kulkarni 	}
3847*14b24e2bSVaishali Kulkarni 
3848*14b24e2bSVaishali Kulkarni 	if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) {
3849*14b24e2bSVaishali Kulkarni 		u8 opcode = ECORE_MFW_GET_FIELD(param, RESOURCE_CMD_REQ_OPCODE);
3850*14b24e2bSVaishali Kulkarni 
3851*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
3852*14b24e2bSVaishali Kulkarni 			  "The resource command is unknown to the MFW [param 0x%08x, opcode %d]\n",
3853*14b24e2bSVaishali Kulkarni 			  param, opcode);
3854*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3855*14b24e2bSVaishali Kulkarni 	}
3856*14b24e2bSVaishali Kulkarni 
3857*14b24e2bSVaishali Kulkarni 	return rc;
3858*14b24e2bSVaishali Kulkarni }
3859*14b24e2bSVaishali Kulkarni 
3860*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3861*14b24e2bSVaishali Kulkarni __ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3862*14b24e2bSVaishali Kulkarni 		      struct ecore_resc_lock_params *p_params)
3863*14b24e2bSVaishali Kulkarni {
3864*14b24e2bSVaishali Kulkarni 	u32 param = 0, mcp_resp, mcp_param;
3865*14b24e2bSVaishali Kulkarni 	u8 opcode;
3866*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3867*14b24e2bSVaishali Kulkarni 
3868*14b24e2bSVaishali Kulkarni 	switch (p_params->timeout) {
3869*14b24e2bSVaishali Kulkarni 	case ECORE_MCP_RESC_LOCK_TO_DEFAULT:
3870*14b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ;
3871*14b24e2bSVaishali Kulkarni 		p_params->timeout = 0;
3872*14b24e2bSVaishali Kulkarni 		break;
3873*14b24e2bSVaishali Kulkarni 	case ECORE_MCP_RESC_LOCK_TO_NONE:
3874*14b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ_WO_AGING;
3875*14b24e2bSVaishali Kulkarni 		p_params->timeout = 0;
3876*14b24e2bSVaishali Kulkarni 		break;
3877*14b24e2bSVaishali Kulkarni 	default:
3878*14b24e2bSVaishali Kulkarni 		opcode = RESOURCE_OPCODE_REQ_W_AGING;
3879*14b24e2bSVaishali Kulkarni 		break;
3880*14b24e2bSVaishali Kulkarni 	}
3881*14b24e2bSVaishali Kulkarni 
3882*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
3883*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
3884*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, p_params->timeout);
3885*14b24e2bSVaishali Kulkarni 
3886*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3887*14b24e2bSVaishali Kulkarni 		   "Resource lock request: param 0x%08x [age %d, opcode %d, resource %d]\n",
3888*14b24e2bSVaishali Kulkarni 		   param, p_params->timeout, opcode, p_params->resource);
3889*14b24e2bSVaishali Kulkarni 
3890*14b24e2bSVaishali Kulkarni 	/* Attempt to acquire the resource */
3891*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
3892*14b24e2bSVaishali Kulkarni 				    &mcp_param);
3893*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3894*14b24e2bSVaishali Kulkarni 		return rc;
3895*14b24e2bSVaishali Kulkarni 
3896*14b24e2bSVaishali Kulkarni 	/* Analyze the response */
3897*14b24e2bSVaishali Kulkarni 	p_params->owner = ECORE_MFW_GET_FIELD(mcp_param,
3898*14b24e2bSVaishali Kulkarni 					     RESOURCE_CMD_RSP_OWNER);
3899*14b24e2bSVaishali Kulkarni 	opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
3900*14b24e2bSVaishali Kulkarni 
3901*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3902*14b24e2bSVaishali Kulkarni 		   "Resource lock response: mcp_param 0x%08x [opcode %d, owner %d]\n",
3903*14b24e2bSVaishali Kulkarni 		   mcp_param, opcode, p_params->owner);
3904*14b24e2bSVaishali Kulkarni 
3905*14b24e2bSVaishali Kulkarni 	switch (opcode) {
3906*14b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_GNT:
3907*14b24e2bSVaishali Kulkarni 		p_params->b_granted = true;
3908*14b24e2bSVaishali Kulkarni 		break;
3909*14b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_BUSY:
3910*14b24e2bSVaishali Kulkarni 		p_params->b_granted = false;
3911*14b24e2bSVaishali Kulkarni 		break;
3912*14b24e2bSVaishali Kulkarni 	default:
3913*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
3914*14b24e2bSVaishali Kulkarni 			  "Unexpected opcode in resource lock response [mcp_param 0x%08x, opcode %d]\n",
3915*14b24e2bSVaishali Kulkarni 			  mcp_param, opcode);
3916*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
3917*14b24e2bSVaishali Kulkarni 	}
3918*14b24e2bSVaishali Kulkarni 
3919*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3920*14b24e2bSVaishali Kulkarni }
3921*14b24e2bSVaishali Kulkarni 
3922*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3923*14b24e2bSVaishali Kulkarni ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3924*14b24e2bSVaishali Kulkarni 		    struct ecore_resc_lock_params *p_params)
3925*14b24e2bSVaishali Kulkarni {
3926*14b24e2bSVaishali Kulkarni 	u32 retry_cnt = 0;
3927*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3928*14b24e2bSVaishali Kulkarni 
3929*14b24e2bSVaishali Kulkarni 	do {
3930*14b24e2bSVaishali Kulkarni 		/* No need for an interval before the first iteration */
3931*14b24e2bSVaishali Kulkarni 		if (retry_cnt) {
3932*14b24e2bSVaishali Kulkarni 			if (p_params->sleep_b4_retry) {
3933*14b24e2bSVaishali Kulkarni 				u16 retry_interval_in_ms =
3934*14b24e2bSVaishali Kulkarni 					DIV_ROUND_UP(p_params->retry_interval,
3935*14b24e2bSVaishali Kulkarni 						     1000);
3936*14b24e2bSVaishali Kulkarni 
3937*14b24e2bSVaishali Kulkarni 				OSAL_MSLEEP(retry_interval_in_ms);
3938*14b24e2bSVaishali Kulkarni 			} else {
3939*14b24e2bSVaishali Kulkarni 				OSAL_UDELAY(p_params->retry_interval);
3940*14b24e2bSVaishali Kulkarni 			}
3941*14b24e2bSVaishali Kulkarni 		}
3942*14b24e2bSVaishali Kulkarni 
3943*14b24e2bSVaishali Kulkarni 		rc = __ecore_mcp_resc_lock(p_hwfn, p_ptt, p_params);
3944*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
3945*14b24e2bSVaishali Kulkarni 			return rc;
3946*14b24e2bSVaishali Kulkarni 
3947*14b24e2bSVaishali Kulkarni 		if (p_params->b_granted)
3948*14b24e2bSVaishali Kulkarni 			break;
3949*14b24e2bSVaishali Kulkarni 	} while (retry_cnt++ < p_params->retry_num);
3950*14b24e2bSVaishali Kulkarni 
3951*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
3952*14b24e2bSVaishali Kulkarni }
3953*14b24e2bSVaishali Kulkarni 
3954*14b24e2bSVaishali Kulkarni enum _ecore_status_t
3955*14b24e2bSVaishali Kulkarni ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
3956*14b24e2bSVaishali Kulkarni 		      struct ecore_resc_unlock_params *p_params)
3957*14b24e2bSVaishali Kulkarni {
3958*14b24e2bSVaishali Kulkarni 	u32 param = 0, mcp_resp, mcp_param;
3959*14b24e2bSVaishali Kulkarni 	u8 opcode;
3960*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
3961*14b24e2bSVaishali Kulkarni 
3962*14b24e2bSVaishali Kulkarni 	opcode = p_params->b_force ? RESOURCE_OPCODE_FORCE_RELEASE
3963*14b24e2bSVaishali Kulkarni 				   : RESOURCE_OPCODE_RELEASE;
3964*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
3965*14b24e2bSVaishali Kulkarni 	ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
3966*14b24e2bSVaishali Kulkarni 
3967*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3968*14b24e2bSVaishali Kulkarni 		   "Resource unlock request: param 0x%08x [opcode %d, resource %d]\n",
3969*14b24e2bSVaishali Kulkarni 		   param, opcode, p_params->resource);
3970*14b24e2bSVaishali Kulkarni 
3971*14b24e2bSVaishali Kulkarni 	/* Attempt to release the resource */
3972*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
3973*14b24e2bSVaishali Kulkarni 				    &mcp_param);
3974*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
3975*14b24e2bSVaishali Kulkarni 		return rc;
3976*14b24e2bSVaishali Kulkarni 
3977*14b24e2bSVaishali Kulkarni 	/* Analyze the response */
3978*14b24e2bSVaishali Kulkarni 	opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
3979*14b24e2bSVaishali Kulkarni 
3980*14b24e2bSVaishali Kulkarni 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3981*14b24e2bSVaishali Kulkarni 		   "Resource unlock response: mcp_param 0x%08x [opcode %d]\n",
3982*14b24e2bSVaishali Kulkarni 		   mcp_param, opcode);
3983*14b24e2bSVaishali Kulkarni 
3984*14b24e2bSVaishali Kulkarni 	switch (opcode) {
3985*14b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_RELEASED_PREVIOUS:
3986*14b24e2bSVaishali Kulkarni 		DP_INFO(p_hwfn,
3987*14b24e2bSVaishali Kulkarni 			"Resource unlock request for an already released resource [%d]\n",
3988*14b24e2bSVaishali Kulkarni 			p_params->resource);
3989*14b24e2bSVaishali Kulkarni 		/* Fallthrough */
3990*14b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_RELEASED:
3991*14b24e2bSVaishali Kulkarni 		p_params->b_released = true;
3992*14b24e2bSVaishali Kulkarni 		break;
3993*14b24e2bSVaishali Kulkarni 	case RESOURCE_OPCODE_WRONG_OWNER:
3994*14b24e2bSVaishali Kulkarni 		p_params->b_released = false;
3995*14b24e2bSVaishali Kulkarni 		break;
3996*14b24e2bSVaishali Kulkarni 	default:
3997*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
3998*14b24e2bSVaishali Kulkarni 			  "Unexpected opcode in resource unlock response [mcp_param 0x%08x, opcode %d]\n",
3999*14b24e2bSVaishali Kulkarni 			  mcp_param, opcode);
4000*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
4001*14b24e2bSVaishali Kulkarni 	}
4002*14b24e2bSVaishali Kulkarni 
4003*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
4004*14b24e2bSVaishali Kulkarni }
4005*14b24e2bSVaishali Kulkarni 
4006*14b24e2bSVaishali Kulkarni enum _ecore_status_t
4007*14b24e2bSVaishali Kulkarni ecore_mcp_update_fcoe_cvid(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
4008*14b24e2bSVaishali Kulkarni 			   u16 vlan)
4009*14b24e2bSVaishali Kulkarni {
4010*14b24e2bSVaishali Kulkarni 	u32 resp = 0, param = 0;
4011*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
4012*14b24e2bSVaishali Kulkarni 
4013*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OEM_UPDATE_FCOE_CVID,
4014*14b24e2bSVaishali Kulkarni 			   (u32)vlan << DRV_MB_PARAM_FCOE_CVID_SHIFT,
4015*14b24e2bSVaishali Kulkarni 			   &resp, &param);
4016*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
4017*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to update fcoe vlan, rc = %d\n", rc);
4018*14b24e2bSVaishali Kulkarni 
4019*14b24e2bSVaishali Kulkarni 	return rc;
4020*14b24e2bSVaishali Kulkarni }
4021*14b24e2bSVaishali Kulkarni 
4022*14b24e2bSVaishali Kulkarni enum _ecore_status_t
4023*14b24e2bSVaishali Kulkarni ecore_mcp_update_fcoe_fabric_name(struct ecore_hwfn *p_hwfn,
4024*14b24e2bSVaishali Kulkarni 				  struct ecore_ptt *p_ptt, u8 *wwn)
4025*14b24e2bSVaishali Kulkarni {
4026*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params;
4027*14b24e2bSVaishali Kulkarni 	struct mcp_wwn fabric_name;
4028*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
4029*14b24e2bSVaishali Kulkarni 
4030*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&fabric_name, sizeof(fabric_name));
4031*14b24e2bSVaishali Kulkarni 	fabric_name.wwn_upper = *(u32 *)wwn;
4032*14b24e2bSVaishali Kulkarni 	fabric_name.wwn_lower = *(u32 *)(wwn + 4);
4033*14b24e2bSVaishali Kulkarni 
4034*14b24e2bSVaishali Kulkarni 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
4035*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_OEM_UPDATE_FCOE_FABRIC_NAME;
4036*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &fabric_name;
4037*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(fabric_name);
4038*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
4039*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS)
4040*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed to update fcoe wwn, rc = %d\n", rc);
4041*14b24e2bSVaishali Kulkarni 
4042*14b24e2bSVaishali Kulkarni 	return rc;
4043*14b24e2bSVaishali Kulkarni }
4044*14b24e2bSVaishali Kulkarni 
4045*14b24e2bSVaishali Kulkarni void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
4046*14b24e2bSVaishali Kulkarni 		      u32 offset, u32 val)
4047*14b24e2bSVaishali Kulkarni {
4048*14b24e2bSVaishali Kulkarni 	struct ecore_mcp_mb_params mb_params = {0};
4049*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t	   rc = ECORE_SUCCESS;
4050*14b24e2bSVaishali Kulkarni 	u32			   dword = val;
4051*14b24e2bSVaishali Kulkarni 
4052*14b24e2bSVaishali Kulkarni 	mb_params.cmd = DRV_MSG_CODE_WRITE_WOL_REG;
4053*14b24e2bSVaishali Kulkarni 	mb_params.param = offset;
4054*14b24e2bSVaishali Kulkarni 	mb_params.p_data_src = &dword;
4055*14b24e2bSVaishali Kulkarni 	mb_params.data_src_size = sizeof(dword);
4056*14b24e2bSVaishali Kulkarni 
4057*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
4058*14b24e2bSVaishali Kulkarni 	if (rc != ECORE_SUCCESS) {
4059*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
4060*14b24e2bSVaishali Kulkarni 			  "Failed to wol write request, rc = %d\n", rc);
4061*14b24e2bSVaishali Kulkarni 	}
4062*14b24e2bSVaishali Kulkarni 
4063*14b24e2bSVaishali Kulkarni 	if (mb_params.mcp_resp != FW_MSG_CODE_WOL_READ_WRITE_OK) {
4064*14b24e2bSVaishali Kulkarni 		DP_NOTICE(p_hwfn, false,
4065*14b24e2bSVaishali Kulkarni 			  "Failed to write value 0x%x to offset 0x%x [mcp_resp 0x%x]\n",
4066*14b24e2bSVaishali Kulkarni 			  val, offset, mb_params.mcp_resp);
4067*14b24e2bSVaishali Kulkarni 		rc = ECORE_UNKNOWN_ERROR;
4068*14b24e2bSVaishali Kulkarni 	}
4069*14b24e2bSVaishali Kulkarni }
4070*14b24e2bSVaishali Kulkarni 
4071*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_get_capabilities(struct ecore_hwfn *p_hwfn,
4072*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
4073*14b24e2bSVaishali Kulkarni {
4074*14b24e2bSVaishali Kulkarni 	u32 mcp_resp;
4075*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
4076*14b24e2bSVaishali Kulkarni 
4077*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT,
4078*14b24e2bSVaishali Kulkarni 			   0, &mcp_resp, &p_hwfn->mcp_info->capabilities);
4079*14b24e2bSVaishali Kulkarni 	if (rc == ECORE_SUCCESS)
4080*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_PROBE),
4081*14b24e2bSVaishali Kulkarni 			   "MFW supported features: %08x\n",
4082*14b24e2bSVaishali Kulkarni 			   p_hwfn->mcp_info->capabilities);
4083*14b24e2bSVaishali Kulkarni 
4084*14b24e2bSVaishali Kulkarni 	return rc;
4085*14b24e2bSVaishali Kulkarni }
4086*14b24e2bSVaishali Kulkarni 
4087*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_mcp_set_capabilities(struct ecore_hwfn *p_hwfn,
4088*14b24e2bSVaishali Kulkarni 						struct ecore_ptt *p_ptt)
4089*14b24e2bSVaishali Kulkarni {
4090*14b24e2bSVaishali Kulkarni 	u32 mcp_resp, mcp_param, features;
4091*14b24e2bSVaishali Kulkarni 
4092*14b24e2bSVaishali Kulkarni 	features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ |
4093*14b24e2bSVaishali Kulkarni 		   DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE;
4094*14b24e2bSVaishali Kulkarni 
4095*14b24e2bSVaishali Kulkarni 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
4096*14b24e2bSVaishali Kulkarni 			     features, &mcp_resp, &mcp_param);
4097*14b24e2bSVaishali Kulkarni }
4098