xref: /freebsd/sys/dev/qlnx/qlnxe/ecore_mcp.c (revision 1c45a62a2f667b45ec10a92ad58ff5a34e68b569)
111e25f0dSDavid C Somayajulu /*
211e25f0dSDavid C Somayajulu  * Copyright (c) 2017-2018 Cavium, Inc.
311e25f0dSDavid C Somayajulu  * All rights reserved.
411e25f0dSDavid C Somayajulu  *
511e25f0dSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
611e25f0dSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
711e25f0dSDavid C Somayajulu  *  are met:
811e25f0dSDavid C Somayajulu  *
911e25f0dSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
1011e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
1111e25f0dSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
1211e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
1311e25f0dSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
1411e25f0dSDavid C Somayajulu  *
1511e25f0dSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1611e25f0dSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1711e25f0dSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1811e25f0dSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1911e25f0dSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2011e25f0dSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2111e25f0dSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2211e25f0dSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2311e25f0dSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2411e25f0dSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2511e25f0dSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
2611e25f0dSDavid C Somayajulu  */
2711e25f0dSDavid C Somayajulu /*
2811e25f0dSDavid C Somayajulu  * File : ecore_mcp.c
2911e25f0dSDavid C Somayajulu  */
3011e25f0dSDavid C Somayajulu #include <sys/cdefs.h>
3111e25f0dSDavid C Somayajulu #include "bcm_osal.h"
3211e25f0dSDavid C Somayajulu #include "ecore.h"
3311e25f0dSDavid C Somayajulu #include "ecore_status.h"
3411e25f0dSDavid C Somayajulu #include "nvm_map.h"
3511e25f0dSDavid C Somayajulu #include "nvm_cfg.h"
3611e25f0dSDavid C Somayajulu #include "ecore_mcp.h"
3711e25f0dSDavid C Somayajulu #include "mcp_public.h"
3811e25f0dSDavid C Somayajulu #include "reg_addr.h"
3911e25f0dSDavid C Somayajulu #include "ecore_hw.h"
4011e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h"
4111e25f0dSDavid C Somayajulu #include "ecore_sriov.h"
4211e25f0dSDavid C Somayajulu #include "ecore_vf.h"
4311e25f0dSDavid C Somayajulu #include "ecore_iov_api.h"
4411e25f0dSDavid C Somayajulu #include "ecore_gtt_reg_addr.h"
4511e25f0dSDavid C Somayajulu #include "ecore_iro.h"
4611e25f0dSDavid C Somayajulu #include "ecore_dcbx.h"
479efd0ba7SDavid C Somayajulu #include "ecore_sp_commands.h"
48217ec208SDavid C Somayajulu #include "ecore_cxt.h"
4911e25f0dSDavid C Somayajulu 
5011e25f0dSDavid C Somayajulu #define CHIP_MCP_RESP_ITER_US 10
5111e25f0dSDavid C Somayajulu #define EMUL_MCP_RESP_ITER_US 1000 * 1000
5211e25f0dSDavid C Somayajulu 
5311e25f0dSDavid C Somayajulu #define ECORE_DRV_MB_MAX_RETRIES	(500 * 1000) /* Account for 5 sec */
5411e25f0dSDavid C Somayajulu #define ECORE_MCP_RESET_RETRIES		(50 * 1000) /* Account for 500 msec */
5511e25f0dSDavid C Somayajulu 
5611e25f0dSDavid C Somayajulu #define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \
5711e25f0dSDavid C Somayajulu 	ecore_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \
5811e25f0dSDavid C Somayajulu 		 _val)
5911e25f0dSDavid C Somayajulu 
6011e25f0dSDavid C Somayajulu #define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \
6111e25f0dSDavid C Somayajulu 	ecore_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset))
6211e25f0dSDavid C Somayajulu 
6311e25f0dSDavid C Somayajulu #define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \
6411e25f0dSDavid C Somayajulu 	DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \
6511e25f0dSDavid C Somayajulu 		     OFFSETOF(struct public_drv_mb, _field), _val)
6611e25f0dSDavid C Somayajulu 
6711e25f0dSDavid C Somayajulu #define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \
6811e25f0dSDavid C Somayajulu 	DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \
6911e25f0dSDavid C Somayajulu 		     OFFSETOF(struct public_drv_mb, _field))
7011e25f0dSDavid C Somayajulu 
7111e25f0dSDavid C Somayajulu #define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \
729efd0ba7SDavid C Somayajulu 	DRV_ID_PDA_COMP_VER_OFFSET)
7311e25f0dSDavid C Somayajulu 
749efd0ba7SDavid C Somayajulu #define MCP_BYTES_PER_MBIT_OFFSET 17
7511e25f0dSDavid C Somayajulu 
76217ec208SDavid C Somayajulu #ifdef _NTDDK_
77217ec208SDavid C Somayajulu #pragma warning(push)
78217ec208SDavid C Somayajulu #pragma warning(disable : 28167)
79217ec208SDavid C Somayajulu #pragma warning(disable : 28123)
80217ec208SDavid C Somayajulu #endif
81217ec208SDavid C Somayajulu 
8211e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
8311e25f0dSDavid C Somayajulu static int loaded;
8411e25f0dSDavid C Somayajulu static int loaded_port[MAX_NUM_PORTS] = { 0 };
8511e25f0dSDavid C Somayajulu #endif
8611e25f0dSDavid C Somayajulu 
ecore_mcp_is_init(struct ecore_hwfn * p_hwfn)8711e25f0dSDavid C Somayajulu bool ecore_mcp_is_init(struct ecore_hwfn *p_hwfn)
8811e25f0dSDavid C Somayajulu {
8911e25f0dSDavid C Somayajulu 	if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base)
9011e25f0dSDavid C Somayajulu 		return false;
9111e25f0dSDavid C Somayajulu 	return true;
9211e25f0dSDavid C Somayajulu }
9311e25f0dSDavid C Somayajulu 
ecore_mcp_cmd_port_init(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)9411e25f0dSDavid C Somayajulu void ecore_mcp_cmd_port_init(struct ecore_hwfn *p_hwfn,
9511e25f0dSDavid C Somayajulu 			     struct ecore_ptt *p_ptt)
9611e25f0dSDavid C Somayajulu {
9711e25f0dSDavid C Somayajulu 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
9811e25f0dSDavid C Somayajulu 					PUBLIC_PORT);
9911e25f0dSDavid C Somayajulu 	u32 mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt, addr);
10011e25f0dSDavid C Somayajulu 
10111e25f0dSDavid C Somayajulu 	p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize,
10211e25f0dSDavid C Somayajulu 						   MFW_PORT(p_hwfn));
10311e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
10411e25f0dSDavid C Somayajulu 		   "port_addr = 0x%x, port_id 0x%02x\n",
10511e25f0dSDavid C Somayajulu 		   p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn));
10611e25f0dSDavid C Somayajulu }
10711e25f0dSDavid C Somayajulu 
ecore_mcp_read_mb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)10811e25f0dSDavid C Somayajulu void ecore_mcp_read_mb(struct ecore_hwfn *p_hwfn,
10911e25f0dSDavid C Somayajulu 		       struct ecore_ptt *p_ptt)
11011e25f0dSDavid C Somayajulu {
11111e25f0dSDavid C Somayajulu 	u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length);
11211e25f0dSDavid C Somayajulu 	OSAL_BE32 tmp;
11311e25f0dSDavid C Somayajulu 	u32 i;
11411e25f0dSDavid C Somayajulu 
11511e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
11611e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
11711e25f0dSDavid C Somayajulu 		return;
11811e25f0dSDavid C Somayajulu #endif
11911e25f0dSDavid C Somayajulu 
12011e25f0dSDavid C Somayajulu 	if (!p_hwfn->mcp_info->public_base)
12111e25f0dSDavid C Somayajulu 		return;
12211e25f0dSDavid C Somayajulu 
12311e25f0dSDavid C Somayajulu 	for (i = 0; i < length; i++) {
12411e25f0dSDavid C Somayajulu 		tmp = ecore_rd(p_hwfn, p_ptt,
12511e25f0dSDavid C Somayajulu 			       p_hwfn->mcp_info->mfw_mb_addr +
12611e25f0dSDavid C Somayajulu 			       (i << 2) + sizeof(u32));
12711e25f0dSDavid C Somayajulu 
12811e25f0dSDavid C Somayajulu 		((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] =
12911e25f0dSDavid C Somayajulu 						OSAL_BE32_TO_CPU(tmp);
13011e25f0dSDavid C Somayajulu 	}
13111e25f0dSDavid C Somayajulu }
13211e25f0dSDavid C Somayajulu 
1339efd0ba7SDavid C Somayajulu struct ecore_mcp_cmd_elem {
1349efd0ba7SDavid C Somayajulu 	osal_list_entry_t list;
1359efd0ba7SDavid C Somayajulu 	struct ecore_mcp_mb_params *p_mb_params;
1369efd0ba7SDavid C Somayajulu 	u16 expected_seq_num;
1379efd0ba7SDavid C Somayajulu 	bool b_is_completed;
1389efd0ba7SDavid C Somayajulu };
1399efd0ba7SDavid C Somayajulu 
1409efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
1419efd0ba7SDavid C Somayajulu static struct ecore_mcp_cmd_elem *
ecore_mcp_cmd_add_elem(struct ecore_hwfn * p_hwfn,struct ecore_mcp_mb_params * p_mb_params,u16 expected_seq_num)1429efd0ba7SDavid C Somayajulu ecore_mcp_cmd_add_elem(struct ecore_hwfn *p_hwfn,
1439efd0ba7SDavid C Somayajulu 		       struct ecore_mcp_mb_params *p_mb_params,
1449efd0ba7SDavid C Somayajulu 		       u16 expected_seq_num)
1459efd0ba7SDavid C Somayajulu {
1469efd0ba7SDavid C Somayajulu 	struct ecore_mcp_cmd_elem *p_cmd_elem = OSAL_NULL;
1479efd0ba7SDavid C Somayajulu 
1489efd0ba7SDavid C Somayajulu 	p_cmd_elem = OSAL_ZALLOC(p_hwfn->p_dev, GFP_ATOMIC,
1499efd0ba7SDavid C Somayajulu 				 sizeof(*p_cmd_elem));
1509efd0ba7SDavid C Somayajulu 	if (!p_cmd_elem) {
1519efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1529efd0ba7SDavid C Somayajulu 			  "Failed to allocate `struct ecore_mcp_cmd_elem'\n");
1539efd0ba7SDavid C Somayajulu 		goto out;
1549efd0ba7SDavid C Somayajulu 	}
1559efd0ba7SDavid C Somayajulu 
1569efd0ba7SDavid C Somayajulu 	p_cmd_elem->p_mb_params = p_mb_params;
1579efd0ba7SDavid C Somayajulu 	p_cmd_elem->expected_seq_num = expected_seq_num;
1589efd0ba7SDavid C Somayajulu 	OSAL_LIST_PUSH_HEAD(&p_cmd_elem->list, &p_hwfn->mcp_info->cmd_list);
1599efd0ba7SDavid C Somayajulu out:
1609efd0ba7SDavid C Somayajulu 	return p_cmd_elem;
1619efd0ba7SDavid C Somayajulu }
1629efd0ba7SDavid C Somayajulu 
1639efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
ecore_mcp_cmd_del_elem(struct ecore_hwfn * p_hwfn,struct ecore_mcp_cmd_elem * p_cmd_elem)1649efd0ba7SDavid C Somayajulu static void ecore_mcp_cmd_del_elem(struct ecore_hwfn *p_hwfn,
1659efd0ba7SDavid C Somayajulu 				   struct ecore_mcp_cmd_elem *p_cmd_elem)
1669efd0ba7SDavid C Somayajulu {
1679efd0ba7SDavid C Somayajulu 	OSAL_LIST_REMOVE_ENTRY(&p_cmd_elem->list, &p_hwfn->mcp_info->cmd_list);
1689efd0ba7SDavid C Somayajulu 	OSAL_FREE(p_hwfn->p_dev, p_cmd_elem);
1699efd0ba7SDavid C Somayajulu }
1709efd0ba7SDavid C Somayajulu 
1719efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
1729efd0ba7SDavid C Somayajulu static struct ecore_mcp_cmd_elem *
ecore_mcp_cmd_get_elem(struct ecore_hwfn * p_hwfn,u16 seq_num)1739efd0ba7SDavid C Somayajulu ecore_mcp_cmd_get_elem(struct ecore_hwfn *p_hwfn, u16 seq_num)
1749efd0ba7SDavid C Somayajulu {
1759efd0ba7SDavid C Somayajulu 	struct ecore_mcp_cmd_elem *p_cmd_elem = OSAL_NULL;
1769efd0ba7SDavid C Somayajulu 
1779efd0ba7SDavid C Somayajulu 	OSAL_LIST_FOR_EACH_ENTRY(p_cmd_elem, &p_hwfn->mcp_info->cmd_list, list,
1789efd0ba7SDavid C Somayajulu 				 struct ecore_mcp_cmd_elem) {
1799efd0ba7SDavid C Somayajulu 		if (p_cmd_elem->expected_seq_num == seq_num)
1809efd0ba7SDavid C Somayajulu 			return p_cmd_elem;
1819efd0ba7SDavid C Somayajulu 	}
1829efd0ba7SDavid C Somayajulu 
1839efd0ba7SDavid C Somayajulu 	return OSAL_NULL;
1849efd0ba7SDavid C Somayajulu }
1859efd0ba7SDavid C Somayajulu 
ecore_mcp_free(struct ecore_hwfn * p_hwfn)18611e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_free(struct ecore_hwfn *p_hwfn)
18711e25f0dSDavid C Somayajulu {
18811e25f0dSDavid C Somayajulu 	if (p_hwfn->mcp_info) {
1899efd0ba7SDavid C Somayajulu 		struct ecore_mcp_cmd_elem *p_cmd_elem = OSAL_NULL, *p_tmp;
1909efd0ba7SDavid C Somayajulu 
19111e25f0dSDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_cur);
19211e25f0dSDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_shadow);
1939efd0ba7SDavid C Somayajulu 
194*1c45a62aSKeith Reynolds 		OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->cmd_lock);
1959efd0ba7SDavid C Somayajulu 		OSAL_LIST_FOR_EACH_ENTRY_SAFE(p_cmd_elem, p_tmp,
1969efd0ba7SDavid C Somayajulu 					      &p_hwfn->mcp_info->cmd_list, list,
1979efd0ba7SDavid C Somayajulu 					      struct ecore_mcp_cmd_elem) {
1989efd0ba7SDavid C Somayajulu 			ecore_mcp_cmd_del_elem(p_hwfn, p_cmd_elem);
1999efd0ba7SDavid C Somayajulu 		}
200*1c45a62aSKeith Reynolds 		OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
2019efd0ba7SDavid C Somayajulu 
20211e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_LOCK_ALLOC
203*1c45a62aSKeith Reynolds 		OSAL_MUTEX_DEALLOC(&p_hwfn->mcp_info->cmd_lock);
204*1c45a62aSKeith Reynolds 		OSAL_MUTEX_DEALLOC(&p_hwfn->mcp_info->link_lock);
20511e25f0dSDavid C Somayajulu #endif
20611e25f0dSDavid C Somayajulu 	}
2079efd0ba7SDavid C Somayajulu 
20811e25f0dSDavid C Somayajulu 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info);
20911e25f0dSDavid C Somayajulu 	p_hwfn->mcp_info = OSAL_NULL;
21011e25f0dSDavid C Somayajulu 
21111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
21211e25f0dSDavid C Somayajulu }
21311e25f0dSDavid C Somayajulu 
214217ec208SDavid C Somayajulu /* Maximum of 1 sec to wait for the SHMEM ready indication */
215217ec208SDavid C Somayajulu #define ECPRE_MCP_SHMEM_RDY_MAX_RETRIES	20
216217ec208SDavid C Somayajulu #define ECORE_MCP_SHMEM_RDY_ITER_MS	50
217217ec208SDavid C Somayajulu 
ecore_load_mcp_offsets(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)21811e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_load_mcp_offsets(struct ecore_hwfn *p_hwfn,
21911e25f0dSDavid C Somayajulu 					    struct ecore_ptt *p_ptt)
22011e25f0dSDavid C Somayajulu {
22111e25f0dSDavid C Somayajulu 	struct ecore_mcp_info *p_info = p_hwfn->mcp_info;
222217ec208SDavid C Somayajulu 	u8 cnt = ECPRE_MCP_SHMEM_RDY_MAX_RETRIES;
223217ec208SDavid C Somayajulu 	u8 msec = ECORE_MCP_SHMEM_RDY_ITER_MS;
22411e25f0dSDavid C Somayajulu 	u32 drv_mb_offsize, mfw_mb_offsize;
22511e25f0dSDavid C Somayajulu 	u32 mcp_pf_id = MCP_PF_ID(p_hwfn);
22611e25f0dSDavid C Somayajulu 
22711e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
22811e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
22911e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Emulation - assume no MFW\n");
23011e25f0dSDavid C Somayajulu 		p_info->public_base = 0;
23111e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
23211e25f0dSDavid C Somayajulu 	}
23311e25f0dSDavid C Somayajulu #endif
23411e25f0dSDavid C Somayajulu 
23511e25f0dSDavid C Somayajulu 	p_info->public_base = ecore_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR);
23611e25f0dSDavid C Somayajulu 	if (!p_info->public_base)
23711e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
23811e25f0dSDavid C Somayajulu 
23911e25f0dSDavid C Somayajulu 	p_info->public_base |= GRCBASE_MCP;
24011e25f0dSDavid C Somayajulu 
241217ec208SDavid C Somayajulu 	/* Get the MFW MB address and number of supported messages */
242217ec208SDavid C Somayajulu 	mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt,
243217ec208SDavid C Somayajulu 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
244217ec208SDavid C Somayajulu 				  PUBLIC_MFW_MB));
245217ec208SDavid C Somayajulu 	p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id);
246217ec208SDavid C Somayajulu 	p_info->mfw_mb_length = (u16)ecore_rd(p_hwfn, p_ptt,
247217ec208SDavid C Somayajulu 					      p_info->mfw_mb_addr);
248217ec208SDavid C Somayajulu 
249217ec208SDavid C Somayajulu 	/* @@@TBD:
250217ec208SDavid C Somayajulu 	 * The driver can notify that there was an MCP reset, and read the SHMEM
251217ec208SDavid C Somayajulu 	 * values before the MFW has completed initializing them.
252217ec208SDavid C Somayajulu 	 * As a temporary solution, the "sup_msgs" field is used as a data ready
253217ec208SDavid C Somayajulu 	 * indication.
254217ec208SDavid C Somayajulu 	 * This should be replaced with an actual indication when it is provided
255217ec208SDavid C Somayajulu 	 * by the MFW.
256217ec208SDavid C Somayajulu 	 */
257217ec208SDavid C Somayajulu 	while (!p_info->mfw_mb_length && cnt--) {
258217ec208SDavid C Somayajulu 		OSAL_MSLEEP(msec);
259217ec208SDavid C Somayajulu 		p_info->mfw_mb_length = (u16)ecore_rd(p_hwfn, p_ptt,
260217ec208SDavid C Somayajulu 						      p_info->mfw_mb_addr);
261217ec208SDavid C Somayajulu 	}
262217ec208SDavid C Somayajulu 
263217ec208SDavid C Somayajulu 	if (!cnt) {
264217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
265217ec208SDavid C Somayajulu 			  "Failed to get the SHMEM ready notification after %d msec\n",
266217ec208SDavid C Somayajulu 			  ECPRE_MCP_SHMEM_RDY_MAX_RETRIES * msec);
267217ec208SDavid C Somayajulu 		return ECORE_TIMEOUT;
268217ec208SDavid C Somayajulu 	}
269217ec208SDavid C Somayajulu 
27011e25f0dSDavid C Somayajulu 	/* Calculate the driver and MFW mailbox address */
27111e25f0dSDavid C Somayajulu 	drv_mb_offsize = ecore_rd(p_hwfn, p_ptt,
27211e25f0dSDavid C Somayajulu 				  SECTION_OFFSIZE_ADDR(p_info->public_base,
27311e25f0dSDavid C Somayajulu 						       PUBLIC_DRV_MB));
27411e25f0dSDavid C Somayajulu 	p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id);
27511e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
27611e25f0dSDavid C Somayajulu 		   "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n",
27711e25f0dSDavid C Somayajulu 		   drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id);
27811e25f0dSDavid C Somayajulu 
27911e25f0dSDavid C Somayajulu 	/* Get the current driver mailbox sequence before sending
28011e25f0dSDavid C Somayajulu 	 * the first command
28111e25f0dSDavid C Somayajulu 	 */
28211e25f0dSDavid C Somayajulu 	p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) &
28311e25f0dSDavid C Somayajulu 				       DRV_MSG_SEQ_NUMBER_MASK;
28411e25f0dSDavid C Somayajulu 
28511e25f0dSDavid C Somayajulu 	/* Get current FW pulse sequence */
28611e25f0dSDavid C Somayajulu 	p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) &
28711e25f0dSDavid C Somayajulu 				DRV_PULSE_SEQ_MASK;
28811e25f0dSDavid C Somayajulu 
2899efd0ba7SDavid C Somayajulu 	p_info->mcp_hist = ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
29011e25f0dSDavid C Somayajulu 
29111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
29211e25f0dSDavid C Somayajulu }
29311e25f0dSDavid C Somayajulu 
ecore_mcp_cmd_init(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)29411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_cmd_init(struct ecore_hwfn *p_hwfn,
29511e25f0dSDavid C Somayajulu 					struct ecore_ptt *p_ptt)
29611e25f0dSDavid C Somayajulu {
29711e25f0dSDavid C Somayajulu 	struct ecore_mcp_info *p_info;
29811e25f0dSDavid C Somayajulu 	u32 size;
29911e25f0dSDavid C Somayajulu 
30011e25f0dSDavid C Somayajulu 	/* Allocate mcp_info structure */
30111e25f0dSDavid C Somayajulu 	p_hwfn->mcp_info = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
30211e25f0dSDavid C Somayajulu 			sizeof(*p_hwfn->mcp_info));
303217ec208SDavid C Somayajulu 	if (!p_hwfn->mcp_info) {
304217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Failed to allocate mcp_info\n");
305217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
306217ec208SDavid C Somayajulu 	}
30711e25f0dSDavid C Somayajulu 	p_info = p_hwfn->mcp_info;
30811e25f0dSDavid C Somayajulu 
3099efd0ba7SDavid C Somayajulu 	/* Initialize the MFW spinlocks */
3109efd0ba7SDavid C Somayajulu #ifdef CONFIG_ECORE_LOCK_ALLOC
311*1c45a62aSKeith Reynolds 	if (OSAL_MUTEX_LOCK_ALLOC(p_hwfn, &p_info->cmd_lock)) {
312217ec208SDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info);
313217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
314217ec208SDavid C Somayajulu 	}
315*1c45a62aSKeith Reynolds 	if (OSAL_MUTEX_ALLOC(p_hwfn, &p_info->link_lock)) {
316*1c45a62aSKeith Reynolds 		OSAL_MUTEX_DEALLOC(&p_info->cmd_lock);
317217ec208SDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info);
318217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
319217ec208SDavid C Somayajulu 	}
3209efd0ba7SDavid C Somayajulu #endif
321*1c45a62aSKeith Reynolds 	OSAL_MUTEX_INIT(&p_info->cmd_lock);
322*1c45a62aSKeith Reynolds 	OSAL_MUTEX_INIT(&p_info->link_lock);
3239efd0ba7SDavid C Somayajulu 
3249efd0ba7SDavid C Somayajulu 	OSAL_LIST_INIT(&p_info->cmd_list);
3259efd0ba7SDavid C Somayajulu 
32611e25f0dSDavid C Somayajulu 	if (ecore_load_mcp_offsets(p_hwfn, p_ptt) != ECORE_SUCCESS) {
32711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "MCP is not initialized\n");
32811e25f0dSDavid C Somayajulu 		/* Do not free mcp_info here, since public_base indicate that
32911e25f0dSDavid C Somayajulu 		 * the MCP is not initialized
33011e25f0dSDavid C Somayajulu 		 */
33111e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
33211e25f0dSDavid C Somayajulu 	}
33311e25f0dSDavid C Somayajulu 
33411e25f0dSDavid C Somayajulu 	size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32);
33511e25f0dSDavid C Somayajulu 	p_info->mfw_mb_cur = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
33611e25f0dSDavid C Somayajulu 	p_info->mfw_mb_shadow = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, size);
337217ec208SDavid C Somayajulu 	if (p_info->mfw_mb_cur == OSAL_NULL || p_info->mfw_mb_shadow == OSAL_NULL)
33811e25f0dSDavid C Somayajulu 		goto err;
33911e25f0dSDavid C Somayajulu 
34011e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
34111e25f0dSDavid C Somayajulu 
34211e25f0dSDavid C Somayajulu err:
343217ec208SDavid C Somayajulu 	DP_NOTICE(p_hwfn, false, "Failed to allocate mcp memory\n");
34411e25f0dSDavid C Somayajulu 	ecore_mcp_free(p_hwfn);
34511e25f0dSDavid C Somayajulu 	return ECORE_NOMEM;
34611e25f0dSDavid C Somayajulu }
34711e25f0dSDavid C Somayajulu 
ecore_mcp_reread_offsets(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)3489efd0ba7SDavid C Somayajulu static void ecore_mcp_reread_offsets(struct ecore_hwfn *p_hwfn,
3499efd0ba7SDavid C Somayajulu 				     struct ecore_ptt *p_ptt)
35011e25f0dSDavid C Somayajulu {
3519efd0ba7SDavid C Somayajulu 	u32 generic_por_0 = ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
35211e25f0dSDavid C Somayajulu 
3539efd0ba7SDavid C Somayajulu 	/* Use MCP history register to check if MCP reset occurred between init
3549efd0ba7SDavid C Somayajulu 	 * time and now.
35511e25f0dSDavid C Somayajulu 	 */
3569efd0ba7SDavid C Somayajulu 	if (p_hwfn->mcp_info->mcp_hist != generic_por_0) {
3579efd0ba7SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
3589efd0ba7SDavid C Somayajulu 			   "Rereading MCP offsets [mcp_hist 0x%08x, generic_por_0 0x%08x]\n",
3599efd0ba7SDavid C Somayajulu 			   p_hwfn->mcp_info->mcp_hist, generic_por_0);
36011e25f0dSDavid C Somayajulu 
3619efd0ba7SDavid C Somayajulu 		ecore_load_mcp_offsets(p_hwfn, p_ptt);
3629efd0ba7SDavid C Somayajulu 		ecore_mcp_cmd_port_init(p_hwfn, p_ptt);
36311e25f0dSDavid C Somayajulu 	}
36411e25f0dSDavid C Somayajulu }
36511e25f0dSDavid C Somayajulu 
ecore_mcp_reset(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)36611e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_reset(struct ecore_hwfn *p_hwfn,
36711e25f0dSDavid C Somayajulu 				     struct ecore_ptt *p_ptt)
36811e25f0dSDavid C Somayajulu {
3699efd0ba7SDavid C Somayajulu 	u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0;
37011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
37111e25f0dSDavid C Somayajulu 
37211e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
37311e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
37411e25f0dSDavid C Somayajulu 		delay = EMUL_MCP_RESP_ITER_US;
37511e25f0dSDavid C Somayajulu #endif
37611e25f0dSDavid C Somayajulu 
3779efd0ba7SDavid C Somayajulu 	if (p_hwfn->mcp_info->b_block_cmd) {
3789efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
3799efd0ba7SDavid C Somayajulu 			  "The MFW is not responsive. Avoid sending MCP_RESET mailbox command.\n");
3809efd0ba7SDavid C Somayajulu 		return ECORE_ABORTED;
3819efd0ba7SDavid C Somayajulu 	}
3829efd0ba7SDavid C Somayajulu 
3839efd0ba7SDavid C Somayajulu 	/* Ensure that only a single thread is accessing the mailbox */
384*1c45a62aSKeith Reynolds 	OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->cmd_lock);
3859efd0ba7SDavid C Somayajulu 
3869efd0ba7SDavid C Somayajulu 	org_mcp_reset_seq = ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0);
38711e25f0dSDavid C Somayajulu 
38811e25f0dSDavid C Somayajulu 	/* Set drv command along with the updated sequence */
3899efd0ba7SDavid C Somayajulu 	ecore_mcp_reread_offsets(p_hwfn, p_ptt);
3909efd0ba7SDavid C Somayajulu 	seq = ++p_hwfn->mcp_info->drv_mb_seq;
39111e25f0dSDavid C Somayajulu 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (DRV_MSG_CODE_MCP_RESET | seq));
39211e25f0dSDavid C Somayajulu 
39311e25f0dSDavid C Somayajulu 	do {
39411e25f0dSDavid C Somayajulu 		/* Wait for MFW response */
39511e25f0dSDavid C Somayajulu 		OSAL_UDELAY(delay);
39611e25f0dSDavid C Somayajulu 		/* Give the FW up to 500 second (50*1000*10usec) */
39711e25f0dSDavid C Somayajulu 	} while ((org_mcp_reset_seq == ecore_rd(p_hwfn, p_ptt,
39811e25f0dSDavid C Somayajulu 						MISCS_REG_GENERIC_POR_0)) &&
39911e25f0dSDavid C Somayajulu 		 (cnt++ < ECORE_MCP_RESET_RETRIES));
40011e25f0dSDavid C Somayajulu 
40111e25f0dSDavid C Somayajulu 	if (org_mcp_reset_seq !=
40211e25f0dSDavid C Somayajulu 	    ecore_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) {
40311e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
40411e25f0dSDavid C Somayajulu 			   "MCP was reset after %d usec\n", cnt * delay);
40511e25f0dSDavid C Somayajulu 	} else {
40611e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to reset MCP\n");
40711e25f0dSDavid C Somayajulu 		rc = ECORE_AGAIN;
40811e25f0dSDavid C Somayajulu 	}
40911e25f0dSDavid C Somayajulu 
410*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
41111e25f0dSDavid C Somayajulu 
41211e25f0dSDavid C Somayajulu 	return rc;
41311e25f0dSDavid C Somayajulu }
41411e25f0dSDavid C Somayajulu 
4159efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
ecore_mcp_has_pending_cmd(struct ecore_hwfn * p_hwfn)4169efd0ba7SDavid C Somayajulu static bool ecore_mcp_has_pending_cmd(struct ecore_hwfn *p_hwfn)
41711e25f0dSDavid C Somayajulu {
4189efd0ba7SDavid C Somayajulu 	struct ecore_mcp_cmd_elem *p_cmd_elem = OSAL_NULL;
4199efd0ba7SDavid C Somayajulu 
4209efd0ba7SDavid C Somayajulu 	/* There is at most one pending command at a certain time, and if it
4219efd0ba7SDavid C Somayajulu 	 * exists - it is placed at the HEAD of the list.
4229efd0ba7SDavid C Somayajulu 	 */
4239efd0ba7SDavid C Somayajulu 	if (!OSAL_LIST_IS_EMPTY(&p_hwfn->mcp_info->cmd_list)) {
4249efd0ba7SDavid C Somayajulu 		p_cmd_elem = OSAL_LIST_FIRST_ENTRY(&p_hwfn->mcp_info->cmd_list,
4259efd0ba7SDavid C Somayajulu 						   struct ecore_mcp_cmd_elem,
4269efd0ba7SDavid C Somayajulu 						   list);
4279efd0ba7SDavid C Somayajulu 		return !p_cmd_elem->b_is_completed;
4289efd0ba7SDavid C Somayajulu 	}
4299efd0ba7SDavid C Somayajulu 
4309efd0ba7SDavid C Somayajulu 	return false;
4319efd0ba7SDavid C Somayajulu }
4329efd0ba7SDavid C Somayajulu 
4339efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
4349efd0ba7SDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_update_pending_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)4359efd0ba7SDavid C Somayajulu ecore_mcp_update_pending_cmd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
4369efd0ba7SDavid C Somayajulu {
4379efd0ba7SDavid C Somayajulu 	struct ecore_mcp_mb_params *p_mb_params;
4389efd0ba7SDavid C Somayajulu 	struct ecore_mcp_cmd_elem *p_cmd_elem;
4399efd0ba7SDavid C Somayajulu 	u32 mcp_resp;
4409efd0ba7SDavid C Somayajulu 	u16 seq_num;
4419efd0ba7SDavid C Somayajulu 
4429efd0ba7SDavid C Somayajulu 	mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header);
4439efd0ba7SDavid C Somayajulu 	seq_num = (u16)(mcp_resp & FW_MSG_SEQ_NUMBER_MASK);
4449efd0ba7SDavid C Somayajulu 
4459efd0ba7SDavid C Somayajulu 	/* Return if no new non-handled response has been received */
4469efd0ba7SDavid C Somayajulu 	if (seq_num != p_hwfn->mcp_info->drv_mb_seq)
4479efd0ba7SDavid C Somayajulu 		return ECORE_AGAIN;
4489efd0ba7SDavid C Somayajulu 
4499efd0ba7SDavid C Somayajulu 	p_cmd_elem = ecore_mcp_cmd_get_elem(p_hwfn, seq_num);
4509efd0ba7SDavid C Somayajulu 	if (!p_cmd_elem) {
4519efd0ba7SDavid C Somayajulu 		DP_ERR(p_hwfn,
4529efd0ba7SDavid C Somayajulu 		       "Failed to find a pending mailbox cmd that expects sequence number %d\n",
4539efd0ba7SDavid C Somayajulu 		       seq_num);
4549efd0ba7SDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
4559efd0ba7SDavid C Somayajulu 	}
4569efd0ba7SDavid C Somayajulu 
4579efd0ba7SDavid C Somayajulu 	p_mb_params = p_cmd_elem->p_mb_params;
4589efd0ba7SDavid C Somayajulu 
4599efd0ba7SDavid C Somayajulu 	/* Get the MFW response along with the sequence number */
4609efd0ba7SDavid C Somayajulu 	p_mb_params->mcp_resp = mcp_resp;
4619efd0ba7SDavid C Somayajulu 
4629efd0ba7SDavid C Somayajulu 	/* Get the MFW param */
4639efd0ba7SDavid C Somayajulu 	p_mb_params->mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param);
4649efd0ba7SDavid C Somayajulu 
4659efd0ba7SDavid C Somayajulu 	/* Get the union data */
4669efd0ba7SDavid C Somayajulu 	if (p_mb_params->p_data_dst != OSAL_NULL &&
4679efd0ba7SDavid C Somayajulu 	    p_mb_params->data_dst_size) {
4689efd0ba7SDavid C Somayajulu 		u32 union_data_addr = p_hwfn->mcp_info->drv_mb_addr +
4699efd0ba7SDavid C Somayajulu 				      OFFSETOF(struct public_drv_mb,
4709efd0ba7SDavid C Somayajulu 					       union_data);
4719efd0ba7SDavid C Somayajulu 		ecore_memcpy_from(p_hwfn, p_ptt, p_mb_params->p_data_dst,
4729efd0ba7SDavid C Somayajulu 				  union_data_addr, p_mb_params->data_dst_size);
4739efd0ba7SDavid C Somayajulu 	}
4749efd0ba7SDavid C Somayajulu 
4759efd0ba7SDavid C Somayajulu 	p_cmd_elem->b_is_completed = true;
4769efd0ba7SDavid C Somayajulu 
4779efd0ba7SDavid C Somayajulu 	return ECORE_SUCCESS;
4789efd0ba7SDavid C Somayajulu }
4799efd0ba7SDavid C Somayajulu 
4809efd0ba7SDavid C Somayajulu /* Must be called while cmd_lock is acquired */
__ecore_mcp_cmd_and_union(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_mb_params * p_mb_params,u16 seq_num)4819efd0ba7SDavid C Somayajulu static void __ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn,
4829efd0ba7SDavid C Somayajulu 				      struct ecore_ptt *p_ptt,
4839efd0ba7SDavid C Somayajulu 				      struct ecore_mcp_mb_params *p_mb_params,
4849efd0ba7SDavid C Somayajulu 				      u16 seq_num)
4859efd0ba7SDavid C Somayajulu {
4869efd0ba7SDavid C Somayajulu 	union drv_union_data union_data;
4879efd0ba7SDavid C Somayajulu 	u32 union_data_addr;
4889efd0ba7SDavid C Somayajulu 
4899efd0ba7SDavid C Somayajulu 	/* Set the union data */
4909efd0ba7SDavid C Somayajulu 	union_data_addr = p_hwfn->mcp_info->drv_mb_addr +
4919efd0ba7SDavid C Somayajulu 			  OFFSETOF(struct public_drv_mb, union_data);
4929efd0ba7SDavid C Somayajulu 	OSAL_MEM_ZERO(&union_data, sizeof(union_data));
4939efd0ba7SDavid C Somayajulu 	if (p_mb_params->p_data_src != OSAL_NULL && p_mb_params->data_src_size)
4949efd0ba7SDavid C Somayajulu 		OSAL_MEMCPY(&union_data, p_mb_params->p_data_src,
4959efd0ba7SDavid C Somayajulu 			    p_mb_params->data_src_size);
4969efd0ba7SDavid C Somayajulu 	ecore_memcpy_to(p_hwfn, p_ptt, union_data_addr, &union_data,
4979efd0ba7SDavid C Somayajulu 			sizeof(union_data));
4989efd0ba7SDavid C Somayajulu 
4999efd0ba7SDavid C Somayajulu 	/* Set the drv param */
5009efd0ba7SDavid C Somayajulu 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, p_mb_params->param);
5019efd0ba7SDavid C Somayajulu 
5029efd0ba7SDavid C Somayajulu 	/* Set the drv command along with the sequence number */
5039efd0ba7SDavid C Somayajulu 	DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (p_mb_params->cmd | seq_num));
5049efd0ba7SDavid C Somayajulu 
5059efd0ba7SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
5069efd0ba7SDavid C Somayajulu 		   "MFW mailbox: command 0x%08x param 0x%08x\n",
5079efd0ba7SDavid C Somayajulu 		   (p_mb_params->cmd | seq_num), p_mb_params->param);
5089efd0ba7SDavid C Somayajulu }
5099efd0ba7SDavid C Somayajulu 
ecore_mcp_cmd_set_blocking(struct ecore_hwfn * p_hwfn,bool block_cmd)5109efd0ba7SDavid C Somayajulu static void ecore_mcp_cmd_set_blocking(struct ecore_hwfn *p_hwfn,
5119efd0ba7SDavid C Somayajulu 				       bool block_cmd)
5129efd0ba7SDavid C Somayajulu {
5139efd0ba7SDavid C Somayajulu 	p_hwfn->mcp_info->b_block_cmd = block_cmd;
5149efd0ba7SDavid C Somayajulu 
5159efd0ba7SDavid C Somayajulu 	DP_INFO(p_hwfn, "%s sending of mailbox commands to the MFW\n",
5169efd0ba7SDavid C Somayajulu 		block_cmd ? "Block" : "Unblock");
5179efd0ba7SDavid C Somayajulu }
5189efd0ba7SDavid C Somayajulu 
ecore_mcp_print_cpu_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)5199efd0ba7SDavid C Somayajulu static void ecore_mcp_print_cpu_info(struct ecore_hwfn *p_hwfn,
5209efd0ba7SDavid C Somayajulu 			      struct ecore_ptt *p_ptt)
5219efd0ba7SDavid C Somayajulu {
5229efd0ba7SDavid C Somayajulu 	u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2;
5239efd0ba7SDavid C Somayajulu 
5249efd0ba7SDavid C Somayajulu 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
5259efd0ba7SDavid C Somayajulu 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
5269efd0ba7SDavid C Somayajulu 	cpu_pc_0 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
5279efd0ba7SDavid C Somayajulu 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
5289efd0ba7SDavid C Somayajulu 	cpu_pc_1 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
5299efd0ba7SDavid C Somayajulu 	OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
5309efd0ba7SDavid C Somayajulu 	cpu_pc_2 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
5319efd0ba7SDavid C Somayajulu 
5329efd0ba7SDavid C Somayajulu 	DP_NOTICE(p_hwfn, false,
5339efd0ba7SDavid C Somayajulu 		  "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n",
5349efd0ba7SDavid C Somayajulu 		  cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2);
5359efd0ba7SDavid C Somayajulu }
5369efd0ba7SDavid C Somayajulu 
5379efd0ba7SDavid C Somayajulu static enum _ecore_status_t
_ecore_mcp_cmd_and_union(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_mb_params * p_mb_params,u32 max_retries,u32 usecs)5389efd0ba7SDavid C Somayajulu _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
5399efd0ba7SDavid C Somayajulu 			 struct ecore_mcp_mb_params *p_mb_params,
540217ec208SDavid C Somayajulu 			 u32 max_retries, u32 usecs)
5419efd0ba7SDavid C Somayajulu {
542217ec208SDavid C Somayajulu 	u32 cnt = 0, msecs = DIV_ROUND_UP(usecs, 1000);
5439efd0ba7SDavid C Somayajulu 	struct ecore_mcp_cmd_elem *p_cmd_elem;
5449efd0ba7SDavid C Somayajulu 	u16 seq_num;
54511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
54611e25f0dSDavid C Somayajulu 
5479efd0ba7SDavid C Somayajulu 	/* Wait until the mailbox is non-occupied */
5489efd0ba7SDavid C Somayajulu 	do {
5499efd0ba7SDavid C Somayajulu 		/* Exit the loop if there is no pending command, or if the
5509efd0ba7SDavid C Somayajulu 		 * pending command is completed during this iteration.
5519efd0ba7SDavid C Somayajulu 		 * The spinlock stays locked until the command is sent.
5529efd0ba7SDavid C Somayajulu 		 */
5539efd0ba7SDavid C Somayajulu 
554*1c45a62aSKeith Reynolds 		OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->cmd_lock);
5559efd0ba7SDavid C Somayajulu 
5569efd0ba7SDavid C Somayajulu 		if (!ecore_mcp_has_pending_cmd(p_hwfn))
5579efd0ba7SDavid C Somayajulu 			break;
5589efd0ba7SDavid C Somayajulu 
5599efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_update_pending_cmd(p_hwfn, p_ptt);
5609efd0ba7SDavid C Somayajulu 		if (rc == ECORE_SUCCESS)
5619efd0ba7SDavid C Somayajulu 			break;
5629efd0ba7SDavid C Somayajulu 		else if (rc != ECORE_AGAIN)
5639efd0ba7SDavid C Somayajulu 			goto err;
5649efd0ba7SDavid C Somayajulu 
565*1c45a62aSKeith Reynolds 		OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
566217ec208SDavid C Somayajulu 		if (ECORE_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) {
567217ec208SDavid C Somayajulu 			OSAL_MSLEEP(msecs);
568217ec208SDavid C Somayajulu 		} else {
569217ec208SDavid C Somayajulu 			OSAL_UDELAY(usecs);
570217ec208SDavid C Somayajulu 		}
571217ec208SDavid C Somayajulu 		OSAL_MFW_CMD_PREEMPT(p_hwfn);
5729efd0ba7SDavid C Somayajulu 	} while (++cnt < max_retries);
5739efd0ba7SDavid C Somayajulu 
5749efd0ba7SDavid C Somayajulu 	if (cnt >= max_retries) {
5759efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
5769efd0ba7SDavid C Somayajulu 			  "The MFW mailbox is occupied by an uncompleted command. Failed to send command 0x%08x [param 0x%08x].\n",
5779efd0ba7SDavid C Somayajulu 			  p_mb_params->cmd, p_mb_params->param);
5789efd0ba7SDavid C Somayajulu 		return ECORE_AGAIN;
5799efd0ba7SDavid C Somayajulu 	}
5809efd0ba7SDavid C Somayajulu 
5819efd0ba7SDavid C Somayajulu 	/* Send the mailbox command */
5829efd0ba7SDavid C Somayajulu 	ecore_mcp_reread_offsets(p_hwfn, p_ptt);
5839efd0ba7SDavid C Somayajulu 	seq_num = ++p_hwfn->mcp_info->drv_mb_seq;
5849efd0ba7SDavid C Somayajulu 	p_cmd_elem = ecore_mcp_cmd_add_elem(p_hwfn, p_mb_params, seq_num);
585217ec208SDavid C Somayajulu 	if (!p_cmd_elem) {
586217ec208SDavid C Somayajulu 		rc = ECORE_NOMEM;
5879efd0ba7SDavid C Somayajulu 		goto err;
588217ec208SDavid C Somayajulu 	}
5899efd0ba7SDavid C Somayajulu 
5909efd0ba7SDavid C Somayajulu 	__ecore_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, seq_num);
591*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
5929efd0ba7SDavid C Somayajulu 
5939efd0ba7SDavid C Somayajulu 	/* Wait for the MFW response */
5949efd0ba7SDavid C Somayajulu 	do {
5959efd0ba7SDavid C Somayajulu 		/* Exit the loop if the command is already completed, or if the
5969efd0ba7SDavid C Somayajulu 		 * command is completed during this iteration.
5979efd0ba7SDavid C Somayajulu 		 * The spinlock stays locked until the list element is removed.
5989efd0ba7SDavid C Somayajulu 		 */
5999efd0ba7SDavid C Somayajulu 
600217ec208SDavid C Somayajulu 		if (ECORE_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) {
601217ec208SDavid C Somayajulu 			OSAL_MSLEEP(msecs);
602217ec208SDavid C Somayajulu 		} else {
603217ec208SDavid C Somayajulu 			OSAL_UDELAY(usecs);
604217ec208SDavid C Somayajulu 		}
605*1c45a62aSKeith Reynolds 		OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->cmd_lock);
6069efd0ba7SDavid C Somayajulu 
6079efd0ba7SDavid C Somayajulu 		if (p_cmd_elem->b_is_completed)
6089efd0ba7SDavid C Somayajulu 			break;
6099efd0ba7SDavid C Somayajulu 
6109efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_update_pending_cmd(p_hwfn, p_ptt);
6119efd0ba7SDavid C Somayajulu 		if (rc == ECORE_SUCCESS)
6129efd0ba7SDavid C Somayajulu 			break;
6139efd0ba7SDavid C Somayajulu 		else if (rc != ECORE_AGAIN)
6149efd0ba7SDavid C Somayajulu 			goto err;
6159efd0ba7SDavid C Somayajulu 
616*1c45a62aSKeith Reynolds 		OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
617217ec208SDavid C Somayajulu 		OSAL_MFW_CMD_PREEMPT(p_hwfn);
6189efd0ba7SDavid C Somayajulu 	} while (++cnt < max_retries);
6199efd0ba7SDavid C Somayajulu 
6209efd0ba7SDavid C Somayajulu 	if (cnt >= max_retries) {
6219efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
6229efd0ba7SDavid C Somayajulu 			  "The MFW failed to respond to command 0x%08x [param 0x%08x].\n",
6239efd0ba7SDavid C Somayajulu 			  p_mb_params->cmd, p_mb_params->param);
6249efd0ba7SDavid C Somayajulu 		ecore_mcp_print_cpu_info(p_hwfn, p_ptt);
6259efd0ba7SDavid C Somayajulu 
626*1c45a62aSKeith Reynolds 		OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->cmd_lock);
6279efd0ba7SDavid C Somayajulu 		ecore_mcp_cmd_del_elem(p_hwfn, p_cmd_elem);
628*1c45a62aSKeith Reynolds 		OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
6299efd0ba7SDavid C Somayajulu 
630217ec208SDavid C Somayajulu 		if (!ECORE_MB_FLAGS_IS_SET(p_mb_params, AVOID_BLOCK))
6319efd0ba7SDavid C Somayajulu 			ecore_mcp_cmd_set_blocking(p_hwfn, true);
6329efd0ba7SDavid C Somayajulu 		ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_MFW_RESP_FAIL);
6339efd0ba7SDavid C Somayajulu 		return ECORE_AGAIN;
6349efd0ba7SDavid C Somayajulu 	}
6359efd0ba7SDavid C Somayajulu 
6369efd0ba7SDavid C Somayajulu 	ecore_mcp_cmd_del_elem(p_hwfn, p_cmd_elem);
637*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
6389efd0ba7SDavid C Somayajulu 
6399efd0ba7SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
6409efd0ba7SDavid C Somayajulu 		   "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n",
6419efd0ba7SDavid C Somayajulu 		   p_mb_params->mcp_resp, p_mb_params->mcp_param,
642217ec208SDavid C Somayajulu 		   (cnt * usecs) / 1000, (cnt * usecs) % 1000);
6439efd0ba7SDavid C Somayajulu 
6449efd0ba7SDavid C Somayajulu 	/* Clear the sequence number from the MFW response */
6459efd0ba7SDavid C Somayajulu 	p_mb_params->mcp_resp &= FW_MSG_CODE_MASK;
6469efd0ba7SDavid C Somayajulu 
6479efd0ba7SDavid C Somayajulu 	return ECORE_SUCCESS;
6489efd0ba7SDavid C Somayajulu 
6499efd0ba7SDavid C Somayajulu err:
650*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->cmd_lock);
6519efd0ba7SDavid C Somayajulu 	return rc;
6529efd0ba7SDavid C Somayajulu }
6539efd0ba7SDavid C Somayajulu 
ecore_mcp_cmd_and_union(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_mb_params * p_mb_params)6549efd0ba7SDavid C Somayajulu static enum _ecore_status_t ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn,
6559efd0ba7SDavid C Somayajulu 						    struct ecore_ptt *p_ptt,
6569efd0ba7SDavid C Somayajulu 						    struct ecore_mcp_mb_params *p_mb_params)
6579efd0ba7SDavid C Somayajulu {
6589efd0ba7SDavid C Somayajulu 	osal_size_t union_data_size = sizeof(union drv_union_data);
6599efd0ba7SDavid C Somayajulu 	u32 max_retries = ECORE_DRV_MB_MAX_RETRIES;
660217ec208SDavid C Somayajulu 	u32 usecs = CHIP_MCP_RESP_ITER_US;
6619efd0ba7SDavid C Somayajulu 
66211e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
66311e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
664217ec208SDavid C Somayajulu 		usecs = EMUL_MCP_RESP_ITER_US;
66511e25f0dSDavid C Somayajulu 	/* There is a built-in delay of 100usec in each MFW response read */
66611e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev))
66711e25f0dSDavid C Somayajulu 		max_retries /= 10;
66811e25f0dSDavid C Somayajulu #endif
669217ec208SDavid C Somayajulu 	if (ECORE_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) {
670217ec208SDavid C Somayajulu 		max_retries = DIV_ROUND_UP(max_retries, 1000);
671217ec208SDavid C Somayajulu 		usecs *= 1000;
672217ec208SDavid C Somayajulu 	}
67311e25f0dSDavid C Somayajulu 
67411e25f0dSDavid C Somayajulu 	/* MCP not initialized */
67511e25f0dSDavid C Somayajulu 	if (!ecore_mcp_is_init(p_hwfn)) {
67611e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "MFW is not initialized!\n");
67711e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
67811e25f0dSDavid C Somayajulu 	}
67911e25f0dSDavid C Somayajulu 
6809efd0ba7SDavid C Somayajulu 	if (p_mb_params->data_src_size > union_data_size ||
6819efd0ba7SDavid C Somayajulu 	    p_mb_params->data_dst_size > union_data_size) {
68211e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn,
68311e25f0dSDavid C Somayajulu 		       "The provided size is larger than the union data size [src_size %u, dst_size %u, union_data_size %zu]\n",
68411e25f0dSDavid C Somayajulu 		       p_mb_params->data_src_size, p_mb_params->data_dst_size,
6859efd0ba7SDavid C Somayajulu 		       union_data_size);
68611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
68711e25f0dSDavid C Somayajulu 	}
68811e25f0dSDavid C Somayajulu 
6899efd0ba7SDavid C Somayajulu 	if (p_hwfn->mcp_info->b_block_cmd) {
6909efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
6919efd0ba7SDavid C Somayajulu 			  "The MFW is not responsive. Avoid sending mailbox command 0x%08x [param 0x%08x].\n",
6929efd0ba7SDavid C Somayajulu 			  p_mb_params->cmd, p_mb_params->param);
6939efd0ba7SDavid C Somayajulu 		return ECORE_ABORTED;
6949efd0ba7SDavid C Somayajulu 	}
69511e25f0dSDavid C Somayajulu 
6969efd0ba7SDavid C Somayajulu 	return _ecore_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries,
697217ec208SDavid C Somayajulu 					usecs);
69811e25f0dSDavid C Somayajulu }
69911e25f0dSDavid C Somayajulu 
ecore_mcp_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param)70011e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_cmd(struct ecore_hwfn *p_hwfn,
70111e25f0dSDavid C Somayajulu 				   struct ecore_ptt *p_ptt, u32 cmd, u32 param,
70211e25f0dSDavid C Somayajulu 				   u32 *o_mcp_resp, u32 *o_mcp_param)
70311e25f0dSDavid C Somayajulu {
70411e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
70511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
70611e25f0dSDavid C Somayajulu 
70711e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
70811e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
70911e25f0dSDavid C Somayajulu 		if (cmd == DRV_MSG_CODE_UNLOAD_REQ) {
71011e25f0dSDavid C Somayajulu 			loaded--;
71111e25f0dSDavid C Somayajulu 			loaded_port[p_hwfn->port_id]--;
71211e25f0dSDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Unload cnt: 0x%x\n",
71311e25f0dSDavid C Somayajulu 				   loaded);
71411e25f0dSDavid C Somayajulu 		}
71511e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
71611e25f0dSDavid C Somayajulu 	}
71711e25f0dSDavid C Somayajulu #endif
71811e25f0dSDavid C Somayajulu 
71911e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
72011e25f0dSDavid C Somayajulu 	mb_params.cmd = cmd;
72111e25f0dSDavid C Somayajulu 	mb_params.param = param;
72211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
72311e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
72411e25f0dSDavid C Somayajulu 		return rc;
72511e25f0dSDavid C Somayajulu 
72611e25f0dSDavid C Somayajulu 	*o_mcp_resp = mb_params.mcp_resp;
72711e25f0dSDavid C Somayajulu 	*o_mcp_param = mb_params.mcp_param;
72811e25f0dSDavid C Somayajulu 
72911e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
73011e25f0dSDavid C Somayajulu }
73111e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_wr_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param,u32 i_txn_size,u32 * i_buf)73211e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_wr_cmd(struct ecore_hwfn *p_hwfn,
73311e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
73411e25f0dSDavid C Somayajulu 					  u32 cmd,
73511e25f0dSDavid C Somayajulu 					  u32 param,
73611e25f0dSDavid C Somayajulu 					  u32 *o_mcp_resp,
73711e25f0dSDavid C Somayajulu 					  u32 *o_mcp_param,
73811e25f0dSDavid C Somayajulu 					  u32 i_txn_size,
73911e25f0dSDavid C Somayajulu 					  u32 *i_buf)
74011e25f0dSDavid C Somayajulu {
74111e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
74211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
74311e25f0dSDavid C Somayajulu 
74411e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
74511e25f0dSDavid C Somayajulu 	mb_params.cmd = cmd;
74611e25f0dSDavid C Somayajulu 	mb_params.param = param;
74711e25f0dSDavid C Somayajulu 	mb_params.p_data_src = i_buf;
74811e25f0dSDavid C Somayajulu 	mb_params.data_src_size = (u8) i_txn_size;
74911e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
75011e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
75111e25f0dSDavid C Somayajulu 		return rc;
75211e25f0dSDavid C Somayajulu 
75311e25f0dSDavid C Somayajulu 	*o_mcp_resp = mb_params.mcp_resp;
75411e25f0dSDavid C Somayajulu 	*o_mcp_param = mb_params.mcp_param;
75511e25f0dSDavid C Somayajulu 
75611e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
75711e25f0dSDavid C Somayajulu }
75811e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_rd_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 cmd,u32 param,u32 * o_mcp_resp,u32 * o_mcp_param,u32 * o_txn_size,u32 * o_buf)75911e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_rd_cmd(struct ecore_hwfn *p_hwfn,
76011e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
76111e25f0dSDavid C Somayajulu 					  u32 cmd,
76211e25f0dSDavid C Somayajulu 					  u32 param,
76311e25f0dSDavid C Somayajulu 					  u32 *o_mcp_resp,
76411e25f0dSDavid C Somayajulu 					  u32 *o_mcp_param,
76511e25f0dSDavid C Somayajulu 					  u32 *o_txn_size,
76611e25f0dSDavid C Somayajulu 					  u32 *o_buf)
76711e25f0dSDavid C Somayajulu {
76811e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
76911e25f0dSDavid C Somayajulu 	u8 raw_data[MCP_DRV_NVM_BUF_LEN];
77011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
77111e25f0dSDavid C Somayajulu 
77211e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
77311e25f0dSDavid C Somayajulu 	mb_params.cmd = cmd;
77411e25f0dSDavid C Somayajulu 	mb_params.param = param;
77511e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = raw_data;
77611e25f0dSDavid C Somayajulu 
77711e25f0dSDavid C Somayajulu 	/* Use the maximal value since the actual one is part of the response */
77811e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = MCP_DRV_NVM_BUF_LEN;
77911e25f0dSDavid C Somayajulu 
78011e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
78111e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
78211e25f0dSDavid C Somayajulu 		return rc;
78311e25f0dSDavid C Somayajulu 
78411e25f0dSDavid C Somayajulu 	*o_mcp_resp = mb_params.mcp_resp;
78511e25f0dSDavid C Somayajulu 	*o_mcp_param = mb_params.mcp_param;
78611e25f0dSDavid C Somayajulu 
78711e25f0dSDavid C Somayajulu 	*o_txn_size = *o_mcp_param;
78811e25f0dSDavid C Somayajulu 	OSAL_MEMCPY(o_buf, raw_data, *o_txn_size);
78911e25f0dSDavid C Somayajulu 
79011e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
79111e25f0dSDavid C Somayajulu }
79211e25f0dSDavid C Somayajulu 
79311e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
ecore_mcp_mf_workaround(struct ecore_hwfn * p_hwfn,u32 * p_load_code)79411e25f0dSDavid C Somayajulu static void ecore_mcp_mf_workaround(struct ecore_hwfn *p_hwfn,
79511e25f0dSDavid C Somayajulu 				    u32 *p_load_code)
79611e25f0dSDavid C Somayajulu {
79711e25f0dSDavid C Somayajulu 	static int load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
79811e25f0dSDavid C Somayajulu 
79911e25f0dSDavid C Somayajulu 	if (!loaded) {
80011e25f0dSDavid C Somayajulu 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
80111e25f0dSDavid C Somayajulu 	} else if (!loaded_port[p_hwfn->port_id]) {
80211e25f0dSDavid C Somayajulu 		load_phase = FW_MSG_CODE_DRV_LOAD_PORT;
80311e25f0dSDavid C Somayajulu 	} else {
80411e25f0dSDavid C Somayajulu 		load_phase = FW_MSG_CODE_DRV_LOAD_FUNCTION;
80511e25f0dSDavid C Somayajulu 	}
80611e25f0dSDavid C Somayajulu 
80711e25f0dSDavid C Somayajulu 	/* On CMT, always tell that it's engine */
808217ec208SDavid C Somayajulu 	if (ECORE_IS_CMT(p_hwfn->p_dev))
80911e25f0dSDavid C Somayajulu 		load_phase = FW_MSG_CODE_DRV_LOAD_ENGINE;
81011e25f0dSDavid C Somayajulu 
81111e25f0dSDavid C Somayajulu 	*p_load_code = load_phase;
81211e25f0dSDavid C Somayajulu 	loaded++;
81311e25f0dSDavid C Somayajulu 	loaded_port[p_hwfn->port_id]++;
81411e25f0dSDavid C Somayajulu 
81511e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
81611e25f0dSDavid C Somayajulu 		   "Load phase: %x load cnt: 0x%x port id=%d port_load=%d\n",
81711e25f0dSDavid C Somayajulu 		   *p_load_code, loaded, p_hwfn->port_id,
81811e25f0dSDavid C Somayajulu 		   loaded_port[p_hwfn->port_id]);
81911e25f0dSDavid C Somayajulu }
82011e25f0dSDavid C Somayajulu #endif
82111e25f0dSDavid C Somayajulu 
82211e25f0dSDavid C Somayajulu static bool
ecore_mcp_can_force_load(u8 drv_role,u8 exist_drv_role,enum ecore_override_force_load override_force_load)82311e25f0dSDavid C Somayajulu ecore_mcp_can_force_load(u8 drv_role, u8 exist_drv_role,
82411e25f0dSDavid C Somayajulu 			 enum ecore_override_force_load override_force_load)
82511e25f0dSDavid C Somayajulu {
82611e25f0dSDavid C Somayajulu 	bool can_force_load = false;
82711e25f0dSDavid C Somayajulu 
82811e25f0dSDavid C Somayajulu 	switch (override_force_load) {
82911e25f0dSDavid C Somayajulu 	case ECORE_OVERRIDE_FORCE_LOAD_ALWAYS:
83011e25f0dSDavid C Somayajulu 		can_force_load = true;
83111e25f0dSDavid C Somayajulu 		break;
83211e25f0dSDavid C Somayajulu 	case ECORE_OVERRIDE_FORCE_LOAD_NEVER:
83311e25f0dSDavid C Somayajulu 		can_force_load = false;
83411e25f0dSDavid C Somayajulu 		break;
83511e25f0dSDavid C Somayajulu 	default:
83611e25f0dSDavid C Somayajulu 		can_force_load = (drv_role == DRV_ROLE_OS &&
83711e25f0dSDavid C Somayajulu 				  exist_drv_role == DRV_ROLE_PREBOOT) ||
83811e25f0dSDavid C Somayajulu 				 (drv_role == DRV_ROLE_KDUMP &&
83911e25f0dSDavid C Somayajulu 				  exist_drv_role == DRV_ROLE_OS);
84011e25f0dSDavid C Somayajulu 		break;
84111e25f0dSDavid C Somayajulu 	}
84211e25f0dSDavid C Somayajulu 
84311e25f0dSDavid C Somayajulu 	return can_force_load;
84411e25f0dSDavid C Somayajulu }
84511e25f0dSDavid C Somayajulu 
ecore_mcp_cancel_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)846217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_cancel_load_req(struct ecore_hwfn *p_hwfn,
84711e25f0dSDavid C Somayajulu 					       struct ecore_ptt *p_ptt)
84811e25f0dSDavid C Somayajulu {
84911e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
85011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
85111e25f0dSDavid C Somayajulu 
85211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CANCEL_LOAD_REQ, 0,
85311e25f0dSDavid C Somayajulu 			   &resp, &param);
854217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
85511e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
85611e25f0dSDavid C Somayajulu 			  "Failed to send cancel load request, rc = %d\n", rc);
85711e25f0dSDavid C Somayajulu 		return rc;
85811e25f0dSDavid C Somayajulu 	}
85911e25f0dSDavid C Somayajulu 
860217ec208SDavid C Somayajulu 	if (resp == FW_MSG_CODE_UNSUPPORTED) {
861217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
862217ec208SDavid C Somayajulu 			"The cancel load command is unsupported by the MFW\n");
863217ec208SDavid C Somayajulu 		return ECORE_NOTIMPL;
864217ec208SDavid C Somayajulu 	}
865217ec208SDavid C Somayajulu 
866217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
867217ec208SDavid C Somayajulu }
868217ec208SDavid C Somayajulu 
86911e25f0dSDavid C Somayajulu #define CONFIG_ECORE_L2_BITMAP_IDX	(0x1 << 0)
87011e25f0dSDavid C Somayajulu #define CONFIG_ECORE_SRIOV_BITMAP_IDX	(0x1 << 1)
87111e25f0dSDavid C Somayajulu #define CONFIG_ECORE_ROCE_BITMAP_IDX	(0x1 << 2)
87211e25f0dSDavid C Somayajulu #define CONFIG_ECORE_IWARP_BITMAP_IDX	(0x1 << 3)
87311e25f0dSDavid C Somayajulu #define CONFIG_ECORE_FCOE_BITMAP_IDX	(0x1 << 4)
87411e25f0dSDavid C Somayajulu #define CONFIG_ECORE_ISCSI_BITMAP_IDX	(0x1 << 5)
87511e25f0dSDavid C Somayajulu #define CONFIG_ECORE_LL2_BITMAP_IDX	(0x1 << 6)
87611e25f0dSDavid C Somayajulu 
ecore_get_config_bitmap(void)87711e25f0dSDavid C Somayajulu static u32 ecore_get_config_bitmap(void)
87811e25f0dSDavid C Somayajulu {
87911e25f0dSDavid C Somayajulu 	u32 config_bitmap = 0x0;
88011e25f0dSDavid C Somayajulu 
88111e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_L2
88211e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_L2_BITMAP_IDX;
88311e25f0dSDavid C Somayajulu #endif
88411e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
88511e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_SRIOV_BITMAP_IDX;
88611e25f0dSDavid C Somayajulu #endif
88711e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ROCE
88811e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_ROCE_BITMAP_IDX;
88911e25f0dSDavid C Somayajulu #endif
89011e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_IWARP
89111e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_IWARP_BITMAP_IDX;
89211e25f0dSDavid C Somayajulu #endif
89311e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_FCOE
89411e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_FCOE_BITMAP_IDX;
89511e25f0dSDavid C Somayajulu #endif
89611e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ISCSI
89711e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_ISCSI_BITMAP_IDX;
89811e25f0dSDavid C Somayajulu #endif
89911e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_LL2
90011e25f0dSDavid C Somayajulu 	config_bitmap |= CONFIG_ECORE_LL2_BITMAP_IDX;
90111e25f0dSDavid C Somayajulu #endif
90211e25f0dSDavid C Somayajulu 
90311e25f0dSDavid C Somayajulu 	return config_bitmap;
90411e25f0dSDavid C Somayajulu }
90511e25f0dSDavid C Somayajulu 
90611e25f0dSDavid C Somayajulu struct ecore_load_req_in_params {
90711e25f0dSDavid C Somayajulu 	u8 hsi_ver;
90811e25f0dSDavid C Somayajulu #define ECORE_LOAD_REQ_HSI_VER_DEFAULT	0
90911e25f0dSDavid C Somayajulu #define ECORE_LOAD_REQ_HSI_VER_1	1
91011e25f0dSDavid C Somayajulu 	u32 drv_ver_0;
91111e25f0dSDavid C Somayajulu 	u32 drv_ver_1;
91211e25f0dSDavid C Somayajulu 	u32 fw_ver;
91311e25f0dSDavid C Somayajulu 	u8 drv_role;
91411e25f0dSDavid C Somayajulu 	u8 timeout_val;
91511e25f0dSDavid C Somayajulu 	u8 force_cmd;
91611e25f0dSDavid C Somayajulu 	bool avoid_eng_reset;
91711e25f0dSDavid C Somayajulu };
91811e25f0dSDavid C Somayajulu 
91911e25f0dSDavid C Somayajulu struct ecore_load_req_out_params {
92011e25f0dSDavid C Somayajulu 	u32 load_code;
92111e25f0dSDavid C Somayajulu 	u32 exist_drv_ver_0;
92211e25f0dSDavid C Somayajulu 	u32 exist_drv_ver_1;
92311e25f0dSDavid C Somayajulu 	u32 exist_fw_ver;
92411e25f0dSDavid C Somayajulu 	u8 exist_drv_role;
92511e25f0dSDavid C Somayajulu 	u8 mfw_hsi_ver;
92611e25f0dSDavid C Somayajulu 	bool drv_exists;
92711e25f0dSDavid C Somayajulu };
92811e25f0dSDavid C Somayajulu 
92911e25f0dSDavid C Somayajulu static enum _ecore_status_t
__ecore_mcp_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_load_req_in_params * p_in_params,struct ecore_load_req_out_params * p_out_params)93011e25f0dSDavid C Somayajulu __ecore_mcp_load_req(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
93111e25f0dSDavid C Somayajulu 		     struct ecore_load_req_in_params *p_in_params,
93211e25f0dSDavid C Somayajulu 		     struct ecore_load_req_out_params *p_out_params)
93311e25f0dSDavid C Somayajulu {
93411e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
93511e25f0dSDavid C Somayajulu 	struct load_req_stc load_req;
93611e25f0dSDavid C Somayajulu 	struct load_rsp_stc load_rsp;
93711e25f0dSDavid C Somayajulu 	u32 hsi_ver;
93811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
93911e25f0dSDavid C Somayajulu 
94011e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&load_req, sizeof(load_req));
94111e25f0dSDavid C Somayajulu 	load_req.drv_ver_0 = p_in_params->drv_ver_0;
94211e25f0dSDavid C Somayajulu 	load_req.drv_ver_1 = p_in_params->drv_ver_1;
94311e25f0dSDavid C Somayajulu 	load_req.fw_ver = p_in_params->fw_ver;
9449efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(load_req.misc0, LOAD_REQ_ROLE, p_in_params->drv_role);
9459efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(load_req.misc0, LOAD_REQ_LOCK_TO,
94611e25f0dSDavid C Somayajulu 		      p_in_params->timeout_val);
9479efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(load_req.misc0, (u64)LOAD_REQ_FORCE, p_in_params->force_cmd);
9489efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(load_req.misc0, (u64)LOAD_REQ_FLAGS0,
94911e25f0dSDavid C Somayajulu 		      p_in_params->avoid_eng_reset);
95011e25f0dSDavid C Somayajulu 
95111e25f0dSDavid C Somayajulu 	hsi_ver = (p_in_params->hsi_ver == ECORE_LOAD_REQ_HSI_VER_DEFAULT) ?
95211e25f0dSDavid C Somayajulu 		  DRV_ID_MCP_HSI_VER_CURRENT :
9539efd0ba7SDavid C Somayajulu 		  (p_in_params->hsi_ver << DRV_ID_MCP_HSI_VER_OFFSET);
95411e25f0dSDavid C Somayajulu 
95511e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
95611e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_LOAD_REQ;
95711e25f0dSDavid C Somayajulu 	mb_params.param = PDA_COMP | hsi_ver | p_hwfn->p_dev->drv_type;
95811e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &load_req;
95911e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(load_req);
96011e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = &load_rsp;
96111e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = sizeof(load_rsp);
962217ec208SDavid C Somayajulu 	mb_params.flags = ECORE_MB_FLAG_CAN_SLEEP | ECORE_MB_FLAG_AVOID_BLOCK;
96311e25f0dSDavid C Somayajulu 
96411e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
96511e25f0dSDavid C Somayajulu 		   "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n",
96611e25f0dSDavid C Somayajulu 		   mb_params.param,
9679efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param, DRV_ID_DRV_INIT_HW),
9689efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param, DRV_ID_DRV_TYPE),
9699efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param, DRV_ID_MCP_HSI_VER),
9709efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param, DRV_ID_PDA_COMP_VER));
97111e25f0dSDavid C Somayajulu 
97211e25f0dSDavid C Somayajulu 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1)
97311e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
97411e25f0dSDavid C Somayajulu 			   "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",
97511e25f0dSDavid C Somayajulu 			   load_req.drv_ver_0, load_req.drv_ver_1,
97611e25f0dSDavid C Somayajulu 			   load_req.fw_ver, load_req.misc0,
9779efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_req.misc0, LOAD_REQ_ROLE),
9789efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_req.misc0, LOAD_REQ_LOCK_TO),
9799efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_req.misc0, LOAD_REQ_FORCE),
9809efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_req.misc0, LOAD_REQ_FLAGS0));
98111e25f0dSDavid C Somayajulu 
98211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
98311e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
98411e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
98511e25f0dSDavid C Somayajulu 			  "Failed to send load request, rc = %d\n", rc);
98611e25f0dSDavid C Somayajulu 		return rc;
98711e25f0dSDavid C Somayajulu 	}
98811e25f0dSDavid C Somayajulu 
98911e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
99011e25f0dSDavid C Somayajulu 		   "Load Response: resp 0x%08x\n", mb_params.mcp_resp);
99111e25f0dSDavid C Somayajulu 	p_out_params->load_code = mb_params.mcp_resp;
99211e25f0dSDavid C Somayajulu 
99311e25f0dSDavid C Somayajulu 	if (p_in_params->hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
99411e25f0dSDavid C Somayajulu 	    p_out_params->load_code != FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
99511e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
99611e25f0dSDavid C Somayajulu 			   "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",
99711e25f0dSDavid C Somayajulu 			   load_rsp.drv_ver_0, load_rsp.drv_ver_1,
99811e25f0dSDavid C Somayajulu 			   load_rsp.fw_ver, load_rsp.misc0,
9999efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_ROLE),
10009efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_HSI),
10019efd0ba7SDavid C Somayajulu 			   GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0));
100211e25f0dSDavid C Somayajulu 
100311e25f0dSDavid C Somayajulu 		p_out_params->exist_drv_ver_0 = load_rsp.drv_ver_0;
100411e25f0dSDavid C Somayajulu 		p_out_params->exist_drv_ver_1 = load_rsp.drv_ver_1;
100511e25f0dSDavid C Somayajulu 		p_out_params->exist_fw_ver = load_rsp.fw_ver;
100611e25f0dSDavid C Somayajulu 		p_out_params->exist_drv_role =
10079efd0ba7SDavid C Somayajulu 			GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_ROLE);
100811e25f0dSDavid C Somayajulu 		p_out_params->mfw_hsi_ver =
10099efd0ba7SDavid C Somayajulu 			GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_HSI);
101011e25f0dSDavid C Somayajulu 		p_out_params->drv_exists =
10119efd0ba7SDavid C Somayajulu 			GET_MFW_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0) &
101211e25f0dSDavid C Somayajulu 			LOAD_RSP_FLAGS0_DRV_EXISTS;
101311e25f0dSDavid C Somayajulu 	}
101411e25f0dSDavid C Somayajulu 
101511e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
101611e25f0dSDavid C Somayajulu }
101711e25f0dSDavid C Somayajulu 
ecore_get_mfw_drv_role(enum ecore_drv_role drv_role,u8 * p_mfw_drv_role)10189efd0ba7SDavid C Somayajulu static void ecore_get_mfw_drv_role(enum ecore_drv_role drv_role,
101911e25f0dSDavid C Somayajulu 				   u8 *p_mfw_drv_role)
102011e25f0dSDavid C Somayajulu {
10219efd0ba7SDavid C Somayajulu 	switch (drv_role) {
102211e25f0dSDavid C Somayajulu 	case ECORE_DRV_ROLE_OS:
102311e25f0dSDavid C Somayajulu 		*p_mfw_drv_role = DRV_ROLE_OS;
102411e25f0dSDavid C Somayajulu 		break;
102511e25f0dSDavid C Somayajulu 	case ECORE_DRV_ROLE_KDUMP:
102611e25f0dSDavid C Somayajulu 		*p_mfw_drv_role = DRV_ROLE_KDUMP;
102711e25f0dSDavid C Somayajulu 		break;
102811e25f0dSDavid C Somayajulu 	}
102911e25f0dSDavid C Somayajulu }
103011e25f0dSDavid C Somayajulu 
103111e25f0dSDavid C Somayajulu enum ecore_load_req_force {
103211e25f0dSDavid C Somayajulu 	ECORE_LOAD_REQ_FORCE_NONE,
103311e25f0dSDavid C Somayajulu 	ECORE_LOAD_REQ_FORCE_PF,
103411e25f0dSDavid C Somayajulu 	ECORE_LOAD_REQ_FORCE_ALL,
103511e25f0dSDavid C Somayajulu };
103611e25f0dSDavid C Somayajulu 
ecore_get_mfw_force_cmd(enum ecore_load_req_force force_cmd,u8 * p_mfw_force_cmd)10379efd0ba7SDavid C Somayajulu static void ecore_get_mfw_force_cmd(enum ecore_load_req_force force_cmd,
103811e25f0dSDavid C Somayajulu 				    u8 *p_mfw_force_cmd)
103911e25f0dSDavid C Somayajulu {
104011e25f0dSDavid C Somayajulu 	switch (force_cmd) {
104111e25f0dSDavid C Somayajulu 	case ECORE_LOAD_REQ_FORCE_NONE:
104211e25f0dSDavid C Somayajulu 		*p_mfw_force_cmd = LOAD_REQ_FORCE_NONE;
104311e25f0dSDavid C Somayajulu 		break;
104411e25f0dSDavid C Somayajulu 	case ECORE_LOAD_REQ_FORCE_PF:
104511e25f0dSDavid C Somayajulu 		*p_mfw_force_cmd = LOAD_REQ_FORCE_PF;
104611e25f0dSDavid C Somayajulu 		break;
104711e25f0dSDavid C Somayajulu 	case ECORE_LOAD_REQ_FORCE_ALL:
104811e25f0dSDavid C Somayajulu 		*p_mfw_force_cmd = LOAD_REQ_FORCE_ALL;
104911e25f0dSDavid C Somayajulu 		break;
105011e25f0dSDavid C Somayajulu 	}
105111e25f0dSDavid C Somayajulu }
105211e25f0dSDavid C Somayajulu 
ecore_mcp_load_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_load_req_params * p_params)105311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_load_req(struct ecore_hwfn *p_hwfn,
105411e25f0dSDavid C Somayajulu 					struct ecore_ptt *p_ptt,
105511e25f0dSDavid C Somayajulu 					struct ecore_load_req_params *p_params)
105611e25f0dSDavid C Somayajulu {
105711e25f0dSDavid C Somayajulu 	struct ecore_load_req_out_params out_params;
105811e25f0dSDavid C Somayajulu 	struct ecore_load_req_in_params in_params;
10599efd0ba7SDavid C Somayajulu 	u8 mfw_drv_role = 0, mfw_force_cmd;
106011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
106111e25f0dSDavid C Somayajulu 
106211e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
106311e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
106411e25f0dSDavid C Somayajulu 		ecore_mcp_mf_workaround(p_hwfn, &p_params->load_code);
106511e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
106611e25f0dSDavid C Somayajulu 	}
106711e25f0dSDavid C Somayajulu #endif
106811e25f0dSDavid C Somayajulu 
106911e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
107011e25f0dSDavid C Somayajulu 	in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_DEFAULT;
107111e25f0dSDavid C Somayajulu 	in_params.drv_ver_0 = ECORE_VERSION;
107211e25f0dSDavid C Somayajulu 	in_params.drv_ver_1 = ecore_get_config_bitmap();
107311e25f0dSDavid C Somayajulu 	in_params.fw_ver = STORM_FW_VERSION;
10749efd0ba7SDavid C Somayajulu 	ecore_get_mfw_drv_role(p_params->drv_role, &mfw_drv_role);
107511e25f0dSDavid C Somayajulu 	in_params.drv_role = mfw_drv_role;
107611e25f0dSDavid C Somayajulu 	in_params.timeout_val = p_params->timeout_val;
10779efd0ba7SDavid C Somayajulu 	ecore_get_mfw_force_cmd(ECORE_LOAD_REQ_FORCE_NONE, &mfw_force_cmd);
107811e25f0dSDavid C Somayajulu 	in_params.force_cmd = mfw_force_cmd;
107911e25f0dSDavid C Somayajulu 	in_params.avoid_eng_reset = p_params->avoid_eng_reset;
108011e25f0dSDavid C Somayajulu 
108111e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
108211e25f0dSDavid C Somayajulu 	rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params, &out_params);
108311e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
108411e25f0dSDavid C Somayajulu 		return rc;
108511e25f0dSDavid C Somayajulu 
108611e25f0dSDavid C Somayajulu 	/* First handle cases where another load request should/might be sent:
108711e25f0dSDavid C Somayajulu 	 * - MFW expects the old interface [HSI version = 1]
108811e25f0dSDavid C Somayajulu 	 * - MFW responds that a force load request is required
108911e25f0dSDavid C Somayajulu 	 */
109011e25f0dSDavid C Somayajulu 	if (out_params.load_code == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) {
109111e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
109211e25f0dSDavid C Somayajulu 			"MFW refused a load request due to HSI > 1. Resending with HSI = 1.\n");
109311e25f0dSDavid C Somayajulu 
109411e25f0dSDavid C Somayajulu 		in_params.hsi_ver = ECORE_LOAD_REQ_HSI_VER_1;
109511e25f0dSDavid C Somayajulu 		OSAL_MEM_ZERO(&out_params, sizeof(out_params));
109611e25f0dSDavid C Somayajulu 		rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
109711e25f0dSDavid C Somayajulu 					  &out_params);
109811e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
109911e25f0dSDavid C Somayajulu 			return rc;
110011e25f0dSDavid C Somayajulu 	} else if (out_params.load_code ==
110111e25f0dSDavid C Somayajulu 		   FW_MSG_CODE_DRV_LOAD_REFUSED_REQUIRES_FORCE) {
110211e25f0dSDavid C Somayajulu 		if (ecore_mcp_can_force_load(in_params.drv_role,
110311e25f0dSDavid C Somayajulu 					     out_params.exist_drv_role,
110411e25f0dSDavid C Somayajulu 					     p_params->override_force_load)) {
110511e25f0dSDavid C Somayajulu 			DP_INFO(p_hwfn,
11069efd0ba7SDavid C Somayajulu 				"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",
110711e25f0dSDavid C Somayajulu 				in_params.drv_role, in_params.fw_ver,
1108217ec208SDavid C Somayajulu 				in_params.drv_ver_0, in_params.drv_ver_1,
110911e25f0dSDavid C Somayajulu 				out_params.exist_drv_role,
111011e25f0dSDavid C Somayajulu 				out_params.exist_fw_ver,
1111217ec208SDavid C Somayajulu 				out_params.exist_drv_ver_0,
1112217ec208SDavid C Somayajulu 				out_params.exist_drv_ver_1);
111311e25f0dSDavid C Somayajulu 
11149efd0ba7SDavid C Somayajulu 			ecore_get_mfw_force_cmd(ECORE_LOAD_REQ_FORCE_ALL,
111511e25f0dSDavid C Somayajulu 						&mfw_force_cmd);
111611e25f0dSDavid C Somayajulu 
111711e25f0dSDavid C Somayajulu 			in_params.force_cmd = mfw_force_cmd;
111811e25f0dSDavid C Somayajulu 			OSAL_MEM_ZERO(&out_params, sizeof(out_params));
111911e25f0dSDavid C Somayajulu 			rc = __ecore_mcp_load_req(p_hwfn, p_ptt, &in_params,
112011e25f0dSDavid C Somayajulu 						  &out_params);
112111e25f0dSDavid C Somayajulu 			if (rc != ECORE_SUCCESS)
112211e25f0dSDavid C Somayajulu 				return rc;
112311e25f0dSDavid C Somayajulu 		} else {
112411e25f0dSDavid C Somayajulu 			DP_NOTICE(p_hwfn, false,
11259efd0ba7SDavid C Somayajulu 				  "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}] - Avoid\n",
112611e25f0dSDavid C Somayajulu 				  in_params.drv_role, in_params.fw_ver,
112711e25f0dSDavid C Somayajulu 				  in_params.drv_ver_0, in_params.drv_ver_1,
112811e25f0dSDavid C Somayajulu 				  out_params.exist_drv_role,
112911e25f0dSDavid C Somayajulu 				  out_params.exist_fw_ver,
113011e25f0dSDavid C Somayajulu 				  out_params.exist_drv_ver_0,
113111e25f0dSDavid C Somayajulu 				  out_params.exist_drv_ver_1);
113211e25f0dSDavid C Somayajulu 
113311e25f0dSDavid C Somayajulu 			ecore_mcp_cancel_load_req(p_hwfn, p_ptt);
113411e25f0dSDavid C Somayajulu 			return ECORE_BUSY;
113511e25f0dSDavid C Somayajulu 		}
113611e25f0dSDavid C Somayajulu 	}
113711e25f0dSDavid C Somayajulu 
113811e25f0dSDavid C Somayajulu 	/* Now handle the other types of responses.
113911e25f0dSDavid C Somayajulu 	 * The "REFUSED_HSI_1" and "REFUSED_REQUIRES_FORCE" responses are not
114011e25f0dSDavid C Somayajulu 	 * expected here after the additional revised load requests were sent.
114111e25f0dSDavid C Somayajulu 	 */
114211e25f0dSDavid C Somayajulu 	switch (out_params.load_code) {
114311e25f0dSDavid C Somayajulu 	case FW_MSG_CODE_DRV_LOAD_ENGINE:
114411e25f0dSDavid C Somayajulu 	case FW_MSG_CODE_DRV_LOAD_PORT:
114511e25f0dSDavid C Somayajulu 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
114611e25f0dSDavid C Somayajulu 		if (out_params.mfw_hsi_ver != ECORE_LOAD_REQ_HSI_VER_1 &&
114711e25f0dSDavid C Somayajulu 		    out_params.drv_exists) {
114811e25f0dSDavid C Somayajulu 			/* The role and fw/driver version match, but the PF is
114911e25f0dSDavid C Somayajulu 			 * already loaded and has not been unloaded gracefully.
115011e25f0dSDavid C Somayajulu 			 * This is unexpected since a quasi-FLR request was
115111e25f0dSDavid C Somayajulu 			 * previously sent as part of ecore_hw_prepare().
115211e25f0dSDavid C Somayajulu 			 */
115311e25f0dSDavid C Somayajulu 			DP_NOTICE(p_hwfn, false,
115411e25f0dSDavid C Somayajulu 				  "PF is already loaded - shouldn't have got here since a quasi-FLR request was previously sent!\n");
115511e25f0dSDavid C Somayajulu 			return ECORE_INVAL;
115611e25f0dSDavid C Somayajulu 		}
115711e25f0dSDavid C Somayajulu 		break;
115811e25f0dSDavid C Somayajulu 	default:
115911e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
11609efd0ba7SDavid C Somayajulu 			  "Unexpected refusal to load request [resp 0x%08x]. Aborting.\n",
116111e25f0dSDavid C Somayajulu 			  out_params.load_code);
11629efd0ba7SDavid C Somayajulu 		return ECORE_BUSY;
116311e25f0dSDavid C Somayajulu 	}
116411e25f0dSDavid C Somayajulu 
116511e25f0dSDavid C Somayajulu 	p_params->load_code = out_params.load_code;
116611e25f0dSDavid C Somayajulu 
116711e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
116811e25f0dSDavid C Somayajulu }
116911e25f0dSDavid C Somayajulu 
ecore_mcp_load_done(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)1170217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_load_done(struct ecore_hwfn *p_hwfn,
1171217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt)
1172217ec208SDavid C Somayajulu {
1173217ec208SDavid C Somayajulu 	u32 resp = 0, param = 0;
1174217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
1175217ec208SDavid C Somayajulu 
1176217ec208SDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_DONE, 0, &resp,
1177217ec208SDavid C Somayajulu 			   &param);
1178217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
1179217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1180217ec208SDavid C Somayajulu 			  "Failed to send a LOAD_DONE command, rc = %d\n", rc);
1181217ec208SDavid C Somayajulu 		return rc;
1182217ec208SDavid C Somayajulu 	}
1183217ec208SDavid C Somayajulu 
1184217ec208SDavid C Somayajulu 	if (resp == FW_MSG_CODE_DRV_LOAD_REFUSED_REJECT) {
1185217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1186217ec208SDavid C Somayajulu 			  "Received a LOAD_REFUSED_REJECT response from the mfw\n");
1187217ec208SDavid C Somayajulu 		return ECORE_ABORTED;
1188217ec208SDavid C Somayajulu 	}
1189217ec208SDavid C Somayajulu 
1190217ec208SDavid C Somayajulu 	/* Check if there is a DID mismatch between nvm-cfg/efuse */
1191217ec208SDavid C Somayajulu 	if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR)
1192217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1193217ec208SDavid C Somayajulu 			  "warning: device configuration is not supported on this board type. The device may not function as expected.\n");
1194217ec208SDavid C Somayajulu 
1195217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
1196217ec208SDavid C Somayajulu }
1197217ec208SDavid C Somayajulu 
ecore_mcp_unload_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)119811e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_unload_req(struct ecore_hwfn *p_hwfn,
119911e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt)
120011e25f0dSDavid C Somayajulu {
1201217ec208SDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
1202217ec208SDavid C Somayajulu 	u32 wol_param;
120311e25f0dSDavid C Somayajulu 
120411e25f0dSDavid C Somayajulu 	switch (p_hwfn->p_dev->wol_config) {
120511e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_DISABLED:
120611e25f0dSDavid C Somayajulu 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED;
120711e25f0dSDavid C Somayajulu 		break;
120811e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_ENABLED:
120911e25f0dSDavid C Somayajulu 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED;
121011e25f0dSDavid C Somayajulu 		break;
121111e25f0dSDavid C Somayajulu 	default:
121211e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
121311e25f0dSDavid C Somayajulu 			  "Unknown WoL configuration %02x\n",
121411e25f0dSDavid C Somayajulu 			  p_hwfn->p_dev->wol_config);
121511e25f0dSDavid C Somayajulu 		/* Fallthrough */
121611e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_DEFAULT:
121711e25f0dSDavid C Somayajulu 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
121811e25f0dSDavid C Somayajulu 	}
121911e25f0dSDavid C Somayajulu 
1220217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
1221217ec208SDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_UNLOAD_REQ;
1222217ec208SDavid C Somayajulu 	mb_params.param = wol_param;
1223217ec208SDavid C Somayajulu 	mb_params.flags = ECORE_MB_FLAG_CAN_SLEEP | ECORE_MB_FLAG_AVOID_BLOCK;
1224217ec208SDavid C Somayajulu 
1225217ec208SDavid C Somayajulu 	return ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
122611e25f0dSDavid C Somayajulu }
122711e25f0dSDavid C Somayajulu 
ecore_mcp_unload_done(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)122811e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_unload_done(struct ecore_hwfn *p_hwfn,
122911e25f0dSDavid C Somayajulu 					   struct ecore_ptt *p_ptt)
123011e25f0dSDavid C Somayajulu {
123111e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
123211e25f0dSDavid C Somayajulu 	struct mcp_mac wol_mac;
123311e25f0dSDavid C Somayajulu 
123411e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
123511e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_UNLOAD_DONE;
123611e25f0dSDavid C Somayajulu 
123711e25f0dSDavid C Somayajulu 	/* Set the primary MAC if WoL is enabled */
123811e25f0dSDavid C Somayajulu 	if (p_hwfn->p_dev->wol_config == ECORE_OV_WOL_ENABLED) {
123911e25f0dSDavid C Somayajulu 		u8 *p_mac = p_hwfn->p_dev->wol_mac;
124011e25f0dSDavid C Somayajulu 
124111e25f0dSDavid C Somayajulu 		OSAL_MEM_ZERO(&wol_mac, sizeof(wol_mac));
124211e25f0dSDavid C Somayajulu 		wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1];
124311e25f0dSDavid C Somayajulu 		wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 |
124411e25f0dSDavid C Somayajulu 				    p_mac[4] << 8 | p_mac[5];
124511e25f0dSDavid C Somayajulu 
124611e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFDOWN),
124711e25f0dSDavid C Somayajulu 			   "Setting WoL MAC: %02x:%02x:%02x:%02x:%02x:%02x --> [%08x,%08x]\n",
124811e25f0dSDavid C Somayajulu 			   p_mac[0], p_mac[1], p_mac[2], p_mac[3], p_mac[4],
124911e25f0dSDavid C Somayajulu 			   p_mac[5], wol_mac.mac_upper, wol_mac.mac_lower);
125011e25f0dSDavid C Somayajulu 
125111e25f0dSDavid C Somayajulu 		mb_params.p_data_src = &wol_mac;
125211e25f0dSDavid C Somayajulu 		mb_params.data_src_size = sizeof(wol_mac);
125311e25f0dSDavid C Somayajulu 	}
125411e25f0dSDavid C Somayajulu 
125511e25f0dSDavid C Somayajulu 	return ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
125611e25f0dSDavid C Somayajulu }
125711e25f0dSDavid C Somayajulu 
ecore_mcp_handle_vf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)125811e25f0dSDavid C Somayajulu static void ecore_mcp_handle_vf_flr(struct ecore_hwfn *p_hwfn,
125911e25f0dSDavid C Somayajulu 				    struct ecore_ptt *p_ptt)
126011e25f0dSDavid C Somayajulu {
126111e25f0dSDavid C Somayajulu 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
126211e25f0dSDavid C Somayajulu 					PUBLIC_PATH);
126311e25f0dSDavid C Somayajulu 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
126411e25f0dSDavid C Somayajulu 	u32 path_addr = SECTION_ADDR(mfw_path_offsize,
126511e25f0dSDavid C Somayajulu 				     ECORE_PATH_ID(p_hwfn));
126611e25f0dSDavid C Somayajulu 	u32 disabled_vfs[VF_MAX_STATIC / 32];
126711e25f0dSDavid C Somayajulu 	int i;
126811e25f0dSDavid C Somayajulu 
126911e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
127011e25f0dSDavid C Somayajulu 		   "Reading Disabled VF information from [offset %08x], path_addr %08x\n",
127111e25f0dSDavid C Somayajulu 		   mfw_path_offsize, path_addr);
127211e25f0dSDavid C Somayajulu 
127311e25f0dSDavid C Somayajulu 	for (i = 0; i < (VF_MAX_STATIC / 32); i++) {
127411e25f0dSDavid C Somayajulu 		disabled_vfs[i] = ecore_rd(p_hwfn, p_ptt,
127511e25f0dSDavid C Somayajulu 					   path_addr +
127611e25f0dSDavid C Somayajulu 					   OFFSETOF(struct public_path,
127711e25f0dSDavid C Somayajulu 						    mcp_vf_disabled) +
127811e25f0dSDavid C Somayajulu 					   sizeof(u32) * i);
127911e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
128011e25f0dSDavid C Somayajulu 			   "FLR-ed VFs [%08x,...,%08x] - %08x\n",
128111e25f0dSDavid C Somayajulu 			   i * 32, (i + 1) * 32 - 1, disabled_vfs[i]);
128211e25f0dSDavid C Somayajulu 	}
128311e25f0dSDavid C Somayajulu 
128411e25f0dSDavid C Somayajulu 	if (ecore_iov_mark_vf_flr(p_hwfn, disabled_vfs))
128511e25f0dSDavid C Somayajulu 		OSAL_VF_FLR_UPDATE(p_hwfn);
128611e25f0dSDavid C Somayajulu }
128711e25f0dSDavid C Somayajulu 
ecore_mcp_ack_vf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * vfs_to_ack)128811e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_ack_vf_flr(struct ecore_hwfn *p_hwfn,
128911e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
129011e25f0dSDavid C Somayajulu 					  u32 *vfs_to_ack)
129111e25f0dSDavid C Somayajulu {
129211e25f0dSDavid C Somayajulu 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
129311e25f0dSDavid C Somayajulu 					PUBLIC_FUNC);
129411e25f0dSDavid C Somayajulu 	u32 mfw_func_offsize = ecore_rd(p_hwfn, p_ptt, addr);
129511e25f0dSDavid C Somayajulu 	u32 func_addr = SECTION_ADDR(mfw_func_offsize,
129611e25f0dSDavid C Somayajulu 				     MCP_PF_ID(p_hwfn));
129711e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
129811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
129911e25f0dSDavid C Somayajulu 	int i;
130011e25f0dSDavid C Somayajulu 
130111e25f0dSDavid C Somayajulu 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
130211e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IOV),
130311e25f0dSDavid C Somayajulu 			   "Acking VFs [%08x,...,%08x] - %08x\n",
130411e25f0dSDavid C Somayajulu 			   i * 32, (i + 1) * 32 - 1, vfs_to_ack[i]);
130511e25f0dSDavid C Somayajulu 
130611e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
130711e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_VF_DISABLED_DONE;
130811e25f0dSDavid C Somayajulu 	mb_params.p_data_src = vfs_to_ack;
130911e25f0dSDavid C Somayajulu 	mb_params.data_src_size = VF_MAX_STATIC / 8;
131011e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
131111e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
131211e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
131311e25f0dSDavid C Somayajulu 			  "Failed to pass ACK for VF flr to MFW\n");
131411e25f0dSDavid C Somayajulu 		return ECORE_TIMEOUT;
131511e25f0dSDavid C Somayajulu 	}
131611e25f0dSDavid C Somayajulu 
131711e25f0dSDavid C Somayajulu 	/* TMP - clear the ACK bits; should be done by MFW */
131811e25f0dSDavid C Somayajulu 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
131911e25f0dSDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt,
132011e25f0dSDavid C Somayajulu 			 func_addr +
132111e25f0dSDavid C Somayajulu 			 OFFSETOF(struct public_func, drv_ack_vf_disabled) +
132211e25f0dSDavid C Somayajulu 			 i * sizeof(u32), 0);
132311e25f0dSDavid C Somayajulu 
132411e25f0dSDavid C Somayajulu 	return rc;
132511e25f0dSDavid C Somayajulu }
132611e25f0dSDavid C Somayajulu 
ecore_mcp_handle_transceiver_change(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)132711e25f0dSDavid C Somayajulu static void ecore_mcp_handle_transceiver_change(struct ecore_hwfn *p_hwfn,
132811e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
132911e25f0dSDavid C Somayajulu {
133011e25f0dSDavid C Somayajulu 	u32 transceiver_state;
133111e25f0dSDavid C Somayajulu 
133211e25f0dSDavid C Somayajulu 	transceiver_state = ecore_rd(p_hwfn, p_ptt,
133311e25f0dSDavid C Somayajulu 				     p_hwfn->mcp_info->port_addr +
133411e25f0dSDavid C Somayajulu 				     OFFSETOF(struct public_port,
133511e25f0dSDavid C Somayajulu 					      transceiver_data));
133611e25f0dSDavid C Somayajulu 
133711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, (ECORE_MSG_HW | ECORE_MSG_SP),
133811e25f0dSDavid C Somayajulu 		   "Received transceiver state update [0x%08x] from mfw [Addr 0x%x]\n",
133911e25f0dSDavid C Somayajulu 		   transceiver_state, (u32)(p_hwfn->mcp_info->port_addr +
134011e25f0dSDavid C Somayajulu 					    OFFSETOF(struct public_port,
134111e25f0dSDavid C Somayajulu 						     transceiver_data)));
134211e25f0dSDavid C Somayajulu 
13439efd0ba7SDavid C Somayajulu 	transceiver_state = GET_MFW_FIELD(transceiver_state,
13449efd0ba7SDavid C Somayajulu 					  ETH_TRANSCEIVER_STATE);
134511e25f0dSDavid C Somayajulu 
134611e25f0dSDavid C Somayajulu 	if (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
134711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Transceiver is present.\n");
134811e25f0dSDavid C Somayajulu 	else
134911e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Transceiver is unplugged.\n");
1350217ec208SDavid C Somayajulu 
1351217ec208SDavid C Somayajulu 	OSAL_TRANSCEIVER_UPDATE(p_hwfn);
135211e25f0dSDavid C Somayajulu }
135311e25f0dSDavid C Somayajulu 
ecore_mcp_read_eee_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_link_state * p_link)135411e25f0dSDavid C Somayajulu static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
135511e25f0dSDavid C Somayajulu 				      struct ecore_ptt *p_ptt,
135611e25f0dSDavid C Somayajulu 				      struct ecore_mcp_link_state *p_link)
135711e25f0dSDavid C Somayajulu {
135811e25f0dSDavid C Somayajulu 	u32 eee_status, val;
135911e25f0dSDavid C Somayajulu 
136011e25f0dSDavid C Somayajulu 	p_link->eee_adv_caps = 0;
136111e25f0dSDavid C Somayajulu 	p_link->eee_lp_adv_caps = 0;
136211e25f0dSDavid C Somayajulu 	eee_status = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
136311e25f0dSDavid C Somayajulu 				     OFFSETOF(struct public_port, eee_status));
136411e25f0dSDavid C Somayajulu 	p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT);
13659efd0ba7SDavid C Somayajulu 	val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_OFFSET;
136611e25f0dSDavid C Somayajulu 	if (val & EEE_1G_ADV)
136711e25f0dSDavid C Somayajulu 		p_link->eee_adv_caps |= ECORE_EEE_1G_ADV;
136811e25f0dSDavid C Somayajulu 	if (val & EEE_10G_ADV)
136911e25f0dSDavid C Somayajulu 		p_link->eee_adv_caps |= ECORE_EEE_10G_ADV;
13709efd0ba7SDavid C Somayajulu 	val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_OFFSET;
137111e25f0dSDavid C Somayajulu 	if (val & EEE_1G_ADV)
137211e25f0dSDavid C Somayajulu 		p_link->eee_lp_adv_caps |= ECORE_EEE_1G_ADV;
137311e25f0dSDavid C Somayajulu 	if (val & EEE_10G_ADV)
137411e25f0dSDavid C Somayajulu 		p_link->eee_lp_adv_caps |= ECORE_EEE_10G_ADV;
137511e25f0dSDavid C Somayajulu }
137611e25f0dSDavid C Somayajulu 
ecore_mcp_get_shmem_func(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct public_func * p_data,int pfid)1377217ec208SDavid C Somayajulu static u32 ecore_mcp_get_shmem_func(struct ecore_hwfn *p_hwfn,
1378217ec208SDavid C Somayajulu 				    struct ecore_ptt *p_ptt,
1379217ec208SDavid C Somayajulu 				    struct public_func *p_data,
1380217ec208SDavid C Somayajulu 				    int pfid)
1381217ec208SDavid C Somayajulu {
1382217ec208SDavid C Somayajulu 	u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1383217ec208SDavid C Somayajulu 					PUBLIC_FUNC);
1384217ec208SDavid C Somayajulu 	u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
1385217ec208SDavid C Somayajulu 	u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
1386217ec208SDavid C Somayajulu 	u32 i, size;
1387217ec208SDavid C Somayajulu 
1388217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(p_data, sizeof(*p_data));
1389217ec208SDavid C Somayajulu 
1390217ec208SDavid C Somayajulu 	size = OSAL_MIN_T(u32, sizeof(*p_data),
1391217ec208SDavid C Somayajulu 			  SECTION_SIZE(mfw_path_offsize));
1392217ec208SDavid C Somayajulu 	for (i = 0; i < size / sizeof(u32); i++)
1393217ec208SDavid C Somayajulu 		((u32 *)p_data)[i] = ecore_rd(p_hwfn, p_ptt,
1394217ec208SDavid C Somayajulu 					      func_addr + (i << 2));
1395217ec208SDavid C Somayajulu 
1396217ec208SDavid C Somayajulu 	return size;
1397217ec208SDavid C Somayajulu }
1398217ec208SDavid C Somayajulu 
ecore_read_pf_bandwidth(struct ecore_hwfn * p_hwfn,struct public_func * p_shmem_info)1399217ec208SDavid C Somayajulu static void ecore_read_pf_bandwidth(struct ecore_hwfn *p_hwfn,
1400217ec208SDavid C Somayajulu 				    struct public_func *p_shmem_info)
1401217ec208SDavid C Somayajulu {
1402217ec208SDavid C Somayajulu 	struct ecore_mcp_function_info *p_info;
1403217ec208SDavid C Somayajulu 
1404217ec208SDavid C Somayajulu 	p_info = &p_hwfn->mcp_info->func_info;
1405217ec208SDavid C Somayajulu 
1406217ec208SDavid C Somayajulu 	/* TODO - bandwidth min/max should have valid values of 1-100,
1407217ec208SDavid C Somayajulu 	 * as well as some indication that the feature is disabled.
1408217ec208SDavid C Somayajulu 	 * Until MFW/qlediag enforce those limitations, Assume THERE IS ALWAYS
1409217ec208SDavid C Somayajulu 	 * limit and correct value to min `1' and max `100' if limit isn't in
1410217ec208SDavid C Somayajulu 	 * range.
1411217ec208SDavid C Somayajulu 	 */
1412217ec208SDavid C Somayajulu 	p_info->bandwidth_min = (p_shmem_info->config &
1413217ec208SDavid C Somayajulu 				 FUNC_MF_CFG_MIN_BW_MASK) >>
1414217ec208SDavid C Somayajulu 				FUNC_MF_CFG_MIN_BW_OFFSET;
1415217ec208SDavid C Somayajulu 	if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) {
1416217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
1417217ec208SDavid C Somayajulu 			"bandwidth minimum out of bounds [%02x]. Set to 1\n",
1418217ec208SDavid C Somayajulu 			p_info->bandwidth_min);
1419217ec208SDavid C Somayajulu 		p_info->bandwidth_min = 1;
1420217ec208SDavid C Somayajulu 	}
1421217ec208SDavid C Somayajulu 
1422217ec208SDavid C Somayajulu 	p_info->bandwidth_max = (p_shmem_info->config &
1423217ec208SDavid C Somayajulu 				 FUNC_MF_CFG_MAX_BW_MASK) >>
1424217ec208SDavid C Somayajulu 				FUNC_MF_CFG_MAX_BW_OFFSET;
1425217ec208SDavid C Somayajulu 	if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) {
1426217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
1427217ec208SDavid C Somayajulu 			"bandwidth maximum out of bounds [%02x]. Set to 100\n",
1428217ec208SDavid C Somayajulu 			p_info->bandwidth_max);
1429217ec208SDavid C Somayajulu 		p_info->bandwidth_max = 100;
1430217ec208SDavid C Somayajulu 	}
1431217ec208SDavid C Somayajulu }
1432217ec208SDavid C Somayajulu 
ecore_mcp_handle_link_change(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,bool b_reset)143311e25f0dSDavid C Somayajulu static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
143411e25f0dSDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
143511e25f0dSDavid C Somayajulu 					 bool b_reset)
143611e25f0dSDavid C Somayajulu {
143711e25f0dSDavid C Somayajulu 	struct ecore_mcp_link_state *p_link;
143811e25f0dSDavid C Somayajulu 	u8 max_bw, min_bw;
143911e25f0dSDavid C Somayajulu 	u32 status = 0;
144011e25f0dSDavid C Somayajulu 
144111e25f0dSDavid C Somayajulu 	/* Prevent SW/attentions from doing this at the same time */
1442*1c45a62aSKeith Reynolds 	OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->link_lock);
144311e25f0dSDavid C Somayajulu 
144411e25f0dSDavid C Somayajulu 	p_link = &p_hwfn->mcp_info->link_output;
144511e25f0dSDavid C Somayajulu 	OSAL_MEMSET(p_link, 0, sizeof(*p_link));
144611e25f0dSDavid C Somayajulu 	if (!b_reset) {
144711e25f0dSDavid C Somayajulu 		status = ecore_rd(p_hwfn, p_ptt,
144811e25f0dSDavid C Somayajulu 				  p_hwfn->mcp_info->port_addr +
144911e25f0dSDavid C Somayajulu 				  OFFSETOF(struct public_port, link_status));
145011e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, (ECORE_MSG_LINK | ECORE_MSG_SP),
145111e25f0dSDavid C Somayajulu 			   "Received link update [0x%08x] from mfw [Addr 0x%x]\n",
145211e25f0dSDavid C Somayajulu 			   status, (u32)(p_hwfn->mcp_info->port_addr +
145311e25f0dSDavid C Somayajulu 			   OFFSETOF(struct public_port, link_status)));
145411e25f0dSDavid C Somayajulu 	} else {
145511e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
145611e25f0dSDavid C Somayajulu 			   "Resetting link indications\n");
145711e25f0dSDavid C Somayajulu 		goto out;
145811e25f0dSDavid C Somayajulu 	}
145911e25f0dSDavid C Somayajulu 
1460217ec208SDavid C Somayajulu 	if (p_hwfn->b_drv_link_init) {
1461217ec208SDavid C Somayajulu 		/* Link indication with modern MFW arrives as per-PF
1462217ec208SDavid C Somayajulu 		 * indication.
1463217ec208SDavid C Somayajulu 		 */
1464217ec208SDavid C Somayajulu 		if (p_hwfn->mcp_info->capabilities &
1465217ec208SDavid C Somayajulu 		    FW_MB_PARAM_FEATURE_SUPPORT_VLINK) {
1466217ec208SDavid C Somayajulu 			struct public_func shmem_info;
1467217ec208SDavid C Somayajulu 
1468217ec208SDavid C Somayajulu 			ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
1469217ec208SDavid C Somayajulu 						 MCP_PF_ID(p_hwfn));
1470217ec208SDavid C Somayajulu 			p_link->link_up = !!(shmem_info.status &
1471217ec208SDavid C Somayajulu 					     FUNC_STATUS_VIRTUAL_LINK_UP);
1472217ec208SDavid C Somayajulu 			ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
1473217ec208SDavid C Somayajulu 		} else {
147411e25f0dSDavid C Somayajulu 			p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
1475217ec208SDavid C Somayajulu 		}
1476217ec208SDavid C Somayajulu 	} else {
147711e25f0dSDavid C Somayajulu 		p_link->link_up = false;
1478217ec208SDavid C Somayajulu 	}
147911e25f0dSDavid C Somayajulu 
148011e25f0dSDavid C Somayajulu 	p_link->full_duplex = true;
148111e25f0dSDavid C Somayajulu 	switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) {
148211e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_100G:
148311e25f0dSDavid C Somayajulu 		p_link->speed = 100000;
148411e25f0dSDavid C Somayajulu 		break;
148511e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_50G:
148611e25f0dSDavid C Somayajulu 		p_link->speed = 50000;
148711e25f0dSDavid C Somayajulu 		break;
148811e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_40G:
148911e25f0dSDavid C Somayajulu 		p_link->speed = 40000;
149011e25f0dSDavid C Somayajulu 		break;
149111e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_25G:
149211e25f0dSDavid C Somayajulu 		p_link->speed = 25000;
149311e25f0dSDavid C Somayajulu 		break;
149411e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_20G:
149511e25f0dSDavid C Somayajulu 		p_link->speed = 20000;
149611e25f0dSDavid C Somayajulu 		break;
149711e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_10G:
149811e25f0dSDavid C Somayajulu 		p_link->speed = 10000;
149911e25f0dSDavid C Somayajulu 		break;
150011e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_1000THD:
150111e25f0dSDavid C Somayajulu 		p_link->full_duplex = false;
150211e25f0dSDavid C Somayajulu 		/* Fall-through */
150311e25f0dSDavid C Somayajulu 	case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD:
150411e25f0dSDavid C Somayajulu 		p_link->speed = 1000;
150511e25f0dSDavid C Somayajulu 		break;
150611e25f0dSDavid C Somayajulu 	default:
150711e25f0dSDavid C Somayajulu 		p_link->speed = 0;
1508217ec208SDavid C Somayajulu 		p_link->link_up = 0;
150911e25f0dSDavid C Somayajulu 	}
151011e25f0dSDavid C Somayajulu 
151111e25f0dSDavid C Somayajulu 	/* We never store total line speed as p_link->speed is
151211e25f0dSDavid C Somayajulu 	 * again changes according to bandwidth allocation.
151311e25f0dSDavid C Somayajulu 	 */
151411e25f0dSDavid C Somayajulu 	if (p_link->link_up && p_link->speed)
151511e25f0dSDavid C Somayajulu 		p_link->line_speed = p_link->speed;
151611e25f0dSDavid C Somayajulu 	else
151711e25f0dSDavid C Somayajulu 		p_link->line_speed = 0;
151811e25f0dSDavid C Somayajulu 
151911e25f0dSDavid C Somayajulu 	max_bw = p_hwfn->mcp_info->func_info.bandwidth_max;
152011e25f0dSDavid C Somayajulu 	min_bw = p_hwfn->mcp_info->func_info.bandwidth_min;
152111e25f0dSDavid C Somayajulu 
152211e25f0dSDavid C Somayajulu 	/* Max bandwidth configuration */
152311e25f0dSDavid C Somayajulu 	__ecore_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw);
152411e25f0dSDavid C Somayajulu 
15259efd0ba7SDavid C Somayajulu 	/* Min bandwidth configuration */
152611e25f0dSDavid C Somayajulu 	__ecore_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw);
152711e25f0dSDavid C Somayajulu 	ecore_configure_vp_wfq_on_link_change(p_hwfn->p_dev, p_ptt,
152811e25f0dSDavid C Somayajulu 					      p_link->min_pf_rate);
152911e25f0dSDavid C Somayajulu 
153011e25f0dSDavid C Somayajulu 	p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
153111e25f0dSDavid C Somayajulu 	p_link->an_complete = !!(status &
153211e25f0dSDavid C Somayajulu 				 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE);
153311e25f0dSDavid C Somayajulu 	p_link->parallel_detection = !!(status &
153411e25f0dSDavid C Somayajulu 					LINK_STATUS_PARALLEL_DETECTION_USED);
153511e25f0dSDavid C Somayajulu 	p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED);
153611e25f0dSDavid C Somayajulu 
153711e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
153811e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ?
153911e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_1G_FD : 0;
154011e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
154111e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ?
154211e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_1G_HD : 0;
154311e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
154411e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ?
154511e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_10G : 0;
154611e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
154711e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ?
154811e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_20G : 0;
154911e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
155011e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_25G_CAPABLE) ?
155111e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_25G : 0;
155211e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
155311e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ?
155411e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_40G : 0;
155511e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
155611e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ?
155711e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_50G : 0;
155811e25f0dSDavid C Somayajulu 	p_link->partner_adv_speed |=
155911e25f0dSDavid C Somayajulu 		(status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ?
156011e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_SPEED_100G : 0;
156111e25f0dSDavid C Somayajulu 
156211e25f0dSDavid C Somayajulu 	p_link->partner_tx_flow_ctrl_en =
156311e25f0dSDavid C Somayajulu 		!!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED);
156411e25f0dSDavid C Somayajulu 	p_link->partner_rx_flow_ctrl_en =
156511e25f0dSDavid C Somayajulu 		!!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
156611e25f0dSDavid C Somayajulu 
156711e25f0dSDavid C Somayajulu 	switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) {
156811e25f0dSDavid C Somayajulu 	case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE:
156911e25f0dSDavid C Somayajulu 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_SYMMETRIC_PAUSE;
157011e25f0dSDavid C Somayajulu 		break;
157111e25f0dSDavid C Somayajulu 	case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE:
157211e25f0dSDavid C Somayajulu 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE;
157311e25f0dSDavid C Somayajulu 		break;
157411e25f0dSDavid C Somayajulu 	case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE:
157511e25f0dSDavid C Somayajulu 		p_link->partner_adv_pause = ECORE_LINK_PARTNER_BOTH_PAUSE;
157611e25f0dSDavid C Somayajulu 		break;
157711e25f0dSDavid C Somayajulu 	default:
157811e25f0dSDavid C Somayajulu 		p_link->partner_adv_pause = 0;
157911e25f0dSDavid C Somayajulu 	}
158011e25f0dSDavid C Somayajulu 
158111e25f0dSDavid C Somayajulu 	p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
158211e25f0dSDavid C Somayajulu 
158311e25f0dSDavid C Somayajulu 	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
158411e25f0dSDavid C Somayajulu 		ecore_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
158511e25f0dSDavid C Somayajulu 
1586217ec208SDavid C Somayajulu 	OSAL_LINK_UPDATE(p_hwfn, p_ptt);
158711e25f0dSDavid C Somayajulu out:
1588*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->link_lock);
158911e25f0dSDavid C Somayajulu }
159011e25f0dSDavid C Somayajulu 
ecore_mcp_set_link(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,bool b_up)159111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_set_link(struct ecore_hwfn *p_hwfn,
159211e25f0dSDavid C Somayajulu 					struct ecore_ptt *p_ptt,
159311e25f0dSDavid C Somayajulu 					bool b_up)
159411e25f0dSDavid C Somayajulu {
159511e25f0dSDavid C Somayajulu 	struct ecore_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
159611e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
159711e25f0dSDavid C Somayajulu 	struct eth_phy_cfg phy_cfg;
159811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
159911e25f0dSDavid C Somayajulu 	u32 cmd;
160011e25f0dSDavid C Somayajulu 
160111e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
160211e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
160311e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
160411e25f0dSDavid C Somayajulu #endif
160511e25f0dSDavid C Somayajulu 
160611e25f0dSDavid C Somayajulu 	/* Set the shmem configuration according to params */
160711e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&phy_cfg, sizeof(phy_cfg));
160811e25f0dSDavid C Somayajulu 	cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET;
160911e25f0dSDavid C Somayajulu 	if (!params->speed.autoneg)
161011e25f0dSDavid C Somayajulu 		phy_cfg.speed = params->speed.forced_speed;
161111e25f0dSDavid C Somayajulu 	phy_cfg.pause |= (params->pause.autoneg) ? ETH_PAUSE_AUTONEG : 0;
161211e25f0dSDavid C Somayajulu 	phy_cfg.pause |= (params->pause.forced_rx) ? ETH_PAUSE_RX : 0;
161311e25f0dSDavid C Somayajulu 	phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0;
161411e25f0dSDavid C Somayajulu 	phy_cfg.adv_speed = params->speed.advertised_speeds;
161511e25f0dSDavid C Somayajulu 	phy_cfg.loopback_mode = params->loopback_mode;
1616217ec208SDavid C Somayajulu 
1617217ec208SDavid C Somayajulu 	/* There are MFWs that share this capability regardless of whether
1618217ec208SDavid C Somayajulu 	 * this is feasible or not. And given that at the very least adv_caps
1619217ec208SDavid C Somayajulu 	 * would be set internally by ecore, we want to make sure LFA would
1620217ec208SDavid C Somayajulu 	 * still work.
1621217ec208SDavid C Somayajulu 	 */
1622217ec208SDavid C Somayajulu 	if ((p_hwfn->mcp_info->capabilities &
1623217ec208SDavid C Somayajulu 	     FW_MB_PARAM_FEATURE_SUPPORT_EEE) &&
1624217ec208SDavid C Somayajulu 	    params->eee.enable) {
162511e25f0dSDavid C Somayajulu 		phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED;
162611e25f0dSDavid C Somayajulu 		if (params->eee.tx_lpi_enable)
162711e25f0dSDavid C Somayajulu 			phy_cfg.eee_cfg |= EEE_CFG_TX_LPI;
162811e25f0dSDavid C Somayajulu 		if (params->eee.adv_caps & ECORE_EEE_1G_ADV)
162911e25f0dSDavid C Somayajulu 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G;
163011e25f0dSDavid C Somayajulu 		if (params->eee.adv_caps & ECORE_EEE_10G_ADV)
163111e25f0dSDavid C Somayajulu 			phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G;
163211e25f0dSDavid C Somayajulu 		phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer <<
16339efd0ba7SDavid C Somayajulu 				    EEE_TX_TIMER_USEC_OFFSET) &
163411e25f0dSDavid C Somayajulu 					EEE_TX_TIMER_USEC_MASK;
163511e25f0dSDavid C Somayajulu 	}
163611e25f0dSDavid C Somayajulu 
163711e25f0dSDavid C Somayajulu 	p_hwfn->b_drv_link_init = b_up;
163811e25f0dSDavid C Somayajulu 
163911e25f0dSDavid C Somayajulu 	if (b_up)
164011e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
164111e25f0dSDavid C Somayajulu 			   "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x\n",
164211e25f0dSDavid C Somayajulu 			   phy_cfg.speed, phy_cfg.pause, phy_cfg.adv_speed,
164311e25f0dSDavid C Somayajulu 			   phy_cfg.loopback_mode);
164411e25f0dSDavid C Somayajulu 	else
164511e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK, "Resetting link\n");
164611e25f0dSDavid C Somayajulu 
164711e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
164811e25f0dSDavid C Somayajulu 	mb_params.cmd = cmd;
164911e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &phy_cfg;
165011e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(phy_cfg);
165111e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
165211e25f0dSDavid C Somayajulu 
165311e25f0dSDavid C Somayajulu 	/* if mcp fails to respond we must abort */
165411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
165511e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
165611e25f0dSDavid C Somayajulu 		return rc;
165711e25f0dSDavid C Somayajulu 	}
165811e25f0dSDavid C Somayajulu 
165911e25f0dSDavid C Somayajulu 	/* Mimic link-change attention, done for several reasons:
166011e25f0dSDavid C Somayajulu 	 *  - On reset, there's no guarantee MFW would trigger
166111e25f0dSDavid C Somayajulu 	 *    an attention.
166211e25f0dSDavid C Somayajulu 	 *  - On initialization, older MFWs might not indicate link change
166311e25f0dSDavid C Somayajulu 	 *    during LFA, so we'll never get an UP indication.
166411e25f0dSDavid C Somayajulu 	 */
166511e25f0dSDavid C Somayajulu 	ecore_mcp_handle_link_change(p_hwfn, p_ptt, !b_up);
166611e25f0dSDavid C Somayajulu 
1667217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
166811e25f0dSDavid C Somayajulu }
166911e25f0dSDavid C Somayajulu 
ecore_get_process_kill_counter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)167011e25f0dSDavid C Somayajulu u32 ecore_get_process_kill_counter(struct ecore_hwfn *p_hwfn,
167111e25f0dSDavid C Somayajulu 				   struct ecore_ptt *p_ptt)
167211e25f0dSDavid C Somayajulu {
167311e25f0dSDavid C Somayajulu 	u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt;
167411e25f0dSDavid C Somayajulu 
167511e25f0dSDavid C Somayajulu 	/* TODO - Add support for VFs */
167611e25f0dSDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
167711e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
167811e25f0dSDavid C Somayajulu 
167911e25f0dSDavid C Somayajulu 	path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
168011e25f0dSDavid C Somayajulu 						 PUBLIC_PATH);
168111e25f0dSDavid C Somayajulu 	path_offsize = ecore_rd(p_hwfn, p_ptt, path_offsize_addr);
168211e25f0dSDavid C Somayajulu 	path_addr = SECTION_ADDR(path_offsize, ECORE_PATH_ID(p_hwfn));
168311e25f0dSDavid C Somayajulu 
168411e25f0dSDavid C Somayajulu 	proc_kill_cnt = ecore_rd(p_hwfn, p_ptt,
168511e25f0dSDavid C Somayajulu 				 path_addr +
168611e25f0dSDavid C Somayajulu 				 OFFSETOF(struct public_path, process_kill)) &
168711e25f0dSDavid C Somayajulu 			PROCESS_KILL_COUNTER_MASK;
168811e25f0dSDavid C Somayajulu 
168911e25f0dSDavid C Somayajulu 	return proc_kill_cnt;
169011e25f0dSDavid C Somayajulu }
169111e25f0dSDavid C Somayajulu 
ecore_mcp_handle_process_kill(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)169211e25f0dSDavid C Somayajulu static void ecore_mcp_handle_process_kill(struct ecore_hwfn *p_hwfn,
169311e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt)
169411e25f0dSDavid C Somayajulu {
169511e25f0dSDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
169611e25f0dSDavid C Somayajulu 	u32 proc_kill_cnt;
169711e25f0dSDavid C Somayajulu 
169811e25f0dSDavid C Somayajulu 	/* Prevent possible attentions/interrupts during the recovery handling
169911e25f0dSDavid C Somayajulu 	 * and till its load phase, during which they will be re-enabled.
170011e25f0dSDavid C Somayajulu 	 */
170111e25f0dSDavid C Somayajulu 	ecore_int_igu_disable_int(p_hwfn, p_ptt);
170211e25f0dSDavid C Somayajulu 
170311e25f0dSDavid C Somayajulu 	DP_NOTICE(p_hwfn, false, "Received a process kill indication\n");
170411e25f0dSDavid C Somayajulu 
170511e25f0dSDavid C Somayajulu 	/* The following operations should be done once, and thus in CMT mode
170611e25f0dSDavid C Somayajulu 	 * are carried out by only the first HW function.
170711e25f0dSDavid C Somayajulu 	 */
170811e25f0dSDavid C Somayajulu 	if (p_hwfn != ECORE_LEADING_HWFN(p_dev))
170911e25f0dSDavid C Somayajulu 		return;
171011e25f0dSDavid C Somayajulu 
171111e25f0dSDavid C Somayajulu 	if (p_dev->recov_in_prog) {
171211e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
171311e25f0dSDavid C Somayajulu 			  "Ignoring the indication since a recovery process is already in progress\n");
171411e25f0dSDavid C Somayajulu 		return;
171511e25f0dSDavid C Somayajulu 	}
171611e25f0dSDavid C Somayajulu 
171711e25f0dSDavid C Somayajulu 	p_dev->recov_in_prog = true;
171811e25f0dSDavid C Somayajulu 
171911e25f0dSDavid C Somayajulu 	proc_kill_cnt = ecore_get_process_kill_counter(p_hwfn, p_ptt);
172011e25f0dSDavid C Somayajulu 	DP_NOTICE(p_hwfn, false, "Process kill counter: %d\n", proc_kill_cnt);
172111e25f0dSDavid C Somayajulu 
172211e25f0dSDavid C Somayajulu 	OSAL_SCHEDULE_RECOVERY_HANDLER(p_hwfn);
172311e25f0dSDavid C Somayajulu }
172411e25f0dSDavid C Somayajulu 
ecore_mcp_send_protocol_stats(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum MFW_DRV_MSG_TYPE type)172511e25f0dSDavid C Somayajulu static void ecore_mcp_send_protocol_stats(struct ecore_hwfn *p_hwfn,
172611e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
172711e25f0dSDavid C Somayajulu 					  enum MFW_DRV_MSG_TYPE type)
172811e25f0dSDavid C Somayajulu {
172911e25f0dSDavid C Somayajulu 	enum ecore_mcp_protocol_type stats_type;
173011e25f0dSDavid C Somayajulu 	union ecore_mcp_protocol_stats stats;
173111e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
173211e25f0dSDavid C Somayajulu 	u32 hsi_param;
173311e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
173411e25f0dSDavid C Somayajulu 
173511e25f0dSDavid C Somayajulu 	switch (type) {
173611e25f0dSDavid C Somayajulu 	case MFW_DRV_MSG_GET_LAN_STATS:
173711e25f0dSDavid C Somayajulu 		stats_type = ECORE_MCP_LAN_STATS;
173811e25f0dSDavid C Somayajulu 		hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN;
173911e25f0dSDavid C Somayajulu 		break;
174011e25f0dSDavid C Somayajulu 	case MFW_DRV_MSG_GET_FCOE_STATS:
174111e25f0dSDavid C Somayajulu 		stats_type = ECORE_MCP_FCOE_STATS;
174211e25f0dSDavid C Somayajulu 		hsi_param = DRV_MSG_CODE_STATS_TYPE_FCOE;
174311e25f0dSDavid C Somayajulu 		break;
174411e25f0dSDavid C Somayajulu 	case MFW_DRV_MSG_GET_ISCSI_STATS:
174511e25f0dSDavid C Somayajulu 		stats_type = ECORE_MCP_ISCSI_STATS;
174611e25f0dSDavid C Somayajulu 		hsi_param = DRV_MSG_CODE_STATS_TYPE_ISCSI;
174711e25f0dSDavid C Somayajulu 		break;
174811e25f0dSDavid C Somayajulu 	case MFW_DRV_MSG_GET_RDMA_STATS:
174911e25f0dSDavid C Somayajulu 		stats_type = ECORE_MCP_RDMA_STATS;
175011e25f0dSDavid C Somayajulu 		hsi_param = DRV_MSG_CODE_STATS_TYPE_RDMA;
175111e25f0dSDavid C Somayajulu 		break;
175211e25f0dSDavid C Somayajulu 	default:
1753217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
1754217ec208SDavid C Somayajulu 			   "Invalid protocol type %d\n", type);
175511e25f0dSDavid C Somayajulu 		return;
175611e25f0dSDavid C Somayajulu 	}
175711e25f0dSDavid C Somayajulu 
175811e25f0dSDavid C Somayajulu 	OSAL_GET_PROTOCOL_STATS(p_hwfn->p_dev, stats_type, &stats);
175911e25f0dSDavid C Somayajulu 
176011e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
176111e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_GET_STATS;
176211e25f0dSDavid C Somayajulu 	mb_params.param = hsi_param;
176311e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &stats;
176411e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(stats);
176511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
176611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
176711e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send protocol stats, rc = %d\n", rc);
176811e25f0dSDavid C Somayajulu }
176911e25f0dSDavid C Somayajulu 
177011e25f0dSDavid C Somayajulu static void
ecore_mcp_update_bw(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)177111e25f0dSDavid C Somayajulu ecore_mcp_update_bw(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
177211e25f0dSDavid C Somayajulu {
177311e25f0dSDavid C Somayajulu 	struct ecore_mcp_function_info *p_info;
177411e25f0dSDavid C Somayajulu 	struct public_func shmem_info;
177511e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
177611e25f0dSDavid C Somayajulu 
1777*1c45a62aSKeith Reynolds 	OSAL_MUTEX_ACQUIRE(&p_hwfn->mcp_info->link_lock);
1778217ec208SDavid C Somayajulu 
177911e25f0dSDavid C Somayajulu 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
178011e25f0dSDavid C Somayajulu 				 MCP_PF_ID(p_hwfn));
178111e25f0dSDavid C Somayajulu 
178211e25f0dSDavid C Somayajulu 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
178311e25f0dSDavid C Somayajulu 
178411e25f0dSDavid C Somayajulu 	p_info = &p_hwfn->mcp_info->func_info;
178511e25f0dSDavid C Somayajulu 
178611e25f0dSDavid C Somayajulu 	ecore_configure_pf_min_bandwidth(p_hwfn->p_dev, p_info->bandwidth_min);
178711e25f0dSDavid C Somayajulu 
178811e25f0dSDavid C Somayajulu 	ecore_configure_pf_max_bandwidth(p_hwfn->p_dev, p_info->bandwidth_max);
178911e25f0dSDavid C Somayajulu 
1790*1c45a62aSKeith Reynolds 	OSAL_MUTEX_RELEASE(&p_hwfn->mcp_info->link_lock);
1791217ec208SDavid C Somayajulu 
179211e25f0dSDavid C Somayajulu 	/* Acknowledge the MFW */
179311e25f0dSDavid C Somayajulu 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp,
179411e25f0dSDavid C Somayajulu 		      &param);
179511e25f0dSDavid C Somayajulu }
179611e25f0dSDavid C Somayajulu 
ecore_mcp_update_stag(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)179711e25f0dSDavid C Somayajulu static void ecore_mcp_update_stag(struct ecore_hwfn *p_hwfn,
179811e25f0dSDavid C Somayajulu 				  struct ecore_ptt *p_ptt)
179911e25f0dSDavid C Somayajulu {
180011e25f0dSDavid C Somayajulu 	struct public_func shmem_info;
180111e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
180211e25f0dSDavid C Somayajulu 
180311e25f0dSDavid C Somayajulu 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
180411e25f0dSDavid C Somayajulu 				 MCP_PF_ID(p_hwfn));
180511e25f0dSDavid C Somayajulu 
180611e25f0dSDavid C Somayajulu 	p_hwfn->mcp_info->func_info.ovlan = (u16)shmem_info.ovlan_stag &
180711e25f0dSDavid C Somayajulu 						 FUNC_MF_CFG_OV_STAG_MASK;
180811e25f0dSDavid C Somayajulu 	p_hwfn->hw_info.ovlan = p_hwfn->mcp_info->func_info.ovlan;
180911e25f0dSDavid C Somayajulu 	if ((p_hwfn->hw_info.hw_mode & (1 << MODE_MF_SD)) &&
18109efd0ba7SDavid C Somayajulu 	    (p_hwfn->hw_info.ovlan != ECORE_MCP_VLAN_UNSET)) {
181111e25f0dSDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt,
181211e25f0dSDavid C Somayajulu 			 NIG_REG_LLH_FUNC_TAG_VALUE,
181311e25f0dSDavid C Somayajulu 			 p_hwfn->hw_info.ovlan);
18149efd0ba7SDavid C Somayajulu 		ecore_sp_pf_update_stag(p_hwfn);
1815217ec208SDavid C Somayajulu 		/* Configure doorbell to add external vlan to EDPM packets */
1816217ec208SDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);
1817217ec208SDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_EXT_VID_BB_K2,
1818217ec208SDavid C Somayajulu 			 p_hwfn->hw_info.ovlan);
18199efd0ba7SDavid C Somayajulu 	}
182011e25f0dSDavid C Somayajulu 
1821217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "ovlan  = %d hw_mode = 0x%x\n",
1822217ec208SDavid C Somayajulu 		   p_hwfn->mcp_info->func_info.ovlan, p_hwfn->hw_info.hw_mode);
182311e25f0dSDavid C Somayajulu 	OSAL_HW_INFO_CHANGE(p_hwfn, ECORE_HW_INFO_CHANGE_OVLAN);
182411e25f0dSDavid C Somayajulu 
182511e25f0dSDavid C Somayajulu 	/* Acknowledge the MFW */
182611e25f0dSDavid C Somayajulu 	ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_S_TAG_UPDATE_ACK, 0,
182711e25f0dSDavid C Somayajulu 		      &resp, &param);
182811e25f0dSDavid C Somayajulu }
182911e25f0dSDavid C Somayajulu 
ecore_mcp_handle_fan_failure(struct ecore_hwfn * p_hwfn)18309efd0ba7SDavid C Somayajulu static void ecore_mcp_handle_fan_failure(struct ecore_hwfn *p_hwfn)
183111e25f0dSDavid C Somayajulu {
183211e25f0dSDavid C Somayajulu 	/* A single notification should be sent to upper driver in CMT mode */
183311e25f0dSDavid C Somayajulu 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
183411e25f0dSDavid C Somayajulu 		return;
183511e25f0dSDavid C Somayajulu 
183611e25f0dSDavid C Somayajulu 	DP_NOTICE(p_hwfn, false,
183711e25f0dSDavid C Somayajulu 		  "Fan failure was detected on the network interface card and it's going to be shut down.\n");
183811e25f0dSDavid C Somayajulu 
183911e25f0dSDavid C Somayajulu 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_FAN_FAIL);
184011e25f0dSDavid C Somayajulu }
184111e25f0dSDavid C Somayajulu 
184211e25f0dSDavid C Somayajulu struct ecore_mdump_cmd_params {
184311e25f0dSDavid C Somayajulu 	u32 cmd;
184411e25f0dSDavid C Somayajulu 	void *p_data_src;
184511e25f0dSDavid C Somayajulu 	u8 data_src_size;
184611e25f0dSDavid C Somayajulu 	void *p_data_dst;
184711e25f0dSDavid C Somayajulu 	u8 data_dst_size;
184811e25f0dSDavid C Somayajulu 	u32 mcp_resp;
184911e25f0dSDavid C Somayajulu };
185011e25f0dSDavid C Somayajulu 
185111e25f0dSDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_mdump_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_cmd_params * p_mdump_cmd_params)185211e25f0dSDavid C Somayajulu ecore_mcp_mdump_cmd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
185311e25f0dSDavid C Somayajulu 		    struct ecore_mdump_cmd_params *p_mdump_cmd_params)
185411e25f0dSDavid C Somayajulu {
185511e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
185611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
185711e25f0dSDavid C Somayajulu 
185811e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
185911e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_MDUMP_CMD;
186011e25f0dSDavid C Somayajulu 	mb_params.param = p_mdump_cmd_params->cmd;
186111e25f0dSDavid C Somayajulu 	mb_params.p_data_src = p_mdump_cmd_params->p_data_src;
186211e25f0dSDavid C Somayajulu 	mb_params.data_src_size = p_mdump_cmd_params->data_src_size;
186311e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = p_mdump_cmd_params->p_data_dst;
186411e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = p_mdump_cmd_params->data_dst_size;
186511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
186611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
186711e25f0dSDavid C Somayajulu 		return rc;
186811e25f0dSDavid C Somayajulu 
186911e25f0dSDavid C Somayajulu 	p_mdump_cmd_params->mcp_resp = mb_params.mcp_resp;
187011e25f0dSDavid C Somayajulu 
187111e25f0dSDavid C Somayajulu 	if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_MDUMP_INVALID_CMD) {
187211e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
187311e25f0dSDavid C Somayajulu 			"The mdump sub command is unsupported by the MFW [mdump_cmd 0x%x]\n",
187411e25f0dSDavid C Somayajulu 			p_mdump_cmd_params->cmd);
187511e25f0dSDavid C Somayajulu 		rc = ECORE_NOTIMPL;
187611e25f0dSDavid C Somayajulu 	} else if (p_mdump_cmd_params->mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
187711e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
187811e25f0dSDavid C Somayajulu 			"The mdump command is not supported by the MFW\n");
187911e25f0dSDavid C Somayajulu 		rc = ECORE_NOTIMPL;
188011e25f0dSDavid C Somayajulu 	}
188111e25f0dSDavid C Somayajulu 
188211e25f0dSDavid C Somayajulu 	return rc;
188311e25f0dSDavid C Somayajulu }
188411e25f0dSDavid C Somayajulu 
ecore_mcp_mdump_ack(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)188511e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_mcp_mdump_ack(struct ecore_hwfn *p_hwfn,
188611e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
188711e25f0dSDavid C Somayajulu {
188811e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
188911e25f0dSDavid C Somayajulu 
189011e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
189111e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_ACK;
189211e25f0dSDavid C Somayajulu 
189311e25f0dSDavid C Somayajulu 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
189411e25f0dSDavid C Somayajulu }
189511e25f0dSDavid C Somayajulu 
ecore_mcp_mdump_set_values(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 epoch)189611e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mdump_set_values(struct ecore_hwfn *p_hwfn,
189711e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt,
189811e25f0dSDavid C Somayajulu 						u32 epoch)
189911e25f0dSDavid C Somayajulu {
190011e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
190111e25f0dSDavid C Somayajulu 
190211e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
190311e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_SET_VALUES;
190411e25f0dSDavid C Somayajulu 	mdump_cmd_params.p_data_src = &epoch;
190511e25f0dSDavid C Somayajulu 	mdump_cmd_params.data_src_size = sizeof(epoch);
190611e25f0dSDavid C Somayajulu 
190711e25f0dSDavid C Somayajulu 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
190811e25f0dSDavid C Somayajulu }
190911e25f0dSDavid C Somayajulu 
ecore_mcp_mdump_trigger(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)191011e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mdump_trigger(struct ecore_hwfn *p_hwfn,
191111e25f0dSDavid C Somayajulu 					     struct ecore_ptt *p_ptt)
191211e25f0dSDavid C Somayajulu {
191311e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
191411e25f0dSDavid C Somayajulu 
191511e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
191611e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_TRIGGER;
191711e25f0dSDavid C Somayajulu 
191811e25f0dSDavid C Somayajulu 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
191911e25f0dSDavid C Somayajulu }
192011e25f0dSDavid C Somayajulu 
192111e25f0dSDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_mdump_get_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct mdump_config_stc * p_mdump_config)192211e25f0dSDavid C Somayajulu ecore_mcp_mdump_get_config(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
192311e25f0dSDavid C Somayajulu 			   struct mdump_config_stc *p_mdump_config)
192411e25f0dSDavid C Somayajulu {
192511e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
192611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
192711e25f0dSDavid C Somayajulu 
192811e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
192911e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_CONFIG;
193011e25f0dSDavid C Somayajulu 	mdump_cmd_params.p_data_dst = p_mdump_config;
193111e25f0dSDavid C Somayajulu 	mdump_cmd_params.data_dst_size = sizeof(*p_mdump_config);
193211e25f0dSDavid C Somayajulu 
193311e25f0dSDavid C Somayajulu 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
193411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
193511e25f0dSDavid C Somayajulu 		return rc;
193611e25f0dSDavid C Somayajulu 
193711e25f0dSDavid C Somayajulu 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
193811e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
193911e25f0dSDavid C Somayajulu 			"Failed to get the mdump configuration and logs info [mcp_resp 0x%x]\n",
194011e25f0dSDavid C Somayajulu 			mdump_cmd_params.mcp_resp);
194111e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
194211e25f0dSDavid C Somayajulu 	}
194311e25f0dSDavid C Somayajulu 
194411e25f0dSDavid C Somayajulu 	return rc;
194511e25f0dSDavid C Somayajulu }
194611e25f0dSDavid C Somayajulu 
194711e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_mdump_get_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_info * p_mdump_info)194811e25f0dSDavid C Somayajulu ecore_mcp_mdump_get_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
194911e25f0dSDavid C Somayajulu 			 struct ecore_mdump_info *p_mdump_info)
195011e25f0dSDavid C Somayajulu {
195111e25f0dSDavid C Somayajulu 	u32 addr, global_offsize, global_addr;
195211e25f0dSDavid C Somayajulu 	struct mdump_config_stc mdump_config;
195311e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
195411e25f0dSDavid C Somayajulu 
195511e25f0dSDavid C Somayajulu 	OSAL_MEMSET(p_mdump_info, 0, sizeof(*p_mdump_info));
195611e25f0dSDavid C Somayajulu 
195711e25f0dSDavid C Somayajulu 	addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
195811e25f0dSDavid C Somayajulu 				    PUBLIC_GLOBAL);
195911e25f0dSDavid C Somayajulu 	global_offsize = ecore_rd(p_hwfn, p_ptt, addr);
196011e25f0dSDavid C Somayajulu 	global_addr = SECTION_ADDR(global_offsize, 0);
196111e25f0dSDavid C Somayajulu 	p_mdump_info->reason = ecore_rd(p_hwfn, p_ptt,
196211e25f0dSDavid C Somayajulu 					global_addr +
196311e25f0dSDavid C Somayajulu 					OFFSETOF(struct public_global,
196411e25f0dSDavid C Somayajulu 						 mdump_reason));
196511e25f0dSDavid C Somayajulu 
196611e25f0dSDavid C Somayajulu 	if (p_mdump_info->reason) {
196711e25f0dSDavid C Somayajulu 		rc = ecore_mcp_mdump_get_config(p_hwfn, p_ptt, &mdump_config);
196811e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
196911e25f0dSDavid C Somayajulu 			return rc;
197011e25f0dSDavid C Somayajulu 
197111e25f0dSDavid C Somayajulu 		p_mdump_info->version = mdump_config.version;
197211e25f0dSDavid C Somayajulu 		p_mdump_info->config = mdump_config.config;
197311e25f0dSDavid C Somayajulu 		p_mdump_info->epoch = mdump_config.epoc;
197411e25f0dSDavid C Somayajulu 		p_mdump_info->num_of_logs = mdump_config.num_of_logs;
197511e25f0dSDavid C Somayajulu 		p_mdump_info->valid_logs = mdump_config.valid_logs;
197611e25f0dSDavid C Somayajulu 
197711e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
197811e25f0dSDavid C Somayajulu 			   "MFW mdump info: reason %d, version 0x%x, config 0x%x, epoch 0x%x, num_of_logs 0x%x, valid_logs 0x%x\n",
197911e25f0dSDavid C Somayajulu 			   p_mdump_info->reason, p_mdump_info->version,
198011e25f0dSDavid C Somayajulu 			   p_mdump_info->config, p_mdump_info->epoch,
198111e25f0dSDavid C Somayajulu 			   p_mdump_info->num_of_logs, p_mdump_info->valid_logs);
198211e25f0dSDavid C Somayajulu 	} else {
198311e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
198411e25f0dSDavid C Somayajulu 			   "MFW mdump info: reason %d\n", p_mdump_info->reason);
198511e25f0dSDavid C Somayajulu 	}
198611e25f0dSDavid C Somayajulu 
198711e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
198811e25f0dSDavid C Somayajulu }
198911e25f0dSDavid C Somayajulu 
ecore_mcp_mdump_clear_logs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)199011e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mdump_clear_logs(struct ecore_hwfn *p_hwfn,
199111e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
199211e25f0dSDavid C Somayajulu {
199311e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
199411e25f0dSDavid C Somayajulu 
199511e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
199611e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLEAR_LOGS;
199711e25f0dSDavid C Somayajulu 
199811e25f0dSDavid C Somayajulu 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
199911e25f0dSDavid C Somayajulu }
200011e25f0dSDavid C Somayajulu 
200111e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_mdump_get_retain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mdump_retain_data * p_mdump_retain)200211e25f0dSDavid C Somayajulu ecore_mcp_mdump_get_retain(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
200311e25f0dSDavid C Somayajulu 			   struct ecore_mdump_retain_data *p_mdump_retain)
200411e25f0dSDavid C Somayajulu {
200511e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
200611e25f0dSDavid C Somayajulu 	struct mdump_retain_data_stc mfw_mdump_retain;
200711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
200811e25f0dSDavid C Somayajulu 
200911e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
201011e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_GET_RETAIN;
201111e25f0dSDavid C Somayajulu 	mdump_cmd_params.p_data_dst = &mfw_mdump_retain;
201211e25f0dSDavid C Somayajulu 	mdump_cmd_params.data_dst_size = sizeof(mfw_mdump_retain);
201311e25f0dSDavid C Somayajulu 
201411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
201511e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
201611e25f0dSDavid C Somayajulu 		return rc;
201711e25f0dSDavid C Somayajulu 
201811e25f0dSDavid C Somayajulu 	if (mdump_cmd_params.mcp_resp != FW_MSG_CODE_OK) {
201911e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
202011e25f0dSDavid C Somayajulu 			"Failed to get the mdump retained data [mcp_resp 0x%x]\n",
202111e25f0dSDavid C Somayajulu 			mdump_cmd_params.mcp_resp);
202211e25f0dSDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
202311e25f0dSDavid C Somayajulu 	}
202411e25f0dSDavid C Somayajulu 
202511e25f0dSDavid C Somayajulu 	p_mdump_retain->valid = mfw_mdump_retain.valid;
202611e25f0dSDavid C Somayajulu 	p_mdump_retain->epoch = mfw_mdump_retain.epoch;
202711e25f0dSDavid C Somayajulu 	p_mdump_retain->pf = mfw_mdump_retain.pf;
202811e25f0dSDavid C Somayajulu 	p_mdump_retain->status = mfw_mdump_retain.status;
202911e25f0dSDavid C Somayajulu 
203011e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
203111e25f0dSDavid C Somayajulu }
203211e25f0dSDavid C Somayajulu 
ecore_mcp_mdump_clr_retain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)203311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mdump_clr_retain(struct ecore_hwfn *p_hwfn,
203411e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
203511e25f0dSDavid C Somayajulu {
203611e25f0dSDavid C Somayajulu 	struct ecore_mdump_cmd_params mdump_cmd_params;
203711e25f0dSDavid C Somayajulu 
203811e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mdump_cmd_params, sizeof(mdump_cmd_params));
203911e25f0dSDavid C Somayajulu 	mdump_cmd_params.cmd = DRV_MSG_CODE_MDUMP_CLR_RETAIN;
204011e25f0dSDavid C Somayajulu 
204111e25f0dSDavid C Somayajulu 	return ecore_mcp_mdump_cmd(p_hwfn, p_ptt, &mdump_cmd_params);
204211e25f0dSDavid C Somayajulu }
204311e25f0dSDavid C Somayajulu 
ecore_mcp_handle_critical_error(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)204411e25f0dSDavid C Somayajulu static void ecore_mcp_handle_critical_error(struct ecore_hwfn *p_hwfn,
204511e25f0dSDavid C Somayajulu 					    struct ecore_ptt *p_ptt)
204611e25f0dSDavid C Somayajulu {
204711e25f0dSDavid C Somayajulu 	struct ecore_mdump_retain_data mdump_retain;
204811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
204911e25f0dSDavid C Somayajulu 
205011e25f0dSDavid C Somayajulu 	/* In CMT mode - no need for more than a single acknowledgement to the
205111e25f0dSDavid C Somayajulu 	 * MFW, and no more than a single notification to the upper driver.
205211e25f0dSDavid C Somayajulu 	 */
205311e25f0dSDavid C Somayajulu 	if (p_hwfn != ECORE_LEADING_HWFN(p_hwfn->p_dev))
205411e25f0dSDavid C Somayajulu 		return;
205511e25f0dSDavid C Somayajulu 
205611e25f0dSDavid C Somayajulu 	rc = ecore_mcp_mdump_get_retain(p_hwfn, p_ptt, &mdump_retain);
205711e25f0dSDavid C Somayajulu 	if (rc == ECORE_SUCCESS && mdump_retain.valid) {
205811e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
205911e25f0dSDavid C Somayajulu 			  "The MFW notified that a critical error occurred in the device [epoch 0x%08x, pf 0x%x, status 0x%08x]\n",
206011e25f0dSDavid C Somayajulu 			  mdump_retain.epoch, mdump_retain.pf,
206111e25f0dSDavid C Somayajulu 			  mdump_retain.status);
206211e25f0dSDavid C Somayajulu 	} else {
206311e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
206411e25f0dSDavid C Somayajulu 			  "The MFW notified that a critical error occurred in the device\n");
206511e25f0dSDavid C Somayajulu 	}
206611e25f0dSDavid C Somayajulu 
206711e25f0dSDavid C Somayajulu 	if (p_hwfn->p_dev->allow_mdump) {
206811e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
206911e25f0dSDavid C Somayajulu 			  "Not acknowledging the notification to allow the MFW crash dump\n");
207011e25f0dSDavid C Somayajulu 		return;
207111e25f0dSDavid C Somayajulu 	}
207211e25f0dSDavid C Somayajulu 
207311e25f0dSDavid C Somayajulu 	DP_NOTICE(p_hwfn, false,
207411e25f0dSDavid C Somayajulu 		  "Acknowledging the notification to not allow the MFW crash dump [driver debug data collection is preferable]\n");
207511e25f0dSDavid C Somayajulu 	ecore_mcp_mdump_ack(p_hwfn, p_ptt);
207611e25f0dSDavid C Somayajulu 	ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_HW_ATTN);
207711e25f0dSDavid C Somayajulu }
207811e25f0dSDavid C Somayajulu 
2079217ec208SDavid C Somayajulu void
ecore_mcp_read_ufp_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)2080217ec208SDavid C Somayajulu ecore_mcp_read_ufp_config(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
2081217ec208SDavid C Somayajulu {
2082217ec208SDavid C Somayajulu 	struct public_func shmem_info;
2083217ec208SDavid C Somayajulu 	u32 port_cfg, val;
2084217ec208SDavid C Somayajulu 
2085217ec208SDavid C Somayajulu 	if (!OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, &p_hwfn->p_dev->mf_bits))
2086217ec208SDavid C Somayajulu 		return;
2087217ec208SDavid C Somayajulu 
2088217ec208SDavid C Somayajulu 	OSAL_MEMSET(&p_hwfn->ufp_info, 0, sizeof(p_hwfn->ufp_info));
2089217ec208SDavid C Somayajulu 	port_cfg = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
2090217ec208SDavid C Somayajulu 			    OFFSETOF(struct public_port, oem_cfg_port));
2091217ec208SDavid C Somayajulu 	val = GET_MFW_FIELD(port_cfg, OEM_CFG_CHANNEL_TYPE);
2092217ec208SDavid C Somayajulu 	if (val != OEM_CFG_CHANNEL_TYPE_STAGGED)
2093217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Incorrect UFP Channel type  %d\n",
2094217ec208SDavid C Somayajulu 			  val);
2095217ec208SDavid C Somayajulu 
2096217ec208SDavid C Somayajulu 	val = GET_MFW_FIELD(port_cfg, OEM_CFG_SCHED_TYPE);
2097217ec208SDavid C Somayajulu 	if (val == OEM_CFG_SCHED_TYPE_ETS)
2098217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.mode = ECORE_UFP_MODE_ETS;
2099217ec208SDavid C Somayajulu 	else if (val == OEM_CFG_SCHED_TYPE_VNIC_BW)
2100217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.mode = ECORE_UFP_MODE_VNIC_BW;
2101217ec208SDavid C Somayajulu 	else {
2102217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.mode = ECORE_UFP_MODE_UNKNOWN;
2103217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Unknown UFP scheduling mode %d\n",
2104217ec208SDavid C Somayajulu 			  val);
2105217ec208SDavid C Somayajulu 	}
2106217ec208SDavid C Somayajulu 
2107217ec208SDavid C Somayajulu 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
2108217ec208SDavid C Somayajulu 				 MCP_PF_ID(p_hwfn));
2109217ec208SDavid C Somayajulu 	val = GET_MFW_FIELD(shmem_info.oem_cfg_func, OEM_CFG_FUNC_TC);
2110217ec208SDavid C Somayajulu 	p_hwfn->ufp_info.tc = (u8)val;
2111217ec208SDavid C Somayajulu 	val = GET_MFW_FIELD(shmem_info.oem_cfg_func,
2112217ec208SDavid C Somayajulu 			    OEM_CFG_FUNC_HOST_PRI_CTRL);
2113217ec208SDavid C Somayajulu 	if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_VNIC)
2114217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.pri_type = ECORE_UFP_PRI_VNIC;
2115217ec208SDavid C Somayajulu 	else if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_OS)
2116217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.pri_type = ECORE_UFP_PRI_OS;
2117217ec208SDavid C Somayajulu 	else {
2118217ec208SDavid C Somayajulu 		p_hwfn->ufp_info.pri_type = ECORE_UFP_PRI_UNKNOWN;
2119217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Unknown Host priority control %d\n",
2120217ec208SDavid C Somayajulu 			  val);
2121217ec208SDavid C Somayajulu 	}
2122217ec208SDavid C Somayajulu 
2123217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
2124217ec208SDavid C Somayajulu 		   "UFP shmem config: mode = %d tc = %d pri_type = %d\n",
2125217ec208SDavid C Somayajulu 		   p_hwfn->ufp_info.mode, p_hwfn->ufp_info.tc,
2126217ec208SDavid C Somayajulu 		   p_hwfn->ufp_info.pri_type);
2127217ec208SDavid C Somayajulu }
2128217ec208SDavid C Somayajulu 
2129217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_handle_ufp_event(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)2130217ec208SDavid C Somayajulu ecore_mcp_handle_ufp_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
2131217ec208SDavid C Somayajulu {
2132217ec208SDavid C Somayajulu 	ecore_mcp_read_ufp_config(p_hwfn, p_ptt);
2133217ec208SDavid C Somayajulu 
2134217ec208SDavid C Somayajulu 	if (p_hwfn->ufp_info.mode == ECORE_UFP_MODE_VNIC_BW) {
2135217ec208SDavid C Somayajulu 		p_hwfn->qm_info.ooo_tc = p_hwfn->ufp_info.tc;
2136217ec208SDavid C Somayajulu 		p_hwfn->hw_info.offload_tc = p_hwfn->ufp_info.tc;
2137217ec208SDavid C Somayajulu 
2138217ec208SDavid C Somayajulu 		ecore_qm_reconf(p_hwfn, p_ptt);
2139217ec208SDavid C Somayajulu 	} else if (p_hwfn->ufp_info.mode == ECORE_UFP_MODE_ETS) {
2140217ec208SDavid C Somayajulu 		/* Merge UFP TC with the dcbx TC data */
2141217ec208SDavid C Somayajulu 		ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
2142217ec208SDavid C Somayajulu 					    ECORE_DCBX_OPERATIONAL_MIB);
2143217ec208SDavid C Somayajulu 	} else {
2144217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "Invalid sched type, discard the UFP config\n");
2145217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2146217ec208SDavid C Somayajulu 	}
2147217ec208SDavid C Somayajulu 
2148217ec208SDavid C Somayajulu 	/* update storm FW with negotiation results */
2149217ec208SDavid C Somayajulu 	ecore_sp_pf_update_ufp(p_hwfn);
2150217ec208SDavid C Somayajulu 
2151217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
2152217ec208SDavid C Somayajulu }
2153217ec208SDavid C Somayajulu 
ecore_mcp_handle_events(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)215411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_handle_events(struct ecore_hwfn *p_hwfn,
215511e25f0dSDavid C Somayajulu 					     struct ecore_ptt *p_ptt)
215611e25f0dSDavid C Somayajulu {
215711e25f0dSDavid C Somayajulu 	struct ecore_mcp_info *info = p_hwfn->mcp_info;
215811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
215911e25f0dSDavid C Somayajulu 	bool found = false;
216011e25f0dSDavid C Somayajulu 	u16 i;
216111e25f0dSDavid C Somayajulu 
216211e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Received message from MFW\n");
216311e25f0dSDavid C Somayajulu 
216411e25f0dSDavid C Somayajulu 	/* Read Messages from MFW */
216511e25f0dSDavid C Somayajulu 	ecore_mcp_read_mb(p_hwfn, p_ptt);
216611e25f0dSDavid C Somayajulu 
216711e25f0dSDavid C Somayajulu 	/* Compare current messages to old ones */
216811e25f0dSDavid C Somayajulu 	for (i = 0; i < info->mfw_mb_length; i++) {
216911e25f0dSDavid C Somayajulu 		if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i])
217011e25f0dSDavid C Somayajulu 			continue;
217111e25f0dSDavid C Somayajulu 
217211e25f0dSDavid C Somayajulu 		found = true;
217311e25f0dSDavid C Somayajulu 
217411e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_LINK,
217511e25f0dSDavid C Somayajulu 			   "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n",
217611e25f0dSDavid C Somayajulu 			   i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]);
217711e25f0dSDavid C Somayajulu 
217811e25f0dSDavid C Somayajulu 		switch (i) {
217911e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_LINK_CHANGE:
218011e25f0dSDavid C Somayajulu 			ecore_mcp_handle_link_change(p_hwfn, p_ptt, false);
218111e25f0dSDavid C Somayajulu 			break;
218211e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_VF_DISABLED:
218311e25f0dSDavid C Somayajulu 			ecore_mcp_handle_vf_flr(p_hwfn, p_ptt);
218411e25f0dSDavid C Somayajulu 			break;
218511e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_LLDP_DATA_UPDATED:
218611e25f0dSDavid C Somayajulu 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
218711e25f0dSDavid C Somayajulu 						    ECORE_DCBX_REMOTE_LLDP_MIB);
218811e25f0dSDavid C Somayajulu 			break;
218911e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED:
219011e25f0dSDavid C Somayajulu 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
219111e25f0dSDavid C Somayajulu 						    ECORE_DCBX_REMOTE_MIB);
219211e25f0dSDavid C Somayajulu 			break;
219311e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED:
219411e25f0dSDavid C Somayajulu 			ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
219511e25f0dSDavid C Somayajulu 						    ECORE_DCBX_OPERATIONAL_MIB);
2196217ec208SDavid C Somayajulu 			/* clear the user-config cache */
2197217ec208SDavid C Somayajulu 			OSAL_MEMSET(&p_hwfn->p_dcbx_info->set, 0,
2198217ec208SDavid C Somayajulu 				    sizeof(struct ecore_dcbx_set));
2199217ec208SDavid C Somayajulu 			break;
2200217ec208SDavid C Somayajulu 		case MFW_DRV_MSG_LLDP_RECEIVED_TLVS_UPDATED:
2201217ec208SDavid C Somayajulu 			ecore_lldp_mib_update_event(p_hwfn, p_ptt);
2202217ec208SDavid C Somayajulu 			break;
2203217ec208SDavid C Somayajulu 		case MFW_DRV_MSG_OEM_CFG_UPDATE:
2204217ec208SDavid C Somayajulu 			ecore_mcp_handle_ufp_event(p_hwfn, p_ptt);
220511e25f0dSDavid C Somayajulu 			break;
220611e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
220711e25f0dSDavid C Somayajulu 			ecore_mcp_handle_transceiver_change(p_hwfn, p_ptt);
220811e25f0dSDavid C Somayajulu 			break;
220911e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_ERROR_RECOVERY:
221011e25f0dSDavid C Somayajulu 			ecore_mcp_handle_process_kill(p_hwfn, p_ptt);
221111e25f0dSDavid C Somayajulu 			break;
221211e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_GET_LAN_STATS:
221311e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_GET_FCOE_STATS:
221411e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_GET_ISCSI_STATS:
221511e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_GET_RDMA_STATS:
221611e25f0dSDavid C Somayajulu 			ecore_mcp_send_protocol_stats(p_hwfn, p_ptt, i);
221711e25f0dSDavid C Somayajulu 			break;
221811e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_BW_UPDATE:
221911e25f0dSDavid C Somayajulu 			ecore_mcp_update_bw(p_hwfn, p_ptt);
222011e25f0dSDavid C Somayajulu 			break;
222111e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_S_TAG_UPDATE:
222211e25f0dSDavid C Somayajulu 			ecore_mcp_update_stag(p_hwfn, p_ptt);
222311e25f0dSDavid C Somayajulu 			break;
222411e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_FAILURE_DETECTED:
22259efd0ba7SDavid C Somayajulu 			ecore_mcp_handle_fan_failure(p_hwfn);
222611e25f0dSDavid C Somayajulu 			break;
222711e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_CRITICAL_ERROR_OCCURRED:
222811e25f0dSDavid C Somayajulu 			ecore_mcp_handle_critical_error(p_hwfn, p_ptt);
222911e25f0dSDavid C Somayajulu 			break;
223011e25f0dSDavid C Somayajulu 		case MFW_DRV_MSG_GET_TLV_REQ:
223111e25f0dSDavid C Somayajulu 			OSAL_MFW_TLV_REQ(p_hwfn);
223211e25f0dSDavid C Somayajulu 			break;
223311e25f0dSDavid C Somayajulu 		default:
223411e25f0dSDavid C Somayajulu 			DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i);
223511e25f0dSDavid C Somayajulu 			rc = ECORE_INVAL;
223611e25f0dSDavid C Somayajulu 		}
223711e25f0dSDavid C Somayajulu 	}
223811e25f0dSDavid C Somayajulu 
223911e25f0dSDavid C Somayajulu 	/* ACK everything */
224011e25f0dSDavid C Somayajulu 	for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) {
224111e25f0dSDavid C Somayajulu 		OSAL_BE32 val = OSAL_CPU_TO_BE32(((u32 *)info->mfw_mb_cur)[i]);
224211e25f0dSDavid C Somayajulu 
224311e25f0dSDavid C Somayajulu 		/* MFW expect answer in BE, so we force write in that format */
224411e25f0dSDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt,
224511e25f0dSDavid C Somayajulu 			 info->mfw_mb_addr + sizeof(u32) +
224611e25f0dSDavid C Somayajulu 			 MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) *
224711e25f0dSDavid C Somayajulu 			 sizeof(u32) + i * sizeof(u32), val);
224811e25f0dSDavid C Somayajulu 	}
224911e25f0dSDavid C Somayajulu 
225011e25f0dSDavid C Somayajulu 	if (!found) {
2251217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
225211e25f0dSDavid C Somayajulu 			"Received an MFW message indication but no new message!\n");
225311e25f0dSDavid C Somayajulu 		rc = ECORE_INVAL;
225411e25f0dSDavid C Somayajulu 	}
225511e25f0dSDavid C Somayajulu 
225611e25f0dSDavid C Somayajulu 	/* Copy the new mfw messages into the shadow */
225711e25f0dSDavid C Somayajulu 	OSAL_MEMCPY(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length);
225811e25f0dSDavid C Somayajulu 
225911e25f0dSDavid C Somayajulu 	return rc;
226011e25f0dSDavid C Somayajulu }
226111e25f0dSDavid C Somayajulu 
ecore_mcp_get_mfw_ver(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_mfw_ver,u32 * p_running_bundle_id)226211e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_mfw_ver(struct ecore_hwfn *p_hwfn,
226311e25f0dSDavid C Somayajulu 					   struct ecore_ptt *p_ptt,
226411e25f0dSDavid C Somayajulu 					   u32 *p_mfw_ver,
226511e25f0dSDavid C Somayajulu 					   u32 *p_running_bundle_id)
226611e25f0dSDavid C Somayajulu {
226711e25f0dSDavid C Somayajulu 	u32 global_offsize;
226811e25f0dSDavid C Somayajulu 
226911e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
227011e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
227111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MFW version\n");
227211e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
227311e25f0dSDavid C Somayajulu 	}
227411e25f0dSDavid C Somayajulu #endif
227511e25f0dSDavid C Somayajulu 
227611e25f0dSDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev)) {
227711e25f0dSDavid C Somayajulu 		if (p_hwfn->vf_iov_info) {
227811e25f0dSDavid C Somayajulu 			struct pfvf_acquire_resp_tlv *p_resp;
227911e25f0dSDavid C Somayajulu 
228011e25f0dSDavid C Somayajulu 			p_resp = &p_hwfn->vf_iov_info->acquire_resp;
228111e25f0dSDavid C Somayajulu 			*p_mfw_ver = p_resp->pfdev_info.mfw_ver;
228211e25f0dSDavid C Somayajulu 			return ECORE_SUCCESS;
228311e25f0dSDavid C Somayajulu 		} else {
228411e25f0dSDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
228511e25f0dSDavid C Somayajulu 				   "VF requested MFW version prior to ACQUIRE\n");
228611e25f0dSDavid C Somayajulu 			return ECORE_INVAL;
228711e25f0dSDavid C Somayajulu 		}
228811e25f0dSDavid C Somayajulu 	}
228911e25f0dSDavid C Somayajulu 
229011e25f0dSDavid C Somayajulu 	global_offsize = ecore_rd(p_hwfn, p_ptt,
229111e25f0dSDavid C Somayajulu 			  SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
229211e25f0dSDavid C Somayajulu 					       PUBLIC_GLOBAL));
229311e25f0dSDavid C Somayajulu 	*p_mfw_ver = ecore_rd(p_hwfn, p_ptt,
229411e25f0dSDavid C Somayajulu 			SECTION_ADDR(global_offsize, 0) +
229511e25f0dSDavid C Somayajulu 			OFFSETOF(struct public_global, mfw_ver));
229611e25f0dSDavid C Somayajulu 
229711e25f0dSDavid C Somayajulu 	if (p_running_bundle_id != OSAL_NULL) {
229811e25f0dSDavid C Somayajulu 		*p_running_bundle_id = ecore_rd(p_hwfn, p_ptt,
229911e25f0dSDavid C Somayajulu 				SECTION_ADDR(global_offsize, 0) +
230011e25f0dSDavid C Somayajulu 				OFFSETOF(struct public_global,
230111e25f0dSDavid C Somayajulu 					 running_bundle_id));
230211e25f0dSDavid C Somayajulu 	}
230311e25f0dSDavid C Somayajulu 
230411e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
230511e25f0dSDavid C Somayajulu }
230611e25f0dSDavid C Somayajulu 
ecore_mcp_get_mbi_ver(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_mbi_ver)230711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_mbi_ver(struct ecore_hwfn *p_hwfn,
230811e25f0dSDavid C Somayajulu 					   struct ecore_ptt *p_ptt,
230911e25f0dSDavid C Somayajulu 					   u32 *p_mbi_ver)
231011e25f0dSDavid C Somayajulu {
231111e25f0dSDavid C Somayajulu 	u32 nvm_cfg_addr, nvm_cfg1_offset, mbi_ver_addr;
231211e25f0dSDavid C Somayajulu 
231311e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
231411e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
231511e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Emulation - can't get MBI version\n");
231611e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
231711e25f0dSDavid C Somayajulu 	}
231811e25f0dSDavid C Somayajulu #endif
231911e25f0dSDavid C Somayajulu 
232011e25f0dSDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
232111e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
232211e25f0dSDavid C Somayajulu 
232311e25f0dSDavid C Somayajulu 	/* Read the address of the nvm_cfg */
232411e25f0dSDavid C Somayajulu 	nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
232511e25f0dSDavid C Somayajulu 	if (!nvm_cfg_addr) {
232611e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Shared memory not initialized\n");
232711e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
232811e25f0dSDavid C Somayajulu 	}
232911e25f0dSDavid C Somayajulu 
233011e25f0dSDavid C Somayajulu 	/* Read the offset of nvm_cfg1 */
233111e25f0dSDavid C Somayajulu 	nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
233211e25f0dSDavid C Somayajulu 
233311e25f0dSDavid C Somayajulu 	mbi_ver_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
233411e25f0dSDavid C Somayajulu 		       OFFSETOF(struct nvm_cfg1, glob) +
233511e25f0dSDavid C Somayajulu 		       OFFSETOF(struct nvm_cfg1_glob, mbi_version);
233611e25f0dSDavid C Somayajulu 	*p_mbi_ver = ecore_rd(p_hwfn, p_ptt, mbi_ver_addr) &
233711e25f0dSDavid C Somayajulu 		     (NVM_CFG1_GLOB_MBI_VERSION_0_MASK |
233811e25f0dSDavid C Somayajulu 		      NVM_CFG1_GLOB_MBI_VERSION_1_MASK |
233911e25f0dSDavid C Somayajulu 		      NVM_CFG1_GLOB_MBI_VERSION_2_MASK);
234011e25f0dSDavid C Somayajulu 
234111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
234211e25f0dSDavid C Somayajulu }
234311e25f0dSDavid C Somayajulu 
ecore_mcp_get_media_type(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_media_type)2344217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_media_type(struct ecore_hwfn *p_hwfn,
2345217ec208SDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
234611e25f0dSDavid C Somayajulu 					      u32 *p_media_type)
234711e25f0dSDavid C Somayajulu {
234811e25f0dSDavid C Somayajulu 
234911e25f0dSDavid C Somayajulu 	/* TODO - Add support for VFs */
2350217ec208SDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
235111e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
235211e25f0dSDavid C Somayajulu 
235311e25f0dSDavid C Somayajulu 	if (!ecore_mcp_is_init(p_hwfn)) {
2354217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "MFW is not initialized!\n");
235511e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
235611e25f0dSDavid C Somayajulu 	}
2357217ec208SDavid C Somayajulu 	if (!p_ptt) {
235811e25f0dSDavid C Somayajulu 		*p_media_type = MEDIA_UNSPECIFIED;
2359217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2360217ec208SDavid C Somayajulu 	} else {
2361217ec208SDavid C Somayajulu 		*p_media_type = ecore_rd(p_hwfn, p_ptt,
2362217ec208SDavid C Somayajulu 					 p_hwfn->mcp_info->port_addr +
2363217ec208SDavid C Somayajulu 					 OFFSETOF(struct public_port,
2364217ec208SDavid C Somayajulu 						  media_type));
2365217ec208SDavid C Somayajulu 	}
236611e25f0dSDavid C Somayajulu 
2367217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
2368217ec208SDavid C Somayajulu }
2369217ec208SDavid C Somayajulu 
ecore_mcp_get_transceiver_data(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_tranceiver_type)2370217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_transceiver_data(struct ecore_hwfn *p_hwfn,
2371217ec208SDavid C Somayajulu 						    struct ecore_ptt *p_ptt,
2372217ec208SDavid C Somayajulu 						    u32 *p_tranceiver_type)
2373217ec208SDavid C Somayajulu {
2374217ec208SDavid C Somayajulu 	/* TODO - Add support for VFs */
2375217ec208SDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
2376217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2377217ec208SDavid C Somayajulu 
2378217ec208SDavid C Somayajulu 	if (!ecore_mcp_is_init(p_hwfn)) {
2379217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "MFW is not initialized!\n");
238011e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
2381217ec208SDavid C Somayajulu 	}
2382217ec208SDavid C Somayajulu 	if (!p_ptt) {
2383217ec208SDavid C Somayajulu 		*p_tranceiver_type = ETH_TRANSCEIVER_TYPE_NONE;
2384217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2385217ec208SDavid C Somayajulu 	} else {
2386217ec208SDavid C Somayajulu 		*p_tranceiver_type = ecore_rd(p_hwfn, p_ptt,
2387217ec208SDavid C Somayajulu 				p_hwfn->mcp_info->port_addr +
2388217ec208SDavid C Somayajulu 				offsetof(struct public_port,
2389217ec208SDavid C Somayajulu 					transceiver_data));
2390217ec208SDavid C Somayajulu 	}
239111e25f0dSDavid C Somayajulu 
2392217ec208SDavid C Somayajulu 	return 0;
2393217ec208SDavid C Somayajulu }
239411e25f0dSDavid C Somayajulu 
is_transceiver_ready(u32 transceiver_state,u32 transceiver_type)2395217ec208SDavid C Somayajulu static int is_transceiver_ready(u32 transceiver_state, u32 transceiver_type)
2396217ec208SDavid C Somayajulu {
2397217ec208SDavid C Somayajulu 
2398217ec208SDavid C Somayajulu 	if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) &&
2399217ec208SDavid C Somayajulu 	    ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) == 0x0) &&
2400217ec208SDavid C Somayajulu 	    (transceiver_type != ETH_TRANSCEIVER_TYPE_NONE)) {
2401217ec208SDavid C Somayajulu 		return 1;
2402217ec208SDavid C Somayajulu 	}
2403217ec208SDavid C Somayajulu 
2404217ec208SDavid C Somayajulu 	return 0;
2405217ec208SDavid C Somayajulu }
2406217ec208SDavid C Somayajulu 
ecore_mcp_trans_speed_mask(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_speed_mask)2407217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_trans_speed_mask(struct ecore_hwfn *p_hwfn,
2408217ec208SDavid C Somayajulu 						struct ecore_ptt *p_ptt,
2409217ec208SDavid C Somayajulu 						u32 *p_speed_mask)
2410217ec208SDavid C Somayajulu {
2411217ec208SDavid C Somayajulu 	u32 transceiver_data, transceiver_type, transceiver_state;
2412217ec208SDavid C Somayajulu 
2413217ec208SDavid C Somayajulu 	ecore_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_data);
2414217ec208SDavid C Somayajulu 
2415217ec208SDavid C Somayajulu 	transceiver_state = GET_MFW_FIELD(transceiver_data,
2416217ec208SDavid C Somayajulu 			    ETH_TRANSCEIVER_STATE);
2417217ec208SDavid C Somayajulu 
2418217ec208SDavid C Somayajulu 	transceiver_type = GET_MFW_FIELD(transceiver_data,
2419217ec208SDavid C Somayajulu 			   ETH_TRANSCEIVER_TYPE);
2420217ec208SDavid C Somayajulu 
2421217ec208SDavid C Somayajulu 	if (is_transceiver_ready(transceiver_state, transceiver_type) == 0) {
2422217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2423217ec208SDavid C Somayajulu 	}
2424217ec208SDavid C Somayajulu 
2425217ec208SDavid C Somayajulu 	switch (transceiver_type) {
2426217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_1G_LX:
2427217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_1G_SX:
2428217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_1G_PCC:
2429217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_1G_ACC:
2430217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_1000BASET:
2431217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
2432217ec208SDavid C Somayajulu 		break;
2433217ec208SDavid C Somayajulu 
2434217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_SR:
2435217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_LR:
2436217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_LRM:
2437217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_ER:
2438217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_PCC:
2439217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_ACC:
2440217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_4x10G:
2441217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
2442217ec208SDavid C Somayajulu 		break;
2443217ec208SDavid C Somayajulu 
2444217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_40G_LR4:
2445217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_40G_SR4:
2446217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
2447217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
2448217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
2449217ec208SDavid C Somayajulu 		 NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
2450217ec208SDavid C Somayajulu 		break;
2451217ec208SDavid C Somayajulu 
2452217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_AOC:
2453217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_SR4:
2454217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_LR4:
2455217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_ER4:
2456217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_ACC:
2457217ec208SDavid C Somayajulu 		*p_speed_mask =
2458217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
2459217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
2460217ec208SDavid C Somayajulu 		break;
2461217ec208SDavid C Somayajulu 
2462217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_SR:
2463217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_LR:
2464217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_AOC:
2465217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_ACC_S:
2466217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_ACC_M:
2467217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_ACC_L:
2468217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
2469217ec208SDavid C Somayajulu 		break;
2470217ec208SDavid C Somayajulu 
2471217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_CA_N:
2472217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_CA_S:
2473217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_25G_CA_L:
2474217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_4x25G_CR:
2475217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
2476217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
2477217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
2478217ec208SDavid C Somayajulu 		break;
2479217ec208SDavid C Somayajulu 
2480217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_40G_CR4:
2481217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
2482217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
2483217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
2484217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
2485217ec208SDavid C Somayajulu 		break;
2486217ec208SDavid C Somayajulu 
2487217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_100G_CR4:
2488217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
2489217ec208SDavid C Somayajulu 		*p_speed_mask =
2490217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
2491217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G |
2492217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
2493217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
2494217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G |
2495217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
2496217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
2497217ec208SDavid C Somayajulu 		break;
2498217ec208SDavid C Somayajulu 
2499217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
2500217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
2501217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC:
2502217ec208SDavid C Somayajulu 		*p_speed_mask =
2503217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
2504217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
2505217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
2506217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
2507217ec208SDavid C Somayajulu 		break;
2508217ec208SDavid C Somayajulu 
2509217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_XLPPI:
2510217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
2511217ec208SDavid C Somayajulu 		break;
2512217ec208SDavid C Somayajulu 
2513217ec208SDavid C Somayajulu 	case ETH_TRANSCEIVER_TYPE_10G_BASET:
2514217ec208SDavid C Somayajulu 		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
2515217ec208SDavid C Somayajulu 			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
2516217ec208SDavid C Somayajulu 		break;
2517217ec208SDavid C Somayajulu 
2518217ec208SDavid C Somayajulu 	default:
2519217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn, "Unknown transcevier type 0x%x\n",
2520217ec208SDavid C Somayajulu 			transceiver_type);
2521217ec208SDavid C Somayajulu 		*p_speed_mask = 0xff;
2522217ec208SDavid C Somayajulu 		break;
2523217ec208SDavid C Somayajulu 	}
2524217ec208SDavid C Somayajulu 
2525217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
2526217ec208SDavid C Somayajulu }
2527217ec208SDavid C Somayajulu 
ecore_mcp_get_board_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_board_config)2528217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_board_config(struct ecore_hwfn *p_hwfn,
2529217ec208SDavid C Somayajulu 						struct ecore_ptt *p_ptt,
2530217ec208SDavid C Somayajulu 						u32 *p_board_config)
2531217ec208SDavid C Somayajulu {
2532217ec208SDavid C Somayajulu 	u32 nvm_cfg_addr, nvm_cfg1_offset, port_cfg_addr;
2533217ec208SDavid C Somayajulu 
2534217ec208SDavid C Somayajulu 	/* TODO - Add support for VFs */
2535217ec208SDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
2536217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2537217ec208SDavid C Somayajulu 
2538217ec208SDavid C Somayajulu 	if (!ecore_mcp_is_init(p_hwfn)) {
2539217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "MFW is not initialized!\n");
2540217ec208SDavid C Somayajulu 		return ECORE_BUSY;
2541217ec208SDavid C Somayajulu 	}
2542217ec208SDavid C Somayajulu 	if (!p_ptt) {
2543217ec208SDavid C Somayajulu 		*p_board_config = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
2544217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2545217ec208SDavid C Somayajulu 	} else {
2546217ec208SDavid C Somayajulu 	nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt,
2547217ec208SDavid C Somayajulu 			MISC_REG_GEN_PURP_CR0);
2548217ec208SDavid C Somayajulu 	nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt,
2549217ec208SDavid C Somayajulu 			nvm_cfg_addr + 4);
2550217ec208SDavid C Somayajulu 	port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
2551217ec208SDavid C Somayajulu 		offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
2552217ec208SDavid C Somayajulu 	*p_board_config  =  ecore_rd(p_hwfn, p_ptt,
2553217ec208SDavid C Somayajulu 				     port_cfg_addr +
2554217ec208SDavid C Somayajulu 				     offsetof(struct nvm_cfg1_port,
2555217ec208SDavid C Somayajulu 				     board_cfg));
2556217ec208SDavid C Somayajulu 	}
255711e25f0dSDavid C Somayajulu 
255811e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
255911e25f0dSDavid C Somayajulu }
256011e25f0dSDavid C Somayajulu 
256111e25f0dSDavid C Somayajulu /* Old MFW has a global configuration for all PFs regarding RDMA support */
256211e25f0dSDavid C Somayajulu static void
ecore_mcp_get_shmem_proto_legacy(struct ecore_hwfn * p_hwfn,enum ecore_pci_personality * p_proto)256311e25f0dSDavid C Somayajulu ecore_mcp_get_shmem_proto_legacy(struct ecore_hwfn *p_hwfn,
256411e25f0dSDavid C Somayajulu 				 enum ecore_pci_personality *p_proto)
256511e25f0dSDavid C Somayajulu {
256611e25f0dSDavid C Somayajulu 	/* There wasn't ever a legacy MFW that published iwarp.
256711e25f0dSDavid C Somayajulu 	 * So at this point, this is either plain l2 or RoCE.
256811e25f0dSDavid C Somayajulu 	 */
256911e25f0dSDavid C Somayajulu 	if (OSAL_TEST_BIT(ECORE_DEV_CAP_ROCE,
257011e25f0dSDavid C Somayajulu 			  &p_hwfn->hw_info.device_capabilities))
257111e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH_ROCE;
257211e25f0dSDavid C Somayajulu 	else
257311e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH;
257411e25f0dSDavid C Somayajulu 
257511e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
257611e25f0dSDavid C Somayajulu 		   "According to Legacy capabilities, L2 personality is %08x\n",
257711e25f0dSDavid C Somayajulu 		   (u32) *p_proto);
257811e25f0dSDavid C Somayajulu }
257911e25f0dSDavid C Somayajulu 
258011e25f0dSDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_get_shmem_proto_mfw(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_pci_personality * p_proto)258111e25f0dSDavid C Somayajulu ecore_mcp_get_shmem_proto_mfw(struct ecore_hwfn *p_hwfn,
258211e25f0dSDavid C Somayajulu 			      struct ecore_ptt *p_ptt,
258311e25f0dSDavid C Somayajulu 			      enum ecore_pci_personality *p_proto)
258411e25f0dSDavid C Somayajulu {
258511e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
258611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
258711e25f0dSDavid C Somayajulu 
258811e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
258911e25f0dSDavid C Somayajulu 			 DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, &param);
259011e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
259111e25f0dSDavid C Somayajulu 		return rc;
259211e25f0dSDavid C Somayajulu 	if (resp != FW_MSG_CODE_OK) {
259311e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
259411e25f0dSDavid C Somayajulu 			   "MFW lacks support for command; Returns %08x\n",
259511e25f0dSDavid C Somayajulu 			   resp);
259611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
259711e25f0dSDavid C Somayajulu 	}
259811e25f0dSDavid C Somayajulu 
259911e25f0dSDavid C Somayajulu 	switch (param) {
260011e25f0dSDavid C Somayajulu 	case FW_MB_PARAM_GET_PF_RDMA_NONE:
260111e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH;
260211e25f0dSDavid C Somayajulu 		break;
260311e25f0dSDavid C Somayajulu 	case FW_MB_PARAM_GET_PF_RDMA_ROCE:
260411e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH_ROCE;
260511e25f0dSDavid C Somayajulu 		break;
260611e25f0dSDavid C Somayajulu 	case FW_MB_PARAM_GET_PF_RDMA_IWARP:
260711e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH_IWARP;
260811e25f0dSDavid C Somayajulu 		break;
260911e25f0dSDavid C Somayajulu 	case FW_MB_PARAM_GET_PF_RDMA_BOTH:
261011e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ETH_RDMA;
261111e25f0dSDavid C Somayajulu 		break;
261211e25f0dSDavid C Somayajulu 	default:
261311e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
261411e25f0dSDavid C Somayajulu 			  "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n",
261511e25f0dSDavid C Somayajulu 			  param);
261611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
261711e25f0dSDavid C Somayajulu 	}
261811e25f0dSDavid C Somayajulu 
261911e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP,
262011e25f0dSDavid C Somayajulu 		   "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n",
262111e25f0dSDavid C Somayajulu 		   (u32) *p_proto, resp, param);
262211e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
262311e25f0dSDavid C Somayajulu }
262411e25f0dSDavid C Somayajulu 
262511e25f0dSDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_get_shmem_proto(struct ecore_hwfn * p_hwfn,struct public_func * p_info,struct ecore_ptt * p_ptt,enum ecore_pci_personality * p_proto)262611e25f0dSDavid C Somayajulu ecore_mcp_get_shmem_proto(struct ecore_hwfn *p_hwfn,
262711e25f0dSDavid C Somayajulu 			  struct public_func *p_info,
262811e25f0dSDavid C Somayajulu 			  struct ecore_ptt *p_ptt,
262911e25f0dSDavid C Somayajulu 			  enum ecore_pci_personality *p_proto)
263011e25f0dSDavid C Somayajulu {
263111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
263211e25f0dSDavid C Somayajulu 
263311e25f0dSDavid C Somayajulu 	switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
263411e25f0dSDavid C Somayajulu 	case FUNC_MF_CFG_PROTOCOL_ETHERNET:
263511e25f0dSDavid C Somayajulu 		if (ecore_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto) !=
263611e25f0dSDavid C Somayajulu 		    ECORE_SUCCESS)
263711e25f0dSDavid C Somayajulu 			ecore_mcp_get_shmem_proto_legacy(p_hwfn, p_proto);
263811e25f0dSDavid C Somayajulu 		break;
263911e25f0dSDavid C Somayajulu 	case FUNC_MF_CFG_PROTOCOL_ISCSI:
264011e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_ISCSI;
264111e25f0dSDavid C Somayajulu 		break;
264211e25f0dSDavid C Somayajulu 	case FUNC_MF_CFG_PROTOCOL_FCOE:
264311e25f0dSDavid C Somayajulu 		*p_proto = ECORE_PCI_FCOE;
264411e25f0dSDavid C Somayajulu 		break;
264511e25f0dSDavid C Somayajulu 	case FUNC_MF_CFG_PROTOCOL_ROCE:
264611e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "RoCE personality is not a valid value!\n");
26479efd0ba7SDavid C Somayajulu 		/* Fallthrough */
264811e25f0dSDavid C Somayajulu 	default:
264911e25f0dSDavid C Somayajulu 		rc = ECORE_INVAL;
265011e25f0dSDavid C Somayajulu 	}
265111e25f0dSDavid C Somayajulu 
265211e25f0dSDavid C Somayajulu 	return rc;
265311e25f0dSDavid C Somayajulu }
265411e25f0dSDavid C Somayajulu 
ecore_mcp_fill_shmem_func_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)265511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_fill_shmem_func_info(struct ecore_hwfn *p_hwfn,
265611e25f0dSDavid C Somayajulu 						    struct ecore_ptt *p_ptt)
265711e25f0dSDavid C Somayajulu {
265811e25f0dSDavid C Somayajulu 	struct ecore_mcp_function_info *info;
265911e25f0dSDavid C Somayajulu 	struct public_func shmem_info;
266011e25f0dSDavid C Somayajulu 
266111e25f0dSDavid C Somayajulu 	ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
266211e25f0dSDavid C Somayajulu 				 MCP_PF_ID(p_hwfn));
266311e25f0dSDavid C Somayajulu 	info = &p_hwfn->mcp_info->func_info;
266411e25f0dSDavid C Somayajulu 
266511e25f0dSDavid C Somayajulu 	info->pause_on_host = (shmem_info.config &
266611e25f0dSDavid C Somayajulu 			       FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0;
266711e25f0dSDavid C Somayajulu 
266811e25f0dSDavid C Somayajulu 	if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
266911e25f0dSDavid C Somayajulu 				      &info->protocol)) {
267011e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Unknown personality %08x\n",
267111e25f0dSDavid C Somayajulu 		       (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
267211e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
267311e25f0dSDavid C Somayajulu 	}
267411e25f0dSDavid C Somayajulu 
267511e25f0dSDavid C Somayajulu 	ecore_read_pf_bandwidth(p_hwfn, &shmem_info);
267611e25f0dSDavid C Somayajulu 
267711e25f0dSDavid C Somayajulu 	if (shmem_info.mac_upper || shmem_info.mac_lower) {
267811e25f0dSDavid C Somayajulu 		info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
267911e25f0dSDavid C Somayajulu 		info->mac[1] = (u8)(shmem_info.mac_upper);
268011e25f0dSDavid C Somayajulu 		info->mac[2] = (u8)(shmem_info.mac_lower >> 24);
268111e25f0dSDavid C Somayajulu 		info->mac[3] = (u8)(shmem_info.mac_lower >> 16);
268211e25f0dSDavid C Somayajulu 		info->mac[4] = (u8)(shmem_info.mac_lower >> 8);
268311e25f0dSDavid C Somayajulu 		info->mac[5] = (u8)(shmem_info.mac_lower);
268411e25f0dSDavid C Somayajulu 
268511e25f0dSDavid C Somayajulu 		/* Store primary MAC for later possible WoL */
268611e25f0dSDavid C Somayajulu 		OSAL_MEMCPY(&p_hwfn->p_dev->wol_mac, info->mac, ETH_ALEN);
268711e25f0dSDavid C Somayajulu 
268811e25f0dSDavid C Somayajulu 	} else {
268911e25f0dSDavid C Somayajulu 		/* TODO - are there protocols for which there's no MAC? */
269011e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "MAC is 0 in shmem\n");
269111e25f0dSDavid C Somayajulu 	}
269211e25f0dSDavid C Somayajulu 
269311e25f0dSDavid C Somayajulu 	/* TODO - are these calculations true for BE machine? */
26949efd0ba7SDavid C Somayajulu 	info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower |
26959efd0ba7SDavid C Somayajulu 			 (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32);
26969efd0ba7SDavid C Somayajulu 	info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower |
26979efd0ba7SDavid C Somayajulu 			 (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32);
269811e25f0dSDavid C Somayajulu 
269911e25f0dSDavid C Somayajulu 	info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
270011e25f0dSDavid C Somayajulu 
270111e25f0dSDavid C Somayajulu 	info->mtu = (u16)shmem_info.mtu_size;
270211e25f0dSDavid C Somayajulu 
270311e25f0dSDavid C Somayajulu 	p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_NONE;
27049efd0ba7SDavid C Somayajulu 	p_hwfn->p_dev->wol_config = (u8)ECORE_OV_WOL_DEFAULT;
270511e25f0dSDavid C Somayajulu 	if (ecore_mcp_is_init(p_hwfn)) {
270611e25f0dSDavid C Somayajulu 		u32 resp = 0, param = 0;
270711e25f0dSDavid C Somayajulu 		enum _ecore_status_t rc;
270811e25f0dSDavid C Somayajulu 
270911e25f0dSDavid C Somayajulu 		rc = ecore_mcp_cmd(p_hwfn, p_ptt,
271011e25f0dSDavid C Somayajulu 				   DRV_MSG_CODE_OS_WOL, 0, &resp, &param);
271111e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
271211e25f0dSDavid C Somayajulu 			return rc;
271311e25f0dSDavid C Somayajulu 		if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED)
271411e25f0dSDavid C Somayajulu 			p_hwfn->hw_info.b_wol_support = ECORE_WOL_SUPPORT_PME;
271511e25f0dSDavid C Somayajulu 	}
271611e25f0dSDavid C Somayajulu 
271711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_IFUP),
271811e25f0dSDavid C Somayajulu 		   "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",
271911e25f0dSDavid C Somayajulu 		   info->pause_on_host, info->protocol,
272011e25f0dSDavid C Somayajulu 		   info->bandwidth_min, info->bandwidth_max,
272111e25f0dSDavid C Somayajulu 		   info->mac[0], info->mac[1], info->mac[2],
272211e25f0dSDavid C Somayajulu 		   info->mac[3], info->mac[4], info->mac[5],
272311e25f0dSDavid C Somayajulu 		   (unsigned long long)info->wwn_port, (unsigned long long)info->wwn_node, info->ovlan,
272411e25f0dSDavid C Somayajulu 		   (u8)p_hwfn->hw_info.b_wol_support);
272511e25f0dSDavid C Somayajulu 
272611e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
272711e25f0dSDavid C Somayajulu }
272811e25f0dSDavid C Somayajulu 
272911e25f0dSDavid C Somayajulu struct ecore_mcp_link_params
ecore_mcp_get_link_params(struct ecore_hwfn * p_hwfn)273011e25f0dSDavid C Somayajulu *ecore_mcp_get_link_params(struct ecore_hwfn *p_hwfn)
273111e25f0dSDavid C Somayajulu {
273211e25f0dSDavid C Somayajulu 	if (!p_hwfn || !p_hwfn->mcp_info)
273311e25f0dSDavid C Somayajulu 		return OSAL_NULL;
273411e25f0dSDavid C Somayajulu 	return &p_hwfn->mcp_info->link_input;
273511e25f0dSDavid C Somayajulu }
273611e25f0dSDavid C Somayajulu 
273711e25f0dSDavid C Somayajulu struct ecore_mcp_link_state
ecore_mcp_get_link_state(struct ecore_hwfn * p_hwfn)273811e25f0dSDavid C Somayajulu *ecore_mcp_get_link_state(struct ecore_hwfn *p_hwfn)
273911e25f0dSDavid C Somayajulu {
274011e25f0dSDavid C Somayajulu 	if (!p_hwfn || !p_hwfn->mcp_info)
274111e25f0dSDavid C Somayajulu 		return OSAL_NULL;
274211e25f0dSDavid C Somayajulu 
274311e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
274411e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
274511e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn, "Non-ASIC - always notify that link is up\n");
274611e25f0dSDavid C Somayajulu 		p_hwfn->mcp_info->link_output.link_up = true;
274711e25f0dSDavid C Somayajulu 	}
274811e25f0dSDavid C Somayajulu #endif
274911e25f0dSDavid C Somayajulu 
275011e25f0dSDavid C Somayajulu 	return &p_hwfn->mcp_info->link_output;
275111e25f0dSDavid C Somayajulu }
275211e25f0dSDavid C Somayajulu 
275311e25f0dSDavid C Somayajulu struct ecore_mcp_link_capabilities
ecore_mcp_get_link_capabilities(struct ecore_hwfn * p_hwfn)275411e25f0dSDavid C Somayajulu *ecore_mcp_get_link_capabilities(struct ecore_hwfn *p_hwfn)
275511e25f0dSDavid C Somayajulu {
275611e25f0dSDavid C Somayajulu 	if (!p_hwfn || !p_hwfn->mcp_info)
275711e25f0dSDavid C Somayajulu 		return OSAL_NULL;
275811e25f0dSDavid C Somayajulu 	return &p_hwfn->mcp_info->link_capabilities;
275911e25f0dSDavid C Somayajulu }
276011e25f0dSDavid C Somayajulu 
ecore_mcp_drain(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)276111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_drain(struct ecore_hwfn *p_hwfn,
276211e25f0dSDavid C Somayajulu 				     struct ecore_ptt *p_ptt)
276311e25f0dSDavid C Somayajulu {
276411e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
276511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
276611e25f0dSDavid C Somayajulu 
276711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt,
276811e25f0dSDavid C Somayajulu 			   DRV_MSG_CODE_NIG_DRAIN, 1000,
276911e25f0dSDavid C Somayajulu 			   &resp, &param);
277011e25f0dSDavid C Somayajulu 
277111e25f0dSDavid C Somayajulu 	/* Wait for the drain to complete before returning */
277211e25f0dSDavid C Somayajulu 	OSAL_MSLEEP(1020);
277311e25f0dSDavid C Somayajulu 
277411e25f0dSDavid C Somayajulu 	return rc;
277511e25f0dSDavid C Somayajulu }
277611e25f0dSDavid C Somayajulu 
277711e25f0dSDavid C Somayajulu #ifndef LINUX_REMOVE
277811e25f0dSDavid C Somayajulu const struct ecore_mcp_function_info
ecore_mcp_get_function_info(struct ecore_hwfn * p_hwfn)277911e25f0dSDavid C Somayajulu *ecore_mcp_get_function_info(struct ecore_hwfn *p_hwfn)
278011e25f0dSDavid C Somayajulu {
278111e25f0dSDavid C Somayajulu 	if (!p_hwfn || !p_hwfn->mcp_info)
278211e25f0dSDavid C Somayajulu 		return OSAL_NULL;
278311e25f0dSDavid C Somayajulu 	return &p_hwfn->mcp_info->func_info;
278411e25f0dSDavid C Somayajulu }
278511e25f0dSDavid C Somayajulu 
ecore_mcp_get_personality_cnt(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 personalities)278611e25f0dSDavid C Somayajulu int ecore_mcp_get_personality_cnt(struct ecore_hwfn *p_hwfn,
278711e25f0dSDavid C Somayajulu 				  struct ecore_ptt *p_ptt,
278811e25f0dSDavid C Somayajulu 				  u32 personalities)
278911e25f0dSDavid C Somayajulu {
279011e25f0dSDavid C Somayajulu 	enum ecore_pci_personality protocol = ECORE_PCI_DEFAULT;
279111e25f0dSDavid C Somayajulu 	struct public_func shmem_info;
279211e25f0dSDavid C Somayajulu 	int i, count = 0, num_pfs;
279311e25f0dSDavid C Somayajulu 
279411e25f0dSDavid C Somayajulu 	num_pfs = NUM_OF_ENG_PFS(p_hwfn->p_dev);
279511e25f0dSDavid C Somayajulu 
279611e25f0dSDavid C Somayajulu 	for (i = 0; i < num_pfs; i++) {
279711e25f0dSDavid C Somayajulu 		ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
279811e25f0dSDavid C Somayajulu 					 MCP_PF_ID_BY_REL(p_hwfn, i));
279911e25f0dSDavid C Somayajulu 		if (shmem_info.config & FUNC_MF_CFG_FUNC_HIDE)
280011e25f0dSDavid C Somayajulu 			continue;
280111e25f0dSDavid C Somayajulu 
280211e25f0dSDavid C Somayajulu 		if (ecore_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
280311e25f0dSDavid C Somayajulu 					      &protocol) !=
280411e25f0dSDavid C Somayajulu 		    ECORE_SUCCESS)
280511e25f0dSDavid C Somayajulu 			continue;
280611e25f0dSDavid C Somayajulu 
280711e25f0dSDavid C Somayajulu 		if ((1 << ((u32)protocol)) & personalities)
280811e25f0dSDavid C Somayajulu 			count++;
280911e25f0dSDavid C Somayajulu 	}
281011e25f0dSDavid C Somayajulu 
281111e25f0dSDavid C Somayajulu 	return count;
281211e25f0dSDavid C Somayajulu }
281311e25f0dSDavid C Somayajulu #endif
281411e25f0dSDavid C Somayajulu 
ecore_mcp_get_flash_size(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * p_flash_size)281511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_flash_size(struct ecore_hwfn *p_hwfn,
281611e25f0dSDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
281711e25f0dSDavid C Somayajulu 					      u32 *p_flash_size)
281811e25f0dSDavid C Somayajulu {
281911e25f0dSDavid C Somayajulu 	u32 flash_size;
282011e25f0dSDavid C Somayajulu 
282111e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
282211e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev)) {
282311e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Emulation - can't get flash size\n");
282411e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
282511e25f0dSDavid C Somayajulu 	}
282611e25f0dSDavid C Somayajulu #endif
282711e25f0dSDavid C Somayajulu 
282811e25f0dSDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
282911e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
283011e25f0dSDavid C Somayajulu 
283111e25f0dSDavid C Somayajulu 	flash_size = ecore_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4);
283211e25f0dSDavid C Somayajulu 	flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >>
283311e25f0dSDavid C Somayajulu 		     MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT;
28349efd0ba7SDavid C Somayajulu 	flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_OFFSET));
283511e25f0dSDavid C Somayajulu 
283611e25f0dSDavid C Somayajulu 	*p_flash_size = flash_size;
283711e25f0dSDavid C Somayajulu 
283811e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
283911e25f0dSDavid C Somayajulu }
284011e25f0dSDavid C Somayajulu 
ecore_start_recovery_process(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)284111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_start_recovery_process(struct ecore_hwfn *p_hwfn,
284211e25f0dSDavid C Somayajulu 						  struct ecore_ptt *p_ptt)
284311e25f0dSDavid C Somayajulu {
284411e25f0dSDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
284511e25f0dSDavid C Somayajulu 
284611e25f0dSDavid C Somayajulu 	if (p_dev->recov_in_prog) {
284711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
284811e25f0dSDavid C Somayajulu 			  "Avoid triggering a recovery since such a process is already in progress\n");
284911e25f0dSDavid C Somayajulu 		return ECORE_AGAIN;
285011e25f0dSDavid C Somayajulu 	}
285111e25f0dSDavid C Somayajulu 
285211e25f0dSDavid C Somayajulu 	DP_NOTICE(p_hwfn, false, "Triggering a recovery process\n");
285311e25f0dSDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1);
285411e25f0dSDavid C Somayajulu 
285511e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
285611e25f0dSDavid C Somayajulu }
285711e25f0dSDavid C Somayajulu 
2858217ec208SDavid C Somayajulu #define ECORE_RECOVERY_PROLOG_SLEEP_MS	100
2859217ec208SDavid C Somayajulu 
ecore_recovery_prolog(struct ecore_dev * p_dev)2860217ec208SDavid C Somayajulu enum _ecore_status_t ecore_recovery_prolog(struct ecore_dev *p_dev)
2861217ec208SDavid C Somayajulu {
2862217ec208SDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
2863217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt = p_hwfn->p_main_ptt;
2864217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2865217ec208SDavid C Somayajulu 
2866217ec208SDavid C Somayajulu 	/* Allow ongoing PCIe transactions to complete */
2867217ec208SDavid C Somayajulu 	OSAL_MSLEEP(ECORE_RECOVERY_PROLOG_SLEEP_MS);
2868217ec208SDavid C Somayajulu 
2869217ec208SDavid C Somayajulu 	/* Clear the PF's internal FID_enable in the PXP */
2870217ec208SDavid C Somayajulu 	rc = ecore_pglueb_set_pfid_enable(p_hwfn, p_ptt, false);
2871217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
2872217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
2873217ec208SDavid C Somayajulu 			  "ecore_pglueb_set_pfid_enable() failed. rc = %d.\n",
2874217ec208SDavid C Somayajulu 			  rc);
2875217ec208SDavid C Somayajulu 
2876217ec208SDavid C Somayajulu 	return rc;
2877217ec208SDavid C Somayajulu }
2878217ec208SDavid C Somayajulu 
28799efd0ba7SDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_config_vf_msix_bb(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 vf_id,u8 num)28809efd0ba7SDavid C Somayajulu ecore_mcp_config_vf_msix_bb(struct ecore_hwfn *p_hwfn,
288111e25f0dSDavid C Somayajulu 			    struct ecore_ptt *p_ptt,
288211e25f0dSDavid C Somayajulu 			    u8 vf_id, u8 num)
288311e25f0dSDavid C Somayajulu {
288411e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0, rc_param = 0;
288511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
288611e25f0dSDavid C Somayajulu 
288711e25f0dSDavid C Somayajulu 	/* Only Leader can configure MSIX, and need to take CMT into account */
288811e25f0dSDavid C Somayajulu 	if (!IS_LEAD_HWFN(p_hwfn))
288911e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
289011e25f0dSDavid C Somayajulu 	num *= p_hwfn->p_dev->num_hwfns;
289111e25f0dSDavid C Somayajulu 
28929efd0ba7SDavid C Somayajulu 	param |= (vf_id << DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_OFFSET) &
289311e25f0dSDavid C Somayajulu 		 DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK;
28949efd0ba7SDavid C Somayajulu 	param |= (num << DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_OFFSET) &
289511e25f0dSDavid C Somayajulu 		 DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK;
289611e25f0dSDavid C Somayajulu 
289711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_VF_MSIX, param,
289811e25f0dSDavid C Somayajulu 			   &resp, &rc_param);
289911e25f0dSDavid C Somayajulu 
290011e25f0dSDavid C Somayajulu 	if (resp != FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE) {
290111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "VF[%d]: MFW failed to set MSI-X\n",
290211e25f0dSDavid C Somayajulu 			  vf_id);
290311e25f0dSDavid C Somayajulu 		rc = ECORE_INVAL;
290411e25f0dSDavid C Somayajulu 	} else {
290511e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
290611e25f0dSDavid C Somayajulu 			   "Requested 0x%02x MSI-x interrupts from VF 0x%02x\n",
290711e25f0dSDavid C Somayajulu 			    num, vf_id);
290811e25f0dSDavid C Somayajulu 	}
290911e25f0dSDavid C Somayajulu 
291011e25f0dSDavid C Somayajulu 	return rc;
291111e25f0dSDavid C Somayajulu }
291211e25f0dSDavid C Somayajulu 
29139efd0ba7SDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_config_vf_msix_ah(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 num)29149efd0ba7SDavid C Somayajulu ecore_mcp_config_vf_msix_ah(struct ecore_hwfn *p_hwfn,
29159efd0ba7SDavid C Somayajulu 			    struct ecore_ptt *p_ptt,
29169efd0ba7SDavid C Somayajulu 			    u8 num)
29179efd0ba7SDavid C Somayajulu {
29189efd0ba7SDavid C Somayajulu 	u32 resp = 0, param = num, rc_param = 0;
29199efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
29209efd0ba7SDavid C Somayajulu 
29219efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_PF_VFS_MSIX,
29229efd0ba7SDavid C Somayajulu 			   param, &resp, &rc_param);
29239efd0ba7SDavid C Somayajulu 
29249efd0ba7SDavid C Somayajulu 	if (resp != FW_MSG_CODE_DRV_CFG_PF_VFS_MSIX_DONE) {
29259efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "MFW failed to set MSI-X for VFs\n");
29269efd0ba7SDavid C Somayajulu 		rc = ECORE_INVAL;
29279efd0ba7SDavid C Somayajulu 	} else {
29289efd0ba7SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
29299efd0ba7SDavid C Somayajulu 			   "Requested 0x%02x MSI-x interrupts for VFs\n",
29309efd0ba7SDavid C Somayajulu 			   num);
29319efd0ba7SDavid C Somayajulu 	}
29329efd0ba7SDavid C Somayajulu 
29339efd0ba7SDavid C Somayajulu 	return rc;
29349efd0ba7SDavid C Somayajulu }
29359efd0ba7SDavid C Somayajulu 
ecore_mcp_config_vf_msix(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 vf_id,u8 num)29369efd0ba7SDavid C Somayajulu enum _ecore_status_t ecore_mcp_config_vf_msix(struct ecore_hwfn *p_hwfn,
29379efd0ba7SDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
29389efd0ba7SDavid C Somayajulu 					      u8 vf_id, u8 num)
29399efd0ba7SDavid C Somayajulu {
29409efd0ba7SDavid C Somayajulu 	if (ECORE_IS_BB(p_hwfn->p_dev))
29419efd0ba7SDavid C Somayajulu 		return ecore_mcp_config_vf_msix_bb(p_hwfn, p_ptt, vf_id, num);
29429efd0ba7SDavid C Somayajulu 	else
29439efd0ba7SDavid C Somayajulu 		return ecore_mcp_config_vf_msix_ah(p_hwfn, p_ptt, num);
29449efd0ba7SDavid C Somayajulu }
29459efd0ba7SDavid C Somayajulu 
294611e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_send_drv_version(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_drv_version * p_ver)294711e25f0dSDavid C Somayajulu ecore_mcp_send_drv_version(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
294811e25f0dSDavid C Somayajulu 			   struct ecore_mcp_drv_version *p_ver)
294911e25f0dSDavid C Somayajulu {
295011e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
295111e25f0dSDavid C Somayajulu 	struct drv_version_stc drv_version;
295211e25f0dSDavid C Somayajulu 	u32 num_words, i;
295311e25f0dSDavid C Somayajulu 	void *p_name;
295411e25f0dSDavid C Somayajulu 	OSAL_BE32 val;
295511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
295611e25f0dSDavid C Somayajulu 
295711e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
295811e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev))
295911e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
296011e25f0dSDavid C Somayajulu #endif
296111e25f0dSDavid C Somayajulu 
296211e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&drv_version, sizeof(drv_version));
296311e25f0dSDavid C Somayajulu 	drv_version.version = p_ver->version;
296411e25f0dSDavid C Somayajulu 	num_words = (MCP_DRV_VER_STR_SIZE - 4) / 4;
296511e25f0dSDavid C Somayajulu 	for (i = 0; i < num_words; i++) {
296611e25f0dSDavid C Somayajulu 		/* The driver name is expected to be in a big-endian format */
296711e25f0dSDavid C Somayajulu 		p_name = &p_ver->name[i * sizeof(u32)];
296811e25f0dSDavid C Somayajulu 		val = OSAL_CPU_TO_BE32(*(u32 *)p_name);
296911e25f0dSDavid C Somayajulu 		*(u32 *)&drv_version.name[i * sizeof(u32)] = val;
297011e25f0dSDavid C Somayajulu 	}
297111e25f0dSDavid C Somayajulu 
297211e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
297311e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_SET_VERSION;
297411e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &drv_version;
297511e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(drv_version);
297611e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
297711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
297811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
297911e25f0dSDavid C Somayajulu 
298011e25f0dSDavid C Somayajulu 	return rc;
298111e25f0dSDavid C Somayajulu }
298211e25f0dSDavid C Somayajulu 
29839efd0ba7SDavid C Somayajulu /* A maximal 100 msec waiting time for the MCP to halt */
29849efd0ba7SDavid C Somayajulu #define ECORE_MCP_HALT_SLEEP_MS		10
29859efd0ba7SDavid C Somayajulu #define ECORE_MCP_HALT_MAX_RETRIES	10
29869efd0ba7SDavid C Somayajulu 
ecore_mcp_halt(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)298711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_halt(struct ecore_hwfn *p_hwfn,
298811e25f0dSDavid C Somayajulu 				    struct ecore_ptt *p_ptt)
298911e25f0dSDavid C Somayajulu {
2990217ec208SDavid C Somayajulu 	u32 resp = 0, param = 0, cpu_state, cnt = 0;
299111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
299211e25f0dSDavid C Somayajulu 
299311e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp,
299411e25f0dSDavid C Somayajulu 			   &param);
29959efd0ba7SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
299611e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
299711e25f0dSDavid C Somayajulu 		return rc;
299811e25f0dSDavid C Somayajulu 	}
299911e25f0dSDavid C Somayajulu 
30009efd0ba7SDavid C Somayajulu 	do {
30019efd0ba7SDavid C Somayajulu 		OSAL_MSLEEP(ECORE_MCP_HALT_SLEEP_MS);
3002217ec208SDavid C Somayajulu 		cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
3003217ec208SDavid C Somayajulu 		if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED)
30049efd0ba7SDavid C Somayajulu 			break;
30059efd0ba7SDavid C Somayajulu 	} while (++cnt < ECORE_MCP_HALT_MAX_RETRIES);
30069efd0ba7SDavid C Somayajulu 
30079efd0ba7SDavid C Somayajulu 	if (cnt == ECORE_MCP_HALT_MAX_RETRIES) {
30089efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
3009217ec208SDavid C Somayajulu 			  "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
3010217ec208SDavid C Somayajulu 			  ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state);
30119efd0ba7SDavid C Somayajulu 		return ECORE_BUSY;
30129efd0ba7SDavid C Somayajulu 	}
30139efd0ba7SDavid C Somayajulu 
30149efd0ba7SDavid C Somayajulu 	ecore_mcp_cmd_set_blocking(p_hwfn, true);
30159efd0ba7SDavid C Somayajulu 
30169efd0ba7SDavid C Somayajulu 	return ECORE_SUCCESS;
30179efd0ba7SDavid C Somayajulu }
30189efd0ba7SDavid C Somayajulu 
3019217ec208SDavid C Somayajulu #define ECORE_MCP_RESUME_SLEEP_MS	10
3020217ec208SDavid C Somayajulu 
ecore_mcp_resume(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)302111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_resume(struct ecore_hwfn *p_hwfn,
302211e25f0dSDavid C Somayajulu 				      struct ecore_ptt *p_ptt)
302311e25f0dSDavid C Somayajulu {
3024217ec208SDavid C Somayajulu 	u32 cpu_mode, cpu_state;
302511e25f0dSDavid C Somayajulu 
302611e25f0dSDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff);
302711e25f0dSDavid C Somayajulu 
302811e25f0dSDavid C Somayajulu 	cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
3029217ec208SDavid C Somayajulu 	cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT;
3030217ec208SDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode);
303111e25f0dSDavid C Somayajulu 
3032217ec208SDavid C Somayajulu 	OSAL_MSLEEP(ECORE_MCP_RESUME_SLEEP_MS);
3033217ec208SDavid C Somayajulu 	cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
3034217ec208SDavid C Somayajulu 
3035217ec208SDavid C Somayajulu 	if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) {
30369efd0ba7SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
3037217ec208SDavid C Somayajulu 			  "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
3038217ec208SDavid C Somayajulu 			  cpu_mode, cpu_state);
30399efd0ba7SDavid C Somayajulu 		return ECORE_BUSY;
30409efd0ba7SDavid C Somayajulu 	}
30419efd0ba7SDavid C Somayajulu 
30429efd0ba7SDavid C Somayajulu 	ecore_mcp_cmd_set_blocking(p_hwfn, false);
30439efd0ba7SDavid C Somayajulu 
30449efd0ba7SDavid C Somayajulu 	return ECORE_SUCCESS;
304511e25f0dSDavid C Somayajulu }
304611e25f0dSDavid C Somayajulu 
304711e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_current_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_client client)304811e25f0dSDavid C Somayajulu ecore_mcp_ov_update_current_config(struct ecore_hwfn *p_hwfn,
304911e25f0dSDavid C Somayajulu 				   struct ecore_ptt *p_ptt,
305011e25f0dSDavid C Somayajulu 				   enum ecore_ov_client client)
305111e25f0dSDavid C Somayajulu {
305211e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
305311e25f0dSDavid C Somayajulu 	u32 drv_mb_param;
30549efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
305511e25f0dSDavid C Somayajulu 
305611e25f0dSDavid C Somayajulu 	switch (client) {
305711e25f0dSDavid C Somayajulu 	case ECORE_OV_CLIENT_DRV:
305811e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS;
305911e25f0dSDavid C Somayajulu 		break;
306011e25f0dSDavid C Somayajulu 	case ECORE_OV_CLIENT_USER:
306111e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER;
306211e25f0dSDavid C Somayajulu 		break;
306311e25f0dSDavid C Somayajulu 	case ECORE_OV_CLIENT_VENDOR_SPEC:
306411e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC;
306511e25f0dSDavid C Somayajulu 		break;
306611e25f0dSDavid C Somayajulu 	default:
306711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
306811e25f0dSDavid C Somayajulu 			  "Invalid client type %d\n", client);
306911e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
307011e25f0dSDavid C Somayajulu 	}
307111e25f0dSDavid C Somayajulu 
307211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG,
307311e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
307411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
307511e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
307611e25f0dSDavid C Somayajulu 
307711e25f0dSDavid C Somayajulu 	return rc;
307811e25f0dSDavid C Somayajulu }
307911e25f0dSDavid C Somayajulu 
308011e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_driver_state(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_driver_state drv_state)308111e25f0dSDavid C Somayajulu ecore_mcp_ov_update_driver_state(struct ecore_hwfn *p_hwfn,
308211e25f0dSDavid C Somayajulu 				 struct ecore_ptt *p_ptt,
308311e25f0dSDavid C Somayajulu 				 enum ecore_ov_driver_state drv_state)
308411e25f0dSDavid C Somayajulu {
308511e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
308611e25f0dSDavid C Somayajulu 	u32 drv_mb_param;
30879efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
308811e25f0dSDavid C Somayajulu 
308911e25f0dSDavid C Somayajulu 	switch (drv_state) {
309011e25f0dSDavid C Somayajulu 	case ECORE_OV_DRIVER_STATE_NOT_LOADED:
309111e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED;
309211e25f0dSDavid C Somayajulu 		break;
309311e25f0dSDavid C Somayajulu 	case ECORE_OV_DRIVER_STATE_DISABLED:
309411e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED;
309511e25f0dSDavid C Somayajulu 		break;
309611e25f0dSDavid C Somayajulu 	case ECORE_OV_DRIVER_STATE_ACTIVE:
309711e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE;
309811e25f0dSDavid C Somayajulu 		break;
309911e25f0dSDavid C Somayajulu 	default:
310011e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
310111e25f0dSDavid C Somayajulu 			  "Invalid driver state %d\n", drv_state);
310211e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
310311e25f0dSDavid C Somayajulu 	}
310411e25f0dSDavid C Somayajulu 
310511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE,
310611e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
310711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
310811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send driver state\n");
310911e25f0dSDavid C Somayajulu 
311011e25f0dSDavid C Somayajulu 	return rc;
311111e25f0dSDavid C Somayajulu }
311211e25f0dSDavid C Somayajulu 
311311e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_get_fc_npiv(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_fc_npiv_tbl * p_table)311411e25f0dSDavid C Somayajulu ecore_mcp_ov_get_fc_npiv(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
311511e25f0dSDavid C Somayajulu 			 struct ecore_fc_npiv_tbl *p_table)
311611e25f0dSDavid C Somayajulu {
311711e25f0dSDavid C Somayajulu 	struct dci_fc_npiv_tbl *p_npiv_table;
311811e25f0dSDavid C Somayajulu 	u8 *p_buf = OSAL_NULL;
311911e25f0dSDavid C Somayajulu 	u32 addr, size, i;
31209efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
312111e25f0dSDavid C Somayajulu 
312211e25f0dSDavid C Somayajulu 	p_table->num_wwpn = 0;
312311e25f0dSDavid C Somayajulu 	p_table->num_wwnn = 0;
312411e25f0dSDavid C Somayajulu 	addr = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
312511e25f0dSDavid C Somayajulu 			OFFSETOF(struct public_port, fc_npiv_nvram_tbl_addr));
312611e25f0dSDavid C Somayajulu 	if (addr == NPIV_TBL_INVALID_ADDR) {
312711e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table doesn't exist\n");
312811e25f0dSDavid C Somayajulu 		return rc;
312911e25f0dSDavid C Somayajulu 	}
313011e25f0dSDavid C Somayajulu 
313111e25f0dSDavid C Somayajulu 	size = ecore_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
313211e25f0dSDavid C Somayajulu 			OFFSETOF(struct public_port, fc_npiv_nvram_tbl_size));
313311e25f0dSDavid C Somayajulu 	if (!size) {
313411e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "NPIV table is empty\n");
313511e25f0dSDavid C Somayajulu 		return rc;
313611e25f0dSDavid C Somayajulu 	}
313711e25f0dSDavid C Somayajulu 
313811e25f0dSDavid C Somayajulu 	p_buf = OSAL_VZALLOC(p_hwfn->p_dev, size);
313911e25f0dSDavid C Somayajulu 	if (!p_buf) {
314011e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Buffer allocation failed\n");
314111e25f0dSDavid C Somayajulu 		return ECORE_NOMEM;
314211e25f0dSDavid C Somayajulu 	}
314311e25f0dSDavid C Somayajulu 
314411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_nvm_read(p_hwfn->p_dev, addr, p_buf, size);
314511e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
314611e25f0dSDavid C Somayajulu 		OSAL_VFREE(p_hwfn->p_dev, p_buf);
314711e25f0dSDavid C Somayajulu 		return rc;
314811e25f0dSDavid C Somayajulu 	}
314911e25f0dSDavid C Somayajulu 
315011e25f0dSDavid C Somayajulu 	p_npiv_table = (struct dci_fc_npiv_tbl *)p_buf;
315111e25f0dSDavid C Somayajulu 	p_table->num_wwpn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
315211e25f0dSDavid C Somayajulu 	p_table->num_wwnn = (u16)p_npiv_table->fc_npiv_cfg.num_of_npiv;
315311e25f0dSDavid C Somayajulu 	for (i = 0; i < p_table->num_wwpn; i++) {
315411e25f0dSDavid C Somayajulu 		OSAL_MEMCPY(p_table->wwpn, p_npiv_table->settings[i].npiv_wwpn,
315511e25f0dSDavid C Somayajulu 			    ECORE_WWN_SIZE);
315611e25f0dSDavid C Somayajulu 		OSAL_MEMCPY(p_table->wwnn, p_npiv_table->settings[i].npiv_wwnn,
315711e25f0dSDavid C Somayajulu 			    ECORE_WWN_SIZE);
315811e25f0dSDavid C Somayajulu 	}
315911e25f0dSDavid C Somayajulu 
316011e25f0dSDavid C Somayajulu 	OSAL_VFREE(p_hwfn->p_dev, p_buf);
316111e25f0dSDavid C Somayajulu 
316211e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
316311e25f0dSDavid C Somayajulu }
316411e25f0dSDavid C Somayajulu 
316511e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_mtu(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 mtu)316611e25f0dSDavid C Somayajulu ecore_mcp_ov_update_mtu(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
316711e25f0dSDavid C Somayajulu 			u16 mtu)
316811e25f0dSDavid C Somayajulu {
316911e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
317011e25f0dSDavid C Somayajulu 	u32 drv_mb_param;
31719efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
317211e25f0dSDavid C Somayajulu 
31739efd0ba7SDavid C Somayajulu 	drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_OFFSET;
317411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU,
317511e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
317611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
317711e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc);
317811e25f0dSDavid C Somayajulu 
317911e25f0dSDavid C Somayajulu 	return rc;
318011e25f0dSDavid C Somayajulu }
318111e25f0dSDavid C Somayajulu 
318211e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * mac)318311e25f0dSDavid C Somayajulu ecore_mcp_ov_update_mac(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
318411e25f0dSDavid C Somayajulu 			u8 *mac)
318511e25f0dSDavid C Somayajulu {
318611e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
318711e25f0dSDavid C Somayajulu 	u32 mfw_mac[2];
31889efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
318911e25f0dSDavid C Somayajulu 
319011e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
319111e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_SET_VMAC;
319211e25f0dSDavid C Somayajulu 	mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC <<
31939efd0ba7SDavid C Somayajulu 				DRV_MSG_CODE_VMAC_TYPE_OFFSET;
319411e25f0dSDavid C Somayajulu 	mb_params.param |= MCP_PF_ID(p_hwfn);
319511e25f0dSDavid C Somayajulu 
319611e25f0dSDavid C Somayajulu 	/* MCP is BE, and on LE platforms PCI would swap access to SHMEM
319711e25f0dSDavid C Somayajulu 	 * in 32-bit granularity.
319811e25f0dSDavid C Somayajulu 	 * So the MAC has to be set in native order [and not byte order],
319911e25f0dSDavid C Somayajulu 	 * otherwise it would be read incorrectly by MFW after swap.
320011e25f0dSDavid C Somayajulu 	 */
320111e25f0dSDavid C Somayajulu 	mfw_mac[0] = mac[0] << 24 | mac[1] << 16 | mac[2] << 8 | mac[3];
320211e25f0dSDavid C Somayajulu 	mfw_mac[1] = mac[4] << 24 | mac[5] << 16;
320311e25f0dSDavid C Somayajulu 
320411e25f0dSDavid C Somayajulu 	mb_params.p_data_src = (u8 *)mfw_mac;
320511e25f0dSDavid C Somayajulu 	mb_params.data_src_size = 8;
320611e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
320711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
320811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc);
320911e25f0dSDavid C Somayajulu 
321011e25f0dSDavid C Somayajulu 	/* Store primary MAC for later possible WoL */
321111e25f0dSDavid C Somayajulu 	OSAL_MEMCPY(p_hwfn->p_dev->wol_mac, mac, ETH_ALEN);
321211e25f0dSDavid C Somayajulu 
321311e25f0dSDavid C Somayajulu 	return rc;
321411e25f0dSDavid C Somayajulu }
321511e25f0dSDavid C Somayajulu 
321611e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_wol(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_wol wol)321711e25f0dSDavid C Somayajulu ecore_mcp_ov_update_wol(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
321811e25f0dSDavid C Somayajulu 			enum ecore_ov_wol wol)
321911e25f0dSDavid C Somayajulu {
322011e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
322111e25f0dSDavid C Somayajulu 	u32 drv_mb_param;
32229efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
322311e25f0dSDavid C Somayajulu 
322411e25f0dSDavid C Somayajulu 	if (p_hwfn->hw_info.b_wol_support == ECORE_WOL_SUPPORT_NONE) {
322511e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
322611e25f0dSDavid C Somayajulu 			   "Can't change WoL configuration when WoL isn't supported\n");
322711e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
322811e25f0dSDavid C Somayajulu 	}
322911e25f0dSDavid C Somayajulu 
323011e25f0dSDavid C Somayajulu 	switch (wol) {
323111e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_DEFAULT:
323211e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT;
323311e25f0dSDavid C Somayajulu 		break;
323411e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_DISABLED:
323511e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_WOL_DISABLED;
323611e25f0dSDavid C Somayajulu 		break;
323711e25f0dSDavid C Somayajulu 	case ECORE_OV_WOL_ENABLED:
323811e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_WOL_ENABLED;
323911e25f0dSDavid C Somayajulu 		break;
324011e25f0dSDavid C Somayajulu 	default:
324111e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Invalid wol state %d\n", wol);
324211e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
324311e25f0dSDavid C Somayajulu 	}
324411e25f0dSDavid C Somayajulu 
324511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL,
324611e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
324711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
324811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc);
324911e25f0dSDavid C Somayajulu 
325011e25f0dSDavid C Somayajulu 	/* Store the WoL update for a future unload */
325111e25f0dSDavid C Somayajulu 	p_hwfn->p_dev->wol_config = (u8)wol;
325211e25f0dSDavid C Somayajulu 
325311e25f0dSDavid C Somayajulu 	return rc;
325411e25f0dSDavid C Somayajulu }
325511e25f0dSDavid C Somayajulu 
325611e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ov_update_eswitch(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_ov_eswitch eswitch)325711e25f0dSDavid C Somayajulu ecore_mcp_ov_update_eswitch(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
325811e25f0dSDavid C Somayajulu 			    enum ecore_ov_eswitch eswitch)
325911e25f0dSDavid C Somayajulu {
326011e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
326111e25f0dSDavid C Somayajulu 	u32 drv_mb_param;
32629efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
326311e25f0dSDavid C Somayajulu 
326411e25f0dSDavid C Somayajulu 	switch (eswitch) {
326511e25f0dSDavid C Somayajulu 	case ECORE_OV_ESWITCH_NONE:
326611e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE;
326711e25f0dSDavid C Somayajulu 		break;
326811e25f0dSDavid C Somayajulu 	case ECORE_OV_ESWITCH_VEB:
326911e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB;
327011e25f0dSDavid C Somayajulu 		break;
327111e25f0dSDavid C Somayajulu 	case ECORE_OV_ESWITCH_VEPA:
327211e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA;
327311e25f0dSDavid C Somayajulu 		break;
327411e25f0dSDavid C Somayajulu 	default:
327511e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch);
327611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
327711e25f0dSDavid C Somayajulu 	}
327811e25f0dSDavid C Somayajulu 
327911e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE,
328011e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
328111e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
328211e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc);
328311e25f0dSDavid C Somayajulu 
328411e25f0dSDavid C Somayajulu 	return rc;
328511e25f0dSDavid C Somayajulu }
328611e25f0dSDavid C Somayajulu 
ecore_mcp_set_led(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_led_mode mode)328711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_set_led(struct ecore_hwfn *p_hwfn,
328811e25f0dSDavid C Somayajulu 				       struct ecore_ptt *p_ptt,
328911e25f0dSDavid C Somayajulu 				       enum ecore_led_mode mode)
329011e25f0dSDavid C Somayajulu {
329111e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0, drv_mb_param;
329211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
329311e25f0dSDavid C Somayajulu 
329411e25f0dSDavid C Somayajulu 	switch (mode) {
329511e25f0dSDavid C Somayajulu 	case ECORE_LED_MODE_ON:
329611e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON;
329711e25f0dSDavid C Somayajulu 		break;
329811e25f0dSDavid C Somayajulu 	case ECORE_LED_MODE_OFF:
329911e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF;
330011e25f0dSDavid C Somayajulu 		break;
330111e25f0dSDavid C Somayajulu 	case ECORE_LED_MODE_RESTORE:
330211e25f0dSDavid C Somayajulu 		drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER;
330311e25f0dSDavid C Somayajulu 		break;
330411e25f0dSDavid C Somayajulu 	default:
330511e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "Invalid LED mode %d\n", mode);
330611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
330711e25f0dSDavid C Somayajulu 	}
330811e25f0dSDavid C Somayajulu 
330911e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE,
331011e25f0dSDavid C Somayajulu 			   drv_mb_param, &resp, &param);
331111e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
331211e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure, aborting\n");
331311e25f0dSDavid C Somayajulu 
331411e25f0dSDavid C Somayajulu 	return rc;
331511e25f0dSDavid C Somayajulu }
331611e25f0dSDavid C Somayajulu 
ecore_mcp_mask_parities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 mask_parities)331711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mask_parities(struct ecore_hwfn *p_hwfn,
331811e25f0dSDavid C Somayajulu 					     struct ecore_ptt *p_ptt,
331911e25f0dSDavid C Somayajulu 					     u32 mask_parities)
332011e25f0dSDavid C Somayajulu {
332111e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
33229efd0ba7SDavid C Somayajulu 	enum _ecore_status_t rc;
332311e25f0dSDavid C Somayajulu 
332411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MASK_PARITIES,
332511e25f0dSDavid C Somayajulu 			   mask_parities, &resp, &param);
332611e25f0dSDavid C Somayajulu 
332711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
332811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP response failure for mask parities, aborting\n");
332911e25f0dSDavid C Somayajulu 	} else if (resp != FW_MSG_CODE_OK) {
333011e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "MCP did not acknowledge mask parity request. Old MFW?\n");
333111e25f0dSDavid C Somayajulu 		rc = ECORE_INVAL;
333211e25f0dSDavid C Somayajulu 	}
333311e25f0dSDavid C Somayajulu 
333411e25f0dSDavid C Somayajulu 	return rc;
333511e25f0dSDavid C Somayajulu }
333611e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_read(struct ecore_dev * p_dev,u32 addr,u8 * p_buf,u32 len)333711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
333811e25f0dSDavid C Somayajulu 			   u8 *p_buf, u32 len)
333911e25f0dSDavid C Somayajulu {
334011e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
334111e25f0dSDavid C Somayajulu 	u32 bytes_left, offset, bytes_to_copy, buf_size;
3342217ec208SDavid C Somayajulu 	u32 nvm_offset, resp = 0, param;
334311e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
334411e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
334511e25f0dSDavid C Somayajulu 
334611e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
334711e25f0dSDavid C Somayajulu 	if (!p_ptt)
334811e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
334911e25f0dSDavid C Somayajulu 
335011e25f0dSDavid C Somayajulu 	bytes_left = len;
335111e25f0dSDavid C Somayajulu 	offset = 0;
335211e25f0dSDavid C Somayajulu 	while (bytes_left > 0) {
335311e25f0dSDavid C Somayajulu 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
335411e25f0dSDavid C Somayajulu 					   MCP_DRV_NVM_BUF_LEN);
33559efd0ba7SDavid C Somayajulu 		nvm_offset = (addr + offset) | (bytes_to_copy <<
33569efd0ba7SDavid C Somayajulu 						DRV_MB_PARAM_NVM_LEN_OFFSET);
33579efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
33589efd0ba7SDavid C Somayajulu 					  DRV_MSG_CODE_NVM_READ_NVRAM,
33599efd0ba7SDavid C Somayajulu 					  nvm_offset, &resp, &param, &buf_size,
33609efd0ba7SDavid C Somayajulu 					  (u32 *)(p_buf + offset));
3361217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
3362217ec208SDavid C Somayajulu 			DP_NOTICE(p_dev, false,
3363217ec208SDavid C Somayajulu 				  "ecore_mcp_nvm_rd_cmd() failed, rc = %d\n",
3364217ec208SDavid C Somayajulu 				  rc);
3365217ec208SDavid C Somayajulu 			resp = FW_MSG_CODE_ERROR;
3366217ec208SDavid C Somayajulu 			break;
3367217ec208SDavid C Somayajulu 		}
3368217ec208SDavid C Somayajulu 
3369217ec208SDavid C Somayajulu 		if (resp != FW_MSG_CODE_NVM_OK) {
3370217ec208SDavid C Somayajulu 			DP_NOTICE(p_dev, false,
3371217ec208SDavid C Somayajulu 				  "nvm read failed, resp = 0x%08x\n", resp);
3372217ec208SDavid C Somayajulu 			rc = ECORE_UNKNOWN_ERROR;
337311e25f0dSDavid C Somayajulu 			break;
337411e25f0dSDavid C Somayajulu 		}
337511e25f0dSDavid C Somayajulu 
337611e25f0dSDavid C Somayajulu 		/* This can be a lengthy process, and it's possible scheduler
337711e25f0dSDavid C Somayajulu 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
337811e25f0dSDavid C Somayajulu 		 */
337911e25f0dSDavid C Somayajulu 		if (bytes_left % 0x1000 <
33809efd0ba7SDavid C Somayajulu 		    (bytes_left - buf_size) % 0x1000)
338111e25f0dSDavid C Somayajulu 			OSAL_MSLEEP(1);
338211e25f0dSDavid C Somayajulu 
33839efd0ba7SDavid C Somayajulu 		offset += buf_size;
33849efd0ba7SDavid C Somayajulu 		bytes_left -= buf_size;
338511e25f0dSDavid C Somayajulu 	}
338611e25f0dSDavid C Somayajulu 
33879efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
338811e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
338911e25f0dSDavid C Somayajulu 
339011e25f0dSDavid C Somayajulu 	return rc;
339111e25f0dSDavid C Somayajulu }
339211e25f0dSDavid C Somayajulu 
ecore_mcp_phy_read(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)339311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
339411e25f0dSDavid C Somayajulu 					u32 addr, u8 *p_buf, u32 len)
339511e25f0dSDavid C Somayajulu {
339611e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
339711e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
33989efd0ba7SDavid C Somayajulu 	u32 resp, param;
339911e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
340011e25f0dSDavid C Somayajulu 
340111e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
340211e25f0dSDavid C Somayajulu 	if (!p_ptt)
340311e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
340411e25f0dSDavid C Somayajulu 
34059efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
34069efd0ba7SDavid C Somayajulu 				  (cmd == ECORE_PHY_CORE_READ) ?
340711e25f0dSDavid C Somayajulu 				  DRV_MSG_CODE_PHY_CORE_READ :
34089efd0ba7SDavid C Somayajulu 				  DRV_MSG_CODE_PHY_RAW_READ,
34099efd0ba7SDavid C Somayajulu 				  addr, &resp, &param, &len, (u32 *)p_buf);
341011e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
341111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
341211e25f0dSDavid C Somayajulu 
34139efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
341411e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
341511e25f0dSDavid C Somayajulu 
341611e25f0dSDavid C Somayajulu 	return rc;
341711e25f0dSDavid C Somayajulu }
341811e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_resp(struct ecore_dev * p_dev,u8 * p_buf)341911e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_resp(struct ecore_dev *p_dev, u8 *p_buf)
342011e25f0dSDavid C Somayajulu {
342111e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
342211e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
342311e25f0dSDavid C Somayajulu 
342411e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
342511e25f0dSDavid C Somayajulu 	if (!p_ptt)
342611e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
342711e25f0dSDavid C Somayajulu 
342811e25f0dSDavid C Somayajulu 	OSAL_MEMCPY(p_buf, &p_dev->mcp_nvm_resp, sizeof(p_dev->mcp_nvm_resp));
342911e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
343011e25f0dSDavid C Somayajulu 
343111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
343211e25f0dSDavid C Somayajulu }
343311e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_del_file(struct ecore_dev * p_dev,u32 addr)343411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_del_file(struct ecore_dev *p_dev,
343511e25f0dSDavid C Somayajulu 					    u32 addr)
343611e25f0dSDavid C Somayajulu {
343711e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
343811e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
34399efd0ba7SDavid C Somayajulu 	u32 resp, param;
344011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
344111e25f0dSDavid C Somayajulu 
344211e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
344311e25f0dSDavid C Somayajulu 	if (!p_ptt)
344411e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
34459efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_DEL_FILE, addr,
34469efd0ba7SDavid C Somayajulu 			   &resp, &param);
34479efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
344811e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
344911e25f0dSDavid C Somayajulu 
345011e25f0dSDavid C Somayajulu 	return rc;
345111e25f0dSDavid C Somayajulu }
345211e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_put_file_begin(struct ecore_dev * p_dev,u32 addr)345311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_put_file_begin(struct ecore_dev *p_dev,
345411e25f0dSDavid C Somayajulu 						  u32 addr)
345511e25f0dSDavid C Somayajulu {
345611e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
345711e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
34589efd0ba7SDavid C Somayajulu 	u32 resp, param;
345911e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
346011e25f0dSDavid C Somayajulu 
346111e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
346211e25f0dSDavid C Somayajulu 	if (!p_ptt)
346311e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
34649efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_PUT_FILE_BEGIN, addr,
34659efd0ba7SDavid C Somayajulu 			   &resp, &param);
34669efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
346711e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
346811e25f0dSDavid C Somayajulu 
346911e25f0dSDavid C Somayajulu 	return rc;
347011e25f0dSDavid C Somayajulu }
347111e25f0dSDavid C Somayajulu 
34729efd0ba7SDavid C Somayajulu /* rc recieves ECORE_INVAL as default parameter because
347311e25f0dSDavid C Somayajulu  * it might not enter the while loop if the len is 0
347411e25f0dSDavid C Somayajulu  */
ecore_mcp_nvm_write(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)347511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_write(struct ecore_dev *p_dev, u32 cmd,
347611e25f0dSDavid C Somayajulu 					 u32 addr, u8 *p_buf, u32 len)
347711e25f0dSDavid C Somayajulu {
3478217ec208SDavid C Somayajulu 	u32 buf_idx, buf_size, nvm_cmd, nvm_offset, resp = 0, param;
347911e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
348011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_INVAL;
348111e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
348211e25f0dSDavid C Somayajulu 
348311e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
348411e25f0dSDavid C Somayajulu 	if (!p_ptt)
348511e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
348611e25f0dSDavid C Somayajulu 
348711e25f0dSDavid C Somayajulu 	switch (cmd) {
348811e25f0dSDavid C Somayajulu 	case ECORE_PUT_FILE_DATA:
34899efd0ba7SDavid C Somayajulu 		nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
349011e25f0dSDavid C Somayajulu 		break;
349111e25f0dSDavid C Somayajulu 	case ECORE_NVM_WRITE_NVRAM:
34929efd0ba7SDavid C Somayajulu 		nvm_cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM;
349311e25f0dSDavid C Somayajulu 		break;
349411e25f0dSDavid C Somayajulu 	case ECORE_EXT_PHY_FW_UPGRADE:
34959efd0ba7SDavid C Somayajulu 		nvm_cmd = DRV_MSG_CODE_EXT_PHY_FW_UPGRADE;
349611e25f0dSDavid C Somayajulu 		break;
3497217ec208SDavid C Somayajulu 	case ECORE_ENCRYPT_PASSWORD:
3498217ec208SDavid C Somayajulu 		nvm_cmd = DRV_MSG_CODE_ENCRYPT_PASSWORD;
3499217ec208SDavid C Somayajulu 		break;
350011e25f0dSDavid C Somayajulu 	default:
350111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "Invalid nvm write command 0x%x\n",
350211e25f0dSDavid C Somayajulu 			  cmd);
3503217ec208SDavid C Somayajulu 		rc = ECORE_INVAL;
3504217ec208SDavid C Somayajulu 		goto out;
350511e25f0dSDavid C Somayajulu 	}
350611e25f0dSDavid C Somayajulu 
350711e25f0dSDavid C Somayajulu 	buf_idx = 0;
350811e25f0dSDavid C Somayajulu 	while (buf_idx < len) {
350911e25f0dSDavid C Somayajulu 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
351011e25f0dSDavid C Somayajulu 				      MCP_DRV_NVM_BUF_LEN);
35119efd0ba7SDavid C Somayajulu 		nvm_offset = ((buf_size << DRV_MB_PARAM_NVM_LEN_OFFSET) |
35129efd0ba7SDavid C Somayajulu 			      addr) +
35139efd0ba7SDavid C Somayajulu 			     buf_idx;
35149efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, nvm_offset,
35159efd0ba7SDavid C Somayajulu 					  &resp, &param, buf_size,
35169efd0ba7SDavid C Somayajulu 					  (u32 *)&p_buf[buf_idx]);
3517217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
3518217ec208SDavid C Somayajulu 			DP_NOTICE(p_dev, false,
3519217ec208SDavid C Somayajulu 				  "ecore_mcp_nvm_write() failed, rc = %d\n",
3520217ec208SDavid C Somayajulu 				  rc);
3521217ec208SDavid C Somayajulu 			resp = FW_MSG_CODE_ERROR;
3522217ec208SDavid C Somayajulu 			break;
3523217ec208SDavid C Somayajulu 		}
3524217ec208SDavid C Somayajulu 
3525217ec208SDavid C Somayajulu 		if (resp != FW_MSG_CODE_OK &&
3526217ec208SDavid C Somayajulu 		    resp != FW_MSG_CODE_NVM_OK &&
3527217ec208SDavid C Somayajulu 		    resp != FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK) {
3528217ec208SDavid C Somayajulu 			DP_NOTICE(p_dev, false,
3529217ec208SDavid C Somayajulu 				  "nvm write failed, resp = 0x%08x\n", resp);
3530217ec208SDavid C Somayajulu 			rc = ECORE_UNKNOWN_ERROR;
3531217ec208SDavid C Somayajulu 			break;
3532217ec208SDavid C Somayajulu 		}
353311e25f0dSDavid C Somayajulu 
353411e25f0dSDavid C Somayajulu 		/* This can be a lengthy process, and it's possible scheduler
353511e25f0dSDavid C Somayajulu 		 * isn't preemptable. Sleep a bit to prevent CPU hogging.
353611e25f0dSDavid C Somayajulu 		 */
353711e25f0dSDavid C Somayajulu 		if (buf_idx % 0x1000 >
353811e25f0dSDavid C Somayajulu 		    (buf_idx + buf_size) % 0x1000)
353911e25f0dSDavid C Somayajulu 			OSAL_MSLEEP(1);
354011e25f0dSDavid C Somayajulu 
354111e25f0dSDavid C Somayajulu 		buf_idx += buf_size;
354211e25f0dSDavid C Somayajulu 	}
354311e25f0dSDavid C Somayajulu 
35449efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
3545217ec208SDavid C Somayajulu out:
354611e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
354711e25f0dSDavid C Somayajulu 
354811e25f0dSDavid C Somayajulu 	return rc;
354911e25f0dSDavid C Somayajulu }
355011e25f0dSDavid C Somayajulu 
ecore_mcp_phy_write(struct ecore_dev * p_dev,u32 cmd,u32 addr,u8 * p_buf,u32 len)355111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_phy_write(struct ecore_dev *p_dev, u32 cmd,
355211e25f0dSDavid C Somayajulu 					 u32 addr, u8 *p_buf, u32 len)
355311e25f0dSDavid C Somayajulu {
355411e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
355511e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
35569efd0ba7SDavid C Somayajulu 	u32 resp, param, nvm_cmd;
355711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
355811e25f0dSDavid C Somayajulu 
355911e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
356011e25f0dSDavid C Somayajulu 	if (!p_ptt)
356111e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
356211e25f0dSDavid C Somayajulu 
35639efd0ba7SDavid C Somayajulu 	nvm_cmd = (cmd == ECORE_PHY_CORE_WRITE) ?  DRV_MSG_CODE_PHY_CORE_WRITE :
356411e25f0dSDavid C Somayajulu 			DRV_MSG_CODE_PHY_RAW_WRITE;
35659efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, addr,
35669efd0ba7SDavid C Somayajulu 				  &resp, &param, len, (u32 *)p_buf);
356711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
356811e25f0dSDavid C Somayajulu 		DP_NOTICE(p_dev, false, "MCP command rc = %d\n", rc);
35699efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
357011e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
357111e25f0dSDavid C Somayajulu 
357211e25f0dSDavid C Somayajulu 	return rc;
357311e25f0dSDavid C Somayajulu }
357411e25f0dSDavid C Somayajulu 
ecore_mcp_nvm_set_secure_mode(struct ecore_dev * p_dev,u32 addr)357511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_nvm_set_secure_mode(struct ecore_dev *p_dev,
357611e25f0dSDavid C Somayajulu 						   u32 addr)
357711e25f0dSDavid C Somayajulu {
357811e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
357911e25f0dSDavid C Somayajulu 	struct ecore_ptt  *p_ptt;
35809efd0ba7SDavid C Somayajulu 	u32 resp, param;
358111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
358211e25f0dSDavid C Somayajulu 
358311e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
358411e25f0dSDavid C Somayajulu 	if (!p_ptt)
358511e25f0dSDavid C Somayajulu 		return ECORE_BUSY;
358611e25f0dSDavid C Somayajulu 
35879efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_SECURE_MODE, addr,
35889efd0ba7SDavid C Somayajulu 			   &resp, &param);
35899efd0ba7SDavid C Somayajulu 	p_dev->mcp_nvm_resp = resp;
359011e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
359111e25f0dSDavid C Somayajulu 
359211e25f0dSDavid C Somayajulu 	return rc;
359311e25f0dSDavid C Somayajulu }
359411e25f0dSDavid C Somayajulu 
ecore_mcp_phy_sfp_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 len,u8 * p_buf)359511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_phy_sfp_read(struct ecore_hwfn *p_hwfn,
359611e25f0dSDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
359711e25f0dSDavid C Somayajulu 					    u32 port, u32 addr, u32 offset,
359811e25f0dSDavid C Somayajulu 					    u32 len, u8 *p_buf)
359911e25f0dSDavid C Somayajulu {
36009efd0ba7SDavid C Somayajulu 	u32 bytes_left, bytes_to_copy, buf_size, nvm_offset;
36019efd0ba7SDavid C Somayajulu 	u32 resp, param;
360211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
360311e25f0dSDavid C Somayajulu 
36049efd0ba7SDavid C Somayajulu 	nvm_offset = (port << DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET) |
36059efd0ba7SDavid C Somayajulu 			(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET);
360611e25f0dSDavid C Somayajulu 	addr = offset;
360711e25f0dSDavid C Somayajulu 	offset = 0;
360811e25f0dSDavid C Somayajulu 	bytes_left = len;
360911e25f0dSDavid C Somayajulu 	while (bytes_left > 0) {
361011e25f0dSDavid C Somayajulu 		bytes_to_copy = OSAL_MIN_T(u32, bytes_left,
361111e25f0dSDavid C Somayajulu 					   MAX_I2C_TRANSACTION_SIZE);
36129efd0ba7SDavid C Somayajulu 		nvm_offset &= (DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
361311e25f0dSDavid C Somayajulu 			       DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
36149efd0ba7SDavid C Somayajulu 		nvm_offset |= ((addr + offset) <<
36159efd0ba7SDavid C Somayajulu 				DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET);
36169efd0ba7SDavid C Somayajulu 		nvm_offset |= (bytes_to_copy <<
36179efd0ba7SDavid C Somayajulu 			       DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET);
36189efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
36199efd0ba7SDavid C Somayajulu 					  DRV_MSG_CODE_TRANSCEIVER_READ,
36209efd0ba7SDavid C Somayajulu 					  nvm_offset, &resp, &param, &buf_size,
36219efd0ba7SDavid C Somayajulu 					  (u32 *)(p_buf + offset));
36229efd0ba7SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
36239efd0ba7SDavid C Somayajulu 			DP_NOTICE(p_hwfn, false,
36249efd0ba7SDavid C Somayajulu 				  "Failed to send a transceiver read command to the MFW. rc = %d.\n",
36259efd0ba7SDavid C Somayajulu 				  rc);
36269efd0ba7SDavid C Somayajulu 			return rc;
36279efd0ba7SDavid C Somayajulu 		}
36289efd0ba7SDavid C Somayajulu 
36299efd0ba7SDavid C Somayajulu 		if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT)
363011e25f0dSDavid C Somayajulu 			return ECORE_NODEV;
36319efd0ba7SDavid C Somayajulu 		else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
363211e25f0dSDavid C Somayajulu 			return ECORE_UNKNOWN_ERROR;
363311e25f0dSDavid C Somayajulu 
36349efd0ba7SDavid C Somayajulu 		offset += buf_size;
36359efd0ba7SDavid C Somayajulu 		bytes_left -= buf_size;
363611e25f0dSDavid C Somayajulu 	}
363711e25f0dSDavid C Somayajulu 
363811e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
363911e25f0dSDavid C Somayajulu }
364011e25f0dSDavid C Somayajulu 
ecore_mcp_phy_sfp_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 len,u8 * p_buf)364111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_phy_sfp_write(struct ecore_hwfn *p_hwfn,
364211e25f0dSDavid C Somayajulu 					     struct ecore_ptt *p_ptt,
364311e25f0dSDavid C Somayajulu 					     u32 port, u32 addr, u32 offset,
364411e25f0dSDavid C Somayajulu 					     u32 len, u8 *p_buf)
364511e25f0dSDavid C Somayajulu {
36469efd0ba7SDavid C Somayajulu 	u32 buf_idx, buf_size, nvm_offset, resp, param;
364711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
364811e25f0dSDavid C Somayajulu 
36499efd0ba7SDavid C Somayajulu 	nvm_offset = (port << DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET) |
36509efd0ba7SDavid C Somayajulu 			(addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET);
365111e25f0dSDavid C Somayajulu 	buf_idx = 0;
365211e25f0dSDavid C Somayajulu 	while (buf_idx < len) {
365311e25f0dSDavid C Somayajulu 		buf_size = OSAL_MIN_T(u32, (len - buf_idx),
365411e25f0dSDavid C Somayajulu 				      MAX_I2C_TRANSACTION_SIZE);
36559efd0ba7SDavid C Somayajulu 		nvm_offset &= (DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
365611e25f0dSDavid C Somayajulu 				 DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
36579efd0ba7SDavid C Somayajulu 		nvm_offset |= ((offset + buf_idx) <<
36589efd0ba7SDavid C Somayajulu 				 DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET);
36599efd0ba7SDavid C Somayajulu 		nvm_offset |= (buf_size <<
36609efd0ba7SDavid C Somayajulu 			       DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET);
36619efd0ba7SDavid C Somayajulu 		rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt,
36629efd0ba7SDavid C Somayajulu 					  DRV_MSG_CODE_TRANSCEIVER_WRITE,
36639efd0ba7SDavid C Somayajulu 					  nvm_offset, &resp, &param, buf_size,
36649efd0ba7SDavid C Somayajulu 					  (u32 *)&p_buf[buf_idx]);
36659efd0ba7SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
36669efd0ba7SDavid C Somayajulu 			DP_NOTICE(p_hwfn, false,
36679efd0ba7SDavid C Somayajulu 				  "Failed to send a transceiver write command to the MFW. rc = %d.\n",
36689efd0ba7SDavid C Somayajulu 				  rc);
36699efd0ba7SDavid C Somayajulu 			return rc;
36709efd0ba7SDavid C Somayajulu 		}
36719efd0ba7SDavid C Somayajulu 
36729efd0ba7SDavid C Somayajulu 		if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT)
367311e25f0dSDavid C Somayajulu 			return ECORE_NODEV;
36749efd0ba7SDavid C Somayajulu 		else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
367511e25f0dSDavid C Somayajulu 			return ECORE_UNKNOWN_ERROR;
367611e25f0dSDavid C Somayajulu 
367711e25f0dSDavid C Somayajulu 		buf_idx += buf_size;
367811e25f0dSDavid C Somayajulu 	}
367911e25f0dSDavid C Somayajulu 
368011e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
368111e25f0dSDavid C Somayajulu }
368211e25f0dSDavid C Somayajulu 
ecore_mcp_gpio_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u32 * gpio_val)368311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_gpio_read(struct ecore_hwfn *p_hwfn,
368411e25f0dSDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
368511e25f0dSDavid C Somayajulu 					 u16 gpio, u32 *gpio_val)
368611e25f0dSDavid C Somayajulu {
368711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
368811e25f0dSDavid C Somayajulu 	u32 drv_mb_param = 0, rsp;
368911e25f0dSDavid C Somayajulu 
36909efd0ba7SDavid C Somayajulu 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_OFFSET);
369111e25f0dSDavid C Somayajulu 
369211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_READ,
369311e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, gpio_val);
369411e25f0dSDavid C Somayajulu 
369511e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
369611e25f0dSDavid C Somayajulu 		return rc;
369711e25f0dSDavid C Somayajulu 
369811e25f0dSDavid C Somayajulu 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
369911e25f0dSDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
370011e25f0dSDavid C Somayajulu 
370111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
370211e25f0dSDavid C Somayajulu }
370311e25f0dSDavid C Somayajulu 
ecore_mcp_gpio_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u16 gpio_val)370411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_gpio_write(struct ecore_hwfn *p_hwfn,
370511e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
370611e25f0dSDavid C Somayajulu 					  u16 gpio, u16 gpio_val)
370711e25f0dSDavid C Somayajulu {
370811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
370911e25f0dSDavid C Somayajulu 	u32 drv_mb_param = 0, param, rsp;
371011e25f0dSDavid C Somayajulu 
37119efd0ba7SDavid C Somayajulu 	drv_mb_param = (gpio << DRV_MB_PARAM_GPIO_NUMBER_OFFSET) |
37129efd0ba7SDavid C Somayajulu 		(gpio_val << DRV_MB_PARAM_GPIO_VALUE_OFFSET);
371311e25f0dSDavid C Somayajulu 
371411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_WRITE,
371511e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, &param);
371611e25f0dSDavid C Somayajulu 
371711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
371811e25f0dSDavid C Somayajulu 		return rc;
371911e25f0dSDavid C Somayajulu 
372011e25f0dSDavid C Somayajulu 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
372111e25f0dSDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
372211e25f0dSDavid C Somayajulu 
372311e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
372411e25f0dSDavid C Somayajulu }
372511e25f0dSDavid C Somayajulu 
ecore_mcp_gpio_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u32 * gpio_direction,u32 * gpio_ctrl)372611e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_gpio_info(struct ecore_hwfn *p_hwfn,
372711e25f0dSDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
372811e25f0dSDavid C Somayajulu 					 u16 gpio, u32 *gpio_direction,
372911e25f0dSDavid C Somayajulu 					 u32 *gpio_ctrl)
373011e25f0dSDavid C Somayajulu {
373111e25f0dSDavid C Somayajulu 	u32 drv_mb_param = 0, rsp, val = 0;
373211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
373311e25f0dSDavid C Somayajulu 
37349efd0ba7SDavid C Somayajulu 	drv_mb_param = gpio << DRV_MB_PARAM_GPIO_NUMBER_OFFSET;
373511e25f0dSDavid C Somayajulu 
373611e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GPIO_INFO,
373711e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, &val);
373811e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
373911e25f0dSDavid C Somayajulu 		return rc;
374011e25f0dSDavid C Somayajulu 
374111e25f0dSDavid C Somayajulu 	*gpio_direction = (val & DRV_MB_PARAM_GPIO_DIRECTION_MASK) >>
37429efd0ba7SDavid C Somayajulu 			   DRV_MB_PARAM_GPIO_DIRECTION_OFFSET;
374311e25f0dSDavid C Somayajulu 	*gpio_ctrl = (val & DRV_MB_PARAM_GPIO_CTRL_MASK) >>
37449efd0ba7SDavid C Somayajulu 		      DRV_MB_PARAM_GPIO_CTRL_OFFSET;
374511e25f0dSDavid C Somayajulu 
374611e25f0dSDavid C Somayajulu 	if ((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_GPIO_OK)
374711e25f0dSDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
374811e25f0dSDavid C Somayajulu 
374911e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
375011e25f0dSDavid C Somayajulu }
375111e25f0dSDavid C Somayajulu 
ecore_mcp_bist_register_test(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)375211e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_bist_register_test(struct ecore_hwfn *p_hwfn,
375311e25f0dSDavid C Somayajulu 						  struct ecore_ptt *p_ptt)
375411e25f0dSDavid C Somayajulu {
375511e25f0dSDavid C Somayajulu 	u32 drv_mb_param = 0, rsp, param;
375611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
375711e25f0dSDavid C Somayajulu 
375811e25f0dSDavid C Somayajulu 	drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST <<
37599efd0ba7SDavid C Somayajulu 			DRV_MB_PARAM_BIST_TEST_INDEX_OFFSET);
376011e25f0dSDavid C Somayajulu 
376111e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
376211e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, &param);
376311e25f0dSDavid C Somayajulu 
376411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
376511e25f0dSDavid C Somayajulu 		return rc;
376611e25f0dSDavid C Somayajulu 
376711e25f0dSDavid C Somayajulu 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
376811e25f0dSDavid C Somayajulu 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
376911e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
377011e25f0dSDavid C Somayajulu 
377111e25f0dSDavid C Somayajulu 	return rc;
377211e25f0dSDavid C Somayajulu }
377311e25f0dSDavid C Somayajulu 
ecore_mcp_bist_clock_test(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)377411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_bist_clock_test(struct ecore_hwfn *p_hwfn,
377511e25f0dSDavid C Somayajulu 					       struct ecore_ptt *p_ptt)
377611e25f0dSDavid C Somayajulu {
377711e25f0dSDavid C Somayajulu 	u32 drv_mb_param, rsp, param;
377811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
377911e25f0dSDavid C Somayajulu 
378011e25f0dSDavid C Somayajulu 	drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST <<
37819efd0ba7SDavid C Somayajulu 			DRV_MB_PARAM_BIST_TEST_INDEX_OFFSET);
378211e25f0dSDavid C Somayajulu 
378311e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
378411e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, &param);
378511e25f0dSDavid C Somayajulu 
378611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
378711e25f0dSDavid C Somayajulu 		return rc;
378811e25f0dSDavid C Somayajulu 
378911e25f0dSDavid C Somayajulu 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
379011e25f0dSDavid C Somayajulu 	    (param != DRV_MB_PARAM_BIST_RC_PASSED))
379111e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
379211e25f0dSDavid C Somayajulu 
379311e25f0dSDavid C Somayajulu 	return rc;
379411e25f0dSDavid C Somayajulu }
379511e25f0dSDavid C Somayajulu 
ecore_mcp_bist_nvm_test_get_num_images(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 * num_images)379611e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_bist_nvm_test_get_num_images(
379711e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, u32 *num_images)
379811e25f0dSDavid C Somayajulu {
379911e25f0dSDavid C Somayajulu 	u32 drv_mb_param = 0, rsp;
380011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
380111e25f0dSDavid C Somayajulu 
380211e25f0dSDavid C Somayajulu 	drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES <<
38039efd0ba7SDavid C Somayajulu 			DRV_MB_PARAM_BIST_TEST_INDEX_OFFSET);
380411e25f0dSDavid C Somayajulu 
380511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
380611e25f0dSDavid C Somayajulu 			   drv_mb_param, &rsp, num_images);
380711e25f0dSDavid C Somayajulu 
380811e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
380911e25f0dSDavid C Somayajulu 		return rc;
381011e25f0dSDavid C Somayajulu 
381111e25f0dSDavid C Somayajulu 	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
381211e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
381311e25f0dSDavid C Somayajulu 
381411e25f0dSDavid C Somayajulu 	return rc;
381511e25f0dSDavid C Somayajulu }
381611e25f0dSDavid C Somayajulu 
ecore_mcp_bist_nvm_test_get_image_att(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct bist_nvm_image_att * p_image_att,u32 image_index)381711e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
381811e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
381911e25f0dSDavid C Somayajulu 	struct bist_nvm_image_att *p_image_att, u32 image_index)
382011e25f0dSDavid C Somayajulu {
38219efd0ba7SDavid C Somayajulu 	u32 buf_size, nvm_offset, resp, param;
382211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
382311e25f0dSDavid C Somayajulu 
38249efd0ba7SDavid C Somayajulu 	nvm_offset = (DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX <<
38259efd0ba7SDavid C Somayajulu 				    DRV_MB_PARAM_BIST_TEST_INDEX_OFFSET);
38269efd0ba7SDavid C Somayajulu 	nvm_offset |= (image_index <<
38279efd0ba7SDavid C Somayajulu 		       DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_OFFSET);
38289efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
38299efd0ba7SDavid C Somayajulu 				  nvm_offset, &resp, &param, &buf_size,
38309efd0ba7SDavid C Somayajulu 				  (u32 *)p_image_att);
383111e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
383211e25f0dSDavid C Somayajulu 		return rc;
383311e25f0dSDavid C Somayajulu 
38349efd0ba7SDavid C Somayajulu 	if (((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
383511e25f0dSDavid C Somayajulu 	    (p_image_att->return_code != 1))
383611e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
383711e25f0dSDavid C Somayajulu 
383811e25f0dSDavid C Somayajulu 	return rc;
383911e25f0dSDavid C Somayajulu }
384011e25f0dSDavid C Somayajulu 
384111e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_get_nvm_image_att(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_nvm_images image_id,struct ecore_nvm_image_att * p_image_att)384211e25f0dSDavid C Somayajulu ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
384311e25f0dSDavid C Somayajulu 			    enum ecore_nvm_images image_id,
384411e25f0dSDavid C Somayajulu 			    struct ecore_nvm_image_att *p_image_att)
384511e25f0dSDavid C Somayajulu {
384611e25f0dSDavid C Somayajulu 	struct bist_nvm_image_att mfw_image_att;
384711e25f0dSDavid C Somayajulu 	enum nvm_image_type type;
384811e25f0dSDavid C Somayajulu 	u32 num_images, i;
384911e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
385011e25f0dSDavid C Somayajulu 
385111e25f0dSDavid C Somayajulu 	/* Translate image_id into MFW definitions */
385211e25f0dSDavid C Somayajulu 	switch (image_id) {
385311e25f0dSDavid C Somayajulu 	case ECORE_NVM_IMAGE_ISCSI_CFG:
385411e25f0dSDavid C Somayajulu 		type = NVM_TYPE_ISCSI_CFG;
385511e25f0dSDavid C Somayajulu 		break;
385611e25f0dSDavid C Somayajulu 	case ECORE_NVM_IMAGE_FCOE_CFG:
385711e25f0dSDavid C Somayajulu 		type = NVM_TYPE_FCOE_CFG;
385811e25f0dSDavid C Somayajulu 		break;
385911e25f0dSDavid C Somayajulu 	case ECORE_NVM_IMAGE_MDUMP:
386011e25f0dSDavid C Somayajulu 		type = NVM_TYPE_MDUMP;
386111e25f0dSDavid C Somayajulu 		break;
386211e25f0dSDavid C Somayajulu 	default:
386311e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
386411e25f0dSDavid C Somayajulu 			  image_id);
386511e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
386611e25f0dSDavid C Somayajulu 	}
386711e25f0dSDavid C Somayajulu 
386811e25f0dSDavid C Somayajulu 	/* Learn number of images, then traverse and see if one fits */
386911e25f0dSDavid C Somayajulu 	rc = ecore_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
387011e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS || !num_images)
387111e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
387211e25f0dSDavid C Somayajulu 
387311e25f0dSDavid C Somayajulu 	for (i = 0; i < num_images; i++) {
387411e25f0dSDavid C Somayajulu 		rc = ecore_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
387511e25f0dSDavid C Somayajulu 							   &mfw_image_att, i);
387611e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
387711e25f0dSDavid C Somayajulu 			return rc;
387811e25f0dSDavid C Somayajulu 
387911e25f0dSDavid C Somayajulu 		if (type == mfw_image_att.image_type)
388011e25f0dSDavid C Somayajulu 			break;
388111e25f0dSDavid C Somayajulu 	}
388211e25f0dSDavid C Somayajulu 	if (i == num_images) {
388311e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
388411e25f0dSDavid C Somayajulu 			   "Failed to find nvram image of type %08x\n",
388511e25f0dSDavid C Somayajulu 			   image_id);
388611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
388711e25f0dSDavid C Somayajulu 	}
388811e25f0dSDavid C Somayajulu 
388911e25f0dSDavid C Somayajulu 	p_image_att->start_addr = mfw_image_att.nvm_start_addr;
389011e25f0dSDavid C Somayajulu 	p_image_att->length = mfw_image_att.len;
389111e25f0dSDavid C Somayajulu 
389211e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
389311e25f0dSDavid C Somayajulu }
389411e25f0dSDavid C Somayajulu 
ecore_mcp_get_nvm_image(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_nvm_images image_id,u8 * p_buffer,u32 buffer_len)389511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
389611e25f0dSDavid C Somayajulu 					     struct ecore_ptt *p_ptt,
389711e25f0dSDavid C Somayajulu 					     enum ecore_nvm_images image_id,
389811e25f0dSDavid C Somayajulu 					     u8 *p_buffer, u32 buffer_len)
389911e25f0dSDavid C Somayajulu {
390011e25f0dSDavid C Somayajulu 	struct ecore_nvm_image_att image_att;
390111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
390211e25f0dSDavid C Somayajulu 
390311e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(p_buffer, buffer_len);
390411e25f0dSDavid C Somayajulu 
390511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_get_nvm_image_att(p_hwfn, p_ptt, image_id, &image_att);
390611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
390711e25f0dSDavid C Somayajulu 		return rc;
390811e25f0dSDavid C Somayajulu 
390911e25f0dSDavid C Somayajulu 	/* Validate sizes - both the image's and the supplied buffer's */
391011e25f0dSDavid C Somayajulu 	if (image_att.length <= 4) {
391111e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
391211e25f0dSDavid C Somayajulu 			   "Image [%d] is too small - only %d bytes\n",
391311e25f0dSDavid C Somayajulu 			   image_id, image_att.length);
391411e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
391511e25f0dSDavid C Somayajulu 	}
391611e25f0dSDavid C Somayajulu 
391711e25f0dSDavid C Somayajulu 	/* Each NVM image is suffixed by CRC; Upper-layer has no need for it */
391811e25f0dSDavid C Somayajulu 	image_att.length -= 4;
391911e25f0dSDavid C Somayajulu 
392011e25f0dSDavid C Somayajulu 	if (image_att.length > buffer_len) {
392111e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
392211e25f0dSDavid C Somayajulu 			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
392311e25f0dSDavid C Somayajulu 			   image_id, image_att.length, buffer_len);
392411e25f0dSDavid C Somayajulu 		return ECORE_NOMEM;
392511e25f0dSDavid C Somayajulu 	}
392611e25f0dSDavid C Somayajulu 
392711e25f0dSDavid C Somayajulu 	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
392811e25f0dSDavid C Somayajulu 				  p_buffer, image_att.length);
392911e25f0dSDavid C Somayajulu }
393011e25f0dSDavid C Somayajulu 
393111e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_get_temperature_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_temperature_info * p_temp_info)393211e25f0dSDavid C Somayajulu ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
393311e25f0dSDavid C Somayajulu 			       struct ecore_ptt *p_ptt,
393411e25f0dSDavid C Somayajulu 			       struct ecore_temperature_info *p_temp_info)
393511e25f0dSDavid C Somayajulu {
393611e25f0dSDavid C Somayajulu 	struct ecore_temperature_sensor *p_temp_sensor;
393711e25f0dSDavid C Somayajulu 	struct temperature_status_stc mfw_temp_info;
393811e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
393911e25f0dSDavid C Somayajulu 	u32 val;
394011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
394111e25f0dSDavid C Somayajulu 	u8 i;
394211e25f0dSDavid C Somayajulu 
394311e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
394411e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_GET_TEMPERATURE;
394511e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = &mfw_temp_info;
394611e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = sizeof(mfw_temp_info);
394711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
394811e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
394911e25f0dSDavid C Somayajulu 		return rc;
395011e25f0dSDavid C Somayajulu 
395111e25f0dSDavid C Somayajulu 	OSAL_BUILD_BUG_ON(ECORE_MAX_NUM_OF_SENSORS != MAX_NUM_OF_SENSORS);
395211e25f0dSDavid C Somayajulu 	p_temp_info->num_sensors = OSAL_MIN_T(u32, mfw_temp_info.num_of_sensors,
395311e25f0dSDavid C Somayajulu 					      ECORE_MAX_NUM_OF_SENSORS);
395411e25f0dSDavid C Somayajulu 	for (i = 0; i < p_temp_info->num_sensors; i++) {
395511e25f0dSDavid C Somayajulu 		val = mfw_temp_info.sensor[i];
395611e25f0dSDavid C Somayajulu 		p_temp_sensor = &p_temp_info->sensors[i];
395711e25f0dSDavid C Somayajulu 		p_temp_sensor->sensor_location = (val & SENSOR_LOCATION_MASK) >>
39589efd0ba7SDavid C Somayajulu 						 SENSOR_LOCATION_OFFSET;
395911e25f0dSDavid C Somayajulu 		p_temp_sensor->threshold_high = (val & THRESHOLD_HIGH_MASK) >>
39609efd0ba7SDavid C Somayajulu 						THRESHOLD_HIGH_OFFSET;
396111e25f0dSDavid C Somayajulu 		p_temp_sensor->critical = (val & CRITICAL_TEMPERATURE_MASK) >>
39629efd0ba7SDavid C Somayajulu 					  CRITICAL_TEMPERATURE_OFFSET;
396311e25f0dSDavid C Somayajulu 		p_temp_sensor->current_temp = (val & CURRENT_TEMP_MASK) >>
39649efd0ba7SDavid C Somayajulu 					      CURRENT_TEMP_OFFSET;
396511e25f0dSDavid C Somayajulu 	}
396611e25f0dSDavid C Somayajulu 
396711e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
396811e25f0dSDavid C Somayajulu }
396911e25f0dSDavid C Somayajulu 
ecore_mcp_get_mba_versions(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mba_vers * p_mba_vers)397011e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_mba_versions(
397111e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn,
397211e25f0dSDavid C Somayajulu 	struct ecore_ptt *p_ptt,
397311e25f0dSDavid C Somayajulu 	struct ecore_mba_vers *p_mba_vers)
397411e25f0dSDavid C Somayajulu {
39759efd0ba7SDavid C Somayajulu 	u32 buf_size, resp, param;
397611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
397711e25f0dSDavid C Somayajulu 
39789efd0ba7SDavid C Somayajulu 	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MBA_VERSION,
39799efd0ba7SDavid C Somayajulu 				  0, &resp, &param, &buf_size,
39809efd0ba7SDavid C Somayajulu 				  &(p_mba_vers->mba_vers[0]));
398111e25f0dSDavid C Somayajulu 
398211e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
398311e25f0dSDavid C Somayajulu 		return rc;
398411e25f0dSDavid C Somayajulu 
39859efd0ba7SDavid C Somayajulu 	if ((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
398611e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
398711e25f0dSDavid C Somayajulu 
398811e25f0dSDavid C Somayajulu 	if (buf_size != MCP_DRV_NVM_BUF_LEN)
398911e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
399011e25f0dSDavid C Somayajulu 
399111e25f0dSDavid C Somayajulu 	return rc;
399211e25f0dSDavid C Somayajulu }
399311e25f0dSDavid C Somayajulu 
ecore_mcp_mem_ecc_events(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u64 * num_events)399411e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_mem_ecc_events(struct ecore_hwfn *p_hwfn,
399511e25f0dSDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
399611e25f0dSDavid C Somayajulu 					      u64 *num_events)
399711e25f0dSDavid C Somayajulu {
3998217ec208SDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
399911e25f0dSDavid C Somayajulu 
4000217ec208SDavid C Somayajulu 	OSAL_MEMSET(&mb_params, 0, sizeof(struct ecore_mcp_mb_params));
4001217ec208SDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_MEM_ECC_EVENTS;
4002217ec208SDavid C Somayajulu 	mb_params.p_data_dst = (union drv_union_data *)num_events;
4003217ec208SDavid C Somayajulu 
4004217ec208SDavid C Somayajulu 	return ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
400511e25f0dSDavid C Somayajulu }
400611e25f0dSDavid C Somayajulu 
400711e25f0dSDavid C Somayajulu static enum resource_id_enum
ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)400811e25f0dSDavid C Somayajulu ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)
400911e25f0dSDavid C Somayajulu {
401011e25f0dSDavid C Somayajulu 	enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
401111e25f0dSDavid C Somayajulu 
401211e25f0dSDavid C Somayajulu 	switch (res_id) {
401311e25f0dSDavid C Somayajulu 	case ECORE_SB:
401411e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_SB_E;
401511e25f0dSDavid C Somayajulu 		break;
401611e25f0dSDavid C Somayajulu 	case ECORE_L2_QUEUE:
401711e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
401811e25f0dSDavid C Somayajulu 		break;
401911e25f0dSDavid C Somayajulu 	case ECORE_VPORT:
402011e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_VPORT_E;
402111e25f0dSDavid C Somayajulu 		break;
402211e25f0dSDavid C Somayajulu 	case ECORE_RSS_ENG:
402311e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
402411e25f0dSDavid C Somayajulu 		break;
402511e25f0dSDavid C Somayajulu 	case ECORE_PQ:
402611e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_PQ_E;
402711e25f0dSDavid C Somayajulu 		break;
402811e25f0dSDavid C Somayajulu 	case ECORE_RL:
402911e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_NUM_RL_E;
403011e25f0dSDavid C Somayajulu 		break;
403111e25f0dSDavid C Somayajulu 	case ECORE_MAC:
403211e25f0dSDavid C Somayajulu 	case ECORE_VLAN:
403311e25f0dSDavid C Somayajulu 		/* Each VFC resource can accommodate both a MAC and a VLAN */
403411e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_VFC_FILTER_E;
403511e25f0dSDavid C Somayajulu 		break;
403611e25f0dSDavid C Somayajulu 	case ECORE_ILT:
403711e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_ILT_E;
403811e25f0dSDavid C Somayajulu 		break;
403911e25f0dSDavid C Somayajulu 	case ECORE_LL2_QUEUE:
404011e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_LL2_QUEUE_E;
404111e25f0dSDavid C Somayajulu 		break;
404211e25f0dSDavid C Somayajulu 	case ECORE_RDMA_CNQ_RAM:
404311e25f0dSDavid C Somayajulu 	case ECORE_CMDQS_CQS:
404411e25f0dSDavid C Somayajulu 		/* CNQ/CMDQS are the same resource */
404511e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_CQS_E;
404611e25f0dSDavid C Somayajulu 		break;
404711e25f0dSDavid C Somayajulu 	case ECORE_RDMA_STATS_QUEUE:
404811e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
404911e25f0dSDavid C Somayajulu 		break;
405011e25f0dSDavid C Somayajulu 	case ECORE_BDQ:
405111e25f0dSDavid C Somayajulu 		mfw_res_id = RESOURCE_BDQ_E;
405211e25f0dSDavid C Somayajulu 		break;
405311e25f0dSDavid C Somayajulu 	default:
405411e25f0dSDavid C Somayajulu 		break;
405511e25f0dSDavid C Somayajulu 	}
405611e25f0dSDavid C Somayajulu 
405711e25f0dSDavid C Somayajulu 	return mfw_res_id;
405811e25f0dSDavid C Somayajulu }
405911e25f0dSDavid C Somayajulu 
406011e25f0dSDavid C Somayajulu #define ECORE_RESC_ALLOC_VERSION_MAJOR	2
406111e25f0dSDavid C Somayajulu #define ECORE_RESC_ALLOC_VERSION_MINOR	0
406211e25f0dSDavid C Somayajulu #define ECORE_RESC_ALLOC_VERSION				\
406311e25f0dSDavid C Somayajulu 	((ECORE_RESC_ALLOC_VERSION_MAJOR <<			\
40649efd0ba7SDavid C Somayajulu 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_OFFSET) |	\
406511e25f0dSDavid C Somayajulu 	 (ECORE_RESC_ALLOC_VERSION_MINOR <<			\
40669efd0ba7SDavid C Somayajulu 	  DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_OFFSET))
406711e25f0dSDavid C Somayajulu 
406811e25f0dSDavid C Somayajulu struct ecore_resc_alloc_in_params {
406911e25f0dSDavid C Somayajulu 	u32 cmd;
407011e25f0dSDavid C Somayajulu 	enum ecore_resources res_id;
407111e25f0dSDavid C Somayajulu 	u32 resc_max_val;
407211e25f0dSDavid C Somayajulu };
407311e25f0dSDavid C Somayajulu 
407411e25f0dSDavid C Somayajulu struct ecore_resc_alloc_out_params {
407511e25f0dSDavid C Somayajulu 	u32 mcp_resp;
407611e25f0dSDavid C Somayajulu 	u32 mcp_param;
407711e25f0dSDavid C Somayajulu 	u32 resc_num;
407811e25f0dSDavid C Somayajulu 	u32 resc_start;
407911e25f0dSDavid C Somayajulu 	u32 vf_resc_num;
408011e25f0dSDavid C Somayajulu 	u32 vf_resc_start;
408111e25f0dSDavid C Somayajulu 	u32 flags;
408211e25f0dSDavid C Somayajulu };
408311e25f0dSDavid C Somayajulu 
408411e25f0dSDavid C Somayajulu static enum _ecore_status_t
ecore_mcp_resc_allocation_msg(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_alloc_in_params * p_in_params,struct ecore_resc_alloc_out_params * p_out_params)408511e25f0dSDavid C Somayajulu ecore_mcp_resc_allocation_msg(struct ecore_hwfn *p_hwfn,
408611e25f0dSDavid C Somayajulu 			      struct ecore_ptt *p_ptt,
408711e25f0dSDavid C Somayajulu 			      struct ecore_resc_alloc_in_params *p_in_params,
408811e25f0dSDavid C Somayajulu 			      struct ecore_resc_alloc_out_params *p_out_params)
408911e25f0dSDavid C Somayajulu {
409011e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
409111e25f0dSDavid C Somayajulu 	struct resource_info mfw_resc_info;
409211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
409311e25f0dSDavid C Somayajulu 
409411e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mfw_resc_info, sizeof(mfw_resc_info));
409511e25f0dSDavid C Somayajulu 
409611e25f0dSDavid C Somayajulu 	mfw_resc_info.res_id = ecore_mcp_get_mfw_res_id(p_in_params->res_id);
409711e25f0dSDavid C Somayajulu 	if (mfw_resc_info.res_id == RESOURCE_NUM_INVALID) {
409811e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn,
409911e25f0dSDavid C Somayajulu 		       "Failed to match resource %d [%s] with the MFW resources\n",
410011e25f0dSDavid C Somayajulu 		       p_in_params->res_id,
410111e25f0dSDavid C Somayajulu 		       ecore_hw_get_resc_name(p_in_params->res_id));
410211e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
410311e25f0dSDavid C Somayajulu 	}
410411e25f0dSDavid C Somayajulu 
410511e25f0dSDavid C Somayajulu 	switch (p_in_params->cmd) {
410611e25f0dSDavid C Somayajulu 	case DRV_MSG_SET_RESOURCE_VALUE_MSG:
410711e25f0dSDavid C Somayajulu 		mfw_resc_info.size = p_in_params->resc_max_val;
410811e25f0dSDavid C Somayajulu 		/* Fallthrough */
410911e25f0dSDavid C Somayajulu 	case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
411011e25f0dSDavid C Somayajulu 		break;
411111e25f0dSDavid C Somayajulu 	default:
411211e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Unexpected resource alloc command [0x%08x]\n",
411311e25f0dSDavid C Somayajulu 		       p_in_params->cmd);
411411e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
411511e25f0dSDavid C Somayajulu 	}
411611e25f0dSDavid C Somayajulu 
411711e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
411811e25f0dSDavid C Somayajulu 	mb_params.cmd = p_in_params->cmd;
411911e25f0dSDavid C Somayajulu 	mb_params.param = ECORE_RESC_ALLOC_VERSION;
412011e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &mfw_resc_info;
412111e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(mfw_resc_info);
412211e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = mb_params.p_data_src;
412311e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = mb_params.data_src_size;
412411e25f0dSDavid C Somayajulu 
412511e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
412611e25f0dSDavid C Somayajulu 		   "Resource message request: cmd 0x%08x, res_id %d [%s], hsi_version %d.%d, val 0x%x\n",
412711e25f0dSDavid C Somayajulu 		   p_in_params->cmd, p_in_params->res_id,
412811e25f0dSDavid C Somayajulu 		   ecore_hw_get_resc_name(p_in_params->res_id),
41299efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param,
413011e25f0dSDavid C Somayajulu 				 DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
41319efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(mb_params.param,
413211e25f0dSDavid C Somayajulu 				 DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
413311e25f0dSDavid C Somayajulu 		   p_in_params->resc_max_val);
413411e25f0dSDavid C Somayajulu 
413511e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
413611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
413711e25f0dSDavid C Somayajulu 		return rc;
413811e25f0dSDavid C Somayajulu 
413911e25f0dSDavid C Somayajulu 	p_out_params->mcp_resp = mb_params.mcp_resp;
414011e25f0dSDavid C Somayajulu 	p_out_params->mcp_param = mb_params.mcp_param;
414111e25f0dSDavid C Somayajulu 	p_out_params->resc_num = mfw_resc_info.size;
414211e25f0dSDavid C Somayajulu 	p_out_params->resc_start = mfw_resc_info.offset;
414311e25f0dSDavid C Somayajulu 	p_out_params->vf_resc_num = mfw_resc_info.vf_size;
414411e25f0dSDavid C Somayajulu 	p_out_params->vf_resc_start = mfw_resc_info.vf_offset;
414511e25f0dSDavid C Somayajulu 	p_out_params->flags = mfw_resc_info.flags;
414611e25f0dSDavid C Somayajulu 
414711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
414811e25f0dSDavid C Somayajulu 		   "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",
41499efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(p_out_params->mcp_param,
415011e25f0dSDavid C Somayajulu 				 FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
41519efd0ba7SDavid C Somayajulu 		   GET_MFW_FIELD(p_out_params->mcp_param,
415211e25f0dSDavid C Somayajulu 				 FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
415311e25f0dSDavid C Somayajulu 		   p_out_params->resc_num, p_out_params->resc_start,
415411e25f0dSDavid C Somayajulu 		   p_out_params->vf_resc_num, p_out_params->vf_resc_start,
415511e25f0dSDavid C Somayajulu 		   p_out_params->flags);
415611e25f0dSDavid C Somayajulu 
415711e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
415811e25f0dSDavid C Somayajulu }
415911e25f0dSDavid C Somayajulu 
416011e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_set_resc_max_val(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_resources res_id,u32 resc_max_val,u32 * p_mcp_resp)416111e25f0dSDavid C Somayajulu ecore_mcp_set_resc_max_val(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
416211e25f0dSDavid C Somayajulu 			   enum ecore_resources res_id, u32 resc_max_val,
416311e25f0dSDavid C Somayajulu 			   u32 *p_mcp_resp)
416411e25f0dSDavid C Somayajulu {
416511e25f0dSDavid C Somayajulu 	struct ecore_resc_alloc_out_params out_params;
416611e25f0dSDavid C Somayajulu 	struct ecore_resc_alloc_in_params in_params;
416711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
416811e25f0dSDavid C Somayajulu 
416911e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
417011e25f0dSDavid C Somayajulu 	in_params.cmd = DRV_MSG_SET_RESOURCE_VALUE_MSG;
417111e25f0dSDavid C Somayajulu 	in_params.res_id = res_id;
417211e25f0dSDavid C Somayajulu 	in_params.resc_max_val = resc_max_val;
417311e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
417411e25f0dSDavid C Somayajulu 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
417511e25f0dSDavid C Somayajulu 					   &out_params);
417611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
417711e25f0dSDavid C Somayajulu 		return rc;
417811e25f0dSDavid C Somayajulu 
417911e25f0dSDavid C Somayajulu 	*p_mcp_resp = out_params.mcp_resp;
418011e25f0dSDavid C Somayajulu 
418111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
418211e25f0dSDavid C Somayajulu }
418311e25f0dSDavid C Somayajulu 
418411e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_get_resc_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,enum ecore_resources res_id,u32 * p_mcp_resp,u32 * p_resc_num,u32 * p_resc_start)418511e25f0dSDavid C Somayajulu ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
418611e25f0dSDavid C Somayajulu 			enum ecore_resources res_id, u32 *p_mcp_resp,
418711e25f0dSDavid C Somayajulu 			u32 *p_resc_num, u32 *p_resc_start)
418811e25f0dSDavid C Somayajulu {
418911e25f0dSDavid C Somayajulu 	struct ecore_resc_alloc_out_params out_params;
419011e25f0dSDavid C Somayajulu 	struct ecore_resc_alloc_in_params in_params;
419111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
419211e25f0dSDavid C Somayajulu 
419311e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&in_params, sizeof(in_params));
419411e25f0dSDavid C Somayajulu 	in_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
419511e25f0dSDavid C Somayajulu 	in_params.res_id = res_id;
419611e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&out_params, sizeof(out_params));
419711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
419811e25f0dSDavid C Somayajulu 					   &out_params);
419911e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
420011e25f0dSDavid C Somayajulu 		return rc;
420111e25f0dSDavid C Somayajulu 
420211e25f0dSDavid C Somayajulu 	*p_mcp_resp = out_params.mcp_resp;
420311e25f0dSDavid C Somayajulu 
420411e25f0dSDavid C Somayajulu 	if (*p_mcp_resp == FW_MSG_CODE_RESOURCE_ALLOC_OK) {
420511e25f0dSDavid C Somayajulu 		*p_resc_num = out_params.resc_num;
420611e25f0dSDavid C Somayajulu 		*p_resc_start = out_params.resc_start;
420711e25f0dSDavid C Somayajulu 	}
420811e25f0dSDavid C Somayajulu 
420911e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
421011e25f0dSDavid C Somayajulu }
421111e25f0dSDavid C Somayajulu 
ecore_mcp_initiate_pf_flr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)421211e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_initiate_pf_flr(struct ecore_hwfn *p_hwfn,
421311e25f0dSDavid C Somayajulu 					       struct ecore_ptt *p_ptt)
421411e25f0dSDavid C Somayajulu {
421511e25f0dSDavid C Somayajulu 	u32 mcp_resp, mcp_param;
421611e25f0dSDavid C Somayajulu 
421711e25f0dSDavid C Somayajulu 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_INITIATE_PF_FLR, 0,
421811e25f0dSDavid C Somayajulu 			     &mcp_resp, &mcp_param);
421911e25f0dSDavid C Somayajulu }
422011e25f0dSDavid C Somayajulu 
ecore_mcp_get_lldp_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 lldp_mac_addr[ETH_ALEN])422111e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_lldp_mac(struct ecore_hwfn *p_hwfn,
422211e25f0dSDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
422311e25f0dSDavid C Somayajulu 					    u8 lldp_mac_addr[ETH_ALEN])
422411e25f0dSDavid C Somayajulu {
422511e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
422611e25f0dSDavid C Somayajulu 	struct mcp_mac lldp_mac;
422711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
422811e25f0dSDavid C Somayajulu 
422911e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
423011e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_GET_LLDP_MAC;
423111e25f0dSDavid C Somayajulu 	mb_params.p_data_dst = &lldp_mac;
423211e25f0dSDavid C Somayajulu 	mb_params.data_dst_size = sizeof(lldp_mac);
423311e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
423411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
423511e25f0dSDavid C Somayajulu 		return rc;
423611e25f0dSDavid C Somayajulu 
423711e25f0dSDavid C Somayajulu 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
423811e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
423911e25f0dSDavid C Somayajulu 			  "MFW lacks support for the GET_LLDP_MAC command [resp 0x%08x]\n",
424011e25f0dSDavid C Somayajulu 			  mb_params.mcp_resp);
424111e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
424211e25f0dSDavid C Somayajulu 	}
424311e25f0dSDavid C Somayajulu 
4244217ec208SDavid C Somayajulu 	*(u16 *)lldp_mac_addr = OSAL_BE16_TO_CPU(*(u16 *)&lldp_mac.mac_upper);
4245217ec208SDavid C Somayajulu 	*(u32 *)(lldp_mac_addr + 2) = OSAL_BE32_TO_CPU(lldp_mac.mac_lower);
424611e25f0dSDavid C Somayajulu 
424711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
424811e25f0dSDavid C Somayajulu 		   "LLDP MAC address is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
424911e25f0dSDavid C Somayajulu 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
425011e25f0dSDavid C Somayajulu 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
425111e25f0dSDavid C Somayajulu 
425211e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
425311e25f0dSDavid C Somayajulu }
425411e25f0dSDavid C Somayajulu 
ecore_mcp_set_lldp_mac(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 lldp_mac_addr[ETH_ALEN])425511e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_set_lldp_mac(struct ecore_hwfn *p_hwfn,
425611e25f0dSDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
425711e25f0dSDavid C Somayajulu 					    u8 lldp_mac_addr[ETH_ALEN])
425811e25f0dSDavid C Somayajulu {
425911e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
426011e25f0dSDavid C Somayajulu 	struct mcp_mac lldp_mac;
426111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
426211e25f0dSDavid C Somayajulu 
426311e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
426411e25f0dSDavid C Somayajulu 		   "Configuring LLDP MAC address to %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
426511e25f0dSDavid C Somayajulu 		   lldp_mac_addr[0], lldp_mac_addr[1], lldp_mac_addr[2],
426611e25f0dSDavid C Somayajulu 		   lldp_mac_addr[3], lldp_mac_addr[4], lldp_mac_addr[5]);
426711e25f0dSDavid C Somayajulu 
426811e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&lldp_mac, sizeof(lldp_mac));
4269217ec208SDavid C Somayajulu 	lldp_mac.mac_upper = OSAL_CPU_TO_BE16(*(u16 *)lldp_mac_addr);
4270217ec208SDavid C Somayajulu 	lldp_mac.mac_lower = OSAL_CPU_TO_BE32(*(u32 *)(lldp_mac_addr + 2));
427111e25f0dSDavid C Somayajulu 
427211e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
427311e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_SET_LLDP_MAC;
427411e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &lldp_mac;
427511e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(lldp_mac);
427611e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
427711e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
427811e25f0dSDavid C Somayajulu 		return rc;
427911e25f0dSDavid C Somayajulu 
428011e25f0dSDavid C Somayajulu 	if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
428111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
428211e25f0dSDavid C Somayajulu 			  "MFW lacks support for the SET_LLDP_MAC command [resp 0x%08x]\n",
428311e25f0dSDavid C Somayajulu 			  mb_params.mcp_resp);
428411e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
428511e25f0dSDavid C Somayajulu 	}
428611e25f0dSDavid C Somayajulu 
428711e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
428811e25f0dSDavid C Somayajulu }
428911e25f0dSDavid C Somayajulu 
ecore_mcp_resource_cmd(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 param,u32 * p_mcp_resp,u32 * p_mcp_param)429011e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn,
429111e25f0dSDavid C Somayajulu 						   struct ecore_ptt *p_ptt,
429211e25f0dSDavid C Somayajulu 						   u32 param, u32 *p_mcp_resp,
429311e25f0dSDavid C Somayajulu 						   u32 *p_mcp_param)
429411e25f0dSDavid C Somayajulu {
429511e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
429611e25f0dSDavid C Somayajulu 
429711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_RESOURCE_CMD, param,
429811e25f0dSDavid C Somayajulu 			   p_mcp_resp, p_mcp_param);
429911e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
430011e25f0dSDavid C Somayajulu 		return rc;
430111e25f0dSDavid C Somayajulu 
430211e25f0dSDavid C Somayajulu 	if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
430311e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
430411e25f0dSDavid C Somayajulu 			"The resource command is unsupported by the MFW\n");
430511e25f0dSDavid C Somayajulu 		return ECORE_NOTIMPL;
430611e25f0dSDavid C Somayajulu 	}
430711e25f0dSDavid C Somayajulu 
430811e25f0dSDavid C Somayajulu 	if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) {
43099efd0ba7SDavid C Somayajulu 		u8 opcode = GET_MFW_FIELD(param, RESOURCE_CMD_REQ_OPCODE);
431011e25f0dSDavid C Somayajulu 
431111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
431211e25f0dSDavid C Somayajulu 			  "The resource command is unknown to the MFW [param 0x%08x, opcode %d]\n",
431311e25f0dSDavid C Somayajulu 			  param, opcode);
431411e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
431511e25f0dSDavid C Somayajulu 	}
431611e25f0dSDavid C Somayajulu 
431711e25f0dSDavid C Somayajulu 	return rc;
431811e25f0dSDavid C Somayajulu }
431911e25f0dSDavid C Somayajulu 
432011e25f0dSDavid C Somayajulu static enum _ecore_status_t
__ecore_mcp_resc_lock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_lock_params * p_params)432111e25f0dSDavid C Somayajulu __ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
432211e25f0dSDavid C Somayajulu 		      struct ecore_resc_lock_params *p_params)
432311e25f0dSDavid C Somayajulu {
432411e25f0dSDavid C Somayajulu 	u32 param = 0, mcp_resp, mcp_param;
4325217ec208SDavid C Somayajulu 	u8 opcode, timeout;
432611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
432711e25f0dSDavid C Somayajulu 
432811e25f0dSDavid C Somayajulu 	switch (p_params->timeout) {
432911e25f0dSDavid C Somayajulu 	case ECORE_MCP_RESC_LOCK_TO_DEFAULT:
433011e25f0dSDavid C Somayajulu 		opcode = RESOURCE_OPCODE_REQ;
4331217ec208SDavid C Somayajulu 		timeout = 0;
433211e25f0dSDavid C Somayajulu 		break;
433311e25f0dSDavid C Somayajulu 	case ECORE_MCP_RESC_LOCK_TO_NONE:
433411e25f0dSDavid C Somayajulu 		opcode = RESOURCE_OPCODE_REQ_WO_AGING;
4335217ec208SDavid C Somayajulu 		timeout = 0;
433611e25f0dSDavid C Somayajulu 		break;
433711e25f0dSDavid C Somayajulu 	default:
433811e25f0dSDavid C Somayajulu 		opcode = RESOURCE_OPCODE_REQ_W_AGING;
4339217ec208SDavid C Somayajulu 		timeout = p_params->timeout;
434011e25f0dSDavid C Somayajulu 		break;
434111e25f0dSDavid C Somayajulu 	}
434211e25f0dSDavid C Somayajulu 
43439efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
43449efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
4345217ec208SDavid C Somayajulu 	SET_MFW_FIELD(param, RESOURCE_CMD_REQ_AGE, timeout);
434611e25f0dSDavid C Somayajulu 
434711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
434811e25f0dSDavid C Somayajulu 		   "Resource lock request: param 0x%08x [age %d, opcode %d, resource %d]\n",
4349217ec208SDavid C Somayajulu 		   param, timeout, opcode, p_params->resource);
435011e25f0dSDavid C Somayajulu 
435111e25f0dSDavid C Somayajulu 	/* Attempt to acquire the resource */
435211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
435311e25f0dSDavid C Somayajulu 				    &mcp_param);
435411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
435511e25f0dSDavid C Somayajulu 		return rc;
435611e25f0dSDavid C Somayajulu 
435711e25f0dSDavid C Somayajulu 	/* Analyze the response */
43589efd0ba7SDavid C Somayajulu 	p_params->owner = GET_MFW_FIELD(mcp_param, RESOURCE_CMD_RSP_OWNER);
43599efd0ba7SDavid C Somayajulu 	opcode = GET_MFW_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
436011e25f0dSDavid C Somayajulu 
436111e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
436211e25f0dSDavid C Somayajulu 		   "Resource lock response: mcp_param 0x%08x [opcode %d, owner %d]\n",
436311e25f0dSDavid C Somayajulu 		   mcp_param, opcode, p_params->owner);
436411e25f0dSDavid C Somayajulu 
436511e25f0dSDavid C Somayajulu 	switch (opcode) {
436611e25f0dSDavid C Somayajulu 	case RESOURCE_OPCODE_GNT:
436711e25f0dSDavid C Somayajulu 		p_params->b_granted = true;
436811e25f0dSDavid C Somayajulu 		break;
436911e25f0dSDavid C Somayajulu 	case RESOURCE_OPCODE_BUSY:
437011e25f0dSDavid C Somayajulu 		p_params->b_granted = false;
437111e25f0dSDavid C Somayajulu 		break;
437211e25f0dSDavid C Somayajulu 	default:
437311e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
437411e25f0dSDavid C Somayajulu 			  "Unexpected opcode in resource lock response [mcp_param 0x%08x, opcode %d]\n",
437511e25f0dSDavid C Somayajulu 			  mcp_param, opcode);
437611e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
437711e25f0dSDavid C Somayajulu 	}
437811e25f0dSDavid C Somayajulu 
437911e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
438011e25f0dSDavid C Somayajulu }
438111e25f0dSDavid C Somayajulu 
438211e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_resc_lock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_lock_params * p_params)438311e25f0dSDavid C Somayajulu ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
438411e25f0dSDavid C Somayajulu 		    struct ecore_resc_lock_params *p_params)
438511e25f0dSDavid C Somayajulu {
438611e25f0dSDavid C Somayajulu 	u32 retry_cnt = 0;
438711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
438811e25f0dSDavid C Somayajulu 
438911e25f0dSDavid C Somayajulu 	do {
439011e25f0dSDavid C Somayajulu 		/* No need for an interval before the first iteration */
439111e25f0dSDavid C Somayajulu 		if (retry_cnt) {
439211e25f0dSDavid C Somayajulu 			if (p_params->sleep_b4_retry) {
4393217ec208SDavid C Somayajulu 				u32 retry_interval_in_ms =
439411e25f0dSDavid C Somayajulu 					DIV_ROUND_UP(p_params->retry_interval,
439511e25f0dSDavid C Somayajulu 						     1000);
439611e25f0dSDavid C Somayajulu 
439711e25f0dSDavid C Somayajulu 				OSAL_MSLEEP(retry_interval_in_ms);
439811e25f0dSDavid C Somayajulu 			} else {
439911e25f0dSDavid C Somayajulu 				OSAL_UDELAY(p_params->retry_interval);
440011e25f0dSDavid C Somayajulu 			}
440111e25f0dSDavid C Somayajulu 		}
440211e25f0dSDavid C Somayajulu 
440311e25f0dSDavid C Somayajulu 		rc = __ecore_mcp_resc_lock(p_hwfn, p_ptt, p_params);
440411e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
440511e25f0dSDavid C Somayajulu 			return rc;
440611e25f0dSDavid C Somayajulu 
440711e25f0dSDavid C Somayajulu 		if (p_params->b_granted)
440811e25f0dSDavid C Somayajulu 			break;
440911e25f0dSDavid C Somayajulu 	} while (retry_cnt++ < p_params->retry_num);
441011e25f0dSDavid C Somayajulu 
441111e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
441211e25f0dSDavid C Somayajulu }
441311e25f0dSDavid C Somayajulu 
441411e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_resc_unlock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_resc_unlock_params * p_params)441511e25f0dSDavid C Somayajulu ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
441611e25f0dSDavid C Somayajulu 		      struct ecore_resc_unlock_params *p_params)
441711e25f0dSDavid C Somayajulu {
441811e25f0dSDavid C Somayajulu 	u32 param = 0, mcp_resp, mcp_param;
441911e25f0dSDavid C Somayajulu 	u8 opcode;
442011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
442111e25f0dSDavid C Somayajulu 
442211e25f0dSDavid C Somayajulu 	opcode = p_params->b_force ? RESOURCE_OPCODE_FORCE_RELEASE
442311e25f0dSDavid C Somayajulu 				   : RESOURCE_OPCODE_RELEASE;
44249efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
44259efd0ba7SDavid C Somayajulu 	SET_MFW_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
442611e25f0dSDavid C Somayajulu 
442711e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
442811e25f0dSDavid C Somayajulu 		   "Resource unlock request: param 0x%08x [opcode %d, resource %d]\n",
442911e25f0dSDavid C Somayajulu 		   param, opcode, p_params->resource);
443011e25f0dSDavid C Somayajulu 
443111e25f0dSDavid C Somayajulu 	/* Attempt to release the resource */
443211e25f0dSDavid C Somayajulu 	rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
443311e25f0dSDavid C Somayajulu 				    &mcp_param);
443411e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
443511e25f0dSDavid C Somayajulu 		return rc;
443611e25f0dSDavid C Somayajulu 
443711e25f0dSDavid C Somayajulu 	/* Analyze the response */
44389efd0ba7SDavid C Somayajulu 	opcode = GET_MFW_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE);
443911e25f0dSDavid C Somayajulu 
444011e25f0dSDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
444111e25f0dSDavid C Somayajulu 		   "Resource unlock response: mcp_param 0x%08x [opcode %d]\n",
444211e25f0dSDavid C Somayajulu 		   mcp_param, opcode);
444311e25f0dSDavid C Somayajulu 
444411e25f0dSDavid C Somayajulu 	switch (opcode) {
444511e25f0dSDavid C Somayajulu 	case RESOURCE_OPCODE_RELEASED_PREVIOUS:
444611e25f0dSDavid C Somayajulu 		DP_INFO(p_hwfn,
444711e25f0dSDavid C Somayajulu 			"Resource unlock request for an already released resource [%d]\n",
444811e25f0dSDavid C Somayajulu 			p_params->resource);
444911e25f0dSDavid C Somayajulu 		/* Fallthrough */
445011e25f0dSDavid C Somayajulu 	case RESOURCE_OPCODE_RELEASED:
445111e25f0dSDavid C Somayajulu 		p_params->b_released = true;
445211e25f0dSDavid C Somayajulu 		break;
445311e25f0dSDavid C Somayajulu 	case RESOURCE_OPCODE_WRONG_OWNER:
445411e25f0dSDavid C Somayajulu 		p_params->b_released = false;
445511e25f0dSDavid C Somayajulu 		break;
445611e25f0dSDavid C Somayajulu 	default:
445711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
445811e25f0dSDavid C Somayajulu 			  "Unexpected opcode in resource unlock response [mcp_param 0x%08x, opcode %d]\n",
445911e25f0dSDavid C Somayajulu 			  mcp_param, opcode);
446011e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
446111e25f0dSDavid C Somayajulu 	}
446211e25f0dSDavid C Somayajulu 
446311e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
446411e25f0dSDavid C Somayajulu }
446511e25f0dSDavid C Somayajulu 
ecore_mcp_resc_lock_default_init(struct ecore_resc_lock_params * p_lock,struct ecore_resc_unlock_params * p_unlock,enum ecore_resc_lock resource,bool b_is_permanent)44669efd0ba7SDavid C Somayajulu void ecore_mcp_resc_lock_default_init(struct ecore_resc_lock_params *p_lock,
44679efd0ba7SDavid C Somayajulu 				      struct ecore_resc_unlock_params *p_unlock,
44689efd0ba7SDavid C Somayajulu 				      enum ecore_resc_lock resource,
44699efd0ba7SDavid C Somayajulu 				      bool b_is_permanent)
44709efd0ba7SDavid C Somayajulu {
44719efd0ba7SDavid C Somayajulu 	if (p_lock != OSAL_NULL) {
44729efd0ba7SDavid C Somayajulu 		OSAL_MEM_ZERO(p_lock, sizeof(*p_lock));
44739efd0ba7SDavid C Somayajulu 
44749efd0ba7SDavid C Somayajulu 		/* Permanent resources don't require aging, and there's no
44759efd0ba7SDavid C Somayajulu 		 * point in trying to acquire them more than once since it's
44769efd0ba7SDavid C Somayajulu 		 * unexpected another entity would release them.
44779efd0ba7SDavid C Somayajulu 		 */
44789efd0ba7SDavid C Somayajulu 		if (b_is_permanent) {
44799efd0ba7SDavid C Somayajulu 			p_lock->timeout = ECORE_MCP_RESC_LOCK_TO_NONE;
44809efd0ba7SDavid C Somayajulu 		} else {
44819efd0ba7SDavid C Somayajulu 			p_lock->retry_num = ECORE_MCP_RESC_LOCK_RETRY_CNT_DFLT;
44829efd0ba7SDavid C Somayajulu 			p_lock->retry_interval =
44839efd0ba7SDavid C Somayajulu 					ECORE_MCP_RESC_LOCK_RETRY_VAL_DFLT;
44849efd0ba7SDavid C Somayajulu 			p_lock->sleep_b4_retry = true;
44859efd0ba7SDavid C Somayajulu 		}
44869efd0ba7SDavid C Somayajulu 
44879efd0ba7SDavid C Somayajulu 		p_lock->resource = resource;
44889efd0ba7SDavid C Somayajulu 	}
44899efd0ba7SDavid C Somayajulu 
44909efd0ba7SDavid C Somayajulu 	if (p_unlock != OSAL_NULL) {
44919efd0ba7SDavid C Somayajulu 		OSAL_MEM_ZERO(p_unlock, sizeof(*p_unlock));
44929efd0ba7SDavid C Somayajulu 		p_unlock->resource = resource;
44939efd0ba7SDavid C Somayajulu 	}
44949efd0ba7SDavid C Somayajulu }
44959efd0ba7SDavid C Somayajulu 
449611e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_update_fcoe_cvid(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 vlan)449711e25f0dSDavid C Somayajulu ecore_mcp_update_fcoe_cvid(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
449811e25f0dSDavid C Somayajulu 			   u16 vlan)
449911e25f0dSDavid C Somayajulu {
450011e25f0dSDavid C Somayajulu 	u32 resp = 0, param = 0;
450111e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
450211e25f0dSDavid C Somayajulu 
450311e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OEM_UPDATE_FCOE_CVID,
45049efd0ba7SDavid C Somayajulu 			   (u32)vlan << DRV_MB_PARAM_FCOE_CVID_OFFSET,
450511e25f0dSDavid C Somayajulu 			   &resp, &param);
450611e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
450711e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to update fcoe vlan, rc = %d\n", rc);
450811e25f0dSDavid C Somayajulu 
450911e25f0dSDavid C Somayajulu 	return rc;
451011e25f0dSDavid C Somayajulu }
451111e25f0dSDavid C Somayajulu 
451211e25f0dSDavid C Somayajulu enum _ecore_status_t
ecore_mcp_update_fcoe_fabric_name(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 * wwn)451311e25f0dSDavid C Somayajulu ecore_mcp_update_fcoe_fabric_name(struct ecore_hwfn *p_hwfn,
451411e25f0dSDavid C Somayajulu 				  struct ecore_ptt *p_ptt, u8 *wwn)
451511e25f0dSDavid C Somayajulu {
451611e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
451711e25f0dSDavid C Somayajulu 	struct mcp_wwn fabric_name;
451811e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
451911e25f0dSDavid C Somayajulu 
452011e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&fabric_name, sizeof(fabric_name));
452111e25f0dSDavid C Somayajulu 	fabric_name.wwn_upper = *(u32 *)wwn;
452211e25f0dSDavid C Somayajulu 	fabric_name.wwn_lower = *(u32 *)(wwn + 4);
452311e25f0dSDavid C Somayajulu 
452411e25f0dSDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
452511e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_OEM_UPDATE_FCOE_FABRIC_NAME;
452611e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &fabric_name;
452711e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(fabric_name);
452811e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
452911e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
453011e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Failed to update fcoe wwn, rc = %d\n", rc);
453111e25f0dSDavid C Somayajulu 
453211e25f0dSDavid C Somayajulu 	return rc;
453311e25f0dSDavid C Somayajulu }
453411e25f0dSDavid C Somayajulu 
ecore_mcp_wol_wr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 offset,u32 val)453511e25f0dSDavid C Somayajulu void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
453611e25f0dSDavid C Somayajulu 		      u32 offset, u32 val)
453711e25f0dSDavid C Somayajulu {
453811e25f0dSDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params = {0};
453911e25f0dSDavid C Somayajulu 	enum _ecore_status_t	   rc = ECORE_SUCCESS;
454011e25f0dSDavid C Somayajulu 	u32			   dword = val;
454111e25f0dSDavid C Somayajulu 
454211e25f0dSDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_WRITE_WOL_REG;
454311e25f0dSDavid C Somayajulu 	mb_params.param = offset;
454411e25f0dSDavid C Somayajulu 	mb_params.p_data_src = &dword;
454511e25f0dSDavid C Somayajulu 	mb_params.data_src_size = sizeof(dword);
454611e25f0dSDavid C Somayajulu 
454711e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
454811e25f0dSDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
454911e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
455011e25f0dSDavid C Somayajulu 			  "Failed to wol write request, rc = %d\n", rc);
455111e25f0dSDavid C Somayajulu 	}
455211e25f0dSDavid C Somayajulu 
455311e25f0dSDavid C Somayajulu 	if (mb_params.mcp_resp != FW_MSG_CODE_WOL_READ_WRITE_OK) {
455411e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
455511e25f0dSDavid C Somayajulu 			  "Failed to write value 0x%x to offset 0x%x [mcp_resp 0x%x]\n",
455611e25f0dSDavid C Somayajulu 			  val, offset, mb_params.mcp_resp);
455711e25f0dSDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
455811e25f0dSDavid C Somayajulu 	}
455911e25f0dSDavid C Somayajulu }
456011e25f0dSDavid C Somayajulu 
ecore_mcp_is_smart_an_supported(struct ecore_hwfn * p_hwfn)4561217ec208SDavid C Somayajulu bool ecore_mcp_is_smart_an_supported(struct ecore_hwfn *p_hwfn)
4562217ec208SDavid C Somayajulu {
4563217ec208SDavid C Somayajulu 	return !!(p_hwfn->mcp_info->capabilities &
4564217ec208SDavid C Somayajulu 		  FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ);
4565217ec208SDavid C Somayajulu }
4566217ec208SDavid C Somayajulu 
ecore_mcp_rlx_odr_supported(struct ecore_hwfn * p_hwfn)4567217ec208SDavid C Somayajulu bool ecore_mcp_rlx_odr_supported(struct ecore_hwfn *p_hwfn)
4568217ec208SDavid C Somayajulu {
4569217ec208SDavid C Somayajulu 	return !!(p_hwfn->mcp_info->capabilities &
4570217ec208SDavid C Somayajulu 		  FW_MB_PARAM_FEATURE_SUPPORT_RELAXED_ORD);
4571217ec208SDavid C Somayajulu }
4572217ec208SDavid C Somayajulu 
ecore_mcp_get_capabilities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)457311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_capabilities(struct ecore_hwfn *p_hwfn,
457411e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
457511e25f0dSDavid C Somayajulu {
457611e25f0dSDavid C Somayajulu 	u32 mcp_resp;
457711e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc;
457811e25f0dSDavid C Somayajulu 
457911e25f0dSDavid C Somayajulu 	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT,
458011e25f0dSDavid C Somayajulu 			   0, &mcp_resp, &p_hwfn->mcp_info->capabilities);
458111e25f0dSDavid C Somayajulu 	if (rc == ECORE_SUCCESS)
458211e25f0dSDavid C Somayajulu 		DP_VERBOSE(p_hwfn, (ECORE_MSG_SP | ECORE_MSG_PROBE),
458311e25f0dSDavid C Somayajulu 			   "MFW supported features: %08x\n",
458411e25f0dSDavid C Somayajulu 			   p_hwfn->mcp_info->capabilities);
458511e25f0dSDavid C Somayajulu 
458611e25f0dSDavid C Somayajulu 	return rc;
458711e25f0dSDavid C Somayajulu }
458811e25f0dSDavid C Somayajulu 
ecore_mcp_set_capabilities(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)458911e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_mcp_set_capabilities(struct ecore_hwfn *p_hwfn,
459011e25f0dSDavid C Somayajulu 						struct ecore_ptt *p_ptt)
459111e25f0dSDavid C Somayajulu {
459211e25f0dSDavid C Somayajulu 	u32 mcp_resp, mcp_param, features;
459311e25f0dSDavid C Somayajulu 
459411e25f0dSDavid C Somayajulu 	features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ |
4595217ec208SDavid C Somayajulu 		   DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE |
4596217ec208SDavid C Somayajulu 		   DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK;
459711e25f0dSDavid C Somayajulu 
459811e25f0dSDavid C Somayajulu 	return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
459911e25f0dSDavid C Somayajulu 			     features, &mcp_resp, &mcp_param);
460011e25f0dSDavid C Somayajulu }
4601217ec208SDavid C Somayajulu 
4602217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_mcp_drv_attribute(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_mcp_drv_attr * p_drv_attr)4603217ec208SDavid C Somayajulu ecore_mcp_drv_attribute(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
4604217ec208SDavid C Somayajulu 			struct ecore_mcp_drv_attr *p_drv_attr)
4605217ec208SDavid C Somayajulu {
4606217ec208SDavid C Somayajulu 	struct attribute_cmd_write_stc attr_cmd_write;
4607217ec208SDavid C Somayajulu 	enum _attribute_commands_e mfw_attr_cmd;
4608217ec208SDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
4609217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4610217ec208SDavid C Somayajulu 
4611217ec208SDavid C Somayajulu 	switch (p_drv_attr->attr_cmd) {
4612217ec208SDavid C Somayajulu 	case ECORE_MCP_DRV_ATTR_CMD_READ:
4613217ec208SDavid C Somayajulu 		mfw_attr_cmd = ATTRIBUTE_CMD_READ;
4614217ec208SDavid C Somayajulu 		break;
4615217ec208SDavid C Somayajulu 	case ECORE_MCP_DRV_ATTR_CMD_WRITE:
4616217ec208SDavid C Somayajulu 		mfw_attr_cmd = ATTRIBUTE_CMD_WRITE;
4617217ec208SDavid C Somayajulu 		break;
4618217ec208SDavid C Somayajulu 	case ECORE_MCP_DRV_ATTR_CMD_READ_CLEAR:
4619217ec208SDavid C Somayajulu 		mfw_attr_cmd = ATTRIBUTE_CMD_READ_CLEAR;
4620217ec208SDavid C Somayajulu 		break;
4621217ec208SDavid C Somayajulu 	case ECORE_MCP_DRV_ATTR_CMD_CLEAR:
4622217ec208SDavid C Somayajulu 		mfw_attr_cmd = ATTRIBUTE_CMD_CLEAR;
4623217ec208SDavid C Somayajulu 		break;
4624217ec208SDavid C Somayajulu 	default:
4625217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Unknown attribute command %d\n",
4626217ec208SDavid C Somayajulu 			  p_drv_attr->attr_cmd);
4627217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4628217ec208SDavid C Somayajulu 	}
4629217ec208SDavid C Somayajulu 
4630217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
4631217ec208SDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_ATTRIBUTE;
4632217ec208SDavid C Somayajulu 	SET_MFW_FIELD(mb_params.param, DRV_MB_PARAM_ATTRIBUTE_KEY,
4633217ec208SDavid C Somayajulu 		      p_drv_attr->attr_num);
4634217ec208SDavid C Somayajulu 	SET_MFW_FIELD(mb_params.param, DRV_MB_PARAM_ATTRIBUTE_CMD,
4635217ec208SDavid C Somayajulu 		      mfw_attr_cmd);
4636217ec208SDavid C Somayajulu 	if (p_drv_attr->attr_cmd == ECORE_MCP_DRV_ATTR_CMD_WRITE) {
4637217ec208SDavid C Somayajulu 		OSAL_MEM_ZERO(&attr_cmd_write, sizeof(attr_cmd_write));
4638217ec208SDavid C Somayajulu 		attr_cmd_write.val = p_drv_attr->val;
4639217ec208SDavid C Somayajulu 		attr_cmd_write.mask = p_drv_attr->mask;
4640217ec208SDavid C Somayajulu 		attr_cmd_write.offset = p_drv_attr->offset;
4641217ec208SDavid C Somayajulu 
4642217ec208SDavid C Somayajulu 		mb_params.p_data_src = &attr_cmd_write;
4643217ec208SDavid C Somayajulu 		mb_params.data_src_size = sizeof(attr_cmd_write);
4644217ec208SDavid C Somayajulu 	}
4645217ec208SDavid C Somayajulu 
4646217ec208SDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
4647217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
4648217ec208SDavid C Somayajulu 		return rc;
4649217ec208SDavid C Somayajulu 
4650217ec208SDavid C Somayajulu 	if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
4651217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
4652217ec208SDavid C Somayajulu 			"The attribute command is not supported by the MFW\n");
4653217ec208SDavid C Somayajulu 		return ECORE_NOTIMPL;
4654217ec208SDavid C Somayajulu 	} else if (mb_params.mcp_resp != FW_MSG_CODE_OK) {
4655217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
4656217ec208SDavid C Somayajulu 			"Failed to send an attribute command [mcp_resp 0x%x, attr_cmd %d, attr_num %d]\n",
4657217ec208SDavid C Somayajulu 			mb_params.mcp_resp, p_drv_attr->attr_cmd,
4658217ec208SDavid C Somayajulu 			p_drv_attr->attr_num);
4659217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4660217ec208SDavid C Somayajulu 	}
4661217ec208SDavid C Somayajulu 
4662217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
4663217ec208SDavid C Somayajulu 		   "Attribute Command: cmd %d [mfw_cmd %d], num %d, in={val 0x%08x, mask 0x%08x, offset 0x%08x}, out={val 0x%08x}\n",
4664217ec208SDavid C Somayajulu 		   p_drv_attr->attr_cmd, mfw_attr_cmd, p_drv_attr->attr_num,
4665217ec208SDavid C Somayajulu 		   p_drv_attr->val, p_drv_attr->mask, p_drv_attr->offset,
4666217ec208SDavid C Somayajulu 		   mb_params.mcp_param);
4667217ec208SDavid C Somayajulu 
4668217ec208SDavid C Somayajulu 	if (p_drv_attr->attr_cmd == ECORE_MCP_DRV_ATTR_CMD_READ ||
4669217ec208SDavid C Somayajulu 	    p_drv_attr->attr_cmd == ECORE_MCP_DRV_ATTR_CMD_READ_CLEAR)
4670217ec208SDavid C Somayajulu 		p_drv_attr->val = mb_params.mcp_param;
4671217ec208SDavid C Somayajulu 
4672217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4673217ec208SDavid C Somayajulu }
4674217ec208SDavid C Somayajulu 
ecore_mcp_get_engine_config(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)4675217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_engine_config(struct ecore_hwfn *p_hwfn,
4676217ec208SDavid C Somayajulu 						 struct ecore_ptt *p_ptt)
4677217ec208SDavid C Somayajulu {
4678217ec208SDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
4679217ec208SDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
4680217ec208SDavid C Somayajulu 	u8 fir_valid, l2_valid;
4681217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4682217ec208SDavid C Somayajulu 
4683217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
4684217ec208SDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_GET_ENGINE_CONFIG;
4685217ec208SDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
4686217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
4687217ec208SDavid C Somayajulu 		return rc;
4688217ec208SDavid C Somayajulu 
4689217ec208SDavid C Somayajulu 	if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
4690217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
4691217ec208SDavid C Somayajulu 			"The get_engine_config command is unsupported by the MFW\n");
4692217ec208SDavid C Somayajulu 		return ECORE_NOTIMPL;
4693217ec208SDavid C Somayajulu 	}
4694217ec208SDavid C Somayajulu 
4695217ec208SDavid C Somayajulu 	fir_valid = GET_MFW_FIELD(mb_params.mcp_param,
4696217ec208SDavid C Somayajulu 				  FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID);
4697217ec208SDavid C Somayajulu 	if (fir_valid)
4698217ec208SDavid C Somayajulu 		p_dev->fir_affin =
4699217ec208SDavid C Somayajulu 			GET_MFW_FIELD(mb_params.mcp_param,
4700217ec208SDavid C Somayajulu 				      FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE);
4701217ec208SDavid C Somayajulu 
4702217ec208SDavid C Somayajulu 	l2_valid = GET_MFW_FIELD(mb_params.mcp_param,
4703217ec208SDavid C Somayajulu 				 FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID);
4704217ec208SDavid C Somayajulu 	if (l2_valid)
4705217ec208SDavid C Somayajulu 		p_dev->l2_affin_hint =
4706217ec208SDavid C Somayajulu 			GET_MFW_FIELD(mb_params.mcp_param,
4707217ec208SDavid C Somayajulu 				      FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE);
4708217ec208SDavid C Somayajulu 
4709217ec208SDavid C Somayajulu 	DP_INFO(p_hwfn,
4710217ec208SDavid C Somayajulu 		"Engine affinity config: FIR={valid %hhd, value %hhd}, L2_hint={valid %hhd, value %hhd}\n",
4711217ec208SDavid C Somayajulu 		fir_valid, p_dev->fir_affin, l2_valid, p_dev->l2_affin_hint);
4712217ec208SDavid C Somayajulu 
4713217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4714217ec208SDavid C Somayajulu }
4715217ec208SDavid C Somayajulu 
ecore_mcp_get_ppfid_bitmap(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)4716217ec208SDavid C Somayajulu enum _ecore_status_t ecore_mcp_get_ppfid_bitmap(struct ecore_hwfn *p_hwfn,
4717217ec208SDavid C Somayajulu 						struct ecore_ptt *p_ptt)
4718217ec208SDavid C Somayajulu {
4719217ec208SDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
4720217ec208SDavid C Somayajulu 	struct ecore_mcp_mb_params mb_params;
4721217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4722217ec208SDavid C Somayajulu 
4723217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
4724217ec208SDavid C Somayajulu 	mb_params.cmd = DRV_MSG_CODE_GET_PPFID_BITMAP;
4725217ec208SDavid C Somayajulu 	rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
4726217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
4727217ec208SDavid C Somayajulu 		return rc;
4728217ec208SDavid C Somayajulu 
4729217ec208SDavid C Somayajulu 	if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
4730217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
4731217ec208SDavid C Somayajulu 			"The get_ppfid_bitmap command is unsupported by the MFW\n");
4732217ec208SDavid C Somayajulu 		return ECORE_NOTIMPL;
4733217ec208SDavid C Somayajulu 	}
4734217ec208SDavid C Somayajulu 
4735217ec208SDavid C Somayajulu 	p_dev->ppfid_bitmap = GET_MFW_FIELD(mb_params.mcp_param,
4736217ec208SDavid C Somayajulu 					    FW_MB_PARAM_PPFID_BITMAP);
4737217ec208SDavid C Somayajulu 
4738217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "PPFID bitmap 0x%hhx\n",
4739217ec208SDavid C Somayajulu 		   p_dev->ppfid_bitmap);
4740217ec208SDavid C Somayajulu 
4741217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4742217ec208SDavid C Somayajulu }
4743217ec208SDavid C Somayajulu 
4744217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ind_table_lock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 retry_num,u32 retry_interval)4745217ec208SDavid C Somayajulu ecore_mcp_ind_table_lock(struct ecore_hwfn *p_hwfn,
4746217ec208SDavid C Somayajulu 			 struct ecore_ptt *p_ptt,
4747217ec208SDavid C Somayajulu 			 u8 retry_num,
4748217ec208SDavid C Somayajulu 			 u32 retry_interval)
4749217ec208SDavid C Somayajulu {
4750217ec208SDavid C Somayajulu 	struct ecore_resc_lock_params resc_lock_params;
4751217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4752217ec208SDavid C Somayajulu 
4753217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&resc_lock_params,
4754217ec208SDavid C Somayajulu 		      sizeof(struct ecore_resc_lock_params));
4755217ec208SDavid C Somayajulu 	resc_lock_params.resource = ECORE_RESC_LOCK_IND_TABLE;
4756217ec208SDavid C Somayajulu 	if (!retry_num)
4757217ec208SDavid C Somayajulu 		retry_num = ECORE_MCP_RESC_LOCK_RETRY_CNT_DFLT;
4758217ec208SDavid C Somayajulu 	resc_lock_params.retry_num = retry_num;
4759217ec208SDavid C Somayajulu 
4760217ec208SDavid C Somayajulu 	if (!retry_interval)
4761217ec208SDavid C Somayajulu 		retry_interval = ECORE_MCP_RESC_LOCK_RETRY_VAL_DFLT;
4762217ec208SDavid C Somayajulu 	resc_lock_params.retry_interval = retry_interval;
4763217ec208SDavid C Somayajulu 
4764217ec208SDavid C Somayajulu 	rc = ecore_mcp_resc_lock(p_hwfn, p_ptt, &resc_lock_params);
4765217ec208SDavid C Somayajulu 	if (rc == ECORE_SUCCESS && !resc_lock_params.b_granted) {
4766217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
4767217ec208SDavid C Somayajulu 			  "Failed to acquire the resource lock for IDT access\n");
4768217ec208SDavid C Somayajulu 		return ECORE_BUSY;
4769217ec208SDavid C Somayajulu 	}
4770217ec208SDavid C Somayajulu 	return rc;
4771217ec208SDavid C Somayajulu }
4772217ec208SDavid C Somayajulu 
4773217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_mcp_ind_table_unlock(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)4774217ec208SDavid C Somayajulu ecore_mcp_ind_table_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
4775217ec208SDavid C Somayajulu {
4776217ec208SDavid C Somayajulu 	struct ecore_resc_unlock_params resc_unlock_params;
4777217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4778217ec208SDavid C Somayajulu 
4779217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&resc_unlock_params,
4780217ec208SDavid C Somayajulu 		      sizeof(struct ecore_resc_unlock_params));
4781217ec208SDavid C Somayajulu 	resc_unlock_params.resource = ECORE_RESC_LOCK_IND_TABLE;
4782217ec208SDavid C Somayajulu 	rc = ecore_mcp_resc_unlock(p_hwfn, p_ptt,
4783217ec208SDavid C Somayajulu 				  &resc_unlock_params);
4784217ec208SDavid C Somayajulu 	return rc;
4785217ec208SDavid C Somayajulu }
4786217ec208SDavid C Somayajulu #ifdef _NTDDK_
4787217ec208SDavid C Somayajulu #pragma warning(pop)
4788217ec208SDavid C Somayajulu #endif
4789