1fe56b9e6SYuval Mintz /* QLogic qed NIC Driver 2e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 3fe56b9e6SYuval Mintz * 4e8f1cb50SMintz, Yuval * This software is available to you under a choice of one of two 5e8f1cb50SMintz, Yuval * licenses. You may choose to be licensed under the terms of the GNU 6e8f1cb50SMintz, Yuval * General Public License (GPL) Version 2, available from the file 7e8f1cb50SMintz, Yuval * COPYING in the main directory of this source tree, or the 8e8f1cb50SMintz, Yuval * OpenIB.org BSD license below: 9e8f1cb50SMintz, Yuval * 10e8f1cb50SMintz, Yuval * Redistribution and use in source and binary forms, with or 11e8f1cb50SMintz, Yuval * without modification, are permitted provided that the following 12e8f1cb50SMintz, Yuval * conditions are met: 13e8f1cb50SMintz, Yuval * 14e8f1cb50SMintz, Yuval * - Redistributions of source code must retain the above 15e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 16e8f1cb50SMintz, Yuval * disclaimer. 17e8f1cb50SMintz, Yuval * 18e8f1cb50SMintz, Yuval * - Redistributions in binary form must reproduce the above 19e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 20e8f1cb50SMintz, Yuval * disclaimer in the documentation and /or other materials 21e8f1cb50SMintz, Yuval * provided with the distribution. 22e8f1cb50SMintz, Yuval * 23e8f1cb50SMintz, Yuval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e8f1cb50SMintz, Yuval * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e8f1cb50SMintz, Yuval * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e8f1cb50SMintz, Yuval * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e8f1cb50SMintz, Yuval * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e8f1cb50SMintz, Yuval * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e8f1cb50SMintz, Yuval * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e8f1cb50SMintz, Yuval * SOFTWARE. 31fe56b9e6SYuval Mintz */ 32fe56b9e6SYuval Mintz 33fe56b9e6SYuval Mintz #include <linux/types.h> 34fe56b9e6SYuval Mintz #include <asm/byteorder.h> 35fe56b9e6SYuval Mintz #include <linux/delay.h> 36fe56b9e6SYuval Mintz #include <linux/errno.h> 37fe56b9e6SYuval Mintz #include <linux/kernel.h> 38fe56b9e6SYuval Mintz #include <linux/slab.h> 395529bad9STomer Tayar #include <linux/spinlock.h> 40fe56b9e6SYuval Mintz #include <linux/string.h> 410fefbfbaSSudarsana Kalluru #include <linux/etherdevice.h> 42fe56b9e6SYuval Mintz #include "qed.h" 4339651abdSSudarsana Reddy Kalluru #include "qed_dcbx.h" 44fe56b9e6SYuval Mintz #include "qed_hsi.h" 45fe56b9e6SYuval Mintz #include "qed_hw.h" 46fe56b9e6SYuval Mintz #include "qed_mcp.h" 47fe56b9e6SYuval Mintz #include "qed_reg_addr.h" 481408cc1fSYuval Mintz #include "qed_sriov.h" 491408cc1fSYuval Mintz 50fe56b9e6SYuval Mintz #define CHIP_MCP_RESP_ITER_US 10 51fe56b9e6SYuval Mintz 52fe56b9e6SYuval Mintz #define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */ 53fe56b9e6SYuval Mintz #define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */ 54fe56b9e6SYuval Mintz 55fe56b9e6SYuval Mintz #define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \ 56fe56b9e6SYuval Mintz qed_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \ 57fe56b9e6SYuval Mintz _val) 58fe56b9e6SYuval Mintz 59fe56b9e6SYuval Mintz #define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \ 60fe56b9e6SYuval Mintz qed_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset)) 61fe56b9e6SYuval Mintz 62fe56b9e6SYuval Mintz #define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \ 63fe56b9e6SYuval Mintz DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \ 64fe56b9e6SYuval Mintz offsetof(struct public_drv_mb, _field), _val) 65fe56b9e6SYuval Mintz 66fe56b9e6SYuval Mintz #define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \ 67fe56b9e6SYuval Mintz DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \ 68fe56b9e6SYuval Mintz offsetof(struct public_drv_mb, _field)) 69fe56b9e6SYuval Mintz 70fe56b9e6SYuval Mintz #define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \ 71fe56b9e6SYuval Mintz DRV_ID_PDA_COMP_VER_SHIFT) 72fe56b9e6SYuval Mintz 73fe56b9e6SYuval Mintz #define MCP_BYTES_PER_MBIT_SHIFT 17 74fe56b9e6SYuval Mintz 75fe56b9e6SYuval Mintz bool qed_mcp_is_init(struct qed_hwfn *p_hwfn) 76fe56b9e6SYuval Mintz { 77fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base) 78fe56b9e6SYuval Mintz return false; 79fe56b9e6SYuval Mintz return true; 80fe56b9e6SYuval Mintz } 81fe56b9e6SYuval Mintz 821a635e48SYuval Mintz void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 83fe56b9e6SYuval Mintz { 84fe56b9e6SYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 85fe56b9e6SYuval Mintz PUBLIC_PORT); 86fe56b9e6SYuval Mintz u32 mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, addr); 87fe56b9e6SYuval Mintz 88fe56b9e6SYuval Mintz p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize, 89fe56b9e6SYuval Mintz MFW_PORT(p_hwfn)); 90fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 91fe56b9e6SYuval Mintz "port_addr = 0x%x, port_id 0x%02x\n", 92fe56b9e6SYuval Mintz p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn)); 93fe56b9e6SYuval Mintz } 94fe56b9e6SYuval Mintz 951a635e48SYuval Mintz void qed_mcp_read_mb(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 96fe56b9e6SYuval Mintz { 97fe56b9e6SYuval Mintz u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length); 98fe56b9e6SYuval Mintz u32 tmp, i; 99fe56b9e6SYuval Mintz 100fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info->public_base) 101fe56b9e6SYuval Mintz return; 102fe56b9e6SYuval Mintz 103fe56b9e6SYuval Mintz for (i = 0; i < length; i++) { 104fe56b9e6SYuval Mintz tmp = qed_rd(p_hwfn, p_ptt, 105fe56b9e6SYuval Mintz p_hwfn->mcp_info->mfw_mb_addr + 106fe56b9e6SYuval Mintz (i << 2) + sizeof(u32)); 107fe56b9e6SYuval Mintz 108fe56b9e6SYuval Mintz /* The MB data is actually BE; Need to force it to cpu */ 109fe56b9e6SYuval Mintz ((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] = 110fe56b9e6SYuval Mintz be32_to_cpu((__force __be32)tmp); 111fe56b9e6SYuval Mintz } 112fe56b9e6SYuval Mintz } 113fe56b9e6SYuval Mintz 1144ed1eea8STomer Tayar struct qed_mcp_cmd_elem { 1154ed1eea8STomer Tayar struct list_head list; 1164ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params; 1174ed1eea8STomer Tayar u16 expected_seq_num; 1184ed1eea8STomer Tayar bool b_is_completed; 1194ed1eea8STomer Tayar }; 1204ed1eea8STomer Tayar 1214ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1224ed1eea8STomer Tayar static struct qed_mcp_cmd_elem * 1234ed1eea8STomer Tayar qed_mcp_cmd_add_elem(struct qed_hwfn *p_hwfn, 1244ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 1254ed1eea8STomer Tayar u16 expected_seq_num) 1264ed1eea8STomer Tayar { 1274ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem = NULL; 1284ed1eea8STomer Tayar 1294ed1eea8STomer Tayar p_cmd_elem = kzalloc(sizeof(*p_cmd_elem), GFP_ATOMIC); 1304ed1eea8STomer Tayar if (!p_cmd_elem) 1314ed1eea8STomer Tayar goto out; 1324ed1eea8STomer Tayar 1334ed1eea8STomer Tayar p_cmd_elem->p_mb_params = p_mb_params; 1344ed1eea8STomer Tayar p_cmd_elem->expected_seq_num = expected_seq_num; 1354ed1eea8STomer Tayar list_add(&p_cmd_elem->list, &p_hwfn->mcp_info->cmd_list); 1364ed1eea8STomer Tayar out: 1374ed1eea8STomer Tayar return p_cmd_elem; 1384ed1eea8STomer Tayar } 1394ed1eea8STomer Tayar 1404ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1414ed1eea8STomer Tayar static void qed_mcp_cmd_del_elem(struct qed_hwfn *p_hwfn, 1424ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem) 1434ed1eea8STomer Tayar { 1444ed1eea8STomer Tayar list_del(&p_cmd_elem->list); 1454ed1eea8STomer Tayar kfree(p_cmd_elem); 1464ed1eea8STomer Tayar } 1474ed1eea8STomer Tayar 1484ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1494ed1eea8STomer Tayar static struct qed_mcp_cmd_elem *qed_mcp_cmd_get_elem(struct qed_hwfn *p_hwfn, 1504ed1eea8STomer Tayar u16 seq_num) 1514ed1eea8STomer Tayar { 1524ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem = NULL; 1534ed1eea8STomer Tayar 1544ed1eea8STomer Tayar list_for_each_entry(p_cmd_elem, &p_hwfn->mcp_info->cmd_list, list) { 1554ed1eea8STomer Tayar if (p_cmd_elem->expected_seq_num == seq_num) 1564ed1eea8STomer Tayar return p_cmd_elem; 1574ed1eea8STomer Tayar } 1584ed1eea8STomer Tayar 1594ed1eea8STomer Tayar return NULL; 1604ed1eea8STomer Tayar } 1614ed1eea8STomer Tayar 162fe56b9e6SYuval Mintz int qed_mcp_free(struct qed_hwfn *p_hwfn) 163fe56b9e6SYuval Mintz { 164fe56b9e6SYuval Mintz if (p_hwfn->mcp_info) { 1654ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem, *p_tmp; 1664ed1eea8STomer Tayar 167fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info->mfw_mb_cur); 168fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info->mfw_mb_shadow); 1694ed1eea8STomer Tayar 1704ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 1714ed1eea8STomer Tayar list_for_each_entry_safe(p_cmd_elem, 1724ed1eea8STomer Tayar p_tmp, 1734ed1eea8STomer Tayar &p_hwfn->mcp_info->cmd_list, list) { 1744ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 175fe56b9e6SYuval Mintz } 1764ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 1774ed1eea8STomer Tayar } 1784ed1eea8STomer Tayar 179fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info); 180fe56b9e6SYuval Mintz 181fe56b9e6SYuval Mintz return 0; 182fe56b9e6SYuval Mintz } 183fe56b9e6SYuval Mintz 1841a635e48SYuval Mintz static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 185fe56b9e6SYuval Mintz { 186fe56b9e6SYuval Mintz struct qed_mcp_info *p_info = p_hwfn->mcp_info; 187fe56b9e6SYuval Mintz u32 drv_mb_offsize, mfw_mb_offsize; 188fe56b9e6SYuval Mintz u32 mcp_pf_id = MCP_PF_ID(p_hwfn); 189fe56b9e6SYuval Mintz 190fe56b9e6SYuval Mintz p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR); 191fe56b9e6SYuval Mintz if (!p_info->public_base) 192fe56b9e6SYuval Mintz return 0; 193fe56b9e6SYuval Mintz 194fe56b9e6SYuval Mintz p_info->public_base |= GRCBASE_MCP; 195fe56b9e6SYuval Mintz 196fe56b9e6SYuval Mintz /* Calculate the driver and MFW mailbox address */ 197fe56b9e6SYuval Mintz drv_mb_offsize = qed_rd(p_hwfn, p_ptt, 198fe56b9e6SYuval Mintz SECTION_OFFSIZE_ADDR(p_info->public_base, 199fe56b9e6SYuval Mintz PUBLIC_DRV_MB)); 200fe56b9e6SYuval Mintz p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id); 201fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 202fe56b9e6SYuval Mintz "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n", 203fe56b9e6SYuval Mintz drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id); 204fe56b9e6SYuval Mintz 205fe56b9e6SYuval Mintz /* Set the MFW MB address */ 206fe56b9e6SYuval Mintz mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, 207fe56b9e6SYuval Mintz SECTION_OFFSIZE_ADDR(p_info->public_base, 208fe56b9e6SYuval Mintz PUBLIC_MFW_MB)); 209fe56b9e6SYuval Mintz p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); 210fe56b9e6SYuval Mintz p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr); 211fe56b9e6SYuval Mintz 212fe56b9e6SYuval Mintz /* Get the current driver mailbox sequence before sending 213fe56b9e6SYuval Mintz * the first command 214fe56b9e6SYuval Mintz */ 215fe56b9e6SYuval Mintz p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) & 216fe56b9e6SYuval Mintz DRV_MSG_SEQ_NUMBER_MASK; 217fe56b9e6SYuval Mintz 218fe56b9e6SYuval Mintz /* Get current FW pulse sequence */ 219fe56b9e6SYuval Mintz p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) & 220fe56b9e6SYuval Mintz DRV_PULSE_SEQ_MASK; 221fe56b9e6SYuval Mintz 2224ed1eea8STomer Tayar p_info->mcp_hist = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 223fe56b9e6SYuval Mintz 224fe56b9e6SYuval Mintz return 0; 225fe56b9e6SYuval Mintz } 226fe56b9e6SYuval Mintz 2271a635e48SYuval Mintz int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 228fe56b9e6SYuval Mintz { 229fe56b9e6SYuval Mintz struct qed_mcp_info *p_info; 230fe56b9e6SYuval Mintz u32 size; 231fe56b9e6SYuval Mintz 232fe56b9e6SYuval Mintz /* Allocate mcp_info structure */ 23360fffb3bSYuval Mintz p_hwfn->mcp_info = kzalloc(sizeof(*p_hwfn->mcp_info), GFP_KERNEL); 234fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info) 235fe56b9e6SYuval Mintz goto err; 236fe56b9e6SYuval Mintz p_info = p_hwfn->mcp_info; 237fe56b9e6SYuval Mintz 2384ed1eea8STomer Tayar /* Initialize the MFW spinlock */ 2394ed1eea8STomer Tayar spin_lock_init(&p_info->cmd_lock); 2404ed1eea8STomer Tayar spin_lock_init(&p_info->link_lock); 2414ed1eea8STomer Tayar 2424ed1eea8STomer Tayar INIT_LIST_HEAD(&p_info->cmd_list); 2434ed1eea8STomer Tayar 244fe56b9e6SYuval Mintz if (qed_load_mcp_offsets(p_hwfn, p_ptt) != 0) { 245fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MCP is not initialized\n"); 246fe56b9e6SYuval Mintz /* Do not free mcp_info here, since public_base indicate that 247fe56b9e6SYuval Mintz * the MCP is not initialized 248fe56b9e6SYuval Mintz */ 249fe56b9e6SYuval Mintz return 0; 250fe56b9e6SYuval Mintz } 251fe56b9e6SYuval Mintz 252fe56b9e6SYuval Mintz size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32); 25360fffb3bSYuval Mintz p_info->mfw_mb_cur = kzalloc(size, GFP_KERNEL); 25483aeb933SYuval Mintz p_info->mfw_mb_shadow = kzalloc(size, GFP_KERNEL); 255fe56b9e6SYuval Mintz if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr) 256fe56b9e6SYuval Mintz goto err; 257fe56b9e6SYuval Mintz 258fe56b9e6SYuval Mintz return 0; 259fe56b9e6SYuval Mintz 260fe56b9e6SYuval Mintz err: 261fe56b9e6SYuval Mintz qed_mcp_free(p_hwfn); 262fe56b9e6SYuval Mintz return -ENOMEM; 263fe56b9e6SYuval Mintz } 264fe56b9e6SYuval Mintz 2654ed1eea8STomer Tayar static void qed_mcp_reread_offsets(struct qed_hwfn *p_hwfn, 2664ed1eea8STomer Tayar struct qed_ptt *p_ptt) 2675529bad9STomer Tayar { 2684ed1eea8STomer Tayar u32 generic_por_0 = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 2695529bad9STomer Tayar 2704ed1eea8STomer Tayar /* Use MCP history register to check if MCP reset occurred between init 2714ed1eea8STomer Tayar * time and now. 2725529bad9STomer Tayar */ 2734ed1eea8STomer Tayar if (p_hwfn->mcp_info->mcp_hist != generic_por_0) { 2744ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, 2754ed1eea8STomer Tayar QED_MSG_SP, 2764ed1eea8STomer Tayar "Rereading MCP offsets [mcp_hist 0x%08x, generic_por_0 0x%08x]\n", 2774ed1eea8STomer Tayar p_hwfn->mcp_info->mcp_hist, generic_por_0); 2785529bad9STomer Tayar 2794ed1eea8STomer Tayar qed_load_mcp_offsets(p_hwfn, p_ptt); 2804ed1eea8STomer Tayar qed_mcp_cmd_port_init(p_hwfn, p_ptt); 2815529bad9STomer Tayar } 2825529bad9STomer Tayar } 2835529bad9STomer Tayar 2841a635e48SYuval Mintz int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 285fe56b9e6SYuval Mintz { 2864ed1eea8STomer Tayar u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0; 287fe56b9e6SYuval Mintz int rc = 0; 288fe56b9e6SYuval Mintz 2894ed1eea8STomer Tayar /* Ensure that only a single thread is accessing the mailbox */ 2904ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 2914ed1eea8STomer Tayar 2924ed1eea8STomer Tayar org_mcp_reset_seq = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 2935529bad9STomer Tayar 294fe56b9e6SYuval Mintz /* Set drv command along with the updated sequence */ 2954ed1eea8STomer Tayar qed_mcp_reread_offsets(p_hwfn, p_ptt); 2964ed1eea8STomer Tayar seq = ++p_hwfn->mcp_info->drv_mb_seq; 2974ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (DRV_MSG_CODE_MCP_RESET | seq)); 298fe56b9e6SYuval Mintz 299fe56b9e6SYuval Mintz do { 300fe56b9e6SYuval Mintz /* Wait for MFW response */ 301fe56b9e6SYuval Mintz udelay(delay); 302fe56b9e6SYuval Mintz /* Give the FW up to 500 second (50*1000*10usec) */ 303fe56b9e6SYuval Mintz } while ((org_mcp_reset_seq == qed_rd(p_hwfn, p_ptt, 304fe56b9e6SYuval Mintz MISCS_REG_GENERIC_POR_0)) && 305fe56b9e6SYuval Mintz (cnt++ < QED_MCP_RESET_RETRIES)); 306fe56b9e6SYuval Mintz 307fe56b9e6SYuval Mintz if (org_mcp_reset_seq != 308fe56b9e6SYuval Mintz qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) { 309fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 310fe56b9e6SYuval Mintz "MCP was reset after %d usec\n", cnt * delay); 311fe56b9e6SYuval Mintz } else { 312fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Failed to reset MCP\n"); 313fe56b9e6SYuval Mintz rc = -EAGAIN; 314fe56b9e6SYuval Mintz } 315fe56b9e6SYuval Mintz 3164ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 3175529bad9STomer Tayar 318fe56b9e6SYuval Mintz return rc; 319fe56b9e6SYuval Mintz } 320fe56b9e6SYuval Mintz 3214ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3224ed1eea8STomer Tayar static bool qed_mcp_has_pending_cmd(struct qed_hwfn *p_hwfn) 323fe56b9e6SYuval Mintz { 3244ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 3254ed1eea8STomer Tayar 3264ed1eea8STomer Tayar /* There is at most one pending command at a certain time, and if it 3274ed1eea8STomer Tayar * exists - it is placed at the HEAD of the list. 3284ed1eea8STomer Tayar */ 3294ed1eea8STomer Tayar if (!list_empty(&p_hwfn->mcp_info->cmd_list)) { 3304ed1eea8STomer Tayar p_cmd_elem = list_first_entry(&p_hwfn->mcp_info->cmd_list, 3314ed1eea8STomer Tayar struct qed_mcp_cmd_elem, list); 3324ed1eea8STomer Tayar return !p_cmd_elem->b_is_completed; 3334ed1eea8STomer Tayar } 3344ed1eea8STomer Tayar 3354ed1eea8STomer Tayar return false; 3364ed1eea8STomer Tayar } 3374ed1eea8STomer Tayar 3384ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3394ed1eea8STomer Tayar static int 3404ed1eea8STomer Tayar qed_mcp_update_pending_cmd(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 3414ed1eea8STomer Tayar { 3424ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params; 3434ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 3444ed1eea8STomer Tayar u32 mcp_resp; 3454ed1eea8STomer Tayar u16 seq_num; 3464ed1eea8STomer Tayar 3474ed1eea8STomer Tayar mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header); 3484ed1eea8STomer Tayar seq_num = (u16)(mcp_resp & FW_MSG_SEQ_NUMBER_MASK); 3494ed1eea8STomer Tayar 3504ed1eea8STomer Tayar /* Return if no new non-handled response has been received */ 3514ed1eea8STomer Tayar if (seq_num != p_hwfn->mcp_info->drv_mb_seq) 3524ed1eea8STomer Tayar return -EAGAIN; 3534ed1eea8STomer Tayar 3544ed1eea8STomer Tayar p_cmd_elem = qed_mcp_cmd_get_elem(p_hwfn, seq_num); 3554ed1eea8STomer Tayar if (!p_cmd_elem) { 3564ed1eea8STomer Tayar DP_ERR(p_hwfn, 3574ed1eea8STomer Tayar "Failed to find a pending mailbox cmd that expects sequence number %d\n", 3584ed1eea8STomer Tayar seq_num); 3594ed1eea8STomer Tayar return -EINVAL; 3604ed1eea8STomer Tayar } 3614ed1eea8STomer Tayar 3624ed1eea8STomer Tayar p_mb_params = p_cmd_elem->p_mb_params; 3634ed1eea8STomer Tayar 3644ed1eea8STomer Tayar /* Get the MFW response along with the sequence number */ 3654ed1eea8STomer Tayar p_mb_params->mcp_resp = mcp_resp; 3664ed1eea8STomer Tayar 3674ed1eea8STomer Tayar /* Get the MFW param */ 3684ed1eea8STomer Tayar p_mb_params->mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param); 3694ed1eea8STomer Tayar 3704ed1eea8STomer Tayar /* Get the union data */ 3712f67af8cSTomer Tayar if (p_mb_params->p_data_dst != NULL && p_mb_params->data_dst_size) { 3724ed1eea8STomer Tayar u32 union_data_addr = p_hwfn->mcp_info->drv_mb_addr + 3734ed1eea8STomer Tayar offsetof(struct public_drv_mb, 3744ed1eea8STomer Tayar union_data); 3754ed1eea8STomer Tayar qed_memcpy_from(p_hwfn, p_ptt, p_mb_params->p_data_dst, 3762f67af8cSTomer Tayar union_data_addr, p_mb_params->data_dst_size); 3774ed1eea8STomer Tayar } 3784ed1eea8STomer Tayar 3794ed1eea8STomer Tayar p_cmd_elem->b_is_completed = true; 3804ed1eea8STomer Tayar 3814ed1eea8STomer Tayar return 0; 3824ed1eea8STomer Tayar } 3834ed1eea8STomer Tayar 3844ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3854ed1eea8STomer Tayar static void __qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 3864ed1eea8STomer Tayar struct qed_ptt *p_ptt, 3874ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 3884ed1eea8STomer Tayar u16 seq_num) 3894ed1eea8STomer Tayar { 3904ed1eea8STomer Tayar union drv_union_data union_data; 3914ed1eea8STomer Tayar u32 union_data_addr; 3924ed1eea8STomer Tayar 3934ed1eea8STomer Tayar /* Set the union data */ 3944ed1eea8STomer Tayar union_data_addr = p_hwfn->mcp_info->drv_mb_addr + 3954ed1eea8STomer Tayar offsetof(struct public_drv_mb, union_data); 3964ed1eea8STomer Tayar memset(&union_data, 0, sizeof(union_data)); 3972f67af8cSTomer Tayar if (p_mb_params->p_data_src != NULL && p_mb_params->data_src_size) 3984ed1eea8STomer Tayar memcpy(&union_data, p_mb_params->p_data_src, 3992f67af8cSTomer Tayar p_mb_params->data_src_size); 4004ed1eea8STomer Tayar qed_memcpy_to(p_hwfn, p_ptt, union_data_addr, &union_data, 4014ed1eea8STomer Tayar sizeof(union_data)); 4024ed1eea8STomer Tayar 4034ed1eea8STomer Tayar /* Set the drv param */ 4044ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, p_mb_params->param); 4054ed1eea8STomer Tayar 4064ed1eea8STomer Tayar /* Set the drv command along with the sequence number */ 4074ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (p_mb_params->cmd | seq_num)); 4084ed1eea8STomer Tayar 4094ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 4104ed1eea8STomer Tayar "MFW mailbox: command 0x%08x param 0x%08x\n", 4114ed1eea8STomer Tayar (p_mb_params->cmd | seq_num), p_mb_params->param); 4124ed1eea8STomer Tayar } 4134ed1eea8STomer Tayar 4144ed1eea8STomer Tayar static int 4154ed1eea8STomer Tayar _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 4164ed1eea8STomer Tayar struct qed_ptt *p_ptt, 4174ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 4184ed1eea8STomer Tayar u32 max_retries, u32 delay) 4194ed1eea8STomer Tayar { 4204ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 4214ed1eea8STomer Tayar u32 cnt = 0; 4224ed1eea8STomer Tayar u16 seq_num; 423fe56b9e6SYuval Mintz int rc = 0; 424fe56b9e6SYuval Mintz 4254ed1eea8STomer Tayar /* Wait until the mailbox is non-occupied */ 426fe56b9e6SYuval Mintz do { 4274ed1eea8STomer Tayar /* Exit the loop if there is no pending command, or if the 4284ed1eea8STomer Tayar * pending command is completed during this iteration. 4294ed1eea8STomer Tayar * The spinlock stays locked until the command is sent. 4304ed1eea8STomer Tayar */ 4314ed1eea8STomer Tayar 4324ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4334ed1eea8STomer Tayar 4344ed1eea8STomer Tayar if (!qed_mcp_has_pending_cmd(p_hwfn)) 4354ed1eea8STomer Tayar break; 4364ed1eea8STomer Tayar 4374ed1eea8STomer Tayar rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt); 4384ed1eea8STomer Tayar if (!rc) 4394ed1eea8STomer Tayar break; 4404ed1eea8STomer Tayar else if (rc != -EAGAIN) 4414ed1eea8STomer Tayar goto err; 4424ed1eea8STomer Tayar 4434ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 444fe56b9e6SYuval Mintz udelay(delay); 4454ed1eea8STomer Tayar } while (++cnt < max_retries); 446fe56b9e6SYuval Mintz 4474ed1eea8STomer Tayar if (cnt >= max_retries) { 4484ed1eea8STomer Tayar DP_NOTICE(p_hwfn, 4494ed1eea8STomer Tayar "The MFW mailbox is occupied by an uncompleted command. Failed to send command 0x%08x [param 0x%08x].\n", 4504ed1eea8STomer Tayar p_mb_params->cmd, p_mb_params->param); 4514ed1eea8STomer Tayar return -EAGAIN; 452fe56b9e6SYuval Mintz } 4534ed1eea8STomer Tayar 4544ed1eea8STomer Tayar /* Send the mailbox command */ 4554ed1eea8STomer Tayar qed_mcp_reread_offsets(p_hwfn, p_ptt); 4564ed1eea8STomer Tayar seq_num = ++p_hwfn->mcp_info->drv_mb_seq; 4574ed1eea8STomer Tayar p_cmd_elem = qed_mcp_cmd_add_elem(p_hwfn, p_mb_params, seq_num); 4584ed1eea8STomer Tayar if (!p_cmd_elem) 4594ed1eea8STomer Tayar goto err; 4604ed1eea8STomer Tayar 4614ed1eea8STomer Tayar __qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, seq_num); 4624ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4634ed1eea8STomer Tayar 4644ed1eea8STomer Tayar /* Wait for the MFW response */ 4654ed1eea8STomer Tayar do { 4664ed1eea8STomer Tayar /* Exit the loop if the command is already completed, or if the 4674ed1eea8STomer Tayar * command is completed during this iteration. 4684ed1eea8STomer Tayar * The spinlock stays locked until the list element is removed. 4694ed1eea8STomer Tayar */ 4704ed1eea8STomer Tayar 4714ed1eea8STomer Tayar udelay(delay); 4724ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4734ed1eea8STomer Tayar 4744ed1eea8STomer Tayar if (p_cmd_elem->b_is_completed) 4754ed1eea8STomer Tayar break; 4764ed1eea8STomer Tayar 4774ed1eea8STomer Tayar rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt); 4784ed1eea8STomer Tayar if (!rc) 4794ed1eea8STomer Tayar break; 4804ed1eea8STomer Tayar else if (rc != -EAGAIN) 4814ed1eea8STomer Tayar goto err; 4824ed1eea8STomer Tayar 4834ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4844ed1eea8STomer Tayar } while (++cnt < max_retries); 4854ed1eea8STomer Tayar 4864ed1eea8STomer Tayar if (cnt >= max_retries) { 4874ed1eea8STomer Tayar DP_NOTICE(p_hwfn, 4884ed1eea8STomer Tayar "The MFW failed to respond to command 0x%08x [param 0x%08x].\n", 4894ed1eea8STomer Tayar p_mb_params->cmd, p_mb_params->param); 4904ed1eea8STomer Tayar 4914ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4924ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 4934ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4944ed1eea8STomer Tayar 4954ed1eea8STomer Tayar return -EAGAIN; 4964ed1eea8STomer Tayar } 4974ed1eea8STomer Tayar 4984ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 4994ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 5004ed1eea8STomer Tayar 5014ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, 5024ed1eea8STomer Tayar QED_MSG_SP, 5034ed1eea8STomer Tayar "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n", 5044ed1eea8STomer Tayar p_mb_params->mcp_resp, 5054ed1eea8STomer Tayar p_mb_params->mcp_param, 5064ed1eea8STomer Tayar (cnt * delay) / 1000, (cnt * delay) % 1000); 5074ed1eea8STomer Tayar 5084ed1eea8STomer Tayar /* Clear the sequence number from the MFW response */ 5094ed1eea8STomer Tayar p_mb_params->mcp_resp &= FW_MSG_CODE_MASK; 5104ed1eea8STomer Tayar 5114ed1eea8STomer Tayar return 0; 5124ed1eea8STomer Tayar 5134ed1eea8STomer Tayar err: 5144ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 515fe56b9e6SYuval Mintz return rc; 516fe56b9e6SYuval Mintz } 517fe56b9e6SYuval Mintz 5185529bad9STomer Tayar static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 519fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 5205529bad9STomer Tayar struct qed_mcp_mb_params *p_mb_params) 521fe56b9e6SYuval Mintz { 5222f67af8cSTomer Tayar size_t union_data_size = sizeof(union drv_union_data); 5234ed1eea8STomer Tayar u32 max_retries = QED_DRV_MB_MAX_RETRIES; 5244ed1eea8STomer Tayar u32 delay = CHIP_MCP_RESP_ITER_US; 525fe56b9e6SYuval Mintz 526fe56b9e6SYuval Mintz /* MCP not initialized */ 527fe56b9e6SYuval Mintz if (!qed_mcp_is_init(p_hwfn)) { 528fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MFW is not initialized!\n"); 529fe56b9e6SYuval Mintz return -EBUSY; 530fe56b9e6SYuval Mintz } 531fe56b9e6SYuval Mintz 5322f67af8cSTomer Tayar if (p_mb_params->data_src_size > union_data_size || 5332f67af8cSTomer Tayar p_mb_params->data_dst_size > union_data_size) { 5342f67af8cSTomer Tayar DP_ERR(p_hwfn, 5352f67af8cSTomer Tayar "The provided size is larger than the union data size [src_size %u, dst_size %u, union_data_size %zu]\n", 5362f67af8cSTomer Tayar p_mb_params->data_src_size, 5372f67af8cSTomer Tayar p_mb_params->data_dst_size, union_data_size); 5382f67af8cSTomer Tayar return -EINVAL; 5392f67af8cSTomer Tayar } 5402f67af8cSTomer Tayar 5414ed1eea8STomer Tayar return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries, 5424ed1eea8STomer Tayar delay); 543fe56b9e6SYuval Mintz } 544fe56b9e6SYuval Mintz 5455529bad9STomer Tayar int qed_mcp_cmd(struct qed_hwfn *p_hwfn, 5465529bad9STomer Tayar struct qed_ptt *p_ptt, 5475529bad9STomer Tayar u32 cmd, 5485529bad9STomer Tayar u32 param, 5495529bad9STomer Tayar u32 *o_mcp_resp, 5505529bad9STomer Tayar u32 *o_mcp_param) 551fe56b9e6SYuval Mintz { 5525529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 5532f67af8cSTomer Tayar struct mcp_mac wol_mac; 5545529bad9STomer Tayar int rc; 555fe56b9e6SYuval Mintz 5565529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 5575529bad9STomer Tayar mb_params.cmd = cmd; 5585529bad9STomer Tayar mb_params.param = param; 55914d39648SMintz, Yuval 56014d39648SMintz, Yuval /* In case of UNLOAD_DONE, set the primary MAC */ 56114d39648SMintz, Yuval if ((cmd == DRV_MSG_CODE_UNLOAD_DONE) && 56214d39648SMintz, Yuval (p_hwfn->cdev->wol_config == QED_OV_WOL_ENABLED)) { 56314d39648SMintz, Yuval u8 *p_mac = p_hwfn->cdev->wol_mac; 56414d39648SMintz, Yuval 5652f67af8cSTomer Tayar memset(&wol_mac, 0, sizeof(wol_mac)); 5662f67af8cSTomer Tayar wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1]; 5672f67af8cSTomer Tayar wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 | 56814d39648SMintz, Yuval p_mac[4] << 8 | p_mac[5]; 56914d39648SMintz, Yuval 57014d39648SMintz, Yuval DP_VERBOSE(p_hwfn, 57114d39648SMintz, Yuval (QED_MSG_SP | NETIF_MSG_IFDOWN), 57214d39648SMintz, Yuval "Setting WoL MAC: %pM --> [%08x,%08x]\n", 5732f67af8cSTomer Tayar p_mac, wol_mac.mac_upper, wol_mac.mac_lower); 57414d39648SMintz, Yuval 5752f67af8cSTomer Tayar mb_params.p_data_src = &wol_mac; 5762f67af8cSTomer Tayar mb_params.data_src_size = sizeof(wol_mac); 57714d39648SMintz, Yuval } 57814d39648SMintz, Yuval 5795529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 5805529bad9STomer Tayar if (rc) 5815529bad9STomer Tayar return rc; 5825529bad9STomer Tayar 5835529bad9STomer Tayar *o_mcp_resp = mb_params.mcp_resp; 5845529bad9STomer Tayar *o_mcp_param = mb_params.mcp_param; 5855529bad9STomer Tayar 5865529bad9STomer Tayar return 0; 587fe56b9e6SYuval Mintz } 588fe56b9e6SYuval Mintz 5894102426fSTomer Tayar int qed_mcp_nvm_rd_cmd(struct qed_hwfn *p_hwfn, 5904102426fSTomer Tayar struct qed_ptt *p_ptt, 5914102426fSTomer Tayar u32 cmd, 5924102426fSTomer Tayar u32 param, 5934102426fSTomer Tayar u32 *o_mcp_resp, 5944102426fSTomer Tayar u32 *o_mcp_param, u32 *o_txn_size, u32 *o_buf) 5954102426fSTomer Tayar { 5964102426fSTomer Tayar struct qed_mcp_mb_params mb_params; 5972f67af8cSTomer Tayar u8 raw_data[MCP_DRV_NVM_BUF_LEN]; 5984102426fSTomer Tayar int rc; 5994102426fSTomer Tayar 6004102426fSTomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 6014102426fSTomer Tayar mb_params.cmd = cmd; 6024102426fSTomer Tayar mb_params.param = param; 6032f67af8cSTomer Tayar mb_params.p_data_dst = raw_data; 6042f67af8cSTomer Tayar 6052f67af8cSTomer Tayar /* Use the maximal value since the actual one is part of the response */ 6062f67af8cSTomer Tayar mb_params.data_dst_size = MCP_DRV_NVM_BUF_LEN; 6072f67af8cSTomer Tayar 6084102426fSTomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 6094102426fSTomer Tayar if (rc) 6104102426fSTomer Tayar return rc; 6114102426fSTomer Tayar 6124102426fSTomer Tayar *o_mcp_resp = mb_params.mcp_resp; 6134102426fSTomer Tayar *o_mcp_param = mb_params.mcp_param; 6144102426fSTomer Tayar 6154102426fSTomer Tayar *o_txn_size = *o_mcp_param; 6162f67af8cSTomer Tayar memcpy(o_buf, raw_data, *o_txn_size); 6174102426fSTomer Tayar 6184102426fSTomer Tayar return 0; 6194102426fSTomer Tayar } 6204102426fSTomer Tayar 621fe56b9e6SYuval Mintz int qed_mcp_load_req(struct qed_hwfn *p_hwfn, 6221a635e48SYuval Mintz struct qed_ptt *p_ptt, u32 *p_load_code) 623fe56b9e6SYuval Mintz { 624fe56b9e6SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 6255529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 6265529bad9STomer Tayar union drv_union_data union_data; 627fe56b9e6SYuval Mintz int rc; 628fe56b9e6SYuval Mintz 6295529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 630fe56b9e6SYuval Mintz /* Load Request */ 6315529bad9STomer Tayar mb_params.cmd = DRV_MSG_CODE_LOAD_REQ; 6325529bad9STomer Tayar mb_params.param = PDA_COMP | DRV_ID_MCP_HSI_VER_CURRENT | 6335529bad9STomer Tayar cdev->drv_type; 6345529bad9STomer Tayar memcpy(&union_data.ver_str, cdev->ver_str, MCP_DRV_VER_STR_SIZE); 6355529bad9STomer Tayar mb_params.p_data_src = &union_data; 6362f67af8cSTomer Tayar mb_params.data_src_size = sizeof(union_data.ver_str); 6375529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 638fe56b9e6SYuval Mintz 639fe56b9e6SYuval Mintz /* if mcp fails to respond we must abort */ 640fe56b9e6SYuval Mintz if (rc) { 641fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 642fe56b9e6SYuval Mintz return rc; 643fe56b9e6SYuval Mintz } 644fe56b9e6SYuval Mintz 6455529bad9STomer Tayar *p_load_code = mb_params.mcp_resp; 6465529bad9STomer Tayar 647fe56b9e6SYuval Mintz /* If MFW refused (e.g. other port is in diagnostic mode) we 648fe56b9e6SYuval Mintz * must abort. This can happen in the following cases: 649fe56b9e6SYuval Mintz * - Other port is in diagnostic mode 650fe56b9e6SYuval Mintz * - Previously loaded function on the engine is not compliant with 651fe56b9e6SYuval Mintz * the requester. 652fe56b9e6SYuval Mintz * - MFW cannot cope with the requester's DRV_MFW_HSI_VERSION. 653fe56b9e6SYuval Mintz * - 654fe56b9e6SYuval Mintz */ 655fe56b9e6SYuval Mintz if (!(*p_load_code) || 656fe56b9e6SYuval Mintz ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI) || 657fe56b9e6SYuval Mintz ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_PDA) || 658fe56b9e6SYuval Mintz ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG)) { 659fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "MCP refused load request, aborting\n"); 660fe56b9e6SYuval Mintz return -EBUSY; 661fe56b9e6SYuval Mintz } 662fe56b9e6SYuval Mintz 663fe56b9e6SYuval Mintz return 0; 664fe56b9e6SYuval Mintz } 665fe56b9e6SYuval Mintz 6660b55e27dSYuval Mintz static void qed_mcp_handle_vf_flr(struct qed_hwfn *p_hwfn, 6670b55e27dSYuval Mintz struct qed_ptt *p_ptt) 6680b55e27dSYuval Mintz { 6690b55e27dSYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 6700b55e27dSYuval Mintz PUBLIC_PATH); 6710b55e27dSYuval Mintz u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); 6720b55e27dSYuval Mintz u32 path_addr = SECTION_ADDR(mfw_path_offsize, 6730b55e27dSYuval Mintz QED_PATH_ID(p_hwfn)); 6740b55e27dSYuval Mintz u32 disabled_vfs[VF_MAX_STATIC / 32]; 6750b55e27dSYuval Mintz int i; 6760b55e27dSYuval Mintz 6770b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, 6780b55e27dSYuval Mintz QED_MSG_SP, 6790b55e27dSYuval Mintz "Reading Disabled VF information from [offset %08x], path_addr %08x\n", 6800b55e27dSYuval Mintz mfw_path_offsize, path_addr); 6810b55e27dSYuval Mintz 6820b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) { 6830b55e27dSYuval Mintz disabled_vfs[i] = qed_rd(p_hwfn, p_ptt, 6840b55e27dSYuval Mintz path_addr + 6850b55e27dSYuval Mintz offsetof(struct public_path, 6860b55e27dSYuval Mintz mcp_vf_disabled) + 6870b55e27dSYuval Mintz sizeof(u32) * i); 6880b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | QED_MSG_IOV), 6890b55e27dSYuval Mintz "FLR-ed VFs [%08x,...,%08x] - %08x\n", 6900b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, disabled_vfs[i]); 6910b55e27dSYuval Mintz } 6920b55e27dSYuval Mintz 6930b55e27dSYuval Mintz if (qed_iov_mark_vf_flr(p_hwfn, disabled_vfs)) 6940b55e27dSYuval Mintz qed_schedule_iov(p_hwfn, QED_IOV_WQ_FLR_FLAG); 6950b55e27dSYuval Mintz } 6960b55e27dSYuval Mintz 6970b55e27dSYuval Mintz int qed_mcp_ack_vf_flr(struct qed_hwfn *p_hwfn, 6980b55e27dSYuval Mintz struct qed_ptt *p_ptt, u32 *vfs_to_ack) 6990b55e27dSYuval Mintz { 7000b55e27dSYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 7010b55e27dSYuval Mintz PUBLIC_FUNC); 7020b55e27dSYuval Mintz u32 mfw_func_offsize = qed_rd(p_hwfn, p_ptt, addr); 7030b55e27dSYuval Mintz u32 func_addr = SECTION_ADDR(mfw_func_offsize, 7040b55e27dSYuval Mintz MCP_PF_ID(p_hwfn)); 7050b55e27dSYuval Mintz struct qed_mcp_mb_params mb_params; 7060b55e27dSYuval Mintz int rc; 7070b55e27dSYuval Mintz int i; 7080b55e27dSYuval Mintz 7090b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 7100b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | QED_MSG_IOV), 7110b55e27dSYuval Mintz "Acking VFs [%08x,...,%08x] - %08x\n", 7120b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, vfs_to_ack[i]); 7130b55e27dSYuval Mintz 7140b55e27dSYuval Mintz memset(&mb_params, 0, sizeof(mb_params)); 7150b55e27dSYuval Mintz mb_params.cmd = DRV_MSG_CODE_VF_DISABLED_DONE; 7162f67af8cSTomer Tayar mb_params.p_data_src = vfs_to_ack; 7172f67af8cSTomer Tayar mb_params.data_src_size = VF_MAX_STATIC / 8; 7180b55e27dSYuval Mintz rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 7190b55e27dSYuval Mintz if (rc) { 7200b55e27dSYuval Mintz DP_NOTICE(p_hwfn, "Failed to pass ACK for VF flr to MFW\n"); 7210b55e27dSYuval Mintz return -EBUSY; 7220b55e27dSYuval Mintz } 7230b55e27dSYuval Mintz 7240b55e27dSYuval Mintz /* Clear the ACK bits */ 7250b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 7260b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, 7270b55e27dSYuval Mintz func_addr + 7280b55e27dSYuval Mintz offsetof(struct public_func, drv_ack_vf_disabled) + 7290b55e27dSYuval Mintz i * sizeof(u32), 0); 7300b55e27dSYuval Mintz 7310b55e27dSYuval Mintz return rc; 7320b55e27dSYuval Mintz } 7330b55e27dSYuval Mintz 734334c03b5SZvi Nachmani static void qed_mcp_handle_transceiver_change(struct qed_hwfn *p_hwfn, 735334c03b5SZvi Nachmani struct qed_ptt *p_ptt) 736334c03b5SZvi Nachmani { 737334c03b5SZvi Nachmani u32 transceiver_state; 738334c03b5SZvi Nachmani 739334c03b5SZvi Nachmani transceiver_state = qed_rd(p_hwfn, p_ptt, 740334c03b5SZvi Nachmani p_hwfn->mcp_info->port_addr + 741334c03b5SZvi Nachmani offsetof(struct public_port, 742334c03b5SZvi Nachmani transceiver_data)); 743334c03b5SZvi Nachmani 744334c03b5SZvi Nachmani DP_VERBOSE(p_hwfn, 745334c03b5SZvi Nachmani (NETIF_MSG_HW | QED_MSG_SP), 746334c03b5SZvi Nachmani "Received transceiver state update [0x%08x] from mfw [Addr 0x%x]\n", 747334c03b5SZvi Nachmani transceiver_state, 748334c03b5SZvi Nachmani (u32)(p_hwfn->mcp_info->port_addr + 7491a635e48SYuval Mintz offsetof(struct public_port, transceiver_data))); 750334c03b5SZvi Nachmani 751334c03b5SZvi Nachmani transceiver_state = GET_FIELD(transceiver_state, 752351a4dedSYuval Mintz ETH_TRANSCEIVER_STATE); 753334c03b5SZvi Nachmani 754351a4dedSYuval Mintz if (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT) 755334c03b5SZvi Nachmani DP_NOTICE(p_hwfn, "Transceiver is present.\n"); 756334c03b5SZvi Nachmani else 757334c03b5SZvi Nachmani DP_NOTICE(p_hwfn, "Transceiver is unplugged.\n"); 758334c03b5SZvi Nachmani } 759334c03b5SZvi Nachmani 760cc875c2eSYuval Mintz static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, 7611a635e48SYuval Mintz struct qed_ptt *p_ptt, bool b_reset) 762cc875c2eSYuval Mintz { 763cc875c2eSYuval Mintz struct qed_mcp_link_state *p_link; 764a64b02d5SManish Chopra u8 max_bw, min_bw; 765cc875c2eSYuval Mintz u32 status = 0; 766cc875c2eSYuval Mintz 76765ed2ffdSMintz, Yuval /* Prevent SW/attentions from doing this at the same time */ 76865ed2ffdSMintz, Yuval spin_lock_bh(&p_hwfn->mcp_info->link_lock); 76965ed2ffdSMintz, Yuval 770cc875c2eSYuval Mintz p_link = &p_hwfn->mcp_info->link_output; 771cc875c2eSYuval Mintz memset(p_link, 0, sizeof(*p_link)); 772cc875c2eSYuval Mintz if (!b_reset) { 773cc875c2eSYuval Mintz status = qed_rd(p_hwfn, p_ptt, 774cc875c2eSYuval Mintz p_hwfn->mcp_info->port_addr + 775cc875c2eSYuval Mintz offsetof(struct public_port, link_status)); 776cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, (NETIF_MSG_LINK | QED_MSG_SP), 777cc875c2eSYuval Mintz "Received link update [0x%08x] from mfw [Addr 0x%x]\n", 778cc875c2eSYuval Mintz status, 779cc875c2eSYuval Mintz (u32)(p_hwfn->mcp_info->port_addr + 7801a635e48SYuval Mintz offsetof(struct public_port, link_status))); 781cc875c2eSYuval Mintz } else { 782cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 783cc875c2eSYuval Mintz "Resetting link indications\n"); 78465ed2ffdSMintz, Yuval goto out; 785cc875c2eSYuval Mintz } 786cc875c2eSYuval Mintz 787fc916ff2SSudarsana Reddy Kalluru if (p_hwfn->b_drv_link_init) 788cc875c2eSYuval Mintz p_link->link_up = !!(status & LINK_STATUS_LINK_UP); 789fc916ff2SSudarsana Reddy Kalluru else 790fc916ff2SSudarsana Reddy Kalluru p_link->link_up = false; 791cc875c2eSYuval Mintz 792cc875c2eSYuval Mintz p_link->full_duplex = true; 793cc875c2eSYuval Mintz switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) { 794cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_100G: 795cc875c2eSYuval Mintz p_link->speed = 100000; 796cc875c2eSYuval Mintz break; 797cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_50G: 798cc875c2eSYuval Mintz p_link->speed = 50000; 799cc875c2eSYuval Mintz break; 800cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_40G: 801cc875c2eSYuval Mintz p_link->speed = 40000; 802cc875c2eSYuval Mintz break; 803cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_25G: 804cc875c2eSYuval Mintz p_link->speed = 25000; 805cc875c2eSYuval Mintz break; 806cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_20G: 807cc875c2eSYuval Mintz p_link->speed = 20000; 808cc875c2eSYuval Mintz break; 809cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_10G: 810cc875c2eSYuval Mintz p_link->speed = 10000; 811cc875c2eSYuval Mintz break; 812cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_1000THD: 813cc875c2eSYuval Mintz p_link->full_duplex = false; 814cc875c2eSYuval Mintz /* Fall-through */ 815cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD: 816cc875c2eSYuval Mintz p_link->speed = 1000; 817cc875c2eSYuval Mintz break; 818cc875c2eSYuval Mintz default: 819cc875c2eSYuval Mintz p_link->speed = 0; 820cc875c2eSYuval Mintz } 821cc875c2eSYuval Mintz 8224b01e519SManish Chopra if (p_link->link_up && p_link->speed) 8234b01e519SManish Chopra p_link->line_speed = p_link->speed; 8244b01e519SManish Chopra else 8254b01e519SManish Chopra p_link->line_speed = 0; 8264b01e519SManish Chopra 8274b01e519SManish Chopra max_bw = p_hwfn->mcp_info->func_info.bandwidth_max; 828a64b02d5SManish Chopra min_bw = p_hwfn->mcp_info->func_info.bandwidth_min; 8294b01e519SManish Chopra 830a64b02d5SManish Chopra /* Max bandwidth configuration */ 8314b01e519SManish Chopra __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw); 832cc875c2eSYuval Mintz 833a64b02d5SManish Chopra /* Min bandwidth configuration */ 834a64b02d5SManish Chopra __qed_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw); 8356f437d43SMintz, Yuval qed_configure_vp_wfq_on_link_change(p_hwfn->cdev, p_ptt, 8366f437d43SMintz, Yuval p_link->min_pf_rate); 837a64b02d5SManish Chopra 838cc875c2eSYuval Mintz p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED); 839cc875c2eSYuval Mintz p_link->an_complete = !!(status & 840cc875c2eSYuval Mintz LINK_STATUS_AUTO_NEGOTIATE_COMPLETE); 841cc875c2eSYuval Mintz p_link->parallel_detection = !!(status & 842cc875c2eSYuval Mintz LINK_STATUS_PARALLEL_DETECTION_USED); 843cc875c2eSYuval Mintz p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED); 844cc875c2eSYuval Mintz 845cc875c2eSYuval Mintz p_link->partner_adv_speed |= 846cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ? 847cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_1G_FD : 0; 848cc875c2eSYuval Mintz p_link->partner_adv_speed |= 849cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ? 850cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_1G_HD : 0; 851cc875c2eSYuval Mintz p_link->partner_adv_speed |= 852cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ? 853cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_10G : 0; 854cc875c2eSYuval Mintz p_link->partner_adv_speed |= 855cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ? 856cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_20G : 0; 857cc875c2eSYuval Mintz p_link->partner_adv_speed |= 858054c67d1SSudarsana Reddy Kalluru (status & LINK_STATUS_LINK_PARTNER_25G_CAPABLE) ? 859054c67d1SSudarsana Reddy Kalluru QED_LINK_PARTNER_SPEED_25G : 0; 860054c67d1SSudarsana Reddy Kalluru p_link->partner_adv_speed |= 861cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ? 862cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_40G : 0; 863cc875c2eSYuval Mintz p_link->partner_adv_speed |= 864cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ? 865cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_50G : 0; 866cc875c2eSYuval Mintz p_link->partner_adv_speed |= 867cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ? 868cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_100G : 0; 869cc875c2eSYuval Mintz 870cc875c2eSYuval Mintz p_link->partner_tx_flow_ctrl_en = 871cc875c2eSYuval Mintz !!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED); 872cc875c2eSYuval Mintz p_link->partner_rx_flow_ctrl_en = 873cc875c2eSYuval Mintz !!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED); 874cc875c2eSYuval Mintz 875cc875c2eSYuval Mintz switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) { 876cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE: 877cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_SYMMETRIC_PAUSE; 878cc875c2eSYuval Mintz break; 879cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE: 880cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_ASYMMETRIC_PAUSE; 881cc875c2eSYuval Mintz break; 882cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE: 883cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_BOTH_PAUSE; 884cc875c2eSYuval Mintz break; 885cc875c2eSYuval Mintz default: 886cc875c2eSYuval Mintz p_link->partner_adv_pause = 0; 887cc875c2eSYuval Mintz } 888cc875c2eSYuval Mintz 889cc875c2eSYuval Mintz p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT); 890cc875c2eSYuval Mintz 891cc875c2eSYuval Mintz qed_link_update(p_hwfn); 89265ed2ffdSMintz, Yuval out: 89365ed2ffdSMintz, Yuval spin_unlock_bh(&p_hwfn->mcp_info->link_lock); 894cc875c2eSYuval Mintz } 895cc875c2eSYuval Mintz 896351a4dedSYuval Mintz int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up) 897cc875c2eSYuval Mintz { 898cc875c2eSYuval Mintz struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input; 8995529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 9002f67af8cSTomer Tayar struct eth_phy_cfg phy_cfg; 901cc875c2eSYuval Mintz int rc = 0; 9025529bad9STomer Tayar u32 cmd; 903cc875c2eSYuval Mintz 904cc875c2eSYuval Mintz /* Set the shmem configuration according to params */ 9052f67af8cSTomer Tayar memset(&phy_cfg, 0, sizeof(phy_cfg)); 906cc875c2eSYuval Mintz cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET; 907cc875c2eSYuval Mintz if (!params->speed.autoneg) 9082f67af8cSTomer Tayar phy_cfg.speed = params->speed.forced_speed; 9092f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.autoneg) ? ETH_PAUSE_AUTONEG : 0; 9102f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.forced_rx) ? ETH_PAUSE_RX : 0; 9112f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0; 9122f67af8cSTomer Tayar phy_cfg.adv_speed = params->speed.advertised_speeds; 9132f67af8cSTomer Tayar phy_cfg.loopback_mode = params->loopback_mode; 914cc875c2eSYuval Mintz 915fc916ff2SSudarsana Reddy Kalluru p_hwfn->b_drv_link_init = b_up; 916fc916ff2SSudarsana Reddy Kalluru 917cc875c2eSYuval Mintz if (b_up) { 918cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 919cc875c2eSYuval Mintz "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n", 9202f67af8cSTomer Tayar phy_cfg.speed, 9212f67af8cSTomer Tayar phy_cfg.pause, 9222f67af8cSTomer Tayar phy_cfg.adv_speed, 9232f67af8cSTomer Tayar phy_cfg.loopback_mode, 9242f67af8cSTomer Tayar phy_cfg.feature_config_flags); 925cc875c2eSYuval Mintz } else { 926cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 927cc875c2eSYuval Mintz "Resetting link\n"); 928cc875c2eSYuval Mintz } 929cc875c2eSYuval Mintz 9305529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 9315529bad9STomer Tayar mb_params.cmd = cmd; 9322f67af8cSTomer Tayar mb_params.p_data_src = &phy_cfg; 9332f67af8cSTomer Tayar mb_params.data_src_size = sizeof(phy_cfg); 9345529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 935cc875c2eSYuval Mintz 936cc875c2eSYuval Mintz /* if mcp fails to respond we must abort */ 937cc875c2eSYuval Mintz if (rc) { 938cc875c2eSYuval Mintz DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 939cc875c2eSYuval Mintz return rc; 940cc875c2eSYuval Mintz } 941cc875c2eSYuval Mintz 94265ed2ffdSMintz, Yuval /* Mimic link-change attention, done for several reasons: 94365ed2ffdSMintz, Yuval * - On reset, there's no guarantee MFW would trigger 94465ed2ffdSMintz, Yuval * an attention. 94565ed2ffdSMintz, Yuval * - On initialization, older MFWs might not indicate link change 94665ed2ffdSMintz, Yuval * during LFA, so we'll never get an UP indication. 94765ed2ffdSMintz, Yuval */ 94865ed2ffdSMintz, Yuval qed_mcp_handle_link_change(p_hwfn, p_ptt, !b_up); 949cc875c2eSYuval Mintz 950cc875c2eSYuval Mintz return 0; 951cc875c2eSYuval Mintz } 952cc875c2eSYuval Mintz 9536c754246SSudarsana Reddy Kalluru static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn, 9546c754246SSudarsana Reddy Kalluru struct qed_ptt *p_ptt, 9556c754246SSudarsana Reddy Kalluru enum MFW_DRV_MSG_TYPE type) 9566c754246SSudarsana Reddy Kalluru { 9576c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type stats_type; 9586c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats stats; 9596c754246SSudarsana Reddy Kalluru struct qed_mcp_mb_params mb_params; 9606c754246SSudarsana Reddy Kalluru u32 hsi_param; 9616c754246SSudarsana Reddy Kalluru 9626c754246SSudarsana Reddy Kalluru switch (type) { 9636c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_LAN_STATS: 9646c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_LAN_STATS; 9656c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN; 9666c754246SSudarsana Reddy Kalluru break; 9676c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_FCOE_STATS: 9686c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_FCOE_STATS; 9696c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_FCOE; 9706c754246SSudarsana Reddy Kalluru break; 9716c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_ISCSI_STATS: 9726c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_ISCSI_STATS; 9736c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_ISCSI; 9746c754246SSudarsana Reddy Kalluru break; 9756c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_RDMA_STATS: 9766c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_RDMA_STATS; 9776c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_RDMA; 9786c754246SSudarsana Reddy Kalluru break; 9796c754246SSudarsana Reddy Kalluru default: 9806c754246SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Invalid protocol type %d\n", type); 9816c754246SSudarsana Reddy Kalluru return; 9826c754246SSudarsana Reddy Kalluru } 9836c754246SSudarsana Reddy Kalluru 9846c754246SSudarsana Reddy Kalluru qed_get_protocol_stats(p_hwfn->cdev, stats_type, &stats); 9856c754246SSudarsana Reddy Kalluru 9866c754246SSudarsana Reddy Kalluru memset(&mb_params, 0, sizeof(mb_params)); 9876c754246SSudarsana Reddy Kalluru mb_params.cmd = DRV_MSG_CODE_GET_STATS; 9886c754246SSudarsana Reddy Kalluru mb_params.param = hsi_param; 9892f67af8cSTomer Tayar mb_params.p_data_src = &stats; 9902f67af8cSTomer Tayar mb_params.data_src_size = sizeof(stats); 9916c754246SSudarsana Reddy Kalluru qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 9926c754246SSudarsana Reddy Kalluru } 9936c754246SSudarsana Reddy Kalluru 9944b01e519SManish Chopra static void qed_read_pf_bandwidth(struct qed_hwfn *p_hwfn, 9954b01e519SManish Chopra struct public_func *p_shmem_info) 9964b01e519SManish Chopra { 9974b01e519SManish Chopra struct qed_mcp_function_info *p_info; 9984b01e519SManish Chopra 9994b01e519SManish Chopra p_info = &p_hwfn->mcp_info->func_info; 10004b01e519SManish Chopra 10014b01e519SManish Chopra p_info->bandwidth_min = (p_shmem_info->config & 10024b01e519SManish Chopra FUNC_MF_CFG_MIN_BW_MASK) >> 10034b01e519SManish Chopra FUNC_MF_CFG_MIN_BW_SHIFT; 10044b01e519SManish Chopra if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) { 10054b01e519SManish Chopra DP_INFO(p_hwfn, 10064b01e519SManish Chopra "bandwidth minimum out of bounds [%02x]. Set to 1\n", 10074b01e519SManish Chopra p_info->bandwidth_min); 10084b01e519SManish Chopra p_info->bandwidth_min = 1; 10094b01e519SManish Chopra } 10104b01e519SManish Chopra 10114b01e519SManish Chopra p_info->bandwidth_max = (p_shmem_info->config & 10124b01e519SManish Chopra FUNC_MF_CFG_MAX_BW_MASK) >> 10134b01e519SManish Chopra FUNC_MF_CFG_MAX_BW_SHIFT; 10144b01e519SManish Chopra if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) { 10154b01e519SManish Chopra DP_INFO(p_hwfn, 10164b01e519SManish Chopra "bandwidth maximum out of bounds [%02x]. Set to 100\n", 10174b01e519SManish Chopra p_info->bandwidth_max); 10184b01e519SManish Chopra p_info->bandwidth_max = 100; 10194b01e519SManish Chopra } 10204b01e519SManish Chopra } 10214b01e519SManish Chopra 10224b01e519SManish Chopra static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, 10234b01e519SManish Chopra struct qed_ptt *p_ptt, 10241a635e48SYuval Mintz struct public_func *p_data, int pfid) 10254b01e519SManish Chopra { 10264b01e519SManish Chopra u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 10274b01e519SManish Chopra PUBLIC_FUNC); 10284b01e519SManish Chopra u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); 10294b01e519SManish Chopra u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid); 10304b01e519SManish Chopra u32 i, size; 10314b01e519SManish Chopra 10324b01e519SManish Chopra memset(p_data, 0, sizeof(*p_data)); 10334b01e519SManish Chopra 10341a635e48SYuval Mintz size = min_t(u32, sizeof(*p_data), QED_SECTION_SIZE(mfw_path_offsize)); 10354b01e519SManish Chopra for (i = 0; i < size / sizeof(u32); i++) 10364b01e519SManish Chopra ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt, 10374b01e519SManish Chopra func_addr + (i << 2)); 10384b01e519SManish Chopra return size; 10394b01e519SManish Chopra } 10404b01e519SManish Chopra 10411a635e48SYuval Mintz static void qed_mcp_update_bw(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 10424b01e519SManish Chopra { 10434b01e519SManish Chopra struct qed_mcp_function_info *p_info; 10444b01e519SManish Chopra struct public_func shmem_info; 10454b01e519SManish Chopra u32 resp = 0, param = 0; 10464b01e519SManish Chopra 10471a635e48SYuval Mintz qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 10484b01e519SManish Chopra 10494b01e519SManish Chopra qed_read_pf_bandwidth(p_hwfn, &shmem_info); 10504b01e519SManish Chopra 10514b01e519SManish Chopra p_info = &p_hwfn->mcp_info->func_info; 10524b01e519SManish Chopra 1053a64b02d5SManish Chopra qed_configure_pf_min_bandwidth(p_hwfn->cdev, p_info->bandwidth_min); 10544b01e519SManish Chopra qed_configure_pf_max_bandwidth(p_hwfn->cdev, p_info->bandwidth_max); 10554b01e519SManish Chopra 10564b01e519SManish Chopra /* Acknowledge the MFW */ 10574b01e519SManish Chopra qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp, 10584b01e519SManish Chopra ¶m); 10594b01e519SManish Chopra } 10604b01e519SManish Chopra 1061cc875c2eSYuval Mintz int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, 1062cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 1063cc875c2eSYuval Mintz { 1064cc875c2eSYuval Mintz struct qed_mcp_info *info = p_hwfn->mcp_info; 1065cc875c2eSYuval Mintz int rc = 0; 1066cc875c2eSYuval Mintz bool found = false; 1067cc875c2eSYuval Mintz u16 i; 1068cc875c2eSYuval Mintz 1069cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, "Received message from MFW\n"); 1070cc875c2eSYuval Mintz 1071cc875c2eSYuval Mintz /* Read Messages from MFW */ 1072cc875c2eSYuval Mintz qed_mcp_read_mb(p_hwfn, p_ptt); 1073cc875c2eSYuval Mintz 1074cc875c2eSYuval Mintz /* Compare current messages to old ones */ 1075cc875c2eSYuval Mintz for (i = 0; i < info->mfw_mb_length; i++) { 1076cc875c2eSYuval Mintz if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i]) 1077cc875c2eSYuval Mintz continue; 1078cc875c2eSYuval Mintz 1079cc875c2eSYuval Mintz found = true; 1080cc875c2eSYuval Mintz 1081cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 1082cc875c2eSYuval Mintz "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", 1083cc875c2eSYuval Mintz i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]); 1084cc875c2eSYuval Mintz 1085cc875c2eSYuval Mintz switch (i) { 1086cc875c2eSYuval Mintz case MFW_DRV_MSG_LINK_CHANGE: 1087cc875c2eSYuval Mintz qed_mcp_handle_link_change(p_hwfn, p_ptt, false); 1088cc875c2eSYuval Mintz break; 10890b55e27dSYuval Mintz case MFW_DRV_MSG_VF_DISABLED: 10900b55e27dSYuval Mintz qed_mcp_handle_vf_flr(p_hwfn, p_ptt); 10910b55e27dSYuval Mintz break; 109239651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_LLDP_DATA_UPDATED: 109339651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 109439651abdSSudarsana Reddy Kalluru QED_DCBX_REMOTE_LLDP_MIB); 109539651abdSSudarsana Reddy Kalluru break; 109639651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED: 109739651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 109839651abdSSudarsana Reddy Kalluru QED_DCBX_REMOTE_MIB); 109939651abdSSudarsana Reddy Kalluru break; 110039651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED: 110139651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 110239651abdSSudarsana Reddy Kalluru QED_DCBX_OPERATIONAL_MIB); 110339651abdSSudarsana Reddy Kalluru break; 1104334c03b5SZvi Nachmani case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: 1105334c03b5SZvi Nachmani qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); 1106334c03b5SZvi Nachmani break; 11076c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_LAN_STATS: 11086c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_FCOE_STATS: 11096c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_ISCSI_STATS: 11106c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_RDMA_STATS: 11116c754246SSudarsana Reddy Kalluru qed_mcp_send_protocol_stats(p_hwfn, p_ptt, i); 11126c754246SSudarsana Reddy Kalluru break; 11134b01e519SManish Chopra case MFW_DRV_MSG_BW_UPDATE: 11144b01e519SManish Chopra qed_mcp_update_bw(p_hwfn, p_ptt); 11154b01e519SManish Chopra break; 1116cc875c2eSYuval Mintz default: 111739815944SMintz, Yuval DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i); 1118cc875c2eSYuval Mintz rc = -EINVAL; 1119cc875c2eSYuval Mintz } 1120cc875c2eSYuval Mintz } 1121cc875c2eSYuval Mintz 1122cc875c2eSYuval Mintz /* ACK everything */ 1123cc875c2eSYuval Mintz for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) { 1124cc875c2eSYuval Mintz __be32 val = cpu_to_be32(((u32 *)info->mfw_mb_cur)[i]); 1125cc875c2eSYuval Mintz 1126cc875c2eSYuval Mintz /* MFW expect answer in BE, so we force write in that format */ 1127cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, 1128cc875c2eSYuval Mintz info->mfw_mb_addr + sizeof(u32) + 1129cc875c2eSYuval Mintz MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) * 1130cc875c2eSYuval Mintz sizeof(u32) + i * sizeof(u32), 1131cc875c2eSYuval Mintz (__force u32)val); 1132cc875c2eSYuval Mintz } 1133cc875c2eSYuval Mintz 1134cc875c2eSYuval Mintz if (!found) { 1135cc875c2eSYuval Mintz DP_NOTICE(p_hwfn, 1136cc875c2eSYuval Mintz "Received an MFW message indication but no new message!\n"); 1137cc875c2eSYuval Mintz rc = -EINVAL; 1138cc875c2eSYuval Mintz } 1139cc875c2eSYuval Mintz 1140cc875c2eSYuval Mintz /* Copy the new mfw messages into the shadow */ 1141cc875c2eSYuval Mintz memcpy(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length); 1142cc875c2eSYuval Mintz 1143cc875c2eSYuval Mintz return rc; 1144cc875c2eSYuval Mintz } 1145cc875c2eSYuval Mintz 11461408cc1fSYuval Mintz int qed_mcp_get_mfw_ver(struct qed_hwfn *p_hwfn, 11471408cc1fSYuval Mintz struct qed_ptt *p_ptt, 11481408cc1fSYuval Mintz u32 *p_mfw_ver, u32 *p_running_bundle_id) 1149fe56b9e6SYuval Mintz { 1150fe56b9e6SYuval Mintz u32 global_offsize; 1151fe56b9e6SYuval Mintz 11521408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) { 11531408cc1fSYuval Mintz if (p_hwfn->vf_iov_info) { 11541408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *p_resp; 11551408cc1fSYuval Mintz 11561408cc1fSYuval Mintz p_resp = &p_hwfn->vf_iov_info->acquire_resp; 11571408cc1fSYuval Mintz *p_mfw_ver = p_resp->pfdev_info.mfw_ver; 11581408cc1fSYuval Mintz return 0; 11591408cc1fSYuval Mintz } else { 11601408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 11611408cc1fSYuval Mintz QED_MSG_IOV, 11621408cc1fSYuval Mintz "VF requested MFW version prior to ACQUIRE\n"); 11631408cc1fSYuval Mintz return -EINVAL; 11641408cc1fSYuval Mintz } 11651408cc1fSYuval Mintz } 1166fe56b9e6SYuval Mintz 1167fe56b9e6SYuval Mintz global_offsize = qed_rd(p_hwfn, p_ptt, 11681408cc1fSYuval Mintz SECTION_OFFSIZE_ADDR(p_hwfn-> 11691408cc1fSYuval Mintz mcp_info->public_base, 1170fe56b9e6SYuval Mintz PUBLIC_GLOBAL)); 11711408cc1fSYuval Mintz *p_mfw_ver = 11721408cc1fSYuval Mintz qed_rd(p_hwfn, p_ptt, 11731408cc1fSYuval Mintz SECTION_ADDR(global_offsize, 11741408cc1fSYuval Mintz 0) + offsetof(struct public_global, mfw_ver)); 1175fe56b9e6SYuval Mintz 11761408cc1fSYuval Mintz if (p_running_bundle_id != NULL) { 11771408cc1fSYuval Mintz *p_running_bundle_id = qed_rd(p_hwfn, p_ptt, 11781408cc1fSYuval Mintz SECTION_ADDR(global_offsize, 0) + 11791408cc1fSYuval Mintz offsetof(struct public_global, 11801408cc1fSYuval Mintz running_bundle_id)); 11811408cc1fSYuval Mintz } 1182fe56b9e6SYuval Mintz 1183fe56b9e6SYuval Mintz return 0; 1184fe56b9e6SYuval Mintz } 1185fe56b9e6SYuval Mintz 11861a635e48SYuval Mintz int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type) 1187cc875c2eSYuval Mintz { 1188cc875c2eSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[0]; 1189cc875c2eSYuval Mintz struct qed_ptt *p_ptt; 1190cc875c2eSYuval Mintz 11911408cc1fSYuval Mintz if (IS_VF(cdev)) 11921408cc1fSYuval Mintz return -EINVAL; 11931408cc1fSYuval Mintz 1194cc875c2eSYuval Mintz if (!qed_mcp_is_init(p_hwfn)) { 1195cc875c2eSYuval Mintz DP_NOTICE(p_hwfn, "MFW is not initialized!\n"); 1196cc875c2eSYuval Mintz return -EBUSY; 1197cc875c2eSYuval Mintz } 1198cc875c2eSYuval Mintz 1199cc875c2eSYuval Mintz *p_media_type = MEDIA_UNSPECIFIED; 1200cc875c2eSYuval Mintz 1201cc875c2eSYuval Mintz p_ptt = qed_ptt_acquire(p_hwfn); 1202cc875c2eSYuval Mintz if (!p_ptt) 1203cc875c2eSYuval Mintz return -EBUSY; 1204cc875c2eSYuval Mintz 1205cc875c2eSYuval Mintz *p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr + 1206cc875c2eSYuval Mintz offsetof(struct public_port, media_type)); 1207cc875c2eSYuval Mintz 1208cc875c2eSYuval Mintz qed_ptt_release(p_hwfn, p_ptt); 1209cc875c2eSYuval Mintz 1210cc875c2eSYuval Mintz return 0; 1211cc875c2eSYuval Mintz } 1212cc875c2eSYuval Mintz 12136927e826SMintz, Yuval /* Old MFW has a global configuration for all PFs regarding RDMA support */ 12146927e826SMintz, Yuval static void 12156927e826SMintz, Yuval qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn, 12166927e826SMintz, Yuval enum qed_pci_personality *p_proto) 12176927e826SMintz, Yuval { 12186927e826SMintz, Yuval /* There wasn't ever a legacy MFW that published iwarp. 12196927e826SMintz, Yuval * So at this point, this is either plain l2 or RoCE. 12206927e826SMintz, Yuval */ 12216927e826SMintz, Yuval if (test_bit(QED_DEV_CAP_ROCE, &p_hwfn->hw_info.device_capabilities)) 12226927e826SMintz, Yuval *p_proto = QED_PCI_ETH_ROCE; 12236927e826SMintz, Yuval else 12246927e826SMintz, Yuval *p_proto = QED_PCI_ETH; 12256927e826SMintz, Yuval 12266927e826SMintz, Yuval DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 12276927e826SMintz, Yuval "According to Legacy capabilities, L2 personality is %08x\n", 12286927e826SMintz, Yuval (u32) *p_proto); 12296927e826SMintz, Yuval } 12306927e826SMintz, Yuval 12316927e826SMintz, Yuval static int 12326927e826SMintz, Yuval qed_mcp_get_shmem_proto_mfw(struct qed_hwfn *p_hwfn, 12336927e826SMintz, Yuval struct qed_ptt *p_ptt, 12346927e826SMintz, Yuval enum qed_pci_personality *p_proto) 12356927e826SMintz, Yuval { 12366927e826SMintz, Yuval u32 resp = 0, param = 0; 12376927e826SMintz, Yuval int rc; 12386927e826SMintz, Yuval 12396927e826SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, 12406927e826SMintz, Yuval DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, ¶m); 12416927e826SMintz, Yuval if (rc) 12426927e826SMintz, Yuval return rc; 12436927e826SMintz, Yuval if (resp != FW_MSG_CODE_OK) { 12446927e826SMintz, Yuval DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 12456927e826SMintz, Yuval "MFW lacks support for command; Returns %08x\n", 12466927e826SMintz, Yuval resp); 12476927e826SMintz, Yuval return -EINVAL; 12486927e826SMintz, Yuval } 12496927e826SMintz, Yuval 12506927e826SMintz, Yuval switch (param) { 12516927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_NONE: 12526927e826SMintz, Yuval *p_proto = QED_PCI_ETH; 12536927e826SMintz, Yuval break; 12546927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_ROCE: 12556927e826SMintz, Yuval *p_proto = QED_PCI_ETH_ROCE; 12566927e826SMintz, Yuval break; 12576927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_BOTH: 12586927e826SMintz, Yuval DP_NOTICE(p_hwfn, 12596927e826SMintz, Yuval "Current day drivers don't support RoCE & iWARP. Default to RoCE-only\n"); 12606927e826SMintz, Yuval *p_proto = QED_PCI_ETH_ROCE; 12616927e826SMintz, Yuval break; 12626927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_IWARP: 12636927e826SMintz, Yuval default: 12646927e826SMintz, Yuval DP_NOTICE(p_hwfn, 12656927e826SMintz, Yuval "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n", 12666927e826SMintz, Yuval param); 12676927e826SMintz, Yuval return -EINVAL; 12686927e826SMintz, Yuval } 12696927e826SMintz, Yuval 12706927e826SMintz, Yuval DP_VERBOSE(p_hwfn, 12716927e826SMintz, Yuval NETIF_MSG_IFUP, 12726927e826SMintz, Yuval "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n", 12736927e826SMintz, Yuval (u32) *p_proto, resp, param); 12746927e826SMintz, Yuval return 0; 12756927e826SMintz, Yuval } 12766927e826SMintz, Yuval 1277fe56b9e6SYuval Mintz static int 1278fe56b9e6SYuval Mintz qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, 1279fe56b9e6SYuval Mintz struct public_func *p_info, 12806927e826SMintz, Yuval struct qed_ptt *p_ptt, 1281fe56b9e6SYuval Mintz enum qed_pci_personality *p_proto) 1282fe56b9e6SYuval Mintz { 1283fe56b9e6SYuval Mintz int rc = 0; 1284fe56b9e6SYuval Mintz 1285fe56b9e6SYuval Mintz switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) { 1286fe56b9e6SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ETHERNET: 12871fe582ecSRam Amrani if (!IS_ENABLED(CONFIG_QED_RDMA)) 12881fe582ecSRam Amrani *p_proto = QED_PCI_ETH; 12891fe582ecSRam Amrani else if (qed_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto)) 12906927e826SMintz, Yuval qed_mcp_get_shmem_proto_legacy(p_hwfn, p_proto); 1291fe56b9e6SYuval Mintz break; 1292c5ac9319SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ISCSI: 1293c5ac9319SYuval Mintz *p_proto = QED_PCI_ISCSI; 1294c5ac9319SYuval Mintz break; 12951e128c81SArun Easi case FUNC_MF_CFG_PROTOCOL_FCOE: 12961e128c81SArun Easi *p_proto = QED_PCI_FCOE; 12971e128c81SArun Easi break; 1298c5ac9319SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ROCE: 1299c5ac9319SYuval Mintz DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n"); 13006927e826SMintz, Yuval /* Fallthrough */ 1301fe56b9e6SYuval Mintz default: 1302fe56b9e6SYuval Mintz rc = -EINVAL; 1303fe56b9e6SYuval Mintz } 1304fe56b9e6SYuval Mintz 1305fe56b9e6SYuval Mintz return rc; 1306fe56b9e6SYuval Mintz } 1307fe56b9e6SYuval Mintz 1308fe56b9e6SYuval Mintz int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, 1309fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1310fe56b9e6SYuval Mintz { 1311fe56b9e6SYuval Mintz struct qed_mcp_function_info *info; 1312fe56b9e6SYuval Mintz struct public_func shmem_info; 1313fe56b9e6SYuval Mintz 13141a635e48SYuval Mintz qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 1315fe56b9e6SYuval Mintz info = &p_hwfn->mcp_info->func_info; 1316fe56b9e6SYuval Mintz 1317fe56b9e6SYuval Mintz info->pause_on_host = (shmem_info.config & 1318fe56b9e6SYuval Mintz FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0; 1319fe56b9e6SYuval Mintz 13206927e826SMintz, Yuval if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt, 13216927e826SMintz, Yuval &info->protocol)) { 1322fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Unknown personality %08x\n", 1323fe56b9e6SYuval Mintz (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK)); 1324fe56b9e6SYuval Mintz return -EINVAL; 1325fe56b9e6SYuval Mintz } 1326fe56b9e6SYuval Mintz 13274b01e519SManish Chopra qed_read_pf_bandwidth(p_hwfn, &shmem_info); 1328fe56b9e6SYuval Mintz 1329fe56b9e6SYuval Mintz if (shmem_info.mac_upper || shmem_info.mac_lower) { 1330fe56b9e6SYuval Mintz info->mac[0] = (u8)(shmem_info.mac_upper >> 8); 1331fe56b9e6SYuval Mintz info->mac[1] = (u8)(shmem_info.mac_upper); 1332fe56b9e6SYuval Mintz info->mac[2] = (u8)(shmem_info.mac_lower >> 24); 1333fe56b9e6SYuval Mintz info->mac[3] = (u8)(shmem_info.mac_lower >> 16); 1334fe56b9e6SYuval Mintz info->mac[4] = (u8)(shmem_info.mac_lower >> 8); 1335fe56b9e6SYuval Mintz info->mac[5] = (u8)(shmem_info.mac_lower); 133614d39648SMintz, Yuval 133714d39648SMintz, Yuval /* Store primary MAC for later possible WoL */ 133814d39648SMintz, Yuval memcpy(&p_hwfn->cdev->wol_mac, info->mac, ETH_ALEN); 1339fe56b9e6SYuval Mintz } else { 1340fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n"); 1341fe56b9e6SYuval Mintz } 1342fe56b9e6SYuval Mintz 1343fe56b9e6SYuval Mintz info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_upper | 1344fe56b9e6SYuval Mintz (((u64)shmem_info.fcoe_wwn_port_name_lower) << 32); 1345fe56b9e6SYuval Mintz info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_upper | 1346fe56b9e6SYuval Mintz (((u64)shmem_info.fcoe_wwn_node_name_lower) << 32); 1347fe56b9e6SYuval Mintz 1348fe56b9e6SYuval Mintz info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK); 1349fe56b9e6SYuval Mintz 13500fefbfbaSSudarsana Kalluru info->mtu = (u16)shmem_info.mtu_size; 13510fefbfbaSSudarsana Kalluru 135214d39648SMintz, Yuval p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_NONE; 135314d39648SMintz, Yuval p_hwfn->cdev->wol_config = (u8)QED_OV_WOL_DEFAULT; 135414d39648SMintz, Yuval if (qed_mcp_is_init(p_hwfn)) { 135514d39648SMintz, Yuval u32 resp = 0, param = 0; 135614d39648SMintz, Yuval int rc; 135714d39648SMintz, Yuval 135814d39648SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, 135914d39648SMintz, Yuval DRV_MSG_CODE_OS_WOL, 0, &resp, ¶m); 136014d39648SMintz, Yuval if (rc) 136114d39648SMintz, Yuval return rc; 136214d39648SMintz, Yuval if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED) 136314d39648SMintz, Yuval p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_PME; 136414d39648SMintz, Yuval } 136514d39648SMintz, Yuval 1366fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP), 136714d39648SMintz, Yuval "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", 1368fe56b9e6SYuval Mintz info->pause_on_host, info->protocol, 1369fe56b9e6SYuval Mintz info->bandwidth_min, info->bandwidth_max, 1370fe56b9e6SYuval Mintz info->mac[0], info->mac[1], info->mac[2], 1371fe56b9e6SYuval Mintz info->mac[3], info->mac[4], info->mac[5], 137214d39648SMintz, Yuval info->wwn_port, info->wwn_node, 137314d39648SMintz, Yuval info->ovlan, (u8)p_hwfn->hw_info.b_wol_support); 1374fe56b9e6SYuval Mintz 1375fe56b9e6SYuval Mintz return 0; 1376fe56b9e6SYuval Mintz } 1377fe56b9e6SYuval Mintz 1378cc875c2eSYuval Mintz struct qed_mcp_link_params 1379cc875c2eSYuval Mintz *qed_mcp_get_link_params(struct qed_hwfn *p_hwfn) 1380cc875c2eSYuval Mintz { 1381cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1382cc875c2eSYuval Mintz return NULL; 1383cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_input; 1384cc875c2eSYuval Mintz } 1385cc875c2eSYuval Mintz 1386cc875c2eSYuval Mintz struct qed_mcp_link_state 1387cc875c2eSYuval Mintz *qed_mcp_get_link_state(struct qed_hwfn *p_hwfn) 1388cc875c2eSYuval Mintz { 1389cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1390cc875c2eSYuval Mintz return NULL; 1391cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_output; 1392cc875c2eSYuval Mintz } 1393cc875c2eSYuval Mintz 1394cc875c2eSYuval Mintz struct qed_mcp_link_capabilities 1395cc875c2eSYuval Mintz *qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn) 1396cc875c2eSYuval Mintz { 1397cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1398cc875c2eSYuval Mintz return NULL; 1399cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_capabilities; 1400cc875c2eSYuval Mintz } 1401cc875c2eSYuval Mintz 14021a635e48SYuval Mintz int qed_mcp_drain(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 1403fe56b9e6SYuval Mintz { 1404fe56b9e6SYuval Mintz u32 resp = 0, param = 0; 1405fe56b9e6SYuval Mintz int rc; 1406fe56b9e6SYuval Mintz 1407fe56b9e6SYuval Mintz rc = qed_mcp_cmd(p_hwfn, p_ptt, 14081a635e48SYuval Mintz DRV_MSG_CODE_NIG_DRAIN, 1000, &resp, ¶m); 1409fe56b9e6SYuval Mintz 1410fe56b9e6SYuval Mintz /* Wait for the drain to complete before returning */ 14118f60bafeSYuval Mintz msleep(1020); 1412fe56b9e6SYuval Mintz 1413fe56b9e6SYuval Mintz return rc; 1414fe56b9e6SYuval Mintz } 1415fe56b9e6SYuval Mintz 1416cee4d264SManish Chopra int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, 14171a635e48SYuval Mintz struct qed_ptt *p_ptt, u32 *p_flash_size) 1418cee4d264SManish Chopra { 1419cee4d264SManish Chopra u32 flash_size; 1420cee4d264SManish Chopra 14211408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) 14221408cc1fSYuval Mintz return -EINVAL; 14231408cc1fSYuval Mintz 1424cee4d264SManish Chopra flash_size = qed_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4); 1425cee4d264SManish Chopra flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >> 1426cee4d264SManish Chopra MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT; 1427cee4d264SManish Chopra flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT)); 1428cee4d264SManish Chopra 1429cee4d264SManish Chopra *p_flash_size = flash_size; 1430cee4d264SManish Chopra 1431cee4d264SManish Chopra return 0; 1432cee4d264SManish Chopra } 1433cee4d264SManish Chopra 14341408cc1fSYuval Mintz int qed_mcp_config_vf_msix(struct qed_hwfn *p_hwfn, 14351408cc1fSYuval Mintz struct qed_ptt *p_ptt, u8 vf_id, u8 num) 14361408cc1fSYuval Mintz { 14371408cc1fSYuval Mintz u32 resp = 0, param = 0, rc_param = 0; 14381408cc1fSYuval Mintz int rc; 14391408cc1fSYuval Mintz 14401408cc1fSYuval Mintz /* Only Leader can configure MSIX, and need to take CMT into account */ 14411408cc1fSYuval Mintz if (!IS_LEAD_HWFN(p_hwfn)) 14421408cc1fSYuval Mintz return 0; 14431408cc1fSYuval Mintz num *= p_hwfn->cdev->num_hwfns; 14441408cc1fSYuval Mintz 14451408cc1fSYuval Mintz param |= (vf_id << DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT) & 14461408cc1fSYuval Mintz DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK; 14471408cc1fSYuval Mintz param |= (num << DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT) & 14481408cc1fSYuval Mintz DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK; 14491408cc1fSYuval Mintz 14501408cc1fSYuval Mintz rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_VF_MSIX, param, 14511408cc1fSYuval Mintz &resp, &rc_param); 14521408cc1fSYuval Mintz 14531408cc1fSYuval Mintz if (resp != FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE) { 14541408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "VF[%d]: MFW failed to set MSI-X\n", vf_id); 14551408cc1fSYuval Mintz rc = -EINVAL; 14561408cc1fSYuval Mintz } else { 14571408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 14581408cc1fSYuval Mintz "Requested 0x%02x MSI-x interrupts from VF 0x%02x\n", 14591408cc1fSYuval Mintz num, vf_id); 14601408cc1fSYuval Mintz } 14611408cc1fSYuval Mintz 14621408cc1fSYuval Mintz return rc; 14631408cc1fSYuval Mintz } 14641408cc1fSYuval Mintz 1465fe56b9e6SYuval Mintz int 1466fe56b9e6SYuval Mintz qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, 1467fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 1468fe56b9e6SYuval Mintz struct qed_mcp_drv_version *p_ver) 1469fe56b9e6SYuval Mintz { 14705529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 14712f67af8cSTomer Tayar struct drv_version_stc drv_version; 14725529bad9STomer Tayar __be32 val; 14735529bad9STomer Tayar u32 i; 14745529bad9STomer Tayar int rc; 1475fe56b9e6SYuval Mintz 14762f67af8cSTomer Tayar memset(&drv_version, 0, sizeof(drv_version)); 14772f67af8cSTomer Tayar drv_version.version = p_ver->version; 147867a99b70SYuval Mintz for (i = 0; i < (MCP_DRV_VER_STR_SIZE - 4) / sizeof(u32); i++) { 147967a99b70SYuval Mintz val = cpu_to_be32(*((u32 *)&p_ver->name[i * sizeof(u32)])); 14802f67af8cSTomer Tayar *(__be32 *)&drv_version.name[i * sizeof(u32)] = val; 1481fe56b9e6SYuval Mintz } 1482fe56b9e6SYuval Mintz 14835529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 14845529bad9STomer Tayar mb_params.cmd = DRV_MSG_CODE_SET_VERSION; 14852f67af8cSTomer Tayar mb_params.p_data_src = &drv_version; 14862f67af8cSTomer Tayar mb_params.data_src_size = sizeof(drv_version); 14875529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 14885529bad9STomer Tayar if (rc) 1489fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 1490fe56b9e6SYuval Mintz 14915529bad9STomer Tayar return rc; 1492fe56b9e6SYuval Mintz } 149391420b83SSudarsana Kalluru 14944102426fSTomer Tayar int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 14954102426fSTomer Tayar { 14964102426fSTomer Tayar u32 resp = 0, param = 0; 14974102426fSTomer Tayar int rc; 14984102426fSTomer Tayar 14994102426fSTomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp, 15004102426fSTomer Tayar ¶m); 15014102426fSTomer Tayar if (rc) 15024102426fSTomer Tayar DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 15034102426fSTomer Tayar 15044102426fSTomer Tayar return rc; 15054102426fSTomer Tayar } 15064102426fSTomer Tayar 15074102426fSTomer Tayar int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 15084102426fSTomer Tayar { 15094102426fSTomer Tayar u32 value, cpu_mode; 15104102426fSTomer Tayar 15114102426fSTomer Tayar qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff); 15124102426fSTomer Tayar 15134102426fSTomer Tayar value = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); 15144102426fSTomer Tayar value &= ~MCP_REG_CPU_MODE_SOFT_HALT; 15154102426fSTomer Tayar qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value); 15164102426fSTomer Tayar cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); 15174102426fSTomer Tayar 15184102426fSTomer Tayar return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0; 15194102426fSTomer Tayar } 15204102426fSTomer Tayar 15210fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, 15220fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 15230fefbfbaSSudarsana Kalluru enum qed_ov_client client) 15240fefbfbaSSudarsana Kalluru { 15250fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 15260fefbfbaSSudarsana Kalluru u32 drv_mb_param; 15270fefbfbaSSudarsana Kalluru int rc; 15280fefbfbaSSudarsana Kalluru 15290fefbfbaSSudarsana Kalluru switch (client) { 15300fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_DRV: 15310fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS; 15320fefbfbaSSudarsana Kalluru break; 15330fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_USER: 15340fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER; 15350fefbfbaSSudarsana Kalluru break; 15360fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_VENDOR_SPEC: 15370fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC; 15380fefbfbaSSudarsana Kalluru break; 15390fefbfbaSSudarsana Kalluru default: 15400fefbfbaSSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid client type %d\n", client); 15410fefbfbaSSudarsana Kalluru return -EINVAL; 15420fefbfbaSSudarsana Kalluru } 15430fefbfbaSSudarsana Kalluru 15440fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG, 15450fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 15460fefbfbaSSudarsana Kalluru if (rc) 15470fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 15480fefbfbaSSudarsana Kalluru 15490fefbfbaSSudarsana Kalluru return rc; 15500fefbfbaSSudarsana Kalluru } 15510fefbfbaSSudarsana Kalluru 15520fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn, 15530fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 15540fefbfbaSSudarsana Kalluru enum qed_ov_driver_state drv_state) 15550fefbfbaSSudarsana Kalluru { 15560fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 15570fefbfbaSSudarsana Kalluru u32 drv_mb_param; 15580fefbfbaSSudarsana Kalluru int rc; 15590fefbfbaSSudarsana Kalluru 15600fefbfbaSSudarsana Kalluru switch (drv_state) { 15610fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_NOT_LOADED: 15620fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED; 15630fefbfbaSSudarsana Kalluru break; 15640fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_DISABLED: 15650fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED; 15660fefbfbaSSudarsana Kalluru break; 15670fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_ACTIVE: 15680fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE; 15690fefbfbaSSudarsana Kalluru break; 15700fefbfbaSSudarsana Kalluru default: 15710fefbfbaSSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid driver state %d\n", drv_state); 15720fefbfbaSSudarsana Kalluru return -EINVAL; 15730fefbfbaSSudarsana Kalluru } 15740fefbfbaSSudarsana Kalluru 15750fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE, 15760fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 15770fefbfbaSSudarsana Kalluru if (rc) 15780fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send driver state\n"); 15790fefbfbaSSudarsana Kalluru 15800fefbfbaSSudarsana Kalluru return rc; 15810fefbfbaSSudarsana Kalluru } 15820fefbfbaSSudarsana Kalluru 15830fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, 15840fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, u16 mtu) 15850fefbfbaSSudarsana Kalluru { 15860fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 15870fefbfbaSSudarsana Kalluru u32 drv_mb_param; 15880fefbfbaSSudarsana Kalluru int rc; 15890fefbfbaSSudarsana Kalluru 15900fefbfbaSSudarsana Kalluru drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT; 15910fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU, 15920fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 15930fefbfbaSSudarsana Kalluru if (rc) 15940fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc); 15950fefbfbaSSudarsana Kalluru 15960fefbfbaSSudarsana Kalluru return rc; 15970fefbfbaSSudarsana Kalluru } 15980fefbfbaSSudarsana Kalluru 15990fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, 16000fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, u8 *mac) 16010fefbfbaSSudarsana Kalluru { 16020fefbfbaSSudarsana Kalluru struct qed_mcp_mb_params mb_params; 160317991002SMintz, Yuval u32 mfw_mac[2]; 16040fefbfbaSSudarsana Kalluru int rc; 16050fefbfbaSSudarsana Kalluru 16060fefbfbaSSudarsana Kalluru memset(&mb_params, 0, sizeof(mb_params)); 16070fefbfbaSSudarsana Kalluru mb_params.cmd = DRV_MSG_CODE_SET_VMAC; 16080fefbfbaSSudarsana Kalluru mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC << 16090fefbfbaSSudarsana Kalluru DRV_MSG_CODE_VMAC_TYPE_SHIFT; 16100fefbfbaSSudarsana Kalluru mb_params.param |= MCP_PF_ID(p_hwfn); 16112f67af8cSTomer Tayar 161217991002SMintz, Yuval /* MCP is BE, and on LE platforms PCI would swap access to SHMEM 161317991002SMintz, Yuval * in 32-bit granularity. 161417991002SMintz, Yuval * So the MAC has to be set in native order [and not byte order], 161517991002SMintz, Yuval * otherwise it would be read incorrectly by MFW after swap. 161617991002SMintz, Yuval */ 161717991002SMintz, Yuval mfw_mac[0] = mac[0] << 24 | mac[1] << 16 | mac[2] << 8 | mac[3]; 161817991002SMintz, Yuval mfw_mac[1] = mac[4] << 24 | mac[5] << 16; 161917991002SMintz, Yuval 162017991002SMintz, Yuval mb_params.p_data_src = (u8 *)mfw_mac; 162117991002SMintz, Yuval mb_params.data_src_size = 8; 16220fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 16230fefbfbaSSudarsana Kalluru if (rc) 16240fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc); 16250fefbfbaSSudarsana Kalluru 162614d39648SMintz, Yuval /* Store primary MAC for later possible WoL */ 162714d39648SMintz, Yuval memcpy(p_hwfn->cdev->wol_mac, mac, ETH_ALEN); 162814d39648SMintz, Yuval 16290fefbfbaSSudarsana Kalluru return rc; 16300fefbfbaSSudarsana Kalluru } 16310fefbfbaSSudarsana Kalluru 16320fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, 16330fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, enum qed_ov_wol wol) 16340fefbfbaSSudarsana Kalluru { 16350fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 16360fefbfbaSSudarsana Kalluru u32 drv_mb_param; 16370fefbfbaSSudarsana Kalluru int rc; 16380fefbfbaSSudarsana Kalluru 163914d39648SMintz, Yuval if (p_hwfn->hw_info.b_wol_support == QED_WOL_SUPPORT_NONE) { 164014d39648SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_SP, 164114d39648SMintz, Yuval "Can't change WoL configuration when WoL isn't supported\n"); 164214d39648SMintz, Yuval return -EINVAL; 164314d39648SMintz, Yuval } 164414d39648SMintz, Yuval 16450fefbfbaSSudarsana Kalluru switch (wol) { 16460fefbfbaSSudarsana Kalluru case QED_OV_WOL_DEFAULT: 16470fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT; 16480fefbfbaSSudarsana Kalluru break; 16490fefbfbaSSudarsana Kalluru case QED_OV_WOL_DISABLED: 16500fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_DISABLED; 16510fefbfbaSSudarsana Kalluru break; 16520fefbfbaSSudarsana Kalluru case QED_OV_WOL_ENABLED: 16530fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_ENABLED; 16540fefbfbaSSudarsana Kalluru break; 16550fefbfbaSSudarsana Kalluru default: 16560fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Invalid wol state %d\n", wol); 16570fefbfbaSSudarsana Kalluru return -EINVAL; 16580fefbfbaSSudarsana Kalluru } 16590fefbfbaSSudarsana Kalluru 16600fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL, 16610fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 16620fefbfbaSSudarsana Kalluru if (rc) 16630fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc); 16640fefbfbaSSudarsana Kalluru 166514d39648SMintz, Yuval /* Store the WoL update for a future unload */ 166614d39648SMintz, Yuval p_hwfn->cdev->wol_config = (u8)wol; 166714d39648SMintz, Yuval 16680fefbfbaSSudarsana Kalluru return rc; 16690fefbfbaSSudarsana Kalluru } 16700fefbfbaSSudarsana Kalluru 16710fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn, 16720fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 16730fefbfbaSSudarsana Kalluru enum qed_ov_eswitch eswitch) 16740fefbfbaSSudarsana Kalluru { 16750fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 16760fefbfbaSSudarsana Kalluru u32 drv_mb_param; 16770fefbfbaSSudarsana Kalluru int rc; 16780fefbfbaSSudarsana Kalluru 16790fefbfbaSSudarsana Kalluru switch (eswitch) { 16800fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_NONE: 16810fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE; 16820fefbfbaSSudarsana Kalluru break; 16830fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_VEB: 16840fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB; 16850fefbfbaSSudarsana Kalluru break; 16860fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_VEPA: 16870fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA; 16880fefbfbaSSudarsana Kalluru break; 16890fefbfbaSSudarsana Kalluru default: 16900fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch); 16910fefbfbaSSudarsana Kalluru return -EINVAL; 16920fefbfbaSSudarsana Kalluru } 16930fefbfbaSSudarsana Kalluru 16940fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE, 16950fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 16960fefbfbaSSudarsana Kalluru if (rc) 16970fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc); 16980fefbfbaSSudarsana Kalluru 16990fefbfbaSSudarsana Kalluru return rc; 17000fefbfbaSSudarsana Kalluru } 17010fefbfbaSSudarsana Kalluru 17021a635e48SYuval Mintz int qed_mcp_set_led(struct qed_hwfn *p_hwfn, 17031a635e48SYuval Mintz struct qed_ptt *p_ptt, enum qed_led_mode mode) 170491420b83SSudarsana Kalluru { 170591420b83SSudarsana Kalluru u32 resp = 0, param = 0, drv_mb_param; 170691420b83SSudarsana Kalluru int rc; 170791420b83SSudarsana Kalluru 170891420b83SSudarsana Kalluru switch (mode) { 170991420b83SSudarsana Kalluru case QED_LED_MODE_ON: 171091420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON; 171191420b83SSudarsana Kalluru break; 171291420b83SSudarsana Kalluru case QED_LED_MODE_OFF: 171391420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF; 171491420b83SSudarsana Kalluru break; 171591420b83SSudarsana Kalluru case QED_LED_MODE_RESTORE: 171691420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER; 171791420b83SSudarsana Kalluru break; 171891420b83SSudarsana Kalluru default: 171991420b83SSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid LED mode %d\n", mode); 172091420b83SSudarsana Kalluru return -EINVAL; 172191420b83SSudarsana Kalluru } 172291420b83SSudarsana Kalluru 172391420b83SSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE, 172491420b83SSudarsana Kalluru drv_mb_param, &resp, ¶m); 172591420b83SSudarsana Kalluru 172691420b83SSudarsana Kalluru return rc; 172791420b83SSudarsana Kalluru } 172803dc76caSSudarsana Reddy Kalluru 17294102426fSTomer Tayar int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn, 17304102426fSTomer Tayar struct qed_ptt *p_ptt, u32 mask_parities) 17314102426fSTomer Tayar { 17324102426fSTomer Tayar u32 resp = 0, param = 0; 17334102426fSTomer Tayar int rc; 17344102426fSTomer Tayar 17354102426fSTomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MASK_PARITIES, 17364102426fSTomer Tayar mask_parities, &resp, ¶m); 17374102426fSTomer Tayar 17384102426fSTomer Tayar if (rc) { 17394102426fSTomer Tayar DP_ERR(p_hwfn, 17404102426fSTomer Tayar "MCP response failure for mask parities, aborting\n"); 17414102426fSTomer Tayar } else if (resp != FW_MSG_CODE_OK) { 17424102426fSTomer Tayar DP_ERR(p_hwfn, 17434102426fSTomer Tayar "MCP did not acknowledge mask parity request. Old MFW?\n"); 17444102426fSTomer Tayar rc = -EINVAL; 17454102426fSTomer Tayar } 17464102426fSTomer Tayar 17474102426fSTomer Tayar return rc; 17484102426fSTomer Tayar } 17494102426fSTomer Tayar 17507a4b21b7SMintz, Yuval int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len) 17517a4b21b7SMintz, Yuval { 17527a4b21b7SMintz, Yuval u32 bytes_left = len, offset = 0, bytes_to_copy, read_len = 0; 17537a4b21b7SMintz, Yuval struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 17547a4b21b7SMintz, Yuval u32 resp = 0, resp_param = 0; 17557a4b21b7SMintz, Yuval struct qed_ptt *p_ptt; 17567a4b21b7SMintz, Yuval int rc = 0; 17577a4b21b7SMintz, Yuval 17587a4b21b7SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 17597a4b21b7SMintz, Yuval if (!p_ptt) 17607a4b21b7SMintz, Yuval return -EBUSY; 17617a4b21b7SMintz, Yuval 17627a4b21b7SMintz, Yuval while (bytes_left > 0) { 17637a4b21b7SMintz, Yuval bytes_to_copy = min_t(u32, bytes_left, MCP_DRV_NVM_BUF_LEN); 17647a4b21b7SMintz, Yuval 17657a4b21b7SMintz, Yuval rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, 17667a4b21b7SMintz, Yuval DRV_MSG_CODE_NVM_READ_NVRAM, 17677a4b21b7SMintz, Yuval addr + offset + 17687a4b21b7SMintz, Yuval (bytes_to_copy << 17697a4b21b7SMintz, Yuval DRV_MB_PARAM_NVM_LEN_SHIFT), 17707a4b21b7SMintz, Yuval &resp, &resp_param, 17717a4b21b7SMintz, Yuval &read_len, 17727a4b21b7SMintz, Yuval (u32 *)(p_buf + offset)); 17737a4b21b7SMintz, Yuval 17747a4b21b7SMintz, Yuval if (rc || (resp != FW_MSG_CODE_NVM_OK)) { 17757a4b21b7SMintz, Yuval DP_NOTICE(cdev, "MCP command rc = %d\n", rc); 17767a4b21b7SMintz, Yuval break; 17777a4b21b7SMintz, Yuval } 17787a4b21b7SMintz, Yuval 17797a4b21b7SMintz, Yuval /* This can be a lengthy process, and it's possible scheduler 17807a4b21b7SMintz, Yuval * isn't preemptable. Sleep a bit to prevent CPU hogging. 17817a4b21b7SMintz, Yuval */ 17827a4b21b7SMintz, Yuval if (bytes_left % 0x1000 < 17837a4b21b7SMintz, Yuval (bytes_left - read_len) % 0x1000) 17847a4b21b7SMintz, Yuval usleep_range(1000, 2000); 17857a4b21b7SMintz, Yuval 17867a4b21b7SMintz, Yuval offset += read_len; 17877a4b21b7SMintz, Yuval bytes_left -= read_len; 17887a4b21b7SMintz, Yuval } 17897a4b21b7SMintz, Yuval 17907a4b21b7SMintz, Yuval cdev->mcp_nvm_resp = resp; 17917a4b21b7SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 17927a4b21b7SMintz, Yuval 17937a4b21b7SMintz, Yuval return rc; 17947a4b21b7SMintz, Yuval } 17957a4b21b7SMintz, Yuval 179603dc76caSSudarsana Reddy Kalluru int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 179703dc76caSSudarsana Reddy Kalluru { 179803dc76caSSudarsana Reddy Kalluru u32 drv_mb_param = 0, rsp, param; 179903dc76caSSudarsana Reddy Kalluru int rc = 0; 180003dc76caSSudarsana Reddy Kalluru 180103dc76caSSudarsana Reddy Kalluru drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST << 180203dc76caSSudarsana Reddy Kalluru DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 180303dc76caSSudarsana Reddy Kalluru 180403dc76caSSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 180503dc76caSSudarsana Reddy Kalluru drv_mb_param, &rsp, ¶m); 180603dc76caSSudarsana Reddy Kalluru 180703dc76caSSudarsana Reddy Kalluru if (rc) 180803dc76caSSudarsana Reddy Kalluru return rc; 180903dc76caSSudarsana Reddy Kalluru 181003dc76caSSudarsana Reddy Kalluru if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 181103dc76caSSudarsana Reddy Kalluru (param != DRV_MB_PARAM_BIST_RC_PASSED)) 181203dc76caSSudarsana Reddy Kalluru rc = -EAGAIN; 181303dc76caSSudarsana Reddy Kalluru 181403dc76caSSudarsana Reddy Kalluru return rc; 181503dc76caSSudarsana Reddy Kalluru } 181603dc76caSSudarsana Reddy Kalluru 181703dc76caSSudarsana Reddy Kalluru int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 181803dc76caSSudarsana Reddy Kalluru { 181903dc76caSSudarsana Reddy Kalluru u32 drv_mb_param, rsp, param; 182003dc76caSSudarsana Reddy Kalluru int rc = 0; 182103dc76caSSudarsana Reddy Kalluru 182203dc76caSSudarsana Reddy Kalluru drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST << 182303dc76caSSudarsana Reddy Kalluru DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 182403dc76caSSudarsana Reddy Kalluru 182503dc76caSSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 182603dc76caSSudarsana Reddy Kalluru drv_mb_param, &rsp, ¶m); 182703dc76caSSudarsana Reddy Kalluru 182803dc76caSSudarsana Reddy Kalluru if (rc) 182903dc76caSSudarsana Reddy Kalluru return rc; 183003dc76caSSudarsana Reddy Kalluru 183103dc76caSSudarsana Reddy Kalluru if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 183203dc76caSSudarsana Reddy Kalluru (param != DRV_MB_PARAM_BIST_RC_PASSED)) 183303dc76caSSudarsana Reddy Kalluru rc = -EAGAIN; 183403dc76caSSudarsana Reddy Kalluru 183503dc76caSSudarsana Reddy Kalluru return rc; 183603dc76caSSudarsana Reddy Kalluru } 18377a4b21b7SMintz, Yuval 18387a4b21b7SMintz, Yuval int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn, 18397a4b21b7SMintz, Yuval struct qed_ptt *p_ptt, 18407a4b21b7SMintz, Yuval u32 *num_images) 18417a4b21b7SMintz, Yuval { 18427a4b21b7SMintz, Yuval u32 drv_mb_param = 0, rsp; 18437a4b21b7SMintz, Yuval int rc = 0; 18447a4b21b7SMintz, Yuval 18457a4b21b7SMintz, Yuval drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES << 18467a4b21b7SMintz, Yuval DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 18477a4b21b7SMintz, Yuval 18487a4b21b7SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 18497a4b21b7SMintz, Yuval drv_mb_param, &rsp, num_images); 18507a4b21b7SMintz, Yuval if (rc) 18517a4b21b7SMintz, Yuval return rc; 18527a4b21b7SMintz, Yuval 18537a4b21b7SMintz, Yuval if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK)) 18547a4b21b7SMintz, Yuval rc = -EINVAL; 18557a4b21b7SMintz, Yuval 18567a4b21b7SMintz, Yuval return rc; 18577a4b21b7SMintz, Yuval } 18587a4b21b7SMintz, Yuval 18597a4b21b7SMintz, Yuval int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn, 18607a4b21b7SMintz, Yuval struct qed_ptt *p_ptt, 18617a4b21b7SMintz, Yuval struct bist_nvm_image_att *p_image_att, 18627a4b21b7SMintz, Yuval u32 image_index) 18637a4b21b7SMintz, Yuval { 18647a4b21b7SMintz, Yuval u32 buf_size = 0, param, resp = 0, resp_param = 0; 18657a4b21b7SMintz, Yuval int rc; 18667a4b21b7SMintz, Yuval 18677a4b21b7SMintz, Yuval param = DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX << 18687a4b21b7SMintz, Yuval DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT; 18697a4b21b7SMintz, Yuval param |= image_index << DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT; 18707a4b21b7SMintz, Yuval 18717a4b21b7SMintz, Yuval rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, 18727a4b21b7SMintz, Yuval DRV_MSG_CODE_BIST_TEST, param, 18737a4b21b7SMintz, Yuval &resp, &resp_param, 18747a4b21b7SMintz, Yuval &buf_size, 18757a4b21b7SMintz, Yuval (u32 *)p_image_att); 18767a4b21b7SMintz, Yuval if (rc) 18777a4b21b7SMintz, Yuval return rc; 18787a4b21b7SMintz, Yuval 18797a4b21b7SMintz, Yuval if (((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 18807a4b21b7SMintz, Yuval (p_image_att->return_code != 1)) 18817a4b21b7SMintz, Yuval rc = -EINVAL; 18827a4b21b7SMintz, Yuval 18837a4b21b7SMintz, Yuval return rc; 18847a4b21b7SMintz, Yuval } 18852edbff8dSTomer Tayar 18862edbff8dSTomer Tayar #define QED_RESC_ALLOC_VERSION_MAJOR 1 18872edbff8dSTomer Tayar #define QED_RESC_ALLOC_VERSION_MINOR 0 18882edbff8dSTomer Tayar #define QED_RESC_ALLOC_VERSION \ 18892edbff8dSTomer Tayar ((QED_RESC_ALLOC_VERSION_MAJOR << \ 18902edbff8dSTomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) | \ 18912edbff8dSTomer Tayar (QED_RESC_ALLOC_VERSION_MINOR << \ 18922edbff8dSTomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT)) 18932edbff8dSTomer Tayar int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn, 18942edbff8dSTomer Tayar struct qed_ptt *p_ptt, 18952edbff8dSTomer Tayar struct resource_info *p_resc_info, 18962edbff8dSTomer Tayar u32 *p_mcp_resp, u32 *p_mcp_param) 18972edbff8dSTomer Tayar { 18982edbff8dSTomer Tayar struct qed_mcp_mb_params mb_params; 18992edbff8dSTomer Tayar int rc; 19002edbff8dSTomer Tayar 19012edbff8dSTomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 19022edbff8dSTomer Tayar mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG; 19032edbff8dSTomer Tayar mb_params.param = QED_RESC_ALLOC_VERSION; 1904bb480242SMintz, Yuval 19052f67af8cSTomer Tayar mb_params.p_data_src = p_resc_info; 19062f67af8cSTomer Tayar mb_params.data_src_size = sizeof(*p_resc_info); 19072f67af8cSTomer Tayar mb_params.p_data_dst = p_resc_info; 19082f67af8cSTomer Tayar mb_params.data_dst_size = sizeof(*p_resc_info); 19092edbff8dSTomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 19102edbff8dSTomer Tayar if (rc) 19112edbff8dSTomer Tayar return rc; 19122edbff8dSTomer Tayar 1913bb480242SMintz, Yuval /* Copy the data back */ 19142edbff8dSTomer Tayar *p_mcp_resp = mb_params.mcp_resp; 19152edbff8dSTomer Tayar *p_mcp_param = mb_params.mcp_param; 19162edbff8dSTomer Tayar 19172edbff8dSTomer Tayar DP_VERBOSE(p_hwfn, 19182edbff8dSTomer Tayar QED_MSG_SP, 19192edbff8dSTomer Tayar "MFW resource_info: version 0x%x, res_id 0x%x, size 0x%x, offset 0x%x, vf_size 0x%x, vf_offset 0x%x, flags 0x%x\n", 19202edbff8dSTomer Tayar *p_mcp_param, 19212edbff8dSTomer Tayar p_resc_info->res_id, 19222edbff8dSTomer Tayar p_resc_info->size, 19232edbff8dSTomer Tayar p_resc_info->offset, 19242edbff8dSTomer Tayar p_resc_info->vf_size, 19252edbff8dSTomer Tayar p_resc_info->vf_offset, p_resc_info->flags); 19262edbff8dSTomer Tayar 19272edbff8dSTomer Tayar return 0; 19282edbff8dSTomer Tayar } 1929