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