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