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" 43cac6f691SSudarsana Reddy Kalluru #include "qed_cxt.h" 4439651abdSSudarsana Reddy Kalluru #include "qed_dcbx.h" 45fe56b9e6SYuval Mintz #include "qed_hsi.h" 46fe56b9e6SYuval Mintz #include "qed_hw.h" 47fe56b9e6SYuval Mintz #include "qed_mcp.h" 48fe56b9e6SYuval Mintz #include "qed_reg_addr.h" 491408cc1fSYuval Mintz #include "qed_sriov.h" 501408cc1fSYuval Mintz 51fe56b9e6SYuval Mintz #define CHIP_MCP_RESP_ITER_US 10 52fe56b9e6SYuval Mintz 53fe56b9e6SYuval Mintz #define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */ 54fe56b9e6SYuval Mintz #define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */ 55fe56b9e6SYuval Mintz 56fe56b9e6SYuval Mintz #define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \ 57fe56b9e6SYuval Mintz qed_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \ 58fe56b9e6SYuval Mintz _val) 59fe56b9e6SYuval Mintz 60fe56b9e6SYuval Mintz #define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \ 61fe56b9e6SYuval Mintz qed_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset)) 62fe56b9e6SYuval Mintz 63fe56b9e6SYuval Mintz #define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \ 64fe56b9e6SYuval Mintz DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \ 65fe56b9e6SYuval Mintz offsetof(struct public_drv_mb, _field), _val) 66fe56b9e6SYuval Mintz 67fe56b9e6SYuval Mintz #define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \ 68fe56b9e6SYuval Mintz DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \ 69fe56b9e6SYuval Mintz offsetof(struct public_drv_mb, _field)) 70fe56b9e6SYuval Mintz 71fe56b9e6SYuval Mintz #define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \ 72fe56b9e6SYuval Mintz DRV_ID_PDA_COMP_VER_SHIFT) 73fe56b9e6SYuval Mintz 74fe56b9e6SYuval Mintz #define MCP_BYTES_PER_MBIT_SHIFT 17 75fe56b9e6SYuval Mintz 76fe56b9e6SYuval Mintz bool qed_mcp_is_init(struct qed_hwfn *p_hwfn) 77fe56b9e6SYuval Mintz { 78fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base) 79fe56b9e6SYuval Mintz return false; 80fe56b9e6SYuval Mintz return true; 81fe56b9e6SYuval Mintz } 82fe56b9e6SYuval Mintz 831a635e48SYuval Mintz void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 84fe56b9e6SYuval Mintz { 85fe56b9e6SYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 86fe56b9e6SYuval Mintz PUBLIC_PORT); 87fe56b9e6SYuval Mintz u32 mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, addr); 88fe56b9e6SYuval Mintz 89fe56b9e6SYuval Mintz p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize, 90fe56b9e6SYuval Mintz MFW_PORT(p_hwfn)); 91fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 92fe56b9e6SYuval Mintz "port_addr = 0x%x, port_id 0x%02x\n", 93fe56b9e6SYuval Mintz p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn)); 94fe56b9e6SYuval Mintz } 95fe56b9e6SYuval Mintz 961a635e48SYuval Mintz void qed_mcp_read_mb(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 97fe56b9e6SYuval Mintz { 98fe56b9e6SYuval Mintz u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length); 99fe56b9e6SYuval Mintz u32 tmp, i; 100fe56b9e6SYuval Mintz 101fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info->public_base) 102fe56b9e6SYuval Mintz return; 103fe56b9e6SYuval Mintz 104fe56b9e6SYuval Mintz for (i = 0; i < length; i++) { 105fe56b9e6SYuval Mintz tmp = qed_rd(p_hwfn, p_ptt, 106fe56b9e6SYuval Mintz p_hwfn->mcp_info->mfw_mb_addr + 107fe56b9e6SYuval Mintz (i << 2) + sizeof(u32)); 108fe56b9e6SYuval Mintz 109fe56b9e6SYuval Mintz /* The MB data is actually BE; Need to force it to cpu */ 110fe56b9e6SYuval Mintz ((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] = 111fe56b9e6SYuval Mintz be32_to_cpu((__force __be32)tmp); 112fe56b9e6SYuval Mintz } 113fe56b9e6SYuval Mintz } 114fe56b9e6SYuval Mintz 1154ed1eea8STomer Tayar struct qed_mcp_cmd_elem { 1164ed1eea8STomer Tayar struct list_head list; 1174ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params; 1184ed1eea8STomer Tayar u16 expected_seq_num; 1194ed1eea8STomer Tayar bool b_is_completed; 1204ed1eea8STomer Tayar }; 1214ed1eea8STomer Tayar 1224ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1234ed1eea8STomer Tayar static struct qed_mcp_cmd_elem * 1244ed1eea8STomer Tayar qed_mcp_cmd_add_elem(struct qed_hwfn *p_hwfn, 1254ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 1264ed1eea8STomer Tayar u16 expected_seq_num) 1274ed1eea8STomer Tayar { 1284ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem = NULL; 1294ed1eea8STomer Tayar 1304ed1eea8STomer Tayar p_cmd_elem = kzalloc(sizeof(*p_cmd_elem), GFP_ATOMIC); 1314ed1eea8STomer Tayar if (!p_cmd_elem) 1324ed1eea8STomer Tayar goto out; 1334ed1eea8STomer Tayar 1344ed1eea8STomer Tayar p_cmd_elem->p_mb_params = p_mb_params; 1354ed1eea8STomer Tayar p_cmd_elem->expected_seq_num = expected_seq_num; 1364ed1eea8STomer Tayar list_add(&p_cmd_elem->list, &p_hwfn->mcp_info->cmd_list); 1374ed1eea8STomer Tayar out: 1384ed1eea8STomer Tayar return p_cmd_elem; 1394ed1eea8STomer Tayar } 1404ed1eea8STomer Tayar 1414ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1424ed1eea8STomer Tayar static void qed_mcp_cmd_del_elem(struct qed_hwfn *p_hwfn, 1434ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem) 1444ed1eea8STomer Tayar { 1454ed1eea8STomer Tayar list_del(&p_cmd_elem->list); 1464ed1eea8STomer Tayar kfree(p_cmd_elem); 1474ed1eea8STomer Tayar } 1484ed1eea8STomer Tayar 1494ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 1504ed1eea8STomer Tayar static struct qed_mcp_cmd_elem *qed_mcp_cmd_get_elem(struct qed_hwfn *p_hwfn, 1514ed1eea8STomer Tayar u16 seq_num) 1524ed1eea8STomer Tayar { 1534ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem = NULL; 1544ed1eea8STomer Tayar 1554ed1eea8STomer Tayar list_for_each_entry(p_cmd_elem, &p_hwfn->mcp_info->cmd_list, list) { 1564ed1eea8STomer Tayar if (p_cmd_elem->expected_seq_num == seq_num) 1574ed1eea8STomer Tayar return p_cmd_elem; 1584ed1eea8STomer Tayar } 1594ed1eea8STomer Tayar 1604ed1eea8STomer Tayar return NULL; 1614ed1eea8STomer Tayar } 1624ed1eea8STomer Tayar 163fe56b9e6SYuval Mintz int qed_mcp_free(struct qed_hwfn *p_hwfn) 164fe56b9e6SYuval Mintz { 165fe56b9e6SYuval Mintz if (p_hwfn->mcp_info) { 1664ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem, *p_tmp; 1674ed1eea8STomer Tayar 168fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info->mfw_mb_cur); 169fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info->mfw_mb_shadow); 1704ed1eea8STomer Tayar 1714ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 1724ed1eea8STomer Tayar list_for_each_entry_safe(p_cmd_elem, 1734ed1eea8STomer Tayar p_tmp, 1744ed1eea8STomer Tayar &p_hwfn->mcp_info->cmd_list, list) { 1754ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 176fe56b9e6SYuval Mintz } 1774ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 1784ed1eea8STomer Tayar } 1794ed1eea8STomer Tayar 180fe56b9e6SYuval Mintz kfree(p_hwfn->mcp_info); 1813587cb87STomer Tayar p_hwfn->mcp_info = NULL; 182fe56b9e6SYuval Mintz 183fe56b9e6SYuval Mintz return 0; 184fe56b9e6SYuval Mintz } 185fe56b9e6SYuval Mintz 1861a635e48SYuval Mintz static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 187fe56b9e6SYuval Mintz { 188fe56b9e6SYuval Mintz struct qed_mcp_info *p_info = p_hwfn->mcp_info; 189fe56b9e6SYuval Mintz u32 drv_mb_offsize, mfw_mb_offsize; 190fe56b9e6SYuval Mintz u32 mcp_pf_id = MCP_PF_ID(p_hwfn); 191fe56b9e6SYuval Mintz 192fe56b9e6SYuval Mintz p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR); 193fe56b9e6SYuval Mintz if (!p_info->public_base) 194fe56b9e6SYuval Mintz return 0; 195fe56b9e6SYuval Mintz 196fe56b9e6SYuval Mintz p_info->public_base |= GRCBASE_MCP; 197fe56b9e6SYuval Mintz 198fe56b9e6SYuval Mintz /* Calculate the driver and MFW mailbox address */ 199fe56b9e6SYuval Mintz drv_mb_offsize = qed_rd(p_hwfn, p_ptt, 200fe56b9e6SYuval Mintz SECTION_OFFSIZE_ADDR(p_info->public_base, 201fe56b9e6SYuval Mintz PUBLIC_DRV_MB)); 202fe56b9e6SYuval Mintz p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id); 203fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 204fe56b9e6SYuval Mintz "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n", 205fe56b9e6SYuval Mintz drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id); 206fe56b9e6SYuval Mintz 207fe56b9e6SYuval Mintz /* Set the MFW MB address */ 208fe56b9e6SYuval Mintz mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, 209fe56b9e6SYuval Mintz SECTION_OFFSIZE_ADDR(p_info->public_base, 210fe56b9e6SYuval Mintz PUBLIC_MFW_MB)); 211fe56b9e6SYuval Mintz p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); 212fe56b9e6SYuval Mintz p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr); 213fe56b9e6SYuval Mintz 214fe56b9e6SYuval Mintz /* Get the current driver mailbox sequence before sending 215fe56b9e6SYuval Mintz * the first command 216fe56b9e6SYuval Mintz */ 217fe56b9e6SYuval Mintz p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) & 218fe56b9e6SYuval Mintz DRV_MSG_SEQ_NUMBER_MASK; 219fe56b9e6SYuval Mintz 220fe56b9e6SYuval Mintz /* Get current FW pulse sequence */ 221fe56b9e6SYuval Mintz p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) & 222fe56b9e6SYuval Mintz DRV_PULSE_SEQ_MASK; 223fe56b9e6SYuval Mintz 2244ed1eea8STomer Tayar p_info->mcp_hist = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 225fe56b9e6SYuval Mintz 226fe56b9e6SYuval Mintz return 0; 227fe56b9e6SYuval Mintz } 228fe56b9e6SYuval Mintz 2291a635e48SYuval Mintz int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 230fe56b9e6SYuval Mintz { 231fe56b9e6SYuval Mintz struct qed_mcp_info *p_info; 232fe56b9e6SYuval Mintz u32 size; 233fe56b9e6SYuval Mintz 234fe56b9e6SYuval Mintz /* Allocate mcp_info structure */ 23560fffb3bSYuval Mintz p_hwfn->mcp_info = kzalloc(sizeof(*p_hwfn->mcp_info), GFP_KERNEL); 236fe56b9e6SYuval Mintz if (!p_hwfn->mcp_info) 237fe56b9e6SYuval Mintz goto err; 238fe56b9e6SYuval Mintz p_info = p_hwfn->mcp_info; 239fe56b9e6SYuval Mintz 2404ed1eea8STomer Tayar /* Initialize the MFW spinlock */ 2414ed1eea8STomer Tayar spin_lock_init(&p_info->cmd_lock); 2424ed1eea8STomer Tayar spin_lock_init(&p_info->link_lock); 2434ed1eea8STomer Tayar 2444ed1eea8STomer Tayar INIT_LIST_HEAD(&p_info->cmd_list); 2454ed1eea8STomer Tayar 246fe56b9e6SYuval Mintz if (qed_load_mcp_offsets(p_hwfn, p_ptt) != 0) { 247fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MCP is not initialized\n"); 248fe56b9e6SYuval Mintz /* Do not free mcp_info here, since public_base indicate that 249fe56b9e6SYuval Mintz * the MCP is not initialized 250fe56b9e6SYuval Mintz */ 251fe56b9e6SYuval Mintz return 0; 252fe56b9e6SYuval Mintz } 253fe56b9e6SYuval Mintz 254fe56b9e6SYuval Mintz size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32); 25560fffb3bSYuval Mintz p_info->mfw_mb_cur = kzalloc(size, GFP_KERNEL); 25683aeb933SYuval Mintz p_info->mfw_mb_shadow = kzalloc(size, GFP_KERNEL); 257eb2a6b80SChristophe Jaillet if (!p_info->mfw_mb_cur || !p_info->mfw_mb_shadow) 258fe56b9e6SYuval Mintz goto err; 259fe56b9e6SYuval Mintz 260fe56b9e6SYuval Mintz return 0; 261fe56b9e6SYuval Mintz 262fe56b9e6SYuval Mintz err: 263fe56b9e6SYuval Mintz qed_mcp_free(p_hwfn); 264fe56b9e6SYuval Mintz return -ENOMEM; 265fe56b9e6SYuval Mintz } 266fe56b9e6SYuval Mintz 2674ed1eea8STomer Tayar static void qed_mcp_reread_offsets(struct qed_hwfn *p_hwfn, 2684ed1eea8STomer Tayar struct qed_ptt *p_ptt) 2695529bad9STomer Tayar { 2704ed1eea8STomer Tayar u32 generic_por_0 = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 2715529bad9STomer Tayar 2724ed1eea8STomer Tayar /* Use MCP history register to check if MCP reset occurred between init 2734ed1eea8STomer Tayar * time and now. 2745529bad9STomer Tayar */ 2754ed1eea8STomer Tayar if (p_hwfn->mcp_info->mcp_hist != generic_por_0) { 2764ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, 2774ed1eea8STomer Tayar QED_MSG_SP, 2784ed1eea8STomer Tayar "Rereading MCP offsets [mcp_hist 0x%08x, generic_por_0 0x%08x]\n", 2794ed1eea8STomer Tayar p_hwfn->mcp_info->mcp_hist, generic_por_0); 2805529bad9STomer Tayar 2814ed1eea8STomer Tayar qed_load_mcp_offsets(p_hwfn, p_ptt); 2824ed1eea8STomer Tayar qed_mcp_cmd_port_init(p_hwfn, p_ptt); 2835529bad9STomer Tayar } 2845529bad9STomer Tayar } 2855529bad9STomer Tayar 2861a635e48SYuval Mintz int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 287fe56b9e6SYuval Mintz { 2884ed1eea8STomer Tayar u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0; 289fe56b9e6SYuval Mintz int rc = 0; 290fe56b9e6SYuval Mintz 2914ed1eea8STomer Tayar /* Ensure that only a single thread is accessing the mailbox */ 2924ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 2934ed1eea8STomer Tayar 2944ed1eea8STomer Tayar org_mcp_reset_seq = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); 2955529bad9STomer Tayar 296fe56b9e6SYuval Mintz /* Set drv command along with the updated sequence */ 2974ed1eea8STomer Tayar qed_mcp_reread_offsets(p_hwfn, p_ptt); 2984ed1eea8STomer Tayar seq = ++p_hwfn->mcp_info->drv_mb_seq; 2994ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (DRV_MSG_CODE_MCP_RESET | seq)); 300fe56b9e6SYuval Mintz 301fe56b9e6SYuval Mintz do { 302fe56b9e6SYuval Mintz /* Wait for MFW response */ 303fe56b9e6SYuval Mintz udelay(delay); 304fe56b9e6SYuval Mintz /* Give the FW up to 500 second (50*1000*10usec) */ 305fe56b9e6SYuval Mintz } while ((org_mcp_reset_seq == qed_rd(p_hwfn, p_ptt, 306fe56b9e6SYuval Mintz MISCS_REG_GENERIC_POR_0)) && 307fe56b9e6SYuval Mintz (cnt++ < QED_MCP_RESET_RETRIES)); 308fe56b9e6SYuval Mintz 309fe56b9e6SYuval Mintz if (org_mcp_reset_seq != 310fe56b9e6SYuval Mintz qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) { 311fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, 312fe56b9e6SYuval Mintz "MCP was reset after %d usec\n", cnt * delay); 313fe56b9e6SYuval Mintz } else { 314fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Failed to reset MCP\n"); 315fe56b9e6SYuval Mintz rc = -EAGAIN; 316fe56b9e6SYuval Mintz } 317fe56b9e6SYuval Mintz 3184ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 3195529bad9STomer Tayar 320fe56b9e6SYuval Mintz return rc; 321fe56b9e6SYuval Mintz } 322fe56b9e6SYuval Mintz 3234ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3244ed1eea8STomer Tayar static bool qed_mcp_has_pending_cmd(struct qed_hwfn *p_hwfn) 325fe56b9e6SYuval Mintz { 3264ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 3274ed1eea8STomer Tayar 3284ed1eea8STomer Tayar /* There is at most one pending command at a certain time, and if it 3294ed1eea8STomer Tayar * exists - it is placed at the HEAD of the list. 3304ed1eea8STomer Tayar */ 3314ed1eea8STomer Tayar if (!list_empty(&p_hwfn->mcp_info->cmd_list)) { 3324ed1eea8STomer Tayar p_cmd_elem = list_first_entry(&p_hwfn->mcp_info->cmd_list, 3334ed1eea8STomer Tayar struct qed_mcp_cmd_elem, list); 3344ed1eea8STomer Tayar return !p_cmd_elem->b_is_completed; 3354ed1eea8STomer Tayar } 3364ed1eea8STomer Tayar 3374ed1eea8STomer Tayar return false; 3384ed1eea8STomer Tayar } 3394ed1eea8STomer Tayar 3404ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3414ed1eea8STomer Tayar static int 3424ed1eea8STomer Tayar qed_mcp_update_pending_cmd(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 3434ed1eea8STomer Tayar { 3444ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params; 3454ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 3464ed1eea8STomer Tayar u32 mcp_resp; 3474ed1eea8STomer Tayar u16 seq_num; 3484ed1eea8STomer Tayar 3494ed1eea8STomer Tayar mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header); 3504ed1eea8STomer Tayar seq_num = (u16)(mcp_resp & FW_MSG_SEQ_NUMBER_MASK); 3514ed1eea8STomer Tayar 3524ed1eea8STomer Tayar /* Return if no new non-handled response has been received */ 3534ed1eea8STomer Tayar if (seq_num != p_hwfn->mcp_info->drv_mb_seq) 3544ed1eea8STomer Tayar return -EAGAIN; 3554ed1eea8STomer Tayar 3564ed1eea8STomer Tayar p_cmd_elem = qed_mcp_cmd_get_elem(p_hwfn, seq_num); 3574ed1eea8STomer Tayar if (!p_cmd_elem) { 3584ed1eea8STomer Tayar DP_ERR(p_hwfn, 3594ed1eea8STomer Tayar "Failed to find a pending mailbox cmd that expects sequence number %d\n", 3604ed1eea8STomer Tayar seq_num); 3614ed1eea8STomer Tayar return -EINVAL; 3624ed1eea8STomer Tayar } 3634ed1eea8STomer Tayar 3644ed1eea8STomer Tayar p_mb_params = p_cmd_elem->p_mb_params; 3654ed1eea8STomer Tayar 3664ed1eea8STomer Tayar /* Get the MFW response along with the sequence number */ 3674ed1eea8STomer Tayar p_mb_params->mcp_resp = mcp_resp; 3684ed1eea8STomer Tayar 3694ed1eea8STomer Tayar /* Get the MFW param */ 3704ed1eea8STomer Tayar p_mb_params->mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param); 3714ed1eea8STomer Tayar 3724ed1eea8STomer Tayar /* Get the union data */ 3732f67af8cSTomer Tayar if (p_mb_params->p_data_dst != NULL && p_mb_params->data_dst_size) { 3744ed1eea8STomer Tayar u32 union_data_addr = p_hwfn->mcp_info->drv_mb_addr + 3754ed1eea8STomer Tayar offsetof(struct public_drv_mb, 3764ed1eea8STomer Tayar union_data); 3774ed1eea8STomer Tayar qed_memcpy_from(p_hwfn, p_ptt, p_mb_params->p_data_dst, 3782f67af8cSTomer Tayar union_data_addr, p_mb_params->data_dst_size); 3794ed1eea8STomer Tayar } 3804ed1eea8STomer Tayar 3814ed1eea8STomer Tayar p_cmd_elem->b_is_completed = true; 3824ed1eea8STomer Tayar 3834ed1eea8STomer Tayar return 0; 3844ed1eea8STomer Tayar } 3854ed1eea8STomer Tayar 3864ed1eea8STomer Tayar /* Must be called while cmd_lock is acquired */ 3874ed1eea8STomer Tayar static void __qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 3884ed1eea8STomer Tayar struct qed_ptt *p_ptt, 3894ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 3904ed1eea8STomer Tayar u16 seq_num) 3914ed1eea8STomer Tayar { 3924ed1eea8STomer Tayar union drv_union_data union_data; 3934ed1eea8STomer Tayar u32 union_data_addr; 3944ed1eea8STomer Tayar 3954ed1eea8STomer Tayar /* Set the union data */ 3964ed1eea8STomer Tayar union_data_addr = p_hwfn->mcp_info->drv_mb_addr + 3974ed1eea8STomer Tayar offsetof(struct public_drv_mb, union_data); 3984ed1eea8STomer Tayar memset(&union_data, 0, sizeof(union_data)); 3992f67af8cSTomer Tayar if (p_mb_params->p_data_src != NULL && p_mb_params->data_src_size) 4004ed1eea8STomer Tayar memcpy(&union_data, p_mb_params->p_data_src, 4012f67af8cSTomer Tayar p_mb_params->data_src_size); 4024ed1eea8STomer Tayar qed_memcpy_to(p_hwfn, p_ptt, union_data_addr, &union_data, 4034ed1eea8STomer Tayar sizeof(union_data)); 4044ed1eea8STomer Tayar 4054ed1eea8STomer Tayar /* Set the drv param */ 4064ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, p_mb_params->param); 4074ed1eea8STomer Tayar 4084ed1eea8STomer Tayar /* Set the drv command along with the sequence number */ 4094ed1eea8STomer Tayar DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (p_mb_params->cmd | seq_num)); 4104ed1eea8STomer Tayar 4114ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 4124ed1eea8STomer Tayar "MFW mailbox: command 0x%08x param 0x%08x\n", 4134ed1eea8STomer Tayar (p_mb_params->cmd | seq_num), p_mb_params->param); 4144ed1eea8STomer Tayar } 4154ed1eea8STomer Tayar 4164ed1eea8STomer Tayar static int 4174ed1eea8STomer Tayar _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 4184ed1eea8STomer Tayar struct qed_ptt *p_ptt, 4194ed1eea8STomer Tayar struct qed_mcp_mb_params *p_mb_params, 4204ed1eea8STomer Tayar u32 max_retries, u32 delay) 4214ed1eea8STomer Tayar { 4224ed1eea8STomer Tayar struct qed_mcp_cmd_elem *p_cmd_elem; 4234ed1eea8STomer Tayar u32 cnt = 0; 4244ed1eea8STomer Tayar u16 seq_num; 425fe56b9e6SYuval Mintz int rc = 0; 426fe56b9e6SYuval Mintz 4274ed1eea8STomer Tayar /* Wait until the mailbox is non-occupied */ 428fe56b9e6SYuval Mintz do { 4294ed1eea8STomer Tayar /* Exit the loop if there is no pending command, or if the 4304ed1eea8STomer Tayar * pending command is completed during this iteration. 4314ed1eea8STomer Tayar * The spinlock stays locked until the command is sent. 4324ed1eea8STomer Tayar */ 4334ed1eea8STomer Tayar 4344ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4354ed1eea8STomer Tayar 4364ed1eea8STomer Tayar if (!qed_mcp_has_pending_cmd(p_hwfn)) 4374ed1eea8STomer Tayar break; 4384ed1eea8STomer Tayar 4394ed1eea8STomer Tayar rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt); 4404ed1eea8STomer Tayar if (!rc) 4414ed1eea8STomer Tayar break; 4424ed1eea8STomer Tayar else if (rc != -EAGAIN) 4434ed1eea8STomer Tayar goto err; 4444ed1eea8STomer Tayar 4454ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 446fe56b9e6SYuval Mintz udelay(delay); 4474ed1eea8STomer Tayar } while (++cnt < max_retries); 448fe56b9e6SYuval Mintz 4494ed1eea8STomer Tayar if (cnt >= max_retries) { 4504ed1eea8STomer Tayar DP_NOTICE(p_hwfn, 4514ed1eea8STomer Tayar "The MFW mailbox is occupied by an uncompleted command. Failed to send command 0x%08x [param 0x%08x].\n", 4524ed1eea8STomer Tayar p_mb_params->cmd, p_mb_params->param); 4534ed1eea8STomer Tayar return -EAGAIN; 454fe56b9e6SYuval Mintz } 4554ed1eea8STomer Tayar 4564ed1eea8STomer Tayar /* Send the mailbox command */ 4574ed1eea8STomer Tayar qed_mcp_reread_offsets(p_hwfn, p_ptt); 4584ed1eea8STomer Tayar seq_num = ++p_hwfn->mcp_info->drv_mb_seq; 4594ed1eea8STomer Tayar p_cmd_elem = qed_mcp_cmd_add_elem(p_hwfn, p_mb_params, seq_num); 460c8004600SDan Carpenter if (!p_cmd_elem) { 461c8004600SDan Carpenter rc = -ENOMEM; 4624ed1eea8STomer Tayar goto err; 463c8004600SDan Carpenter } 4644ed1eea8STomer Tayar 4654ed1eea8STomer Tayar __qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, seq_num); 4664ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4674ed1eea8STomer Tayar 4684ed1eea8STomer Tayar /* Wait for the MFW response */ 4694ed1eea8STomer Tayar do { 4704ed1eea8STomer Tayar /* Exit the loop if the command is already completed, or if the 4714ed1eea8STomer Tayar * command is completed during this iteration. 4724ed1eea8STomer Tayar * The spinlock stays locked until the list element is removed. 4734ed1eea8STomer Tayar */ 4744ed1eea8STomer Tayar 4754ed1eea8STomer Tayar udelay(delay); 4764ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4774ed1eea8STomer Tayar 4784ed1eea8STomer Tayar if (p_cmd_elem->b_is_completed) 4794ed1eea8STomer Tayar break; 4804ed1eea8STomer Tayar 4814ed1eea8STomer Tayar rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt); 4824ed1eea8STomer Tayar if (!rc) 4834ed1eea8STomer Tayar break; 4844ed1eea8STomer Tayar else if (rc != -EAGAIN) 4854ed1eea8STomer Tayar goto err; 4864ed1eea8STomer Tayar 4874ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4884ed1eea8STomer Tayar } while (++cnt < max_retries); 4894ed1eea8STomer Tayar 4904ed1eea8STomer Tayar if (cnt >= max_retries) { 4914ed1eea8STomer Tayar DP_NOTICE(p_hwfn, 4924ed1eea8STomer Tayar "The MFW failed to respond to command 0x%08x [param 0x%08x].\n", 4934ed1eea8STomer Tayar p_mb_params->cmd, p_mb_params->param); 4944ed1eea8STomer Tayar 4954ed1eea8STomer Tayar spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); 4964ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 4974ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 4984ed1eea8STomer Tayar 4994ed1eea8STomer Tayar return -EAGAIN; 5004ed1eea8STomer Tayar } 5014ed1eea8STomer Tayar 5024ed1eea8STomer Tayar qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); 5034ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 5044ed1eea8STomer Tayar 5054ed1eea8STomer Tayar DP_VERBOSE(p_hwfn, 5064ed1eea8STomer Tayar QED_MSG_SP, 5074ed1eea8STomer Tayar "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n", 5084ed1eea8STomer Tayar p_mb_params->mcp_resp, 5094ed1eea8STomer Tayar p_mb_params->mcp_param, 5104ed1eea8STomer Tayar (cnt * delay) / 1000, (cnt * delay) % 1000); 5114ed1eea8STomer Tayar 5124ed1eea8STomer Tayar /* Clear the sequence number from the MFW response */ 5134ed1eea8STomer Tayar p_mb_params->mcp_resp &= FW_MSG_CODE_MASK; 5144ed1eea8STomer Tayar 5154ed1eea8STomer Tayar return 0; 5164ed1eea8STomer Tayar 5174ed1eea8STomer Tayar err: 5184ed1eea8STomer Tayar spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); 519fe56b9e6SYuval Mintz return rc; 520fe56b9e6SYuval Mintz } 521fe56b9e6SYuval Mintz 5225529bad9STomer Tayar static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, 523fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 5245529bad9STomer Tayar struct qed_mcp_mb_params *p_mb_params) 525fe56b9e6SYuval Mintz { 5262f67af8cSTomer Tayar size_t union_data_size = sizeof(union drv_union_data); 5274ed1eea8STomer Tayar u32 max_retries = QED_DRV_MB_MAX_RETRIES; 5284ed1eea8STomer Tayar u32 delay = CHIP_MCP_RESP_ITER_US; 529fe56b9e6SYuval Mintz 530fe56b9e6SYuval Mintz /* MCP not initialized */ 531fe56b9e6SYuval Mintz if (!qed_mcp_is_init(p_hwfn)) { 532fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MFW is not initialized!\n"); 533fe56b9e6SYuval Mintz return -EBUSY; 534fe56b9e6SYuval Mintz } 535fe56b9e6SYuval Mintz 5362f67af8cSTomer Tayar if (p_mb_params->data_src_size > union_data_size || 5372f67af8cSTomer Tayar p_mb_params->data_dst_size > union_data_size) { 5382f67af8cSTomer Tayar DP_ERR(p_hwfn, 5392f67af8cSTomer Tayar "The provided size is larger than the union data size [src_size %u, dst_size %u, union_data_size %zu]\n", 5402f67af8cSTomer Tayar p_mb_params->data_src_size, 5412f67af8cSTomer Tayar p_mb_params->data_dst_size, union_data_size); 5422f67af8cSTomer Tayar return -EINVAL; 5432f67af8cSTomer Tayar } 5442f67af8cSTomer Tayar 5454ed1eea8STomer Tayar return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries, 5464ed1eea8STomer Tayar delay); 547fe56b9e6SYuval Mintz } 548fe56b9e6SYuval Mintz 5495529bad9STomer Tayar int qed_mcp_cmd(struct qed_hwfn *p_hwfn, 5505529bad9STomer Tayar struct qed_ptt *p_ptt, 5515529bad9STomer Tayar u32 cmd, 5525529bad9STomer Tayar u32 param, 5535529bad9STomer Tayar u32 *o_mcp_resp, 5545529bad9STomer Tayar u32 *o_mcp_param) 555fe56b9e6SYuval Mintz { 5565529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 5575529bad9STomer Tayar int rc; 558fe56b9e6SYuval Mintz 5595529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 5605529bad9STomer Tayar mb_params.cmd = cmd; 5615529bad9STomer Tayar mb_params.param = param; 56214d39648SMintz, Yuval 5635529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 5645529bad9STomer Tayar if (rc) 5655529bad9STomer Tayar return rc; 5665529bad9STomer Tayar 5675529bad9STomer Tayar *o_mcp_resp = mb_params.mcp_resp; 5685529bad9STomer Tayar *o_mcp_param = mb_params.mcp_param; 5695529bad9STomer Tayar 5705529bad9STomer Tayar return 0; 571fe56b9e6SYuval Mintz } 572fe56b9e6SYuval Mintz 573bf774d14SYueHaibing static int 574bf774d14SYueHaibing qed_mcp_nvm_wr_cmd(struct qed_hwfn *p_hwfn, 57562e4d438SSudarsana Reddy Kalluru struct qed_ptt *p_ptt, 57662e4d438SSudarsana Reddy Kalluru u32 cmd, 57762e4d438SSudarsana Reddy Kalluru u32 param, 57862e4d438SSudarsana Reddy Kalluru u32 *o_mcp_resp, 57962e4d438SSudarsana Reddy Kalluru u32 *o_mcp_param, u32 i_txn_size, u32 *i_buf) 58062e4d438SSudarsana Reddy Kalluru { 58162e4d438SSudarsana Reddy Kalluru struct qed_mcp_mb_params mb_params; 58262e4d438SSudarsana Reddy Kalluru int rc; 58362e4d438SSudarsana Reddy Kalluru 58462e4d438SSudarsana Reddy Kalluru memset(&mb_params, 0, sizeof(mb_params)); 58562e4d438SSudarsana Reddy Kalluru mb_params.cmd = cmd; 58662e4d438SSudarsana Reddy Kalluru mb_params.param = param; 58762e4d438SSudarsana Reddy Kalluru mb_params.p_data_src = i_buf; 58862e4d438SSudarsana Reddy Kalluru mb_params.data_src_size = (u8)i_txn_size; 58962e4d438SSudarsana Reddy Kalluru rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 59062e4d438SSudarsana Reddy Kalluru if (rc) 59162e4d438SSudarsana Reddy Kalluru return rc; 59262e4d438SSudarsana Reddy Kalluru 59362e4d438SSudarsana Reddy Kalluru *o_mcp_resp = mb_params.mcp_resp; 59462e4d438SSudarsana Reddy Kalluru *o_mcp_param = mb_params.mcp_param; 59562e4d438SSudarsana Reddy Kalluru 5965e7ba042SDenis Bolotin /* nvm_info needs to be updated */ 5975e7ba042SDenis Bolotin p_hwfn->nvm_info.valid = false; 5985e7ba042SDenis Bolotin 59962e4d438SSudarsana Reddy Kalluru return 0; 60062e4d438SSudarsana Reddy Kalluru } 60162e4d438SSudarsana Reddy Kalluru 6024102426fSTomer Tayar int qed_mcp_nvm_rd_cmd(struct qed_hwfn *p_hwfn, 6034102426fSTomer Tayar struct qed_ptt *p_ptt, 6044102426fSTomer Tayar u32 cmd, 6054102426fSTomer Tayar u32 param, 6064102426fSTomer Tayar u32 *o_mcp_resp, 6074102426fSTomer Tayar u32 *o_mcp_param, u32 *o_txn_size, u32 *o_buf) 6084102426fSTomer Tayar { 6094102426fSTomer Tayar struct qed_mcp_mb_params mb_params; 6102f67af8cSTomer Tayar u8 raw_data[MCP_DRV_NVM_BUF_LEN]; 6114102426fSTomer Tayar int rc; 6124102426fSTomer Tayar 6134102426fSTomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 6144102426fSTomer Tayar mb_params.cmd = cmd; 6154102426fSTomer Tayar mb_params.param = param; 6162f67af8cSTomer Tayar mb_params.p_data_dst = raw_data; 6172f67af8cSTomer Tayar 6182f67af8cSTomer Tayar /* Use the maximal value since the actual one is part of the response */ 6192f67af8cSTomer Tayar mb_params.data_dst_size = MCP_DRV_NVM_BUF_LEN; 6202f67af8cSTomer Tayar 6214102426fSTomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 6224102426fSTomer Tayar if (rc) 6234102426fSTomer Tayar return rc; 6244102426fSTomer Tayar 6254102426fSTomer Tayar *o_mcp_resp = mb_params.mcp_resp; 6264102426fSTomer Tayar *o_mcp_param = mb_params.mcp_param; 6274102426fSTomer Tayar 6284102426fSTomer Tayar *o_txn_size = *o_mcp_param; 6292f67af8cSTomer Tayar memcpy(o_buf, raw_data, *o_txn_size); 6304102426fSTomer Tayar 6314102426fSTomer Tayar return 0; 6324102426fSTomer Tayar } 6334102426fSTomer Tayar 6345d24bcf1STomer Tayar static bool 6355d24bcf1STomer Tayar qed_mcp_can_force_load(u8 drv_role, 6365d24bcf1STomer Tayar u8 exist_drv_role, 6375d24bcf1STomer Tayar enum qed_override_force_load override_force_load) 638fe56b9e6SYuval Mintz { 6395d24bcf1STomer Tayar bool can_force_load = false; 6405d24bcf1STomer Tayar 6415d24bcf1STomer Tayar switch (override_force_load) { 6425d24bcf1STomer Tayar case QED_OVERRIDE_FORCE_LOAD_ALWAYS: 6435d24bcf1STomer Tayar can_force_load = true; 6445d24bcf1STomer Tayar break; 6455d24bcf1STomer Tayar case QED_OVERRIDE_FORCE_LOAD_NEVER: 6465d24bcf1STomer Tayar can_force_load = false; 6475d24bcf1STomer Tayar break; 6485d24bcf1STomer Tayar default: 6495d24bcf1STomer Tayar can_force_load = (drv_role == DRV_ROLE_OS && 6505d24bcf1STomer Tayar exist_drv_role == DRV_ROLE_PREBOOT) || 6515d24bcf1STomer Tayar (drv_role == DRV_ROLE_KDUMP && 6525d24bcf1STomer Tayar exist_drv_role == DRV_ROLE_OS); 6535d24bcf1STomer Tayar break; 6545d24bcf1STomer Tayar } 6555d24bcf1STomer Tayar 6565d24bcf1STomer Tayar return can_force_load; 6575d24bcf1STomer Tayar } 6585d24bcf1STomer Tayar 6595d24bcf1STomer Tayar static int qed_mcp_cancel_load_req(struct qed_hwfn *p_hwfn, 6605d24bcf1STomer Tayar struct qed_ptt *p_ptt) 6615d24bcf1STomer Tayar { 6625d24bcf1STomer Tayar u32 resp = 0, param = 0; 663fe56b9e6SYuval Mintz int rc; 664fe56b9e6SYuval Mintz 6655d24bcf1STomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CANCEL_LOAD_REQ, 0, 6665d24bcf1STomer Tayar &resp, ¶m); 6675d24bcf1STomer Tayar if (rc) 6685d24bcf1STomer Tayar DP_NOTICE(p_hwfn, 6695d24bcf1STomer Tayar "Failed to send cancel load request, rc = %d\n", rc); 670fe56b9e6SYuval Mintz 671fe56b9e6SYuval Mintz return rc; 672fe56b9e6SYuval Mintz } 673fe56b9e6SYuval Mintz 6745d24bcf1STomer Tayar #define CONFIG_QEDE_BITMAP_IDX BIT(0) 6755d24bcf1STomer Tayar #define CONFIG_QED_SRIOV_BITMAP_IDX BIT(1) 6765d24bcf1STomer Tayar #define CONFIG_QEDR_BITMAP_IDX BIT(2) 6775d24bcf1STomer Tayar #define CONFIG_QEDF_BITMAP_IDX BIT(4) 6785d24bcf1STomer Tayar #define CONFIG_QEDI_BITMAP_IDX BIT(5) 6795d24bcf1STomer Tayar #define CONFIG_QED_LL2_BITMAP_IDX BIT(6) 6805529bad9STomer Tayar 6815d24bcf1STomer Tayar static u32 qed_get_config_bitmap(void) 6825d24bcf1STomer Tayar { 6835d24bcf1STomer Tayar u32 config_bitmap = 0x0; 6845d24bcf1STomer Tayar 6855d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QEDE)) 6865d24bcf1STomer Tayar config_bitmap |= CONFIG_QEDE_BITMAP_IDX; 6875d24bcf1STomer Tayar 6885d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QED_SRIOV)) 6895d24bcf1STomer Tayar config_bitmap |= CONFIG_QED_SRIOV_BITMAP_IDX; 6905d24bcf1STomer Tayar 6915d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QED_RDMA)) 6925d24bcf1STomer Tayar config_bitmap |= CONFIG_QEDR_BITMAP_IDX; 6935d24bcf1STomer Tayar 6945d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QED_FCOE)) 6955d24bcf1STomer Tayar config_bitmap |= CONFIG_QEDF_BITMAP_IDX; 6965d24bcf1STomer Tayar 6975d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QED_ISCSI)) 6985d24bcf1STomer Tayar config_bitmap |= CONFIG_QEDI_BITMAP_IDX; 6995d24bcf1STomer Tayar 7005d24bcf1STomer Tayar if (IS_ENABLED(CONFIG_QED_LL2)) 7015d24bcf1STomer Tayar config_bitmap |= CONFIG_QED_LL2_BITMAP_IDX; 7025d24bcf1STomer Tayar 7035d24bcf1STomer Tayar return config_bitmap; 7045d24bcf1STomer Tayar } 7055d24bcf1STomer Tayar 7065d24bcf1STomer Tayar struct qed_load_req_in_params { 7075d24bcf1STomer Tayar u8 hsi_ver; 7085d24bcf1STomer Tayar #define QED_LOAD_REQ_HSI_VER_DEFAULT 0 7095d24bcf1STomer Tayar #define QED_LOAD_REQ_HSI_VER_1 1 7105d24bcf1STomer Tayar u32 drv_ver_0; 7115d24bcf1STomer Tayar u32 drv_ver_1; 7125d24bcf1STomer Tayar u32 fw_ver; 7135d24bcf1STomer Tayar u8 drv_role; 7145d24bcf1STomer Tayar u8 timeout_val; 7155d24bcf1STomer Tayar u8 force_cmd; 7165d24bcf1STomer Tayar bool avoid_eng_reset; 7175d24bcf1STomer Tayar }; 7185d24bcf1STomer Tayar 7195d24bcf1STomer Tayar struct qed_load_req_out_params { 7205d24bcf1STomer Tayar u32 load_code; 7215d24bcf1STomer Tayar u32 exist_drv_ver_0; 7225d24bcf1STomer Tayar u32 exist_drv_ver_1; 7235d24bcf1STomer Tayar u32 exist_fw_ver; 7245d24bcf1STomer Tayar u8 exist_drv_role; 7255d24bcf1STomer Tayar u8 mfw_hsi_ver; 7265d24bcf1STomer Tayar bool drv_exists; 7275d24bcf1STomer Tayar }; 7285d24bcf1STomer Tayar 7295d24bcf1STomer Tayar static int 7305d24bcf1STomer Tayar __qed_mcp_load_req(struct qed_hwfn *p_hwfn, 7315d24bcf1STomer Tayar struct qed_ptt *p_ptt, 7325d24bcf1STomer Tayar struct qed_load_req_in_params *p_in_params, 7335d24bcf1STomer Tayar struct qed_load_req_out_params *p_out_params) 7345d24bcf1STomer Tayar { 7355d24bcf1STomer Tayar struct qed_mcp_mb_params mb_params; 7365d24bcf1STomer Tayar struct load_req_stc load_req; 7375d24bcf1STomer Tayar struct load_rsp_stc load_rsp; 7385d24bcf1STomer Tayar u32 hsi_ver; 7395d24bcf1STomer Tayar int rc; 7405d24bcf1STomer Tayar 7415d24bcf1STomer Tayar memset(&load_req, 0, sizeof(load_req)); 7425d24bcf1STomer Tayar load_req.drv_ver_0 = p_in_params->drv_ver_0; 7435d24bcf1STomer Tayar load_req.drv_ver_1 = p_in_params->drv_ver_1; 7445d24bcf1STomer Tayar load_req.fw_ver = p_in_params->fw_ver; 7455d24bcf1STomer Tayar QED_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_ROLE, p_in_params->drv_role); 7465d24bcf1STomer Tayar QED_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_LOCK_TO, 7475d24bcf1STomer Tayar p_in_params->timeout_val); 7485d24bcf1STomer Tayar QED_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FORCE, 7495d24bcf1STomer Tayar p_in_params->force_cmd); 7505d24bcf1STomer Tayar QED_MFW_SET_FIELD(load_req.misc0, LOAD_REQ_FLAGS0, 7515d24bcf1STomer Tayar p_in_params->avoid_eng_reset); 7525d24bcf1STomer Tayar 7535d24bcf1STomer Tayar hsi_ver = (p_in_params->hsi_ver == QED_LOAD_REQ_HSI_VER_DEFAULT) ? 7545d24bcf1STomer Tayar DRV_ID_MCP_HSI_VER_CURRENT : 7555d24bcf1STomer Tayar (p_in_params->hsi_ver << DRV_ID_MCP_HSI_VER_SHIFT); 7565d24bcf1STomer Tayar 7575d24bcf1STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 7585d24bcf1STomer Tayar mb_params.cmd = DRV_MSG_CODE_LOAD_REQ; 7595d24bcf1STomer Tayar mb_params.param = PDA_COMP | hsi_ver | p_hwfn->cdev->drv_type; 7605d24bcf1STomer Tayar mb_params.p_data_src = &load_req; 7615d24bcf1STomer Tayar mb_params.data_src_size = sizeof(load_req); 7625d24bcf1STomer Tayar mb_params.p_data_dst = &load_rsp; 7635d24bcf1STomer Tayar mb_params.data_dst_size = sizeof(load_rsp); 7645d24bcf1STomer Tayar 7655d24bcf1STomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 7665d24bcf1STomer Tayar "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n", 7675d24bcf1STomer Tayar mb_params.param, 7685d24bcf1STomer Tayar QED_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_INIT_HW), 7695d24bcf1STomer Tayar QED_MFW_GET_FIELD(mb_params.param, DRV_ID_DRV_TYPE), 7705d24bcf1STomer Tayar QED_MFW_GET_FIELD(mb_params.param, DRV_ID_MCP_HSI_VER), 7715d24bcf1STomer Tayar QED_MFW_GET_FIELD(mb_params.param, DRV_ID_PDA_COMP_VER)); 7725d24bcf1STomer Tayar 7735d24bcf1STomer Tayar if (p_in_params->hsi_ver != QED_LOAD_REQ_HSI_VER_1) { 7745d24bcf1STomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 7755d24bcf1STomer Tayar "Load Request: drv_ver 0x%08x_0x%08x, fw_ver 0x%08x, misc0 0x%08x [role %d, timeout %d, force %d, flags0 0x%x]\n", 7765d24bcf1STomer Tayar load_req.drv_ver_0, 7775d24bcf1STomer Tayar load_req.drv_ver_1, 7785d24bcf1STomer Tayar load_req.fw_ver, 7795d24bcf1STomer Tayar load_req.misc0, 7805d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_ROLE), 7815d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_req.misc0, 7825d24bcf1STomer Tayar LOAD_REQ_LOCK_TO), 7835d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_FORCE), 7845d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_req.misc0, LOAD_REQ_FLAGS0)); 7855d24bcf1STomer Tayar } 7865d24bcf1STomer Tayar 7875d24bcf1STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 7885d24bcf1STomer Tayar if (rc) { 7895d24bcf1STomer Tayar DP_NOTICE(p_hwfn, "Failed to send load request, rc = %d\n", rc); 7905d24bcf1STomer Tayar return rc; 7915d24bcf1STomer Tayar } 7925d24bcf1STomer Tayar 7935d24bcf1STomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 7945d24bcf1STomer Tayar "Load Response: resp 0x%08x\n", mb_params.mcp_resp); 7955d24bcf1STomer Tayar p_out_params->load_code = mb_params.mcp_resp; 7965d24bcf1STomer Tayar 7975d24bcf1STomer Tayar if (p_in_params->hsi_ver != QED_LOAD_REQ_HSI_VER_1 && 7985d24bcf1STomer Tayar p_out_params->load_code != FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) { 7995d24bcf1STomer Tayar DP_VERBOSE(p_hwfn, 8005d24bcf1STomer Tayar QED_MSG_SP, 8015d24bcf1STomer Tayar "Load Response: exist_drv_ver 0x%08x_0x%08x, exist_fw_ver 0x%08x, misc0 0x%08x [exist_role %d, mfw_hsi %d, flags0 0x%x]\n", 8025d24bcf1STomer Tayar load_rsp.drv_ver_0, 8035d24bcf1STomer Tayar load_rsp.drv_ver_1, 8045d24bcf1STomer Tayar load_rsp.fw_ver, 8055d24bcf1STomer Tayar load_rsp.misc0, 8065d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE), 8075d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI), 8085d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0)); 8095d24bcf1STomer Tayar 8105d24bcf1STomer Tayar p_out_params->exist_drv_ver_0 = load_rsp.drv_ver_0; 8115d24bcf1STomer Tayar p_out_params->exist_drv_ver_1 = load_rsp.drv_ver_1; 8125d24bcf1STomer Tayar p_out_params->exist_fw_ver = load_rsp.fw_ver; 8135d24bcf1STomer Tayar p_out_params->exist_drv_role = 8145d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_ROLE); 8155d24bcf1STomer Tayar p_out_params->mfw_hsi_ver = 8165d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_HSI); 8175d24bcf1STomer Tayar p_out_params->drv_exists = 8185d24bcf1STomer Tayar QED_MFW_GET_FIELD(load_rsp.misc0, LOAD_RSP_FLAGS0) & 8195d24bcf1STomer Tayar LOAD_RSP_FLAGS0_DRV_EXISTS; 8205d24bcf1STomer Tayar } 8215d24bcf1STomer Tayar 8225d24bcf1STomer Tayar return 0; 8235d24bcf1STomer Tayar } 8245d24bcf1STomer Tayar 8255d24bcf1STomer Tayar static int eocre_get_mfw_drv_role(struct qed_hwfn *p_hwfn, 8265d24bcf1STomer Tayar enum qed_drv_role drv_role, 8275d24bcf1STomer Tayar u8 *p_mfw_drv_role) 8285d24bcf1STomer Tayar { 8295d24bcf1STomer Tayar switch (drv_role) { 8305d24bcf1STomer Tayar case QED_DRV_ROLE_OS: 8315d24bcf1STomer Tayar *p_mfw_drv_role = DRV_ROLE_OS; 8325d24bcf1STomer Tayar break; 8335d24bcf1STomer Tayar case QED_DRV_ROLE_KDUMP: 8345d24bcf1STomer Tayar *p_mfw_drv_role = DRV_ROLE_KDUMP; 8355d24bcf1STomer Tayar break; 8365d24bcf1STomer Tayar default: 8375d24bcf1STomer Tayar DP_ERR(p_hwfn, "Unexpected driver role %d\n", drv_role); 8385d24bcf1STomer Tayar return -EINVAL; 8395d24bcf1STomer Tayar } 8405d24bcf1STomer Tayar 8415d24bcf1STomer Tayar return 0; 8425d24bcf1STomer Tayar } 8435d24bcf1STomer Tayar 8445d24bcf1STomer Tayar enum qed_load_req_force { 8455d24bcf1STomer Tayar QED_LOAD_REQ_FORCE_NONE, 8465d24bcf1STomer Tayar QED_LOAD_REQ_FORCE_PF, 8475d24bcf1STomer Tayar QED_LOAD_REQ_FORCE_ALL, 8485d24bcf1STomer Tayar }; 8495d24bcf1STomer Tayar 8505d24bcf1STomer Tayar static void qed_get_mfw_force_cmd(struct qed_hwfn *p_hwfn, 8515d24bcf1STomer Tayar 8525d24bcf1STomer Tayar enum qed_load_req_force force_cmd, 8535d24bcf1STomer Tayar u8 *p_mfw_force_cmd) 8545d24bcf1STomer Tayar { 8555d24bcf1STomer Tayar switch (force_cmd) { 8565d24bcf1STomer Tayar case QED_LOAD_REQ_FORCE_NONE: 8575d24bcf1STomer Tayar *p_mfw_force_cmd = LOAD_REQ_FORCE_NONE; 8585d24bcf1STomer Tayar break; 8595d24bcf1STomer Tayar case QED_LOAD_REQ_FORCE_PF: 8605d24bcf1STomer Tayar *p_mfw_force_cmd = LOAD_REQ_FORCE_PF; 8615d24bcf1STomer Tayar break; 8625d24bcf1STomer Tayar case QED_LOAD_REQ_FORCE_ALL: 8635d24bcf1STomer Tayar *p_mfw_force_cmd = LOAD_REQ_FORCE_ALL; 8645d24bcf1STomer Tayar break; 8655d24bcf1STomer Tayar } 8665d24bcf1STomer Tayar } 8675d24bcf1STomer Tayar 8685d24bcf1STomer Tayar int qed_mcp_load_req(struct qed_hwfn *p_hwfn, 8695d24bcf1STomer Tayar struct qed_ptt *p_ptt, 8705d24bcf1STomer Tayar struct qed_load_req_params *p_params) 8715d24bcf1STomer Tayar { 8725d24bcf1STomer Tayar struct qed_load_req_out_params out_params; 8735d24bcf1STomer Tayar struct qed_load_req_in_params in_params; 8745d24bcf1STomer Tayar u8 mfw_drv_role, mfw_force_cmd; 8755d24bcf1STomer Tayar int rc; 8765d24bcf1STomer Tayar 8775d24bcf1STomer Tayar memset(&in_params, 0, sizeof(in_params)); 8785d24bcf1STomer Tayar in_params.hsi_ver = QED_LOAD_REQ_HSI_VER_DEFAULT; 8795d24bcf1STomer Tayar in_params.drv_ver_0 = QED_VERSION; 8805d24bcf1STomer Tayar in_params.drv_ver_1 = qed_get_config_bitmap(); 8815d24bcf1STomer Tayar in_params.fw_ver = STORM_FW_VERSION; 8825d24bcf1STomer Tayar rc = eocre_get_mfw_drv_role(p_hwfn, p_params->drv_role, &mfw_drv_role); 8835d24bcf1STomer Tayar if (rc) 8845d24bcf1STomer Tayar return rc; 8855d24bcf1STomer Tayar 8865d24bcf1STomer Tayar in_params.drv_role = mfw_drv_role; 8875d24bcf1STomer Tayar in_params.timeout_val = p_params->timeout_val; 8885d24bcf1STomer Tayar qed_get_mfw_force_cmd(p_hwfn, 8895d24bcf1STomer Tayar QED_LOAD_REQ_FORCE_NONE, &mfw_force_cmd); 8905d24bcf1STomer Tayar 8915d24bcf1STomer Tayar in_params.force_cmd = mfw_force_cmd; 8925d24bcf1STomer Tayar in_params.avoid_eng_reset = p_params->avoid_eng_reset; 8935d24bcf1STomer Tayar 8945d24bcf1STomer Tayar memset(&out_params, 0, sizeof(out_params)); 8955d24bcf1STomer Tayar rc = __qed_mcp_load_req(p_hwfn, p_ptt, &in_params, &out_params); 8965d24bcf1STomer Tayar if (rc) 8975d24bcf1STomer Tayar return rc; 8985d24bcf1STomer Tayar 8995d24bcf1STomer Tayar /* First handle cases where another load request should/might be sent: 9005d24bcf1STomer Tayar * - MFW expects the old interface [HSI version = 1] 9015d24bcf1STomer Tayar * - MFW responds that a force load request is required 902fe56b9e6SYuval Mintz */ 9035d24bcf1STomer Tayar if (out_params.load_code == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI_1) { 9045d24bcf1STomer Tayar DP_INFO(p_hwfn, 9055d24bcf1STomer Tayar "MFW refused a load request due to HSI > 1. Resending with HSI = 1\n"); 9065d24bcf1STomer Tayar 9075d24bcf1STomer Tayar in_params.hsi_ver = QED_LOAD_REQ_HSI_VER_1; 9085d24bcf1STomer Tayar memset(&out_params, 0, sizeof(out_params)); 9095d24bcf1STomer Tayar rc = __qed_mcp_load_req(p_hwfn, p_ptt, &in_params, &out_params); 9105d24bcf1STomer Tayar if (rc) 9115d24bcf1STomer Tayar return rc; 9125d24bcf1STomer Tayar } else if (out_params.load_code == 9135d24bcf1STomer Tayar FW_MSG_CODE_DRV_LOAD_REFUSED_REQUIRES_FORCE) { 9145d24bcf1STomer Tayar if (qed_mcp_can_force_load(in_params.drv_role, 9155d24bcf1STomer Tayar out_params.exist_drv_role, 9165d24bcf1STomer Tayar p_params->override_force_load)) { 9175d24bcf1STomer Tayar DP_INFO(p_hwfn, 9185d24bcf1STomer Tayar "A force load is required [{role, fw_ver, drv_ver}: loading={%d, 0x%08x, x%08x_0x%08x}, existing={%d, 0x%08x, 0x%08x_0x%08x}]\n", 9195d24bcf1STomer Tayar in_params.drv_role, in_params.fw_ver, 9205d24bcf1STomer Tayar in_params.drv_ver_0, in_params.drv_ver_1, 9215d24bcf1STomer Tayar out_params.exist_drv_role, 9225d24bcf1STomer Tayar out_params.exist_fw_ver, 9235d24bcf1STomer Tayar out_params.exist_drv_ver_0, 9245d24bcf1STomer Tayar out_params.exist_drv_ver_1); 9255d24bcf1STomer Tayar 9265d24bcf1STomer Tayar qed_get_mfw_force_cmd(p_hwfn, 9275d24bcf1STomer Tayar QED_LOAD_REQ_FORCE_ALL, 9285d24bcf1STomer Tayar &mfw_force_cmd); 9295d24bcf1STomer Tayar 9305d24bcf1STomer Tayar in_params.force_cmd = mfw_force_cmd; 9315d24bcf1STomer Tayar memset(&out_params, 0, sizeof(out_params)); 9325d24bcf1STomer Tayar rc = __qed_mcp_load_req(p_hwfn, p_ptt, &in_params, 9335d24bcf1STomer Tayar &out_params); 9345d24bcf1STomer Tayar if (rc) 9355d24bcf1STomer Tayar return rc; 9365d24bcf1STomer Tayar } else { 9375d24bcf1STomer Tayar DP_NOTICE(p_hwfn, 9385d24bcf1STomer Tayar "A force load is required [{role, fw_ver, drv_ver}: loading={%d, 0x%08x, x%08x_0x%08x}, existing={%d, 0x%08x, 0x%08x_0x%08x}] - Avoid\n", 9395d24bcf1STomer Tayar in_params.drv_role, in_params.fw_ver, 9405d24bcf1STomer Tayar in_params.drv_ver_0, in_params.drv_ver_1, 9415d24bcf1STomer Tayar out_params.exist_drv_role, 9425d24bcf1STomer Tayar out_params.exist_fw_ver, 9435d24bcf1STomer Tayar out_params.exist_drv_ver_0, 9445d24bcf1STomer Tayar out_params.exist_drv_ver_1); 9455d24bcf1STomer Tayar DP_NOTICE(p_hwfn, 9465d24bcf1STomer Tayar "Avoid sending a force load request to prevent disruption of active PFs\n"); 9475d24bcf1STomer Tayar 9485d24bcf1STomer Tayar qed_mcp_cancel_load_req(p_hwfn, p_ptt); 949fe56b9e6SYuval Mintz return -EBUSY; 950fe56b9e6SYuval Mintz } 9515d24bcf1STomer Tayar } 9525d24bcf1STomer Tayar 9535d24bcf1STomer Tayar /* Now handle the other types of responses. 9545d24bcf1STomer Tayar * The "REFUSED_HSI_1" and "REFUSED_REQUIRES_FORCE" responses are not 9555d24bcf1STomer Tayar * expected here after the additional revised load requests were sent. 9565d24bcf1STomer Tayar */ 9575d24bcf1STomer Tayar switch (out_params.load_code) { 9585d24bcf1STomer Tayar case FW_MSG_CODE_DRV_LOAD_ENGINE: 9595d24bcf1STomer Tayar case FW_MSG_CODE_DRV_LOAD_PORT: 9605d24bcf1STomer Tayar case FW_MSG_CODE_DRV_LOAD_FUNCTION: 9615d24bcf1STomer Tayar if (out_params.mfw_hsi_ver != QED_LOAD_REQ_HSI_VER_1 && 9625d24bcf1STomer Tayar out_params.drv_exists) { 9635d24bcf1STomer Tayar /* The role and fw/driver version match, but the PF is 9645d24bcf1STomer Tayar * already loaded and has not been unloaded gracefully. 9655d24bcf1STomer Tayar */ 9665d24bcf1STomer Tayar DP_NOTICE(p_hwfn, 9675d24bcf1STomer Tayar "PF is already loaded\n"); 9685d24bcf1STomer Tayar return -EINVAL; 9695d24bcf1STomer Tayar } 9705d24bcf1STomer Tayar break; 9715d24bcf1STomer Tayar default: 9725d24bcf1STomer Tayar DP_NOTICE(p_hwfn, 9735d24bcf1STomer Tayar "Unexpected refusal to load request [resp 0x%08x]. Aborting.\n", 9745d24bcf1STomer Tayar out_params.load_code); 9755d24bcf1STomer Tayar return -EBUSY; 9765d24bcf1STomer Tayar } 9775d24bcf1STomer Tayar 9785d24bcf1STomer Tayar p_params->load_code = out_params.load_code; 979fe56b9e6SYuval Mintz 980fe56b9e6SYuval Mintz return 0; 981fe56b9e6SYuval Mintz } 982fe56b9e6SYuval Mintz 9831226337aSTomer Tayar int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 9841226337aSTomer Tayar { 9851226337aSTomer Tayar u32 wol_param, mcp_resp, mcp_param; 9861226337aSTomer Tayar 9871226337aSTomer Tayar switch (p_hwfn->cdev->wol_config) { 9881226337aSTomer Tayar case QED_OV_WOL_DISABLED: 9891226337aSTomer Tayar wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED; 9901226337aSTomer Tayar break; 9911226337aSTomer Tayar case QED_OV_WOL_ENABLED: 9921226337aSTomer Tayar wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED; 9931226337aSTomer Tayar break; 9941226337aSTomer Tayar default: 9951226337aSTomer Tayar DP_NOTICE(p_hwfn, 9961226337aSTomer Tayar "Unknown WoL configuration %02x\n", 9971226337aSTomer Tayar p_hwfn->cdev->wol_config); 9981226337aSTomer Tayar /* Fallthrough */ 9991226337aSTomer Tayar case QED_OV_WOL_DEFAULT: 10001226337aSTomer Tayar wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP; 10011226337aSTomer Tayar } 10021226337aSTomer Tayar 10031226337aSTomer Tayar return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param, 10041226337aSTomer Tayar &mcp_resp, &mcp_param); 10051226337aSTomer Tayar } 10061226337aSTomer Tayar 10071226337aSTomer Tayar int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 10081226337aSTomer Tayar { 10091226337aSTomer Tayar struct qed_mcp_mb_params mb_params; 10101226337aSTomer Tayar struct mcp_mac wol_mac; 10111226337aSTomer Tayar 10121226337aSTomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 10131226337aSTomer Tayar mb_params.cmd = DRV_MSG_CODE_UNLOAD_DONE; 10141226337aSTomer Tayar 10151226337aSTomer Tayar /* Set the primary MAC if WoL is enabled */ 10161226337aSTomer Tayar if (p_hwfn->cdev->wol_config == QED_OV_WOL_ENABLED) { 10171226337aSTomer Tayar u8 *p_mac = p_hwfn->cdev->wol_mac; 10181226337aSTomer Tayar 10191226337aSTomer Tayar memset(&wol_mac, 0, sizeof(wol_mac)); 10201226337aSTomer Tayar wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1]; 10211226337aSTomer Tayar wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 | 10221226337aSTomer Tayar p_mac[4] << 8 | p_mac[5]; 10231226337aSTomer Tayar 10241226337aSTomer Tayar DP_VERBOSE(p_hwfn, 10251226337aSTomer Tayar (QED_MSG_SP | NETIF_MSG_IFDOWN), 10261226337aSTomer Tayar "Setting WoL MAC: %pM --> [%08x,%08x]\n", 10271226337aSTomer Tayar p_mac, wol_mac.mac_upper, wol_mac.mac_lower); 10281226337aSTomer Tayar 10291226337aSTomer Tayar mb_params.p_data_src = &wol_mac; 10301226337aSTomer Tayar mb_params.data_src_size = sizeof(wol_mac); 10311226337aSTomer Tayar } 10321226337aSTomer Tayar 10331226337aSTomer Tayar return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 10341226337aSTomer Tayar } 10351226337aSTomer Tayar 10360b55e27dSYuval Mintz static void qed_mcp_handle_vf_flr(struct qed_hwfn *p_hwfn, 10370b55e27dSYuval Mintz struct qed_ptt *p_ptt) 10380b55e27dSYuval Mintz { 10390b55e27dSYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 10400b55e27dSYuval Mintz PUBLIC_PATH); 10410b55e27dSYuval Mintz u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); 10420b55e27dSYuval Mintz u32 path_addr = SECTION_ADDR(mfw_path_offsize, 10430b55e27dSYuval Mintz QED_PATH_ID(p_hwfn)); 10440b55e27dSYuval Mintz u32 disabled_vfs[VF_MAX_STATIC / 32]; 10450b55e27dSYuval Mintz int i; 10460b55e27dSYuval Mintz 10470b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, 10480b55e27dSYuval Mintz QED_MSG_SP, 10490b55e27dSYuval Mintz "Reading Disabled VF information from [offset %08x], path_addr %08x\n", 10500b55e27dSYuval Mintz mfw_path_offsize, path_addr); 10510b55e27dSYuval Mintz 10520b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) { 10530b55e27dSYuval Mintz disabled_vfs[i] = qed_rd(p_hwfn, p_ptt, 10540b55e27dSYuval Mintz path_addr + 10550b55e27dSYuval Mintz offsetof(struct public_path, 10560b55e27dSYuval Mintz mcp_vf_disabled) + 10570b55e27dSYuval Mintz sizeof(u32) * i); 10580b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | QED_MSG_IOV), 10590b55e27dSYuval Mintz "FLR-ed VFs [%08x,...,%08x] - %08x\n", 10600b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, disabled_vfs[i]); 10610b55e27dSYuval Mintz } 10620b55e27dSYuval Mintz 10630b55e27dSYuval Mintz if (qed_iov_mark_vf_flr(p_hwfn, disabled_vfs)) 10640b55e27dSYuval Mintz qed_schedule_iov(p_hwfn, QED_IOV_WQ_FLR_FLAG); 10650b55e27dSYuval Mintz } 10660b55e27dSYuval Mintz 10670b55e27dSYuval Mintz int qed_mcp_ack_vf_flr(struct qed_hwfn *p_hwfn, 10680b55e27dSYuval Mintz struct qed_ptt *p_ptt, u32 *vfs_to_ack) 10690b55e27dSYuval Mintz { 10700b55e27dSYuval Mintz u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 10710b55e27dSYuval Mintz PUBLIC_FUNC); 10720b55e27dSYuval Mintz u32 mfw_func_offsize = qed_rd(p_hwfn, p_ptt, addr); 10730b55e27dSYuval Mintz u32 func_addr = SECTION_ADDR(mfw_func_offsize, 10740b55e27dSYuval Mintz MCP_PF_ID(p_hwfn)); 10750b55e27dSYuval Mintz struct qed_mcp_mb_params mb_params; 10760b55e27dSYuval Mintz int rc; 10770b55e27dSYuval Mintz int i; 10780b55e27dSYuval Mintz 10790b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 10800b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | QED_MSG_IOV), 10810b55e27dSYuval Mintz "Acking VFs [%08x,...,%08x] - %08x\n", 10820b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, vfs_to_ack[i]); 10830b55e27dSYuval Mintz 10840b55e27dSYuval Mintz memset(&mb_params, 0, sizeof(mb_params)); 10850b55e27dSYuval Mintz mb_params.cmd = DRV_MSG_CODE_VF_DISABLED_DONE; 10862f67af8cSTomer Tayar mb_params.p_data_src = vfs_to_ack; 10872f67af8cSTomer Tayar mb_params.data_src_size = VF_MAX_STATIC / 8; 10880b55e27dSYuval Mintz rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 10890b55e27dSYuval Mintz if (rc) { 10900b55e27dSYuval Mintz DP_NOTICE(p_hwfn, "Failed to pass ACK for VF flr to MFW\n"); 10910b55e27dSYuval Mintz return -EBUSY; 10920b55e27dSYuval Mintz } 10930b55e27dSYuval Mintz 10940b55e27dSYuval Mintz /* Clear the ACK bits */ 10950b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 10960b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, 10970b55e27dSYuval Mintz func_addr + 10980b55e27dSYuval Mintz offsetof(struct public_func, drv_ack_vf_disabled) + 10990b55e27dSYuval Mintz i * sizeof(u32), 0); 11000b55e27dSYuval Mintz 11010b55e27dSYuval Mintz return rc; 11020b55e27dSYuval Mintz } 11030b55e27dSYuval Mintz 1104334c03b5SZvi Nachmani static void qed_mcp_handle_transceiver_change(struct qed_hwfn *p_hwfn, 1105334c03b5SZvi Nachmani struct qed_ptt *p_ptt) 1106334c03b5SZvi Nachmani { 1107334c03b5SZvi Nachmani u32 transceiver_state; 1108334c03b5SZvi Nachmani 1109334c03b5SZvi Nachmani transceiver_state = qed_rd(p_hwfn, p_ptt, 1110334c03b5SZvi Nachmani p_hwfn->mcp_info->port_addr + 1111334c03b5SZvi Nachmani offsetof(struct public_port, 1112334c03b5SZvi Nachmani transceiver_data)); 1113334c03b5SZvi Nachmani 1114334c03b5SZvi Nachmani DP_VERBOSE(p_hwfn, 1115334c03b5SZvi Nachmani (NETIF_MSG_HW | QED_MSG_SP), 1116334c03b5SZvi Nachmani "Received transceiver state update [0x%08x] from mfw [Addr 0x%x]\n", 1117334c03b5SZvi Nachmani transceiver_state, 1118334c03b5SZvi Nachmani (u32)(p_hwfn->mcp_info->port_addr + 11191a635e48SYuval Mintz offsetof(struct public_port, transceiver_data))); 1120334c03b5SZvi Nachmani 1121334c03b5SZvi Nachmani transceiver_state = GET_FIELD(transceiver_state, 1122351a4dedSYuval Mintz ETH_TRANSCEIVER_STATE); 1123334c03b5SZvi Nachmani 1124351a4dedSYuval Mintz if (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT) 1125334c03b5SZvi Nachmani DP_NOTICE(p_hwfn, "Transceiver is present.\n"); 1126334c03b5SZvi Nachmani else 1127334c03b5SZvi Nachmani DP_NOTICE(p_hwfn, "Transceiver is unplugged.\n"); 1128334c03b5SZvi Nachmani } 1129334c03b5SZvi Nachmani 1130645874e5SSudarsana Reddy Kalluru static void qed_mcp_read_eee_config(struct qed_hwfn *p_hwfn, 1131645874e5SSudarsana Reddy Kalluru struct qed_ptt *p_ptt, 1132645874e5SSudarsana Reddy Kalluru struct qed_mcp_link_state *p_link) 1133645874e5SSudarsana Reddy Kalluru { 1134645874e5SSudarsana Reddy Kalluru u32 eee_status, val; 1135645874e5SSudarsana Reddy Kalluru 1136645874e5SSudarsana Reddy Kalluru p_link->eee_adv_caps = 0; 1137645874e5SSudarsana Reddy Kalluru p_link->eee_lp_adv_caps = 0; 1138645874e5SSudarsana Reddy Kalluru eee_status = qed_rd(p_hwfn, 1139645874e5SSudarsana Reddy Kalluru p_ptt, 1140645874e5SSudarsana Reddy Kalluru p_hwfn->mcp_info->port_addr + 1141645874e5SSudarsana Reddy Kalluru offsetof(struct public_port, eee_status)); 1142645874e5SSudarsana Reddy Kalluru p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT); 1143645874e5SSudarsana Reddy Kalluru val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_OFFSET; 1144645874e5SSudarsana Reddy Kalluru if (val & EEE_1G_ADV) 1145645874e5SSudarsana Reddy Kalluru p_link->eee_adv_caps |= QED_EEE_1G_ADV; 1146645874e5SSudarsana Reddy Kalluru if (val & EEE_10G_ADV) 1147645874e5SSudarsana Reddy Kalluru p_link->eee_adv_caps |= QED_EEE_10G_ADV; 1148645874e5SSudarsana Reddy Kalluru val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_OFFSET; 1149645874e5SSudarsana Reddy Kalluru if (val & EEE_1G_ADV) 1150645874e5SSudarsana Reddy Kalluru p_link->eee_lp_adv_caps |= QED_EEE_1G_ADV; 1151645874e5SSudarsana Reddy Kalluru if (val & EEE_10G_ADV) 1152645874e5SSudarsana Reddy Kalluru p_link->eee_lp_adv_caps |= QED_EEE_10G_ADV; 1153645874e5SSudarsana Reddy Kalluru } 1154645874e5SSudarsana Reddy Kalluru 1155cc875c2eSYuval Mintz static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, 11561a635e48SYuval Mintz struct qed_ptt *p_ptt, bool b_reset) 1157cc875c2eSYuval Mintz { 1158cc875c2eSYuval Mintz struct qed_mcp_link_state *p_link; 1159a64b02d5SManish Chopra u8 max_bw, min_bw; 1160cc875c2eSYuval Mintz u32 status = 0; 1161cc875c2eSYuval Mintz 116265ed2ffdSMintz, Yuval /* Prevent SW/attentions from doing this at the same time */ 116365ed2ffdSMintz, Yuval spin_lock_bh(&p_hwfn->mcp_info->link_lock); 116465ed2ffdSMintz, Yuval 1165cc875c2eSYuval Mintz p_link = &p_hwfn->mcp_info->link_output; 1166cc875c2eSYuval Mintz memset(p_link, 0, sizeof(*p_link)); 1167cc875c2eSYuval Mintz if (!b_reset) { 1168cc875c2eSYuval Mintz status = qed_rd(p_hwfn, p_ptt, 1169cc875c2eSYuval Mintz p_hwfn->mcp_info->port_addr + 1170cc875c2eSYuval Mintz offsetof(struct public_port, link_status)); 1171cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, (NETIF_MSG_LINK | QED_MSG_SP), 1172cc875c2eSYuval Mintz "Received link update [0x%08x] from mfw [Addr 0x%x]\n", 1173cc875c2eSYuval Mintz status, 1174cc875c2eSYuval Mintz (u32)(p_hwfn->mcp_info->port_addr + 11751a635e48SYuval Mintz offsetof(struct public_port, link_status))); 1176cc875c2eSYuval Mintz } else { 1177cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 1178cc875c2eSYuval Mintz "Resetting link indications\n"); 117965ed2ffdSMintz, Yuval goto out; 1180cc875c2eSYuval Mintz } 1181cc875c2eSYuval Mintz 1182fc916ff2SSudarsana Reddy Kalluru if (p_hwfn->b_drv_link_init) 1183cc875c2eSYuval Mintz p_link->link_up = !!(status & LINK_STATUS_LINK_UP); 1184fc916ff2SSudarsana Reddy Kalluru else 1185fc916ff2SSudarsana Reddy Kalluru p_link->link_up = false; 1186cc875c2eSYuval Mintz 1187cc875c2eSYuval Mintz p_link->full_duplex = true; 1188cc875c2eSYuval Mintz switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) { 1189cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_100G: 1190cc875c2eSYuval Mintz p_link->speed = 100000; 1191cc875c2eSYuval Mintz break; 1192cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_50G: 1193cc875c2eSYuval Mintz p_link->speed = 50000; 1194cc875c2eSYuval Mintz break; 1195cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_40G: 1196cc875c2eSYuval Mintz p_link->speed = 40000; 1197cc875c2eSYuval Mintz break; 1198cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_25G: 1199cc875c2eSYuval Mintz p_link->speed = 25000; 1200cc875c2eSYuval Mintz break; 1201cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_20G: 1202cc875c2eSYuval Mintz p_link->speed = 20000; 1203cc875c2eSYuval Mintz break; 1204cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_10G: 1205cc875c2eSYuval Mintz p_link->speed = 10000; 1206cc875c2eSYuval Mintz break; 1207cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_1000THD: 1208cc875c2eSYuval Mintz p_link->full_duplex = false; 1209cc875c2eSYuval Mintz /* Fall-through */ 1210cc875c2eSYuval Mintz case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD: 1211cc875c2eSYuval Mintz p_link->speed = 1000; 1212cc875c2eSYuval Mintz break; 1213cc875c2eSYuval Mintz default: 1214cc875c2eSYuval Mintz p_link->speed = 0; 121558874c7bSSudarsana Reddy Kalluru p_link->link_up = 0; 1216cc875c2eSYuval Mintz } 1217cc875c2eSYuval Mintz 12184b01e519SManish Chopra if (p_link->link_up && p_link->speed) 12194b01e519SManish Chopra p_link->line_speed = p_link->speed; 12204b01e519SManish Chopra else 12214b01e519SManish Chopra p_link->line_speed = 0; 12224b01e519SManish Chopra 12234b01e519SManish Chopra max_bw = p_hwfn->mcp_info->func_info.bandwidth_max; 1224a64b02d5SManish Chopra min_bw = p_hwfn->mcp_info->func_info.bandwidth_min; 12254b01e519SManish Chopra 1226a64b02d5SManish Chopra /* Max bandwidth configuration */ 12274b01e519SManish Chopra __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw); 1228cc875c2eSYuval Mintz 1229a64b02d5SManish Chopra /* Min bandwidth configuration */ 1230a64b02d5SManish Chopra __qed_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw); 12316f437d43SMintz, Yuval qed_configure_vp_wfq_on_link_change(p_hwfn->cdev, p_ptt, 12326f437d43SMintz, Yuval p_link->min_pf_rate); 1233a64b02d5SManish Chopra 1234cc875c2eSYuval Mintz p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED); 1235cc875c2eSYuval Mintz p_link->an_complete = !!(status & 1236cc875c2eSYuval Mintz LINK_STATUS_AUTO_NEGOTIATE_COMPLETE); 1237cc875c2eSYuval Mintz p_link->parallel_detection = !!(status & 1238cc875c2eSYuval Mintz LINK_STATUS_PARALLEL_DETECTION_USED); 1239cc875c2eSYuval Mintz p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED); 1240cc875c2eSYuval Mintz 1241cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1242cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ? 1243cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_1G_FD : 0; 1244cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1245cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ? 1246cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_1G_HD : 0; 1247cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1248cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ? 1249cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_10G : 0; 1250cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1251cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ? 1252cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_20G : 0; 1253cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1254054c67d1SSudarsana Reddy Kalluru (status & LINK_STATUS_LINK_PARTNER_25G_CAPABLE) ? 1255054c67d1SSudarsana Reddy Kalluru QED_LINK_PARTNER_SPEED_25G : 0; 1256054c67d1SSudarsana Reddy Kalluru p_link->partner_adv_speed |= 1257cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ? 1258cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_40G : 0; 1259cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1260cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ? 1261cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_50G : 0; 1262cc875c2eSYuval Mintz p_link->partner_adv_speed |= 1263cc875c2eSYuval Mintz (status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ? 1264cc875c2eSYuval Mintz QED_LINK_PARTNER_SPEED_100G : 0; 1265cc875c2eSYuval Mintz 1266cc875c2eSYuval Mintz p_link->partner_tx_flow_ctrl_en = 1267cc875c2eSYuval Mintz !!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED); 1268cc875c2eSYuval Mintz p_link->partner_rx_flow_ctrl_en = 1269cc875c2eSYuval Mintz !!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED); 1270cc875c2eSYuval Mintz 1271cc875c2eSYuval Mintz switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) { 1272cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE: 1273cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_SYMMETRIC_PAUSE; 1274cc875c2eSYuval Mintz break; 1275cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE: 1276cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_ASYMMETRIC_PAUSE; 1277cc875c2eSYuval Mintz break; 1278cc875c2eSYuval Mintz case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE: 1279cc875c2eSYuval Mintz p_link->partner_adv_pause = QED_LINK_PARTNER_BOTH_PAUSE; 1280cc875c2eSYuval Mintz break; 1281cc875c2eSYuval Mintz default: 1282cc875c2eSYuval Mintz p_link->partner_adv_pause = 0; 1283cc875c2eSYuval Mintz } 1284cc875c2eSYuval Mintz 1285cc875c2eSYuval Mintz p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT); 1286cc875c2eSYuval Mintz 1287645874e5SSudarsana Reddy Kalluru if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) 1288645874e5SSudarsana Reddy Kalluru qed_mcp_read_eee_config(p_hwfn, p_ptt, p_link); 1289645874e5SSudarsana Reddy Kalluru 1290cc875c2eSYuval Mintz qed_link_update(p_hwfn); 129165ed2ffdSMintz, Yuval out: 129265ed2ffdSMintz, Yuval spin_unlock_bh(&p_hwfn->mcp_info->link_lock); 1293cc875c2eSYuval Mintz } 1294cc875c2eSYuval Mintz 1295351a4dedSYuval Mintz int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up) 1296cc875c2eSYuval Mintz { 1297cc875c2eSYuval Mintz struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input; 12985529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 12992f67af8cSTomer Tayar struct eth_phy_cfg phy_cfg; 1300cc875c2eSYuval Mintz int rc = 0; 13015529bad9STomer Tayar u32 cmd; 1302cc875c2eSYuval Mintz 1303cc875c2eSYuval Mintz /* Set the shmem configuration according to params */ 13042f67af8cSTomer Tayar memset(&phy_cfg, 0, sizeof(phy_cfg)); 1305cc875c2eSYuval Mintz cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET; 1306cc875c2eSYuval Mintz if (!params->speed.autoneg) 13072f67af8cSTomer Tayar phy_cfg.speed = params->speed.forced_speed; 13082f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.autoneg) ? ETH_PAUSE_AUTONEG : 0; 13092f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.forced_rx) ? ETH_PAUSE_RX : 0; 13102f67af8cSTomer Tayar phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0; 13112f67af8cSTomer Tayar phy_cfg.adv_speed = params->speed.advertised_speeds; 13122f67af8cSTomer Tayar phy_cfg.loopback_mode = params->loopback_mode; 13134ad95a93SSudarsana Reddy Kalluru 13144ad95a93SSudarsana Reddy Kalluru /* There are MFWs that share this capability regardless of whether 13154ad95a93SSudarsana Reddy Kalluru * this is feasible or not. And given that at the very least adv_caps 13164ad95a93SSudarsana Reddy Kalluru * would be set internally by qed, we want to make sure LFA would 13174ad95a93SSudarsana Reddy Kalluru * still work. 13184ad95a93SSudarsana Reddy Kalluru */ 13194ad95a93SSudarsana Reddy Kalluru if ((p_hwfn->mcp_info->capabilities & 13204ad95a93SSudarsana Reddy Kalluru FW_MB_PARAM_FEATURE_SUPPORT_EEE) && params->eee.enable) { 1321645874e5SSudarsana Reddy Kalluru phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED; 1322645874e5SSudarsana Reddy Kalluru if (params->eee.tx_lpi_enable) 1323645874e5SSudarsana Reddy Kalluru phy_cfg.eee_cfg |= EEE_CFG_TX_LPI; 1324645874e5SSudarsana Reddy Kalluru if (params->eee.adv_caps & QED_EEE_1G_ADV) 1325645874e5SSudarsana Reddy Kalluru phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G; 1326645874e5SSudarsana Reddy Kalluru if (params->eee.adv_caps & QED_EEE_10G_ADV) 1327645874e5SSudarsana Reddy Kalluru phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G; 1328645874e5SSudarsana Reddy Kalluru phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer << 1329645874e5SSudarsana Reddy Kalluru EEE_TX_TIMER_USEC_OFFSET) & 1330645874e5SSudarsana Reddy Kalluru EEE_TX_TIMER_USEC_MASK; 1331645874e5SSudarsana Reddy Kalluru } 1332cc875c2eSYuval Mintz 1333fc916ff2SSudarsana Reddy Kalluru p_hwfn->b_drv_link_init = b_up; 1334fc916ff2SSudarsana Reddy Kalluru 1335cc875c2eSYuval Mintz if (b_up) { 1336cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 1337cc875c2eSYuval Mintz "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n", 13382f67af8cSTomer Tayar phy_cfg.speed, 13392f67af8cSTomer Tayar phy_cfg.pause, 13402f67af8cSTomer Tayar phy_cfg.adv_speed, 13412f67af8cSTomer Tayar phy_cfg.loopback_mode, 13422f67af8cSTomer Tayar phy_cfg.feature_config_flags); 1343cc875c2eSYuval Mintz } else { 1344cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 1345cc875c2eSYuval Mintz "Resetting link\n"); 1346cc875c2eSYuval Mintz } 1347cc875c2eSYuval Mintz 13485529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 13495529bad9STomer Tayar mb_params.cmd = cmd; 13502f67af8cSTomer Tayar mb_params.p_data_src = &phy_cfg; 13512f67af8cSTomer Tayar mb_params.data_src_size = sizeof(phy_cfg); 13525529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 1353cc875c2eSYuval Mintz 1354cc875c2eSYuval Mintz /* if mcp fails to respond we must abort */ 1355cc875c2eSYuval Mintz if (rc) { 1356cc875c2eSYuval Mintz DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 1357cc875c2eSYuval Mintz return rc; 1358cc875c2eSYuval Mintz } 1359cc875c2eSYuval Mintz 136065ed2ffdSMintz, Yuval /* Mimic link-change attention, done for several reasons: 136165ed2ffdSMintz, Yuval * - On reset, there's no guarantee MFW would trigger 136265ed2ffdSMintz, Yuval * an attention. 136365ed2ffdSMintz, Yuval * - On initialization, older MFWs might not indicate link change 136465ed2ffdSMintz, Yuval * during LFA, so we'll never get an UP indication. 136565ed2ffdSMintz, Yuval */ 136665ed2ffdSMintz, Yuval qed_mcp_handle_link_change(p_hwfn, p_ptt, !b_up); 1367cc875c2eSYuval Mintz 1368cc875c2eSYuval Mintz return 0; 1369cc875c2eSYuval Mintz } 1370cc875c2eSYuval Mintz 13716c754246SSudarsana Reddy Kalluru static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn, 13726c754246SSudarsana Reddy Kalluru struct qed_ptt *p_ptt, 13736c754246SSudarsana Reddy Kalluru enum MFW_DRV_MSG_TYPE type) 13746c754246SSudarsana Reddy Kalluru { 13756c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type stats_type; 13766c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats stats; 13776c754246SSudarsana Reddy Kalluru struct qed_mcp_mb_params mb_params; 13786c754246SSudarsana Reddy Kalluru u32 hsi_param; 13796c754246SSudarsana Reddy Kalluru 13806c754246SSudarsana Reddy Kalluru switch (type) { 13816c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_LAN_STATS: 13826c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_LAN_STATS; 13836c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN; 13846c754246SSudarsana Reddy Kalluru break; 13856c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_FCOE_STATS: 13866c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_FCOE_STATS; 13876c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_FCOE; 13886c754246SSudarsana Reddy Kalluru break; 13896c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_ISCSI_STATS: 13906c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_ISCSI_STATS; 13916c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_ISCSI; 13926c754246SSudarsana Reddy Kalluru break; 13936c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_RDMA_STATS: 13946c754246SSudarsana Reddy Kalluru stats_type = QED_MCP_RDMA_STATS; 13956c754246SSudarsana Reddy Kalluru hsi_param = DRV_MSG_CODE_STATS_TYPE_RDMA; 13966c754246SSudarsana Reddy Kalluru break; 13976c754246SSudarsana Reddy Kalluru default: 13986c754246SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Invalid protocol type %d\n", type); 13996c754246SSudarsana Reddy Kalluru return; 14006c754246SSudarsana Reddy Kalluru } 14016c754246SSudarsana Reddy Kalluru 14026c754246SSudarsana Reddy Kalluru qed_get_protocol_stats(p_hwfn->cdev, stats_type, &stats); 14036c754246SSudarsana Reddy Kalluru 14046c754246SSudarsana Reddy Kalluru memset(&mb_params, 0, sizeof(mb_params)); 14056c754246SSudarsana Reddy Kalluru mb_params.cmd = DRV_MSG_CODE_GET_STATS; 14066c754246SSudarsana Reddy Kalluru mb_params.param = hsi_param; 14072f67af8cSTomer Tayar mb_params.p_data_src = &stats; 14082f67af8cSTomer Tayar mb_params.data_src_size = sizeof(stats); 14096c754246SSudarsana Reddy Kalluru qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 14106c754246SSudarsana Reddy Kalluru } 14116c754246SSudarsana Reddy Kalluru 14124b01e519SManish Chopra static void qed_read_pf_bandwidth(struct qed_hwfn *p_hwfn, 14134b01e519SManish Chopra struct public_func *p_shmem_info) 14144b01e519SManish Chopra { 14154b01e519SManish Chopra struct qed_mcp_function_info *p_info; 14164b01e519SManish Chopra 14174b01e519SManish Chopra p_info = &p_hwfn->mcp_info->func_info; 14184b01e519SManish Chopra 14194b01e519SManish Chopra p_info->bandwidth_min = (p_shmem_info->config & 14204b01e519SManish Chopra FUNC_MF_CFG_MIN_BW_MASK) >> 14214b01e519SManish Chopra FUNC_MF_CFG_MIN_BW_SHIFT; 14224b01e519SManish Chopra if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) { 14234b01e519SManish Chopra DP_INFO(p_hwfn, 14244b01e519SManish Chopra "bandwidth minimum out of bounds [%02x]. Set to 1\n", 14254b01e519SManish Chopra p_info->bandwidth_min); 14264b01e519SManish Chopra p_info->bandwidth_min = 1; 14274b01e519SManish Chopra } 14284b01e519SManish Chopra 14294b01e519SManish Chopra p_info->bandwidth_max = (p_shmem_info->config & 14304b01e519SManish Chopra FUNC_MF_CFG_MAX_BW_MASK) >> 14314b01e519SManish Chopra FUNC_MF_CFG_MAX_BW_SHIFT; 14324b01e519SManish Chopra if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) { 14334b01e519SManish Chopra DP_INFO(p_hwfn, 14344b01e519SManish Chopra "bandwidth maximum out of bounds [%02x]. Set to 100\n", 14354b01e519SManish Chopra p_info->bandwidth_max); 14364b01e519SManish Chopra p_info->bandwidth_max = 100; 14374b01e519SManish Chopra } 14384b01e519SManish Chopra } 14394b01e519SManish Chopra 14404b01e519SManish Chopra static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, 14414b01e519SManish Chopra struct qed_ptt *p_ptt, 14421a635e48SYuval Mintz struct public_func *p_data, int pfid) 14434b01e519SManish Chopra { 14444b01e519SManish Chopra u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 14454b01e519SManish Chopra PUBLIC_FUNC); 14464b01e519SManish Chopra u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); 14474b01e519SManish Chopra u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid); 14484b01e519SManish Chopra u32 i, size; 14494b01e519SManish Chopra 14504b01e519SManish Chopra memset(p_data, 0, sizeof(*p_data)); 14514b01e519SManish Chopra 14521a635e48SYuval Mintz size = min_t(u32, sizeof(*p_data), QED_SECTION_SIZE(mfw_path_offsize)); 14534b01e519SManish Chopra for (i = 0; i < size / sizeof(u32); i++) 14544b01e519SManish Chopra ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt, 14554b01e519SManish Chopra func_addr + (i << 2)); 14564b01e519SManish Chopra return size; 14574b01e519SManish Chopra } 14584b01e519SManish Chopra 14591a635e48SYuval Mintz static void qed_mcp_update_bw(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 14604b01e519SManish Chopra { 14614b01e519SManish Chopra struct qed_mcp_function_info *p_info; 14624b01e519SManish Chopra struct public_func shmem_info; 14634b01e519SManish Chopra u32 resp = 0, param = 0; 14644b01e519SManish Chopra 14651a635e48SYuval Mintz qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 14664b01e519SManish Chopra 14674b01e519SManish Chopra qed_read_pf_bandwidth(p_hwfn, &shmem_info); 14684b01e519SManish Chopra 14694b01e519SManish Chopra p_info = &p_hwfn->mcp_info->func_info; 14704b01e519SManish Chopra 1471a64b02d5SManish Chopra qed_configure_pf_min_bandwidth(p_hwfn->cdev, p_info->bandwidth_min); 14724b01e519SManish Chopra qed_configure_pf_max_bandwidth(p_hwfn->cdev, p_info->bandwidth_max); 14734b01e519SManish Chopra 14744b01e519SManish Chopra /* Acknowledge the MFW */ 14754b01e519SManish Chopra qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp, 14764b01e519SManish Chopra ¶m); 14774b01e519SManish Chopra } 14784b01e519SManish Chopra 14792a351fd9SMintz, Yuval static void qed_mcp_update_stag(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 14802a351fd9SMintz, Yuval { 14812a351fd9SMintz, Yuval struct public_func shmem_info; 14822a351fd9SMintz, Yuval u32 resp = 0, param = 0; 14832a351fd9SMintz, Yuval 14842a351fd9SMintz, Yuval qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 14852a351fd9SMintz, Yuval 14862a351fd9SMintz, Yuval p_hwfn->mcp_info->func_info.ovlan = (u16)shmem_info.ovlan_stag & 14872a351fd9SMintz, Yuval FUNC_MF_CFG_OV_STAG_MASK; 14882a351fd9SMintz, Yuval p_hwfn->hw_info.ovlan = p_hwfn->mcp_info->func_info.ovlan; 14892a351fd9SMintz, Yuval if ((p_hwfn->hw_info.hw_mode & BIT(MODE_MF_SD)) && 14902a351fd9SMintz, Yuval (p_hwfn->hw_info.ovlan != QED_MCP_VLAN_UNSET)) { 14912a351fd9SMintz, Yuval qed_wr(p_hwfn, p_ptt, 14922a351fd9SMintz, Yuval NIG_REG_LLH_FUNC_TAG_VALUE, p_hwfn->hw_info.ovlan); 14932a351fd9SMintz, Yuval qed_sp_pf_update_stag(p_hwfn); 14942a351fd9SMintz, Yuval } 14952a351fd9SMintz, Yuval 14962a351fd9SMintz, Yuval /* Acknowledge the MFW */ 14972a351fd9SMintz, Yuval qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_S_TAG_UPDATE_ACK, 0, 14982a351fd9SMintz, Yuval &resp, ¶m); 14992a351fd9SMintz, Yuval } 15002a351fd9SMintz, Yuval 1501cac6f691SSudarsana Reddy Kalluru void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 1502cac6f691SSudarsana Reddy Kalluru { 1503cac6f691SSudarsana Reddy Kalluru struct public_func shmem_info; 1504cac6f691SSudarsana Reddy Kalluru u32 port_cfg, val; 1505cac6f691SSudarsana Reddy Kalluru 1506cac6f691SSudarsana Reddy Kalluru if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) 1507cac6f691SSudarsana Reddy Kalluru return; 1508cac6f691SSudarsana Reddy Kalluru 1509cac6f691SSudarsana Reddy Kalluru memset(&p_hwfn->ufp_info, 0, sizeof(p_hwfn->ufp_info)); 1510cac6f691SSudarsana Reddy Kalluru port_cfg = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr + 1511cac6f691SSudarsana Reddy Kalluru offsetof(struct public_port, oem_cfg_port)); 1512cac6f691SSudarsana Reddy Kalluru val = (port_cfg & OEM_CFG_CHANNEL_TYPE_MASK) >> 1513cac6f691SSudarsana Reddy Kalluru OEM_CFG_CHANNEL_TYPE_OFFSET; 1514cac6f691SSudarsana Reddy Kalluru if (val != OEM_CFG_CHANNEL_TYPE_STAGGED) 1515cac6f691SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Incorrect UFP Channel type %d\n", val); 1516cac6f691SSudarsana Reddy Kalluru 1517cac6f691SSudarsana Reddy Kalluru val = (port_cfg & OEM_CFG_SCHED_TYPE_MASK) >> OEM_CFG_SCHED_TYPE_OFFSET; 1518cac6f691SSudarsana Reddy Kalluru if (val == OEM_CFG_SCHED_TYPE_ETS) { 1519cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.mode = QED_UFP_MODE_ETS; 1520cac6f691SSudarsana Reddy Kalluru } else if (val == OEM_CFG_SCHED_TYPE_VNIC_BW) { 1521cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.mode = QED_UFP_MODE_VNIC_BW; 1522cac6f691SSudarsana Reddy Kalluru } else { 1523cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.mode = QED_UFP_MODE_UNKNOWN; 1524cac6f691SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Unknown UFP scheduling mode %d\n", val); 1525cac6f691SSudarsana Reddy Kalluru } 1526cac6f691SSudarsana Reddy Kalluru 1527cac6f691SSudarsana Reddy Kalluru qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 1528b5fabb08SSudarsana Reddy Kalluru val = (shmem_info.oem_cfg_func & OEM_CFG_FUNC_TC_MASK) >> 1529b5fabb08SSudarsana Reddy Kalluru OEM_CFG_FUNC_TC_OFFSET; 1530cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.tc = (u8)val; 1531b5fabb08SSudarsana Reddy Kalluru val = (shmem_info.oem_cfg_func & OEM_CFG_FUNC_HOST_PRI_CTRL_MASK) >> 1532cac6f691SSudarsana Reddy Kalluru OEM_CFG_FUNC_HOST_PRI_CTRL_OFFSET; 1533cac6f691SSudarsana Reddy Kalluru if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_VNIC) { 1534cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.pri_type = QED_UFP_PRI_VNIC; 1535cac6f691SSudarsana Reddy Kalluru } else if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_OS) { 1536cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.pri_type = QED_UFP_PRI_OS; 1537cac6f691SSudarsana Reddy Kalluru } else { 1538cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.pri_type = QED_UFP_PRI_UNKNOWN; 1539cac6f691SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Unknown Host priority control %d\n", val); 1540cac6f691SSudarsana Reddy Kalluru } 1541cac6f691SSudarsana Reddy Kalluru 1542cac6f691SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, 1543cac6f691SSudarsana Reddy Kalluru "UFP shmem config: mode = %d tc = %d pri_type = %d\n", 1544cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.mode, 1545cac6f691SSudarsana Reddy Kalluru p_hwfn->ufp_info.tc, p_hwfn->ufp_info.pri_type); 1546cac6f691SSudarsana Reddy Kalluru } 1547cac6f691SSudarsana Reddy Kalluru 1548cac6f691SSudarsana Reddy Kalluru static int 1549cac6f691SSudarsana Reddy Kalluru qed_mcp_handle_ufp_event(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 1550cac6f691SSudarsana Reddy Kalluru { 1551cac6f691SSudarsana Reddy Kalluru qed_mcp_read_ufp_config(p_hwfn, p_ptt); 1552cac6f691SSudarsana Reddy Kalluru 1553cac6f691SSudarsana Reddy Kalluru if (p_hwfn->ufp_info.mode == QED_UFP_MODE_VNIC_BW) { 1554cac6f691SSudarsana Reddy Kalluru p_hwfn->qm_info.ooo_tc = p_hwfn->ufp_info.tc; 1555cac6f691SSudarsana Reddy Kalluru p_hwfn->hw_info.offload_tc = p_hwfn->ufp_info.tc; 1556cac6f691SSudarsana Reddy Kalluru 1557cac6f691SSudarsana Reddy Kalluru qed_qm_reconf(p_hwfn, p_ptt); 1558cac6f691SSudarsana Reddy Kalluru } else if (p_hwfn->ufp_info.mode == QED_UFP_MODE_ETS) { 1559cac6f691SSudarsana Reddy Kalluru /* Merge UFP TC with the dcbx TC data */ 1560cac6f691SSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 1561cac6f691SSudarsana Reddy Kalluru QED_DCBX_OPERATIONAL_MIB); 1562cac6f691SSudarsana Reddy Kalluru } else { 1563cac6f691SSudarsana Reddy Kalluru DP_ERR(p_hwfn, "Invalid sched type, discard the UFP config\n"); 1564cac6f691SSudarsana Reddy Kalluru return -EINVAL; 1565cac6f691SSudarsana Reddy Kalluru } 1566cac6f691SSudarsana Reddy Kalluru 1567cac6f691SSudarsana Reddy Kalluru /* update storm FW with negotiation results */ 1568cac6f691SSudarsana Reddy Kalluru qed_sp_pf_update_ufp(p_hwfn); 1569cac6f691SSudarsana Reddy Kalluru 1570cac6f691SSudarsana Reddy Kalluru /* update stag pcp value */ 1571cac6f691SSudarsana Reddy Kalluru qed_sp_pf_update_stag(p_hwfn); 1572cac6f691SSudarsana Reddy Kalluru 1573cac6f691SSudarsana Reddy Kalluru return 0; 1574cac6f691SSudarsana Reddy Kalluru } 1575cac6f691SSudarsana Reddy Kalluru 1576cc875c2eSYuval Mintz int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, 1577cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 1578cc875c2eSYuval Mintz { 1579cc875c2eSYuval Mintz struct qed_mcp_info *info = p_hwfn->mcp_info; 1580cc875c2eSYuval Mintz int rc = 0; 1581cc875c2eSYuval Mintz bool found = false; 1582cc875c2eSYuval Mintz u16 i; 1583cc875c2eSYuval Mintz 1584cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_SP, "Received message from MFW\n"); 1585cc875c2eSYuval Mintz 1586cc875c2eSYuval Mintz /* Read Messages from MFW */ 1587cc875c2eSYuval Mintz qed_mcp_read_mb(p_hwfn, p_ptt); 1588cc875c2eSYuval Mintz 1589cc875c2eSYuval Mintz /* Compare current messages to old ones */ 1590cc875c2eSYuval Mintz for (i = 0; i < info->mfw_mb_length; i++) { 1591cc875c2eSYuval Mintz if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i]) 1592cc875c2eSYuval Mintz continue; 1593cc875c2eSYuval Mintz 1594cc875c2eSYuval Mintz found = true; 1595cc875c2eSYuval Mintz 1596cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, 1597cc875c2eSYuval Mintz "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", 1598cc875c2eSYuval Mintz i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]); 1599cc875c2eSYuval Mintz 1600cc875c2eSYuval Mintz switch (i) { 1601cc875c2eSYuval Mintz case MFW_DRV_MSG_LINK_CHANGE: 1602cc875c2eSYuval Mintz qed_mcp_handle_link_change(p_hwfn, p_ptt, false); 1603cc875c2eSYuval Mintz break; 16040b55e27dSYuval Mintz case MFW_DRV_MSG_VF_DISABLED: 16050b55e27dSYuval Mintz qed_mcp_handle_vf_flr(p_hwfn, p_ptt); 16060b55e27dSYuval Mintz break; 160739651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_LLDP_DATA_UPDATED: 160839651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 160939651abdSSudarsana Reddy Kalluru QED_DCBX_REMOTE_LLDP_MIB); 161039651abdSSudarsana Reddy Kalluru break; 161139651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED: 161239651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 161339651abdSSudarsana Reddy Kalluru QED_DCBX_REMOTE_MIB); 161439651abdSSudarsana Reddy Kalluru break; 161539651abdSSudarsana Reddy Kalluru case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED: 161639651abdSSudarsana Reddy Kalluru qed_dcbx_mib_update_event(p_hwfn, p_ptt, 161739651abdSSudarsana Reddy Kalluru QED_DCBX_OPERATIONAL_MIB); 161839651abdSSudarsana Reddy Kalluru break; 1619cac6f691SSudarsana Reddy Kalluru case MFW_DRV_MSG_OEM_CFG_UPDATE: 1620cac6f691SSudarsana Reddy Kalluru qed_mcp_handle_ufp_event(p_hwfn, p_ptt); 1621cac6f691SSudarsana Reddy Kalluru break; 1622334c03b5SZvi Nachmani case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: 1623334c03b5SZvi Nachmani qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); 1624334c03b5SZvi Nachmani break; 16256c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_LAN_STATS: 16266c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_FCOE_STATS: 16276c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_ISCSI_STATS: 16286c754246SSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_RDMA_STATS: 16296c754246SSudarsana Reddy Kalluru qed_mcp_send_protocol_stats(p_hwfn, p_ptt, i); 16306c754246SSudarsana Reddy Kalluru break; 16314b01e519SManish Chopra case MFW_DRV_MSG_BW_UPDATE: 16324b01e519SManish Chopra qed_mcp_update_bw(p_hwfn, p_ptt); 16334b01e519SManish Chopra break; 16342a351fd9SMintz, Yuval case MFW_DRV_MSG_S_TAG_UPDATE: 16352a351fd9SMintz, Yuval qed_mcp_update_stag(p_hwfn, p_ptt); 16362a351fd9SMintz, Yuval break; 163759ccf86fSSudarsana Reddy Kalluru case MFW_DRV_MSG_GET_TLV_REQ: 163859ccf86fSSudarsana Reddy Kalluru qed_mfw_tlv_req(p_hwfn); 16392a351fd9SMintz, Yuval break; 1640cc875c2eSYuval Mintz default: 164139815944SMintz, Yuval DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i); 1642cc875c2eSYuval Mintz rc = -EINVAL; 1643cc875c2eSYuval Mintz } 1644cc875c2eSYuval Mintz } 1645cc875c2eSYuval Mintz 1646cc875c2eSYuval Mintz /* ACK everything */ 1647cc875c2eSYuval Mintz for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) { 1648cc875c2eSYuval Mintz __be32 val = cpu_to_be32(((u32 *)info->mfw_mb_cur)[i]); 1649cc875c2eSYuval Mintz 1650cc875c2eSYuval Mintz /* MFW expect answer in BE, so we force write in that format */ 1651cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, 1652cc875c2eSYuval Mintz info->mfw_mb_addr + sizeof(u32) + 1653cc875c2eSYuval Mintz MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) * 1654cc875c2eSYuval Mintz sizeof(u32) + i * sizeof(u32), 1655cc875c2eSYuval Mintz (__force u32)val); 1656cc875c2eSYuval Mintz } 1657cc875c2eSYuval Mintz 1658cc875c2eSYuval Mintz if (!found) { 1659cc875c2eSYuval Mintz DP_NOTICE(p_hwfn, 1660cc875c2eSYuval Mintz "Received an MFW message indication but no new message!\n"); 1661cc875c2eSYuval Mintz rc = -EINVAL; 1662cc875c2eSYuval Mintz } 1663cc875c2eSYuval Mintz 1664cc875c2eSYuval Mintz /* Copy the new mfw messages into the shadow */ 1665cc875c2eSYuval Mintz memcpy(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length); 1666cc875c2eSYuval Mintz 1667cc875c2eSYuval Mintz return rc; 1668cc875c2eSYuval Mintz } 1669cc875c2eSYuval Mintz 16701408cc1fSYuval Mintz int qed_mcp_get_mfw_ver(struct qed_hwfn *p_hwfn, 16711408cc1fSYuval Mintz struct qed_ptt *p_ptt, 16721408cc1fSYuval Mintz u32 *p_mfw_ver, u32 *p_running_bundle_id) 1673fe56b9e6SYuval Mintz { 1674fe56b9e6SYuval Mintz u32 global_offsize; 1675fe56b9e6SYuval Mintz 16761408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) { 16771408cc1fSYuval Mintz if (p_hwfn->vf_iov_info) { 16781408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *p_resp; 16791408cc1fSYuval Mintz 16801408cc1fSYuval Mintz p_resp = &p_hwfn->vf_iov_info->acquire_resp; 16811408cc1fSYuval Mintz *p_mfw_ver = p_resp->pfdev_info.mfw_ver; 16821408cc1fSYuval Mintz return 0; 16831408cc1fSYuval Mintz } else { 16841408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 16851408cc1fSYuval Mintz QED_MSG_IOV, 16861408cc1fSYuval Mintz "VF requested MFW version prior to ACQUIRE\n"); 16871408cc1fSYuval Mintz return -EINVAL; 16881408cc1fSYuval Mintz } 16891408cc1fSYuval Mintz } 1690fe56b9e6SYuval Mintz 1691fe56b9e6SYuval Mintz global_offsize = qed_rd(p_hwfn, p_ptt, 16921408cc1fSYuval Mintz SECTION_OFFSIZE_ADDR(p_hwfn-> 16931408cc1fSYuval Mintz mcp_info->public_base, 1694fe56b9e6SYuval Mintz PUBLIC_GLOBAL)); 16951408cc1fSYuval Mintz *p_mfw_ver = 16961408cc1fSYuval Mintz qed_rd(p_hwfn, p_ptt, 16971408cc1fSYuval Mintz SECTION_ADDR(global_offsize, 16981408cc1fSYuval Mintz 0) + offsetof(struct public_global, mfw_ver)); 1699fe56b9e6SYuval Mintz 17001408cc1fSYuval Mintz if (p_running_bundle_id != NULL) { 17011408cc1fSYuval Mintz *p_running_bundle_id = qed_rd(p_hwfn, p_ptt, 17021408cc1fSYuval Mintz SECTION_ADDR(global_offsize, 0) + 17031408cc1fSYuval Mintz offsetof(struct public_global, 17041408cc1fSYuval Mintz running_bundle_id)); 17051408cc1fSYuval Mintz } 1706fe56b9e6SYuval Mintz 1707fe56b9e6SYuval Mintz return 0; 1708fe56b9e6SYuval Mintz } 1709fe56b9e6SYuval Mintz 1710ae33666aSTomer Tayar int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn, 1711ae33666aSTomer Tayar struct qed_ptt *p_ptt, u32 *p_mbi_ver) 1712ae33666aSTomer Tayar { 1713ae33666aSTomer Tayar u32 nvm_cfg_addr, nvm_cfg1_offset, mbi_ver_addr; 1714ae33666aSTomer Tayar 1715ae33666aSTomer Tayar if (IS_VF(p_hwfn->cdev)) 1716ae33666aSTomer Tayar return -EINVAL; 1717ae33666aSTomer Tayar 1718ae33666aSTomer Tayar /* Read the address of the nvm_cfg */ 1719ae33666aSTomer Tayar nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0); 1720ae33666aSTomer Tayar if (!nvm_cfg_addr) { 1721ae33666aSTomer Tayar DP_NOTICE(p_hwfn, "Shared memory not initialized\n"); 1722ae33666aSTomer Tayar return -EINVAL; 1723ae33666aSTomer Tayar } 1724ae33666aSTomer Tayar 1725ae33666aSTomer Tayar /* Read the offset of nvm_cfg1 */ 1726ae33666aSTomer Tayar nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4); 1727ae33666aSTomer Tayar 1728ae33666aSTomer Tayar mbi_ver_addr = MCP_REG_SCRATCH + nvm_cfg1_offset + 1729ae33666aSTomer Tayar offsetof(struct nvm_cfg1, glob) + 1730ae33666aSTomer Tayar offsetof(struct nvm_cfg1_glob, mbi_version); 1731ae33666aSTomer Tayar *p_mbi_ver = qed_rd(p_hwfn, p_ptt, 1732ae33666aSTomer Tayar mbi_ver_addr) & 1733ae33666aSTomer Tayar (NVM_CFG1_GLOB_MBI_VERSION_0_MASK | 1734ae33666aSTomer Tayar NVM_CFG1_GLOB_MBI_VERSION_1_MASK | 1735ae33666aSTomer Tayar NVM_CFG1_GLOB_MBI_VERSION_2_MASK); 1736ae33666aSTomer Tayar 1737ae33666aSTomer Tayar return 0; 1738ae33666aSTomer Tayar } 1739ae33666aSTomer Tayar 17401a635e48SYuval Mintz int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type) 1741cc875c2eSYuval Mintz { 1742cc875c2eSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[0]; 1743cc875c2eSYuval Mintz struct qed_ptt *p_ptt; 1744cc875c2eSYuval Mintz 17451408cc1fSYuval Mintz if (IS_VF(cdev)) 17461408cc1fSYuval Mintz return -EINVAL; 17471408cc1fSYuval Mintz 1748cc875c2eSYuval Mintz if (!qed_mcp_is_init(p_hwfn)) { 1749cc875c2eSYuval Mintz DP_NOTICE(p_hwfn, "MFW is not initialized!\n"); 1750cc875c2eSYuval Mintz return -EBUSY; 1751cc875c2eSYuval Mintz } 1752cc875c2eSYuval Mintz 1753cc875c2eSYuval Mintz *p_media_type = MEDIA_UNSPECIFIED; 1754cc875c2eSYuval Mintz 1755cc875c2eSYuval Mintz p_ptt = qed_ptt_acquire(p_hwfn); 1756cc875c2eSYuval Mintz if (!p_ptt) 1757cc875c2eSYuval Mintz return -EBUSY; 1758cc875c2eSYuval Mintz 1759cc875c2eSYuval Mintz *p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr + 1760cc875c2eSYuval Mintz offsetof(struct public_port, media_type)); 1761cc875c2eSYuval Mintz 1762cc875c2eSYuval Mintz qed_ptt_release(p_hwfn, p_ptt); 1763cc875c2eSYuval Mintz 1764cc875c2eSYuval Mintz return 0; 1765cc875c2eSYuval Mintz } 1766cc875c2eSYuval Mintz 17676927e826SMintz, Yuval /* Old MFW has a global configuration for all PFs regarding RDMA support */ 17686927e826SMintz, Yuval static void 17696927e826SMintz, Yuval qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn, 17706927e826SMintz, Yuval enum qed_pci_personality *p_proto) 17716927e826SMintz, Yuval { 17726927e826SMintz, Yuval /* There wasn't ever a legacy MFW that published iwarp. 17736927e826SMintz, Yuval * So at this point, this is either plain l2 or RoCE. 17746927e826SMintz, Yuval */ 17756927e826SMintz, Yuval if (test_bit(QED_DEV_CAP_ROCE, &p_hwfn->hw_info.device_capabilities)) 17766927e826SMintz, Yuval *p_proto = QED_PCI_ETH_ROCE; 17776927e826SMintz, Yuval else 17786927e826SMintz, Yuval *p_proto = QED_PCI_ETH; 17796927e826SMintz, Yuval 17806927e826SMintz, Yuval DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 17816927e826SMintz, Yuval "According to Legacy capabilities, L2 personality is %08x\n", 17826927e826SMintz, Yuval (u32) *p_proto); 17836927e826SMintz, Yuval } 17846927e826SMintz, Yuval 17856927e826SMintz, Yuval static int 17866927e826SMintz, Yuval qed_mcp_get_shmem_proto_mfw(struct qed_hwfn *p_hwfn, 17876927e826SMintz, Yuval struct qed_ptt *p_ptt, 17886927e826SMintz, Yuval enum qed_pci_personality *p_proto) 17896927e826SMintz, Yuval { 17906927e826SMintz, Yuval u32 resp = 0, param = 0; 17916927e826SMintz, Yuval int rc; 17926927e826SMintz, Yuval 17936927e826SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, 17946927e826SMintz, Yuval DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, ¶m); 17956927e826SMintz, Yuval if (rc) 17966927e826SMintz, Yuval return rc; 17976927e826SMintz, Yuval if (resp != FW_MSG_CODE_OK) { 17986927e826SMintz, Yuval DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 17996927e826SMintz, Yuval "MFW lacks support for command; Returns %08x\n", 18006927e826SMintz, Yuval resp); 18016927e826SMintz, Yuval return -EINVAL; 18026927e826SMintz, Yuval } 18036927e826SMintz, Yuval 18046927e826SMintz, Yuval switch (param) { 18056927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_NONE: 18066927e826SMintz, Yuval *p_proto = QED_PCI_ETH; 18076927e826SMintz, Yuval break; 18086927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_ROCE: 18096927e826SMintz, Yuval *p_proto = QED_PCI_ETH_ROCE; 18106927e826SMintz, Yuval break; 18116927e826SMintz, Yuval case FW_MB_PARAM_GET_PF_RDMA_IWARP: 1812e0a8f9deSMichal Kalderon *p_proto = QED_PCI_ETH_IWARP; 1813e0a8f9deSMichal Kalderon break; 1814e0a8f9deSMichal Kalderon case FW_MB_PARAM_GET_PF_RDMA_BOTH: 1815e0a8f9deSMichal Kalderon *p_proto = QED_PCI_ETH_RDMA; 1816e0a8f9deSMichal Kalderon break; 18176927e826SMintz, Yuval default: 18186927e826SMintz, Yuval DP_NOTICE(p_hwfn, 18196927e826SMintz, Yuval "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n", 18206927e826SMintz, Yuval param); 18216927e826SMintz, Yuval return -EINVAL; 18226927e826SMintz, Yuval } 18236927e826SMintz, Yuval 18246927e826SMintz, Yuval DP_VERBOSE(p_hwfn, 18256927e826SMintz, Yuval NETIF_MSG_IFUP, 18266927e826SMintz, Yuval "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n", 18276927e826SMintz, Yuval (u32) *p_proto, resp, param); 18286927e826SMintz, Yuval return 0; 18296927e826SMintz, Yuval } 18306927e826SMintz, Yuval 1831fe56b9e6SYuval Mintz static int 1832fe56b9e6SYuval Mintz qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, 1833fe56b9e6SYuval Mintz struct public_func *p_info, 18346927e826SMintz, Yuval struct qed_ptt *p_ptt, 1835fe56b9e6SYuval Mintz enum qed_pci_personality *p_proto) 1836fe56b9e6SYuval Mintz { 1837fe56b9e6SYuval Mintz int rc = 0; 1838fe56b9e6SYuval Mintz 1839fe56b9e6SYuval Mintz switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) { 1840fe56b9e6SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ETHERNET: 18411fe582ecSRam Amrani if (!IS_ENABLED(CONFIG_QED_RDMA)) 18421fe582ecSRam Amrani *p_proto = QED_PCI_ETH; 18431fe582ecSRam Amrani else if (qed_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto)) 18446927e826SMintz, Yuval qed_mcp_get_shmem_proto_legacy(p_hwfn, p_proto); 1845fe56b9e6SYuval Mintz break; 1846c5ac9319SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ISCSI: 1847c5ac9319SYuval Mintz *p_proto = QED_PCI_ISCSI; 1848c5ac9319SYuval Mintz break; 18491e128c81SArun Easi case FUNC_MF_CFG_PROTOCOL_FCOE: 18501e128c81SArun Easi *p_proto = QED_PCI_FCOE; 18511e128c81SArun Easi break; 1852c5ac9319SYuval Mintz case FUNC_MF_CFG_PROTOCOL_ROCE: 1853c5ac9319SYuval Mintz DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n"); 18546927e826SMintz, Yuval /* Fallthrough */ 1855fe56b9e6SYuval Mintz default: 1856fe56b9e6SYuval Mintz rc = -EINVAL; 1857fe56b9e6SYuval Mintz } 1858fe56b9e6SYuval Mintz 1859fe56b9e6SYuval Mintz return rc; 1860fe56b9e6SYuval Mintz } 1861fe56b9e6SYuval Mintz 1862fe56b9e6SYuval Mintz int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, 1863fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1864fe56b9e6SYuval Mintz { 1865fe56b9e6SYuval Mintz struct qed_mcp_function_info *info; 1866fe56b9e6SYuval Mintz struct public_func shmem_info; 1867fe56b9e6SYuval Mintz 18681a635e48SYuval Mintz qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); 1869fe56b9e6SYuval Mintz info = &p_hwfn->mcp_info->func_info; 1870fe56b9e6SYuval Mintz 1871fe56b9e6SYuval Mintz info->pause_on_host = (shmem_info.config & 1872fe56b9e6SYuval Mintz FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0; 1873fe56b9e6SYuval Mintz 18746927e826SMintz, Yuval if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt, 18756927e826SMintz, Yuval &info->protocol)) { 1876fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Unknown personality %08x\n", 1877fe56b9e6SYuval Mintz (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK)); 1878fe56b9e6SYuval Mintz return -EINVAL; 1879fe56b9e6SYuval Mintz } 1880fe56b9e6SYuval Mintz 18814b01e519SManish Chopra qed_read_pf_bandwidth(p_hwfn, &shmem_info); 1882fe56b9e6SYuval Mintz 1883fe56b9e6SYuval Mintz if (shmem_info.mac_upper || shmem_info.mac_lower) { 1884fe56b9e6SYuval Mintz info->mac[0] = (u8)(shmem_info.mac_upper >> 8); 1885fe56b9e6SYuval Mintz info->mac[1] = (u8)(shmem_info.mac_upper); 1886fe56b9e6SYuval Mintz info->mac[2] = (u8)(shmem_info.mac_lower >> 24); 1887fe56b9e6SYuval Mintz info->mac[3] = (u8)(shmem_info.mac_lower >> 16); 1888fe56b9e6SYuval Mintz info->mac[4] = (u8)(shmem_info.mac_lower >> 8); 1889fe56b9e6SYuval Mintz info->mac[5] = (u8)(shmem_info.mac_lower); 189014d39648SMintz, Yuval 189114d39648SMintz, Yuval /* Store primary MAC for later possible WoL */ 189214d39648SMintz, Yuval memcpy(&p_hwfn->cdev->wol_mac, info->mac, ETH_ALEN); 1893fe56b9e6SYuval Mintz } else { 1894fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n"); 1895fe56b9e6SYuval Mintz } 1896fe56b9e6SYuval Mintz 189757796759SMintz, Yuval info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower | 189857796759SMintz, Yuval (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32); 189957796759SMintz, Yuval info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower | 190057796759SMintz, Yuval (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32); 1901fe56b9e6SYuval Mintz 1902fe56b9e6SYuval Mintz info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK); 1903fe56b9e6SYuval Mintz 19040fefbfbaSSudarsana Kalluru info->mtu = (u16)shmem_info.mtu_size; 19050fefbfbaSSudarsana Kalluru 190614d39648SMintz, Yuval p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_NONE; 190714d39648SMintz, Yuval p_hwfn->cdev->wol_config = (u8)QED_OV_WOL_DEFAULT; 190814d39648SMintz, Yuval if (qed_mcp_is_init(p_hwfn)) { 190914d39648SMintz, Yuval u32 resp = 0, param = 0; 191014d39648SMintz, Yuval int rc; 191114d39648SMintz, Yuval 191214d39648SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, 191314d39648SMintz, Yuval DRV_MSG_CODE_OS_WOL, 0, &resp, ¶m); 191414d39648SMintz, Yuval if (rc) 191514d39648SMintz, Yuval return rc; 191614d39648SMintz, Yuval if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED) 191714d39648SMintz, Yuval p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_PME; 191814d39648SMintz, Yuval } 191914d39648SMintz, Yuval 1920fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP), 192114d39648SMintz, 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", 1922fe56b9e6SYuval Mintz info->pause_on_host, info->protocol, 1923fe56b9e6SYuval Mintz info->bandwidth_min, info->bandwidth_max, 1924fe56b9e6SYuval Mintz info->mac[0], info->mac[1], info->mac[2], 1925fe56b9e6SYuval Mintz info->mac[3], info->mac[4], info->mac[5], 192614d39648SMintz, Yuval info->wwn_port, info->wwn_node, 192714d39648SMintz, Yuval info->ovlan, (u8)p_hwfn->hw_info.b_wol_support); 1928fe56b9e6SYuval Mintz 1929fe56b9e6SYuval Mintz return 0; 1930fe56b9e6SYuval Mintz } 1931fe56b9e6SYuval Mintz 1932cc875c2eSYuval Mintz struct qed_mcp_link_params 1933cc875c2eSYuval Mintz *qed_mcp_get_link_params(struct qed_hwfn *p_hwfn) 1934cc875c2eSYuval Mintz { 1935cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1936cc875c2eSYuval Mintz return NULL; 1937cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_input; 1938cc875c2eSYuval Mintz } 1939cc875c2eSYuval Mintz 1940cc875c2eSYuval Mintz struct qed_mcp_link_state 1941cc875c2eSYuval Mintz *qed_mcp_get_link_state(struct qed_hwfn *p_hwfn) 1942cc875c2eSYuval Mintz { 1943cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1944cc875c2eSYuval Mintz return NULL; 1945cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_output; 1946cc875c2eSYuval Mintz } 1947cc875c2eSYuval Mintz 1948cc875c2eSYuval Mintz struct qed_mcp_link_capabilities 1949cc875c2eSYuval Mintz *qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn) 1950cc875c2eSYuval Mintz { 1951cc875c2eSYuval Mintz if (!p_hwfn || !p_hwfn->mcp_info) 1952cc875c2eSYuval Mintz return NULL; 1953cc875c2eSYuval Mintz return &p_hwfn->mcp_info->link_capabilities; 1954cc875c2eSYuval Mintz } 1955cc875c2eSYuval Mintz 19561a635e48SYuval Mintz int qed_mcp_drain(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 1957fe56b9e6SYuval Mintz { 1958fe56b9e6SYuval Mintz u32 resp = 0, param = 0; 1959fe56b9e6SYuval Mintz int rc; 1960fe56b9e6SYuval Mintz 1961fe56b9e6SYuval Mintz rc = qed_mcp_cmd(p_hwfn, p_ptt, 19621a635e48SYuval Mintz DRV_MSG_CODE_NIG_DRAIN, 1000, &resp, ¶m); 1963fe56b9e6SYuval Mintz 1964fe56b9e6SYuval Mintz /* Wait for the drain to complete before returning */ 19658f60bafeSYuval Mintz msleep(1020); 1966fe56b9e6SYuval Mintz 1967fe56b9e6SYuval Mintz return rc; 1968fe56b9e6SYuval Mintz } 1969fe56b9e6SYuval Mintz 1970cee4d264SManish Chopra int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, 19711a635e48SYuval Mintz struct qed_ptt *p_ptt, u32 *p_flash_size) 1972cee4d264SManish Chopra { 1973cee4d264SManish Chopra u32 flash_size; 1974cee4d264SManish Chopra 19751408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) 19761408cc1fSYuval Mintz return -EINVAL; 19771408cc1fSYuval Mintz 1978cee4d264SManish Chopra flash_size = qed_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4); 1979cee4d264SManish Chopra flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >> 1980cee4d264SManish Chopra MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT; 1981cee4d264SManish Chopra flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT)); 1982cee4d264SManish Chopra 1983cee4d264SManish Chopra *p_flash_size = flash_size; 1984cee4d264SManish Chopra 1985cee4d264SManish Chopra return 0; 1986cee4d264SManish Chopra } 1987cee4d264SManish Chopra 198888072fd4SMintz, Yuval static int 198988072fd4SMintz, Yuval qed_mcp_config_vf_msix_bb(struct qed_hwfn *p_hwfn, 19901408cc1fSYuval Mintz struct qed_ptt *p_ptt, u8 vf_id, u8 num) 19911408cc1fSYuval Mintz { 19921408cc1fSYuval Mintz u32 resp = 0, param = 0, rc_param = 0; 19931408cc1fSYuval Mintz int rc; 19941408cc1fSYuval Mintz 19951408cc1fSYuval Mintz /* Only Leader can configure MSIX, and need to take CMT into account */ 19961408cc1fSYuval Mintz if (!IS_LEAD_HWFN(p_hwfn)) 19971408cc1fSYuval Mintz return 0; 19981408cc1fSYuval Mintz num *= p_hwfn->cdev->num_hwfns; 19991408cc1fSYuval Mintz 20001408cc1fSYuval Mintz param |= (vf_id << DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT) & 20011408cc1fSYuval Mintz DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK; 20021408cc1fSYuval Mintz param |= (num << DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT) & 20031408cc1fSYuval Mintz DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK; 20041408cc1fSYuval Mintz 20051408cc1fSYuval Mintz rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_VF_MSIX, param, 20061408cc1fSYuval Mintz &resp, &rc_param); 20071408cc1fSYuval Mintz 20081408cc1fSYuval Mintz if (resp != FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE) { 20091408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "VF[%d]: MFW failed to set MSI-X\n", vf_id); 20101408cc1fSYuval Mintz rc = -EINVAL; 20111408cc1fSYuval Mintz } else { 20121408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 20131408cc1fSYuval Mintz "Requested 0x%02x MSI-x interrupts from VF 0x%02x\n", 20141408cc1fSYuval Mintz num, vf_id); 20151408cc1fSYuval Mintz } 20161408cc1fSYuval Mintz 20171408cc1fSYuval Mintz return rc; 20181408cc1fSYuval Mintz } 20191408cc1fSYuval Mintz 202088072fd4SMintz, Yuval static int 202188072fd4SMintz, Yuval qed_mcp_config_vf_msix_ah(struct qed_hwfn *p_hwfn, 202288072fd4SMintz, Yuval struct qed_ptt *p_ptt, u8 num) 202388072fd4SMintz, Yuval { 202488072fd4SMintz, Yuval u32 resp = 0, param = num, rc_param = 0; 202588072fd4SMintz, Yuval int rc; 202688072fd4SMintz, Yuval 202788072fd4SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_CFG_PF_VFS_MSIX, 202888072fd4SMintz, Yuval param, &resp, &rc_param); 202988072fd4SMintz, Yuval 203088072fd4SMintz, Yuval if (resp != FW_MSG_CODE_DRV_CFG_PF_VFS_MSIX_DONE) { 203188072fd4SMintz, Yuval DP_NOTICE(p_hwfn, "MFW failed to set MSI-X for VFs\n"); 203288072fd4SMintz, Yuval rc = -EINVAL; 203388072fd4SMintz, Yuval } else { 203488072fd4SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 203588072fd4SMintz, Yuval "Requested 0x%02x MSI-x interrupts for VFs\n", num); 203688072fd4SMintz, Yuval } 203788072fd4SMintz, Yuval 203888072fd4SMintz, Yuval return rc; 203988072fd4SMintz, Yuval } 204088072fd4SMintz, Yuval 204188072fd4SMintz, Yuval int qed_mcp_config_vf_msix(struct qed_hwfn *p_hwfn, 204288072fd4SMintz, Yuval struct qed_ptt *p_ptt, u8 vf_id, u8 num) 204388072fd4SMintz, Yuval { 204488072fd4SMintz, Yuval if (QED_IS_BB(p_hwfn->cdev)) 204588072fd4SMintz, Yuval return qed_mcp_config_vf_msix_bb(p_hwfn, p_ptt, vf_id, num); 204688072fd4SMintz, Yuval else 204788072fd4SMintz, Yuval return qed_mcp_config_vf_msix_ah(p_hwfn, p_ptt, num); 204888072fd4SMintz, Yuval } 204988072fd4SMintz, Yuval 2050fe56b9e6SYuval Mintz int 2051fe56b9e6SYuval Mintz qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, 2052fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 2053fe56b9e6SYuval Mintz struct qed_mcp_drv_version *p_ver) 2054fe56b9e6SYuval Mintz { 20555529bad9STomer Tayar struct qed_mcp_mb_params mb_params; 20562f67af8cSTomer Tayar struct drv_version_stc drv_version; 20575529bad9STomer Tayar __be32 val; 20585529bad9STomer Tayar u32 i; 20595529bad9STomer Tayar int rc; 2060fe56b9e6SYuval Mintz 20612f67af8cSTomer Tayar memset(&drv_version, 0, sizeof(drv_version)); 20622f67af8cSTomer Tayar drv_version.version = p_ver->version; 206367a99b70SYuval Mintz for (i = 0; i < (MCP_DRV_VER_STR_SIZE - 4) / sizeof(u32); i++) { 206467a99b70SYuval Mintz val = cpu_to_be32(*((u32 *)&p_ver->name[i * sizeof(u32)])); 20652f67af8cSTomer Tayar *(__be32 *)&drv_version.name[i * sizeof(u32)] = val; 2066fe56b9e6SYuval Mintz } 2067fe56b9e6SYuval Mintz 20685529bad9STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 20695529bad9STomer Tayar mb_params.cmd = DRV_MSG_CODE_SET_VERSION; 20702f67af8cSTomer Tayar mb_params.p_data_src = &drv_version; 20712f67af8cSTomer Tayar mb_params.data_src_size = sizeof(drv_version); 20725529bad9STomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 20735529bad9STomer Tayar if (rc) 2074fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 2075fe56b9e6SYuval Mintz 20765529bad9STomer Tayar return rc; 2077fe56b9e6SYuval Mintz } 207891420b83SSudarsana Kalluru 20794102426fSTomer Tayar int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 20804102426fSTomer Tayar { 20814102426fSTomer Tayar u32 resp = 0, param = 0; 20824102426fSTomer Tayar int rc; 20834102426fSTomer Tayar 20844102426fSTomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp, 20854102426fSTomer Tayar ¶m); 20864102426fSTomer Tayar if (rc) 20874102426fSTomer Tayar DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 20884102426fSTomer Tayar 20894102426fSTomer Tayar return rc; 20904102426fSTomer Tayar } 20914102426fSTomer Tayar 20924102426fSTomer Tayar int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 20934102426fSTomer Tayar { 20944102426fSTomer Tayar u32 value, cpu_mode; 20954102426fSTomer Tayar 20964102426fSTomer Tayar qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff); 20974102426fSTomer Tayar 20984102426fSTomer Tayar value = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); 20994102426fSTomer Tayar value &= ~MCP_REG_CPU_MODE_SOFT_HALT; 21004102426fSTomer Tayar qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value); 21014102426fSTomer Tayar cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); 21024102426fSTomer Tayar 21034102426fSTomer Tayar return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0; 21044102426fSTomer Tayar } 21054102426fSTomer Tayar 21060fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, 21070fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 21080fefbfbaSSudarsana Kalluru enum qed_ov_client client) 21090fefbfbaSSudarsana Kalluru { 21100fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 21110fefbfbaSSudarsana Kalluru u32 drv_mb_param; 21120fefbfbaSSudarsana Kalluru int rc; 21130fefbfbaSSudarsana Kalluru 21140fefbfbaSSudarsana Kalluru switch (client) { 21150fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_DRV: 21160fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS; 21170fefbfbaSSudarsana Kalluru break; 21180fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_USER: 21190fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER; 21200fefbfbaSSudarsana Kalluru break; 21210fefbfbaSSudarsana Kalluru case QED_OV_CLIENT_VENDOR_SPEC: 21220fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC; 21230fefbfbaSSudarsana Kalluru break; 21240fefbfbaSSudarsana Kalluru default: 21250fefbfbaSSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid client type %d\n", client); 21260fefbfbaSSudarsana Kalluru return -EINVAL; 21270fefbfbaSSudarsana Kalluru } 21280fefbfbaSSudarsana Kalluru 21290fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG, 21300fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 21310fefbfbaSSudarsana Kalluru if (rc) 21320fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "MCP response failure, aborting\n"); 21330fefbfbaSSudarsana Kalluru 21340fefbfbaSSudarsana Kalluru return rc; 21350fefbfbaSSudarsana Kalluru } 21360fefbfbaSSudarsana Kalluru 21370fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn, 21380fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 21390fefbfbaSSudarsana Kalluru enum qed_ov_driver_state drv_state) 21400fefbfbaSSudarsana Kalluru { 21410fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 21420fefbfbaSSudarsana Kalluru u32 drv_mb_param; 21430fefbfbaSSudarsana Kalluru int rc; 21440fefbfbaSSudarsana Kalluru 21450fefbfbaSSudarsana Kalluru switch (drv_state) { 21460fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_NOT_LOADED: 21470fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED; 21480fefbfbaSSudarsana Kalluru break; 21490fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_DISABLED: 21500fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED; 21510fefbfbaSSudarsana Kalluru break; 21520fefbfbaSSudarsana Kalluru case QED_OV_DRIVER_STATE_ACTIVE: 21530fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE; 21540fefbfbaSSudarsana Kalluru break; 21550fefbfbaSSudarsana Kalluru default: 21560fefbfbaSSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid driver state %d\n", drv_state); 21570fefbfbaSSudarsana Kalluru return -EINVAL; 21580fefbfbaSSudarsana Kalluru } 21590fefbfbaSSudarsana Kalluru 21600fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE, 21610fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 21620fefbfbaSSudarsana Kalluru if (rc) 21630fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send driver state\n"); 21640fefbfbaSSudarsana Kalluru 21650fefbfbaSSudarsana Kalluru return rc; 21660fefbfbaSSudarsana Kalluru } 21670fefbfbaSSudarsana Kalluru 21680fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, 21690fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, u16 mtu) 21700fefbfbaSSudarsana Kalluru { 21710fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 21720fefbfbaSSudarsana Kalluru u32 drv_mb_param; 21730fefbfbaSSudarsana Kalluru int rc; 21740fefbfbaSSudarsana Kalluru 21750fefbfbaSSudarsana Kalluru drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT; 21760fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU, 21770fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 21780fefbfbaSSudarsana Kalluru if (rc) 21790fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc); 21800fefbfbaSSudarsana Kalluru 21810fefbfbaSSudarsana Kalluru return rc; 21820fefbfbaSSudarsana Kalluru } 21830fefbfbaSSudarsana Kalluru 21840fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, 21850fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, u8 *mac) 21860fefbfbaSSudarsana Kalluru { 21870fefbfbaSSudarsana Kalluru struct qed_mcp_mb_params mb_params; 218817991002SMintz, Yuval u32 mfw_mac[2]; 21890fefbfbaSSudarsana Kalluru int rc; 21900fefbfbaSSudarsana Kalluru 21910fefbfbaSSudarsana Kalluru memset(&mb_params, 0, sizeof(mb_params)); 21920fefbfbaSSudarsana Kalluru mb_params.cmd = DRV_MSG_CODE_SET_VMAC; 21930fefbfbaSSudarsana Kalluru mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC << 21940fefbfbaSSudarsana Kalluru DRV_MSG_CODE_VMAC_TYPE_SHIFT; 21950fefbfbaSSudarsana Kalluru mb_params.param |= MCP_PF_ID(p_hwfn); 21962f67af8cSTomer Tayar 219717991002SMintz, Yuval /* MCP is BE, and on LE platforms PCI would swap access to SHMEM 219817991002SMintz, Yuval * in 32-bit granularity. 219917991002SMintz, Yuval * So the MAC has to be set in native order [and not byte order], 220017991002SMintz, Yuval * otherwise it would be read incorrectly by MFW after swap. 220117991002SMintz, Yuval */ 220217991002SMintz, Yuval mfw_mac[0] = mac[0] << 24 | mac[1] << 16 | mac[2] << 8 | mac[3]; 220317991002SMintz, Yuval mfw_mac[1] = mac[4] << 24 | mac[5] << 16; 220417991002SMintz, Yuval 220517991002SMintz, Yuval mb_params.p_data_src = (u8 *)mfw_mac; 220617991002SMintz, Yuval mb_params.data_src_size = 8; 22070fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 22080fefbfbaSSudarsana Kalluru if (rc) 22090fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc); 22100fefbfbaSSudarsana Kalluru 221114d39648SMintz, Yuval /* Store primary MAC for later possible WoL */ 221214d39648SMintz, Yuval memcpy(p_hwfn->cdev->wol_mac, mac, ETH_ALEN); 221314d39648SMintz, Yuval 22140fefbfbaSSudarsana Kalluru return rc; 22150fefbfbaSSudarsana Kalluru } 22160fefbfbaSSudarsana Kalluru 22170fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn, 22180fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, enum qed_ov_wol wol) 22190fefbfbaSSudarsana Kalluru { 22200fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 22210fefbfbaSSudarsana Kalluru u32 drv_mb_param; 22220fefbfbaSSudarsana Kalluru int rc; 22230fefbfbaSSudarsana Kalluru 222414d39648SMintz, Yuval if (p_hwfn->hw_info.b_wol_support == QED_WOL_SUPPORT_NONE) { 222514d39648SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_SP, 222614d39648SMintz, Yuval "Can't change WoL configuration when WoL isn't supported\n"); 222714d39648SMintz, Yuval return -EINVAL; 222814d39648SMintz, Yuval } 222914d39648SMintz, Yuval 22300fefbfbaSSudarsana Kalluru switch (wol) { 22310fefbfbaSSudarsana Kalluru case QED_OV_WOL_DEFAULT: 22320fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT; 22330fefbfbaSSudarsana Kalluru break; 22340fefbfbaSSudarsana Kalluru case QED_OV_WOL_DISABLED: 22350fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_DISABLED; 22360fefbfbaSSudarsana Kalluru break; 22370fefbfbaSSudarsana Kalluru case QED_OV_WOL_ENABLED: 22380fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_WOL_ENABLED; 22390fefbfbaSSudarsana Kalluru break; 22400fefbfbaSSudarsana Kalluru default: 22410fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Invalid wol state %d\n", wol); 22420fefbfbaSSudarsana Kalluru return -EINVAL; 22430fefbfbaSSudarsana Kalluru } 22440fefbfbaSSudarsana Kalluru 22450fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL, 22460fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 22470fefbfbaSSudarsana Kalluru if (rc) 22480fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc); 22490fefbfbaSSudarsana Kalluru 225014d39648SMintz, Yuval /* Store the WoL update for a future unload */ 225114d39648SMintz, Yuval p_hwfn->cdev->wol_config = (u8)wol; 225214d39648SMintz, Yuval 22530fefbfbaSSudarsana Kalluru return rc; 22540fefbfbaSSudarsana Kalluru } 22550fefbfbaSSudarsana Kalluru 22560fefbfbaSSudarsana Kalluru int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn, 22570fefbfbaSSudarsana Kalluru struct qed_ptt *p_ptt, 22580fefbfbaSSudarsana Kalluru enum qed_ov_eswitch eswitch) 22590fefbfbaSSudarsana Kalluru { 22600fefbfbaSSudarsana Kalluru u32 resp = 0, param = 0; 22610fefbfbaSSudarsana Kalluru u32 drv_mb_param; 22620fefbfbaSSudarsana Kalluru int rc; 22630fefbfbaSSudarsana Kalluru 22640fefbfbaSSudarsana Kalluru switch (eswitch) { 22650fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_NONE: 22660fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE; 22670fefbfbaSSudarsana Kalluru break; 22680fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_VEB: 22690fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB; 22700fefbfbaSSudarsana Kalluru break; 22710fefbfbaSSudarsana Kalluru case QED_OV_ESWITCH_VEPA: 22720fefbfbaSSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA; 22730fefbfbaSSudarsana Kalluru break; 22740fefbfbaSSudarsana Kalluru default: 22750fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch); 22760fefbfbaSSudarsana Kalluru return -EINVAL; 22770fefbfbaSSudarsana Kalluru } 22780fefbfbaSSudarsana Kalluru 22790fefbfbaSSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE, 22800fefbfbaSSudarsana Kalluru drv_mb_param, &resp, ¶m); 22810fefbfbaSSudarsana Kalluru if (rc) 22820fefbfbaSSudarsana Kalluru DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc); 22830fefbfbaSSudarsana Kalluru 22840fefbfbaSSudarsana Kalluru return rc; 22850fefbfbaSSudarsana Kalluru } 22860fefbfbaSSudarsana Kalluru 22871a635e48SYuval Mintz int qed_mcp_set_led(struct qed_hwfn *p_hwfn, 22881a635e48SYuval Mintz struct qed_ptt *p_ptt, enum qed_led_mode mode) 228991420b83SSudarsana Kalluru { 229091420b83SSudarsana Kalluru u32 resp = 0, param = 0, drv_mb_param; 229191420b83SSudarsana Kalluru int rc; 229291420b83SSudarsana Kalluru 229391420b83SSudarsana Kalluru switch (mode) { 229491420b83SSudarsana Kalluru case QED_LED_MODE_ON: 229591420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_ON; 229691420b83SSudarsana Kalluru break; 229791420b83SSudarsana Kalluru case QED_LED_MODE_OFF: 229891420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OFF; 229991420b83SSudarsana Kalluru break; 230091420b83SSudarsana Kalluru case QED_LED_MODE_RESTORE: 230191420b83SSudarsana Kalluru drv_mb_param = DRV_MB_PARAM_SET_LED_MODE_OPER; 230291420b83SSudarsana Kalluru break; 230391420b83SSudarsana Kalluru default: 230491420b83SSudarsana Kalluru DP_NOTICE(p_hwfn, "Invalid LED mode %d\n", mode); 230591420b83SSudarsana Kalluru return -EINVAL; 230691420b83SSudarsana Kalluru } 230791420b83SSudarsana Kalluru 230891420b83SSudarsana Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LED_MODE, 230991420b83SSudarsana Kalluru drv_mb_param, &resp, ¶m); 231091420b83SSudarsana Kalluru 231191420b83SSudarsana Kalluru return rc; 231291420b83SSudarsana Kalluru } 231303dc76caSSudarsana Reddy Kalluru 23144102426fSTomer Tayar int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn, 23154102426fSTomer Tayar struct qed_ptt *p_ptt, u32 mask_parities) 23164102426fSTomer Tayar { 23174102426fSTomer Tayar u32 resp = 0, param = 0; 23184102426fSTomer Tayar int rc; 23194102426fSTomer Tayar 23204102426fSTomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MASK_PARITIES, 23214102426fSTomer Tayar mask_parities, &resp, ¶m); 23224102426fSTomer Tayar 23234102426fSTomer Tayar if (rc) { 23244102426fSTomer Tayar DP_ERR(p_hwfn, 23254102426fSTomer Tayar "MCP response failure for mask parities, aborting\n"); 23264102426fSTomer Tayar } else if (resp != FW_MSG_CODE_OK) { 23274102426fSTomer Tayar DP_ERR(p_hwfn, 23284102426fSTomer Tayar "MCP did not acknowledge mask parity request. Old MFW?\n"); 23294102426fSTomer Tayar rc = -EINVAL; 23304102426fSTomer Tayar } 23314102426fSTomer Tayar 23324102426fSTomer Tayar return rc; 23334102426fSTomer Tayar } 23344102426fSTomer Tayar 23357a4b21b7SMintz, Yuval int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len) 23367a4b21b7SMintz, Yuval { 23377a4b21b7SMintz, Yuval u32 bytes_left = len, offset = 0, bytes_to_copy, read_len = 0; 23387a4b21b7SMintz, Yuval struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 23397a4b21b7SMintz, Yuval u32 resp = 0, resp_param = 0; 23407a4b21b7SMintz, Yuval struct qed_ptt *p_ptt; 23417a4b21b7SMintz, Yuval int rc = 0; 23427a4b21b7SMintz, Yuval 23437a4b21b7SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 23447a4b21b7SMintz, Yuval if (!p_ptt) 23457a4b21b7SMintz, Yuval return -EBUSY; 23467a4b21b7SMintz, Yuval 23477a4b21b7SMintz, Yuval while (bytes_left > 0) { 23487a4b21b7SMintz, Yuval bytes_to_copy = min_t(u32, bytes_left, MCP_DRV_NVM_BUF_LEN); 23497a4b21b7SMintz, Yuval 23507a4b21b7SMintz, Yuval rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, 23517a4b21b7SMintz, Yuval DRV_MSG_CODE_NVM_READ_NVRAM, 23527a4b21b7SMintz, Yuval addr + offset + 23537a4b21b7SMintz, Yuval (bytes_to_copy << 2354da090917STomer Tayar DRV_MB_PARAM_NVM_LEN_OFFSET), 23557a4b21b7SMintz, Yuval &resp, &resp_param, 23567a4b21b7SMintz, Yuval &read_len, 23577a4b21b7SMintz, Yuval (u32 *)(p_buf + offset)); 23587a4b21b7SMintz, Yuval 23597a4b21b7SMintz, Yuval if (rc || (resp != FW_MSG_CODE_NVM_OK)) { 23607a4b21b7SMintz, Yuval DP_NOTICE(cdev, "MCP command rc = %d\n", rc); 23617a4b21b7SMintz, Yuval break; 23627a4b21b7SMintz, Yuval } 23637a4b21b7SMintz, Yuval 23647a4b21b7SMintz, Yuval /* This can be a lengthy process, and it's possible scheduler 23657a4b21b7SMintz, Yuval * isn't preemptable. Sleep a bit to prevent CPU hogging. 23667a4b21b7SMintz, Yuval */ 23677a4b21b7SMintz, Yuval if (bytes_left % 0x1000 < 23687a4b21b7SMintz, Yuval (bytes_left - read_len) % 0x1000) 23697a4b21b7SMintz, Yuval usleep_range(1000, 2000); 23707a4b21b7SMintz, Yuval 23717a4b21b7SMintz, Yuval offset += read_len; 23727a4b21b7SMintz, Yuval bytes_left -= read_len; 23737a4b21b7SMintz, Yuval } 23747a4b21b7SMintz, Yuval 23757a4b21b7SMintz, Yuval cdev->mcp_nvm_resp = resp; 23767a4b21b7SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 23777a4b21b7SMintz, Yuval 23787a4b21b7SMintz, Yuval return rc; 23797a4b21b7SMintz, Yuval } 23807a4b21b7SMintz, Yuval 238162e4d438SSudarsana Reddy Kalluru int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf) 238262e4d438SSudarsana Reddy Kalluru { 238362e4d438SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 238462e4d438SSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 238562e4d438SSudarsana Reddy Kalluru 238662e4d438SSudarsana Reddy Kalluru p_ptt = qed_ptt_acquire(p_hwfn); 238762e4d438SSudarsana Reddy Kalluru if (!p_ptt) 238862e4d438SSudarsana Reddy Kalluru return -EBUSY; 238962e4d438SSudarsana Reddy Kalluru 239062e4d438SSudarsana Reddy Kalluru memcpy(p_buf, &cdev->mcp_nvm_resp, sizeof(cdev->mcp_nvm_resp)); 239162e4d438SSudarsana Reddy Kalluru qed_ptt_release(p_hwfn, p_ptt); 239262e4d438SSudarsana Reddy Kalluru 239362e4d438SSudarsana Reddy Kalluru return 0; 239462e4d438SSudarsana Reddy Kalluru } 239562e4d438SSudarsana Reddy Kalluru 239662e4d438SSudarsana Reddy Kalluru int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr) 239762e4d438SSudarsana Reddy Kalluru { 239862e4d438SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 239962e4d438SSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 240062e4d438SSudarsana Reddy Kalluru u32 resp, param; 240162e4d438SSudarsana Reddy Kalluru int rc; 240262e4d438SSudarsana Reddy Kalluru 240362e4d438SSudarsana Reddy Kalluru p_ptt = qed_ptt_acquire(p_hwfn); 240462e4d438SSudarsana Reddy Kalluru if (!p_ptt) 240562e4d438SSudarsana Reddy Kalluru return -EBUSY; 240662e4d438SSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_PUT_FILE_BEGIN, addr, 240762e4d438SSudarsana Reddy Kalluru &resp, ¶m); 240862e4d438SSudarsana Reddy Kalluru cdev->mcp_nvm_resp = resp; 240962e4d438SSudarsana Reddy Kalluru qed_ptt_release(p_hwfn, p_ptt); 241062e4d438SSudarsana Reddy Kalluru 241162e4d438SSudarsana Reddy Kalluru return rc; 241262e4d438SSudarsana Reddy Kalluru } 241362e4d438SSudarsana Reddy Kalluru 241462e4d438SSudarsana Reddy Kalluru int qed_mcp_nvm_write(struct qed_dev *cdev, 241562e4d438SSudarsana Reddy Kalluru u32 cmd, u32 addr, u8 *p_buf, u32 len) 241662e4d438SSudarsana Reddy Kalluru { 241762e4d438SSudarsana Reddy Kalluru u32 buf_idx = 0, buf_size, nvm_cmd, nvm_offset, resp = 0, param; 241862e4d438SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 241962e4d438SSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 242062e4d438SSudarsana Reddy Kalluru int rc = -EINVAL; 242162e4d438SSudarsana Reddy Kalluru 242262e4d438SSudarsana Reddy Kalluru p_ptt = qed_ptt_acquire(p_hwfn); 242362e4d438SSudarsana Reddy Kalluru if (!p_ptt) 242462e4d438SSudarsana Reddy Kalluru return -EBUSY; 242562e4d438SSudarsana Reddy Kalluru 242662e4d438SSudarsana Reddy Kalluru switch (cmd) { 242762e4d438SSudarsana Reddy Kalluru case QED_PUT_FILE_DATA: 242862e4d438SSudarsana Reddy Kalluru nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA; 242962e4d438SSudarsana Reddy Kalluru break; 243062e4d438SSudarsana Reddy Kalluru case QED_NVM_WRITE_NVRAM: 243162e4d438SSudarsana Reddy Kalluru nvm_cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM; 243262e4d438SSudarsana Reddy Kalluru break; 243362e4d438SSudarsana Reddy Kalluru default: 243462e4d438SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, "Invalid nvm write command 0x%x\n", cmd); 243562e4d438SSudarsana Reddy Kalluru rc = -EINVAL; 243662e4d438SSudarsana Reddy Kalluru goto out; 243762e4d438SSudarsana Reddy Kalluru } 243862e4d438SSudarsana Reddy Kalluru 243962e4d438SSudarsana Reddy Kalluru while (buf_idx < len) { 244062e4d438SSudarsana Reddy Kalluru buf_size = min_t(u32, (len - buf_idx), MCP_DRV_NVM_BUF_LEN); 244162e4d438SSudarsana Reddy Kalluru nvm_offset = ((buf_size << DRV_MB_PARAM_NVM_LEN_OFFSET) | 244262e4d438SSudarsana Reddy Kalluru addr) + buf_idx; 244362e4d438SSudarsana Reddy Kalluru rc = qed_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, nvm_offset, 244462e4d438SSudarsana Reddy Kalluru &resp, ¶m, buf_size, 244562e4d438SSudarsana Reddy Kalluru (u32 *)&p_buf[buf_idx]); 244662e4d438SSudarsana Reddy Kalluru if (rc) { 244762e4d438SSudarsana Reddy Kalluru DP_NOTICE(cdev, "nvm write failed, rc = %d\n", rc); 244862e4d438SSudarsana Reddy Kalluru resp = FW_MSG_CODE_ERROR; 244962e4d438SSudarsana Reddy Kalluru break; 245062e4d438SSudarsana Reddy Kalluru } 245162e4d438SSudarsana Reddy Kalluru 245262e4d438SSudarsana Reddy Kalluru if (resp != FW_MSG_CODE_OK && 245362e4d438SSudarsana Reddy Kalluru resp != FW_MSG_CODE_NVM_OK && 245462e4d438SSudarsana Reddy Kalluru resp != FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK) { 245562e4d438SSudarsana Reddy Kalluru DP_NOTICE(cdev, 245662e4d438SSudarsana Reddy Kalluru "nvm write failed, resp = 0x%08x\n", resp); 245762e4d438SSudarsana Reddy Kalluru rc = -EINVAL; 245862e4d438SSudarsana Reddy Kalluru break; 245962e4d438SSudarsana Reddy Kalluru } 246062e4d438SSudarsana Reddy Kalluru 246162e4d438SSudarsana Reddy Kalluru /* This can be a lengthy process, and it's possible scheduler 246262e4d438SSudarsana Reddy Kalluru * isn't pre-emptable. Sleep a bit to prevent CPU hogging. 246362e4d438SSudarsana Reddy Kalluru */ 246462e4d438SSudarsana Reddy Kalluru if (buf_idx % 0x1000 > (buf_idx + buf_size) % 0x1000) 246562e4d438SSudarsana Reddy Kalluru usleep_range(1000, 2000); 246662e4d438SSudarsana Reddy Kalluru 246762e4d438SSudarsana Reddy Kalluru buf_idx += buf_size; 246862e4d438SSudarsana Reddy Kalluru } 246962e4d438SSudarsana Reddy Kalluru 247062e4d438SSudarsana Reddy Kalluru cdev->mcp_nvm_resp = resp; 247162e4d438SSudarsana Reddy Kalluru out: 247262e4d438SSudarsana Reddy Kalluru qed_ptt_release(p_hwfn, p_ptt); 247362e4d438SSudarsana Reddy Kalluru 247462e4d438SSudarsana Reddy Kalluru return rc; 247562e4d438SSudarsana Reddy Kalluru } 247662e4d438SSudarsana Reddy Kalluru 2477b51dab46SSudarsana Reddy Kalluru int qed_mcp_phy_sfp_read(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 2478b51dab46SSudarsana Reddy Kalluru u32 port, u32 addr, u32 offset, u32 len, u8 *p_buf) 2479b51dab46SSudarsana Reddy Kalluru { 2480b51dab46SSudarsana Reddy Kalluru u32 bytes_left, bytes_to_copy, buf_size, nvm_offset = 0; 2481b51dab46SSudarsana Reddy Kalluru u32 resp, param; 2482b51dab46SSudarsana Reddy Kalluru int rc; 2483b51dab46SSudarsana Reddy Kalluru 2484b51dab46SSudarsana Reddy Kalluru nvm_offset |= (port << DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET) & 2485b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_PORT_MASK; 2486b51dab46SSudarsana Reddy Kalluru nvm_offset |= (addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET) & 2487b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK; 2488b51dab46SSudarsana Reddy Kalluru 2489b51dab46SSudarsana Reddy Kalluru addr = offset; 2490b51dab46SSudarsana Reddy Kalluru offset = 0; 2491b51dab46SSudarsana Reddy Kalluru bytes_left = len; 2492b51dab46SSudarsana Reddy Kalluru while (bytes_left > 0) { 2493b51dab46SSudarsana Reddy Kalluru bytes_to_copy = min_t(u32, bytes_left, 2494b51dab46SSudarsana Reddy Kalluru MAX_I2C_TRANSACTION_SIZE); 2495b51dab46SSudarsana Reddy Kalluru nvm_offset &= (DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK | 2496b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_PORT_MASK); 2497b51dab46SSudarsana Reddy Kalluru nvm_offset |= ((addr + offset) << 2498b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET) & 2499b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_OFFSET_MASK; 2500b51dab46SSudarsana Reddy Kalluru nvm_offset |= (bytes_to_copy << 2501b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET) & 2502b51dab46SSudarsana Reddy Kalluru DRV_MB_PARAM_TRANSCEIVER_SIZE_MASK; 2503b51dab46SSudarsana Reddy Kalluru rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, 2504b51dab46SSudarsana Reddy Kalluru DRV_MSG_CODE_TRANSCEIVER_READ, 2505b51dab46SSudarsana Reddy Kalluru nvm_offset, &resp, ¶m, &buf_size, 2506b51dab46SSudarsana Reddy Kalluru (u32 *)(p_buf + offset)); 2507b51dab46SSudarsana Reddy Kalluru if (rc) { 2508b51dab46SSudarsana Reddy Kalluru DP_NOTICE(p_hwfn, 2509b51dab46SSudarsana Reddy Kalluru "Failed to send a transceiver read command to the MFW. rc = %d.\n", 2510b51dab46SSudarsana Reddy Kalluru rc); 2511b51dab46SSudarsana Reddy Kalluru return rc; 2512b51dab46SSudarsana Reddy Kalluru } 2513b51dab46SSudarsana Reddy Kalluru 2514b51dab46SSudarsana Reddy Kalluru if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) 2515b51dab46SSudarsana Reddy Kalluru return -ENODEV; 2516b51dab46SSudarsana Reddy Kalluru else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK) 2517b51dab46SSudarsana Reddy Kalluru return -EINVAL; 2518b51dab46SSudarsana Reddy Kalluru 2519b51dab46SSudarsana Reddy Kalluru offset += buf_size; 2520b51dab46SSudarsana Reddy Kalluru bytes_left -= buf_size; 2521b51dab46SSudarsana Reddy Kalluru } 2522b51dab46SSudarsana Reddy Kalluru 2523b51dab46SSudarsana Reddy Kalluru return 0; 2524b51dab46SSudarsana Reddy Kalluru } 2525b51dab46SSudarsana Reddy Kalluru 252603dc76caSSudarsana Reddy Kalluru int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 252703dc76caSSudarsana Reddy Kalluru { 252803dc76caSSudarsana Reddy Kalluru u32 drv_mb_param = 0, rsp, param; 252903dc76caSSudarsana Reddy Kalluru int rc = 0; 253003dc76caSSudarsana Reddy Kalluru 253103dc76caSSudarsana Reddy Kalluru drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST << 253203dc76caSSudarsana Reddy Kalluru DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 253303dc76caSSudarsana Reddy Kalluru 253403dc76caSSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 253503dc76caSSudarsana Reddy Kalluru drv_mb_param, &rsp, ¶m); 253603dc76caSSudarsana Reddy Kalluru 253703dc76caSSudarsana Reddy Kalluru if (rc) 253803dc76caSSudarsana Reddy Kalluru return rc; 253903dc76caSSudarsana Reddy Kalluru 254003dc76caSSudarsana Reddy Kalluru if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 254103dc76caSSudarsana Reddy Kalluru (param != DRV_MB_PARAM_BIST_RC_PASSED)) 254203dc76caSSudarsana Reddy Kalluru rc = -EAGAIN; 254303dc76caSSudarsana Reddy Kalluru 254403dc76caSSudarsana Reddy Kalluru return rc; 254503dc76caSSudarsana Reddy Kalluru } 254603dc76caSSudarsana Reddy Kalluru 254703dc76caSSudarsana Reddy Kalluru int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 254803dc76caSSudarsana Reddy Kalluru { 254903dc76caSSudarsana Reddy Kalluru u32 drv_mb_param, rsp, param; 255003dc76caSSudarsana Reddy Kalluru int rc = 0; 255103dc76caSSudarsana Reddy Kalluru 255203dc76caSSudarsana Reddy Kalluru drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST << 255303dc76caSSudarsana Reddy Kalluru DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 255403dc76caSSudarsana Reddy Kalluru 255503dc76caSSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 255603dc76caSSudarsana Reddy Kalluru drv_mb_param, &rsp, ¶m); 255703dc76caSSudarsana Reddy Kalluru 255803dc76caSSudarsana Reddy Kalluru if (rc) 255903dc76caSSudarsana Reddy Kalluru return rc; 256003dc76caSSudarsana Reddy Kalluru 256103dc76caSSudarsana Reddy Kalluru if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 256203dc76caSSudarsana Reddy Kalluru (param != DRV_MB_PARAM_BIST_RC_PASSED)) 256303dc76caSSudarsana Reddy Kalluru rc = -EAGAIN; 256403dc76caSSudarsana Reddy Kalluru 256503dc76caSSudarsana Reddy Kalluru return rc; 256603dc76caSSudarsana Reddy Kalluru } 25677a4b21b7SMintz, Yuval 256843645ce0SSudarsana Reddy Kalluru int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn, 25697a4b21b7SMintz, Yuval struct qed_ptt *p_ptt, 25707a4b21b7SMintz, Yuval u32 *num_images) 25717a4b21b7SMintz, Yuval { 25727a4b21b7SMintz, Yuval u32 drv_mb_param = 0, rsp; 25737a4b21b7SMintz, Yuval int rc = 0; 25747a4b21b7SMintz, Yuval 25757a4b21b7SMintz, Yuval drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES << 25767a4b21b7SMintz, Yuval DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT); 25777a4b21b7SMintz, Yuval 25787a4b21b7SMintz, Yuval rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST, 25797a4b21b7SMintz, Yuval drv_mb_param, &rsp, num_images); 25807a4b21b7SMintz, Yuval if (rc) 25817a4b21b7SMintz, Yuval return rc; 25827a4b21b7SMintz, Yuval 25837a4b21b7SMintz, Yuval if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK)) 25847a4b21b7SMintz, Yuval rc = -EINVAL; 25857a4b21b7SMintz, Yuval 25867a4b21b7SMintz, Yuval return rc; 25877a4b21b7SMintz, Yuval } 25887a4b21b7SMintz, Yuval 258943645ce0SSudarsana Reddy Kalluru int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn, 25907a4b21b7SMintz, Yuval struct qed_ptt *p_ptt, 25917a4b21b7SMintz, Yuval struct bist_nvm_image_att *p_image_att, 25927a4b21b7SMintz, Yuval u32 image_index) 25937a4b21b7SMintz, Yuval { 25947a4b21b7SMintz, Yuval u32 buf_size = 0, param, resp = 0, resp_param = 0; 25957a4b21b7SMintz, Yuval int rc; 25967a4b21b7SMintz, Yuval 25977a4b21b7SMintz, Yuval param = DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX << 25987a4b21b7SMintz, Yuval DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT; 25997a4b21b7SMintz, Yuval param |= image_index << DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT; 26007a4b21b7SMintz, Yuval 26017a4b21b7SMintz, Yuval rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt, 26027a4b21b7SMintz, Yuval DRV_MSG_CODE_BIST_TEST, param, 26037a4b21b7SMintz, Yuval &resp, &resp_param, 26047a4b21b7SMintz, Yuval &buf_size, 26057a4b21b7SMintz, Yuval (u32 *)p_image_att); 26067a4b21b7SMintz, Yuval if (rc) 26077a4b21b7SMintz, Yuval return rc; 26087a4b21b7SMintz, Yuval 26097a4b21b7SMintz, Yuval if (((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) || 26107a4b21b7SMintz, Yuval (p_image_att->return_code != 1)) 26117a4b21b7SMintz, Yuval rc = -EINVAL; 26127a4b21b7SMintz, Yuval 26137a4b21b7SMintz, Yuval return rc; 26147a4b21b7SMintz, Yuval } 26152edbff8dSTomer Tayar 261643645ce0SSudarsana Reddy Kalluru int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn) 261743645ce0SSudarsana Reddy Kalluru { 26185e7ba042SDenis Bolotin struct qed_nvm_image_info nvm_info; 261943645ce0SSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 262043645ce0SSudarsana Reddy Kalluru int rc; 262143645ce0SSudarsana Reddy Kalluru u32 i; 262243645ce0SSudarsana Reddy Kalluru 26235e7ba042SDenis Bolotin if (p_hwfn->nvm_info.valid) 26245e7ba042SDenis Bolotin return 0; 26255e7ba042SDenis Bolotin 262643645ce0SSudarsana Reddy Kalluru p_ptt = qed_ptt_acquire(p_hwfn); 262743645ce0SSudarsana Reddy Kalluru if (!p_ptt) { 262843645ce0SSudarsana Reddy Kalluru DP_ERR(p_hwfn, "failed to acquire ptt\n"); 262943645ce0SSudarsana Reddy Kalluru return -EBUSY; 263043645ce0SSudarsana Reddy Kalluru } 263143645ce0SSudarsana Reddy Kalluru 263243645ce0SSudarsana Reddy Kalluru /* Acquire from MFW the amount of available images */ 26335e7ba042SDenis Bolotin nvm_info.num_images = 0; 263443645ce0SSudarsana Reddy Kalluru rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, 26355e7ba042SDenis Bolotin p_ptt, &nvm_info.num_images); 263643645ce0SSudarsana Reddy Kalluru if (rc == -EOPNOTSUPP) { 263743645ce0SSudarsana Reddy Kalluru DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n"); 263843645ce0SSudarsana Reddy Kalluru goto out; 26395e7ba042SDenis Bolotin } else if (rc || !nvm_info.num_images) { 264043645ce0SSudarsana Reddy Kalluru DP_ERR(p_hwfn, "Failed getting number of images\n"); 264143645ce0SSudarsana Reddy Kalluru goto err0; 264243645ce0SSudarsana Reddy Kalluru } 264343645ce0SSudarsana Reddy Kalluru 26445e7ba042SDenis Bolotin nvm_info.image_att = kmalloc_array(nvm_info.num_images, 264543645ce0SSudarsana Reddy Kalluru sizeof(struct bist_nvm_image_att), 264643645ce0SSudarsana Reddy Kalluru GFP_KERNEL); 26475e7ba042SDenis Bolotin if (!nvm_info.image_att) { 264843645ce0SSudarsana Reddy Kalluru rc = -ENOMEM; 264943645ce0SSudarsana Reddy Kalluru goto err0; 265043645ce0SSudarsana Reddy Kalluru } 265143645ce0SSudarsana Reddy Kalluru 265243645ce0SSudarsana Reddy Kalluru /* Iterate over images and get their attributes */ 26535e7ba042SDenis Bolotin for (i = 0; i < nvm_info.num_images; i++) { 265443645ce0SSudarsana Reddy Kalluru rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt, 26555e7ba042SDenis Bolotin &nvm_info.image_att[i], i); 265643645ce0SSudarsana Reddy Kalluru if (rc) { 265743645ce0SSudarsana Reddy Kalluru DP_ERR(p_hwfn, 265843645ce0SSudarsana Reddy Kalluru "Failed getting image index %d attributes\n", i); 265943645ce0SSudarsana Reddy Kalluru goto err1; 266043645ce0SSudarsana Reddy Kalluru } 266143645ce0SSudarsana Reddy Kalluru 266243645ce0SSudarsana Reddy Kalluru DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n", i, 26635e7ba042SDenis Bolotin nvm_info.image_att[i].len); 266443645ce0SSudarsana Reddy Kalluru } 266543645ce0SSudarsana Reddy Kalluru out: 26665e7ba042SDenis Bolotin /* Update hwfn's nvm_info */ 26675e7ba042SDenis Bolotin if (nvm_info.num_images) { 26685e7ba042SDenis Bolotin p_hwfn->nvm_info.num_images = nvm_info.num_images; 26695e7ba042SDenis Bolotin kfree(p_hwfn->nvm_info.image_att); 26705e7ba042SDenis Bolotin p_hwfn->nvm_info.image_att = nvm_info.image_att; 26715e7ba042SDenis Bolotin p_hwfn->nvm_info.valid = true; 26725e7ba042SDenis Bolotin } 26735e7ba042SDenis Bolotin 267443645ce0SSudarsana Reddy Kalluru qed_ptt_release(p_hwfn, p_ptt); 267543645ce0SSudarsana Reddy Kalluru return 0; 267643645ce0SSudarsana Reddy Kalluru 267743645ce0SSudarsana Reddy Kalluru err1: 26785e7ba042SDenis Bolotin kfree(nvm_info.image_att); 267943645ce0SSudarsana Reddy Kalluru err0: 268043645ce0SSudarsana Reddy Kalluru qed_ptt_release(p_hwfn, p_ptt); 268143645ce0SSudarsana Reddy Kalluru return rc; 268243645ce0SSudarsana Reddy Kalluru } 268343645ce0SSudarsana Reddy Kalluru 26841ac4329aSDenis Bolotin int 268520675b37SMintz, Yuval qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn, 268620675b37SMintz, Yuval enum qed_nvm_images image_id, 268720675b37SMintz, Yuval struct qed_nvm_image_att *p_image_att) 268820675b37SMintz, Yuval { 268920675b37SMintz, Yuval enum nvm_image_type type; 269043645ce0SSudarsana Reddy Kalluru u32 i; 269120675b37SMintz, Yuval 269220675b37SMintz, Yuval /* Translate image_id into MFW definitions */ 269320675b37SMintz, Yuval switch (image_id) { 269420675b37SMintz, Yuval case QED_NVM_IMAGE_ISCSI_CFG: 269520675b37SMintz, Yuval type = NVM_TYPE_ISCSI_CFG; 269620675b37SMintz, Yuval break; 269720675b37SMintz, Yuval case QED_NVM_IMAGE_FCOE_CFG: 269820675b37SMintz, Yuval type = NVM_TYPE_FCOE_CFG; 269920675b37SMintz, Yuval break; 27001ac4329aSDenis Bolotin case QED_NVM_IMAGE_NVM_CFG1: 27011ac4329aSDenis Bolotin type = NVM_TYPE_NVM_CFG1; 27021ac4329aSDenis Bolotin break; 27031ac4329aSDenis Bolotin case QED_NVM_IMAGE_DEFAULT_CFG: 27041ac4329aSDenis Bolotin type = NVM_TYPE_DEFAULT_CFG; 27051ac4329aSDenis Bolotin break; 27061ac4329aSDenis Bolotin case QED_NVM_IMAGE_NVM_META: 27071ac4329aSDenis Bolotin type = NVM_TYPE_META; 27081ac4329aSDenis Bolotin break; 270920675b37SMintz, Yuval default: 271020675b37SMintz, Yuval DP_NOTICE(p_hwfn, "Unknown request of image_id %08x\n", 271120675b37SMintz, Yuval image_id); 271220675b37SMintz, Yuval return -EINVAL; 271320675b37SMintz, Yuval } 271420675b37SMintz, Yuval 27155e7ba042SDenis Bolotin qed_mcp_nvm_info_populate(p_hwfn); 271643645ce0SSudarsana Reddy Kalluru for (i = 0; i < p_hwfn->nvm_info.num_images; i++) 271743645ce0SSudarsana Reddy Kalluru if (type == p_hwfn->nvm_info.image_att[i].image_type) 271820675b37SMintz, Yuval break; 271943645ce0SSudarsana Reddy Kalluru if (i == p_hwfn->nvm_info.num_images) { 272020675b37SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_STORAGE, 272120675b37SMintz, Yuval "Failed to find nvram image of type %08x\n", 272220675b37SMintz, Yuval image_id); 272343645ce0SSudarsana Reddy Kalluru return -ENOENT; 272420675b37SMintz, Yuval } 272520675b37SMintz, Yuval 272643645ce0SSudarsana Reddy Kalluru p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr; 272743645ce0SSudarsana Reddy Kalluru p_image_att->length = p_hwfn->nvm_info.image_att[i].len; 272820675b37SMintz, Yuval 272920675b37SMintz, Yuval return 0; 273020675b37SMintz, Yuval } 273120675b37SMintz, Yuval 273220675b37SMintz, Yuval int qed_mcp_get_nvm_image(struct qed_hwfn *p_hwfn, 273320675b37SMintz, Yuval enum qed_nvm_images image_id, 273420675b37SMintz, Yuval u8 *p_buffer, u32 buffer_len) 273520675b37SMintz, Yuval { 273620675b37SMintz, Yuval struct qed_nvm_image_att image_att; 273720675b37SMintz, Yuval int rc; 273820675b37SMintz, Yuval 273920675b37SMintz, Yuval memset(p_buffer, 0, buffer_len); 274020675b37SMintz, Yuval 2741b60bfdfeSDenis Bolotin rc = qed_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att); 274220675b37SMintz, Yuval if (rc) 274320675b37SMintz, Yuval return rc; 274420675b37SMintz, Yuval 274520675b37SMintz, Yuval /* Validate sizes - both the image's and the supplied buffer's */ 274620675b37SMintz, Yuval if (image_att.length <= 4) { 274720675b37SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_STORAGE, 274820675b37SMintz, Yuval "Image [%d] is too small - only %d bytes\n", 274920675b37SMintz, Yuval image_id, image_att.length); 275020675b37SMintz, Yuval return -EINVAL; 275120675b37SMintz, Yuval } 275220675b37SMintz, Yuval 275320675b37SMintz, Yuval if (image_att.length > buffer_len) { 275420675b37SMintz, Yuval DP_VERBOSE(p_hwfn, 275520675b37SMintz, Yuval QED_MSG_STORAGE, 275620675b37SMintz, Yuval "Image [%d] is too big - %08x bytes where only %08x are available\n", 275720675b37SMintz, Yuval image_id, image_att.length, buffer_len); 275820675b37SMintz, Yuval return -ENOMEM; 275920675b37SMintz, Yuval } 276020675b37SMintz, Yuval 276120675b37SMintz, Yuval return qed_mcp_nvm_read(p_hwfn->cdev, image_att.start_addr, 276220675b37SMintz, Yuval p_buffer, image_att.length); 276320675b37SMintz, Yuval } 276420675b37SMintz, Yuval 27659c8517c4STomer Tayar static enum resource_id_enum qed_mcp_get_mfw_res_id(enum qed_resources res_id) 27669c8517c4STomer Tayar { 27679c8517c4STomer Tayar enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID; 27689c8517c4STomer Tayar 27699c8517c4STomer Tayar switch (res_id) { 27709c8517c4STomer Tayar case QED_SB: 27719c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_SB_E; 27729c8517c4STomer Tayar break; 27739c8517c4STomer Tayar case QED_L2_QUEUE: 27749c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_L2_QUEUE_E; 27759c8517c4STomer Tayar break; 27769c8517c4STomer Tayar case QED_VPORT: 27779c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_VPORT_E; 27789c8517c4STomer Tayar break; 27799c8517c4STomer Tayar case QED_RSS_ENG: 27809c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E; 27819c8517c4STomer Tayar break; 27829c8517c4STomer Tayar case QED_PQ: 27839c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_PQ_E; 27849c8517c4STomer Tayar break; 27859c8517c4STomer Tayar case QED_RL: 27869c8517c4STomer Tayar mfw_res_id = RESOURCE_NUM_RL_E; 27879c8517c4STomer Tayar break; 27889c8517c4STomer Tayar case QED_MAC: 27899c8517c4STomer Tayar case QED_VLAN: 27909c8517c4STomer Tayar /* Each VFC resource can accommodate both a MAC and a VLAN */ 27919c8517c4STomer Tayar mfw_res_id = RESOURCE_VFC_FILTER_E; 27929c8517c4STomer Tayar break; 27939c8517c4STomer Tayar case QED_ILT: 27949c8517c4STomer Tayar mfw_res_id = RESOURCE_ILT_E; 27959c8517c4STomer Tayar break; 27969c8517c4STomer Tayar case QED_LL2_QUEUE: 27979c8517c4STomer Tayar mfw_res_id = RESOURCE_LL2_QUEUE_E; 27989c8517c4STomer Tayar break; 27999c8517c4STomer Tayar case QED_RDMA_CNQ_RAM: 28009c8517c4STomer Tayar case QED_CMDQS_CQS: 28019c8517c4STomer Tayar /* CNQ/CMDQS are the same resource */ 28029c8517c4STomer Tayar mfw_res_id = RESOURCE_CQS_E; 28039c8517c4STomer Tayar break; 28049c8517c4STomer Tayar case QED_RDMA_STATS_QUEUE: 28059c8517c4STomer Tayar mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E; 28069c8517c4STomer Tayar break; 28079c8517c4STomer Tayar case QED_BDQ: 28089c8517c4STomer Tayar mfw_res_id = RESOURCE_BDQ_E; 28099c8517c4STomer Tayar break; 28109c8517c4STomer Tayar default: 28119c8517c4STomer Tayar break; 28129c8517c4STomer Tayar } 28139c8517c4STomer Tayar 28149c8517c4STomer Tayar return mfw_res_id; 28159c8517c4STomer Tayar } 28169c8517c4STomer Tayar 28179c8517c4STomer Tayar #define QED_RESC_ALLOC_VERSION_MAJOR 2 28182edbff8dSTomer Tayar #define QED_RESC_ALLOC_VERSION_MINOR 0 28192edbff8dSTomer Tayar #define QED_RESC_ALLOC_VERSION \ 28202edbff8dSTomer Tayar ((QED_RESC_ALLOC_VERSION_MAJOR << \ 28212edbff8dSTomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) | \ 28222edbff8dSTomer Tayar (QED_RESC_ALLOC_VERSION_MINOR << \ 28232edbff8dSTomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT)) 28249c8517c4STomer Tayar 28259c8517c4STomer Tayar struct qed_resc_alloc_in_params { 28269c8517c4STomer Tayar u32 cmd; 28279c8517c4STomer Tayar enum qed_resources res_id; 28289c8517c4STomer Tayar u32 resc_max_val; 28299c8517c4STomer Tayar }; 28309c8517c4STomer Tayar 28319c8517c4STomer Tayar struct qed_resc_alloc_out_params { 28329c8517c4STomer Tayar u32 mcp_resp; 28339c8517c4STomer Tayar u32 mcp_param; 28349c8517c4STomer Tayar u32 resc_num; 28359c8517c4STomer Tayar u32 resc_start; 28369c8517c4STomer Tayar u32 vf_resc_num; 28379c8517c4STomer Tayar u32 vf_resc_start; 28389c8517c4STomer Tayar u32 flags; 28399c8517c4STomer Tayar }; 28409c8517c4STomer Tayar 28419c8517c4STomer Tayar static int 28429c8517c4STomer Tayar qed_mcp_resc_allocation_msg(struct qed_hwfn *p_hwfn, 28432edbff8dSTomer Tayar struct qed_ptt *p_ptt, 28449c8517c4STomer Tayar struct qed_resc_alloc_in_params *p_in_params, 28459c8517c4STomer Tayar struct qed_resc_alloc_out_params *p_out_params) 28462edbff8dSTomer Tayar { 28472edbff8dSTomer Tayar struct qed_mcp_mb_params mb_params; 28489c8517c4STomer Tayar struct resource_info mfw_resc_info; 28492edbff8dSTomer Tayar int rc; 28502edbff8dSTomer Tayar 28519c8517c4STomer Tayar memset(&mfw_resc_info, 0, sizeof(mfw_resc_info)); 2852bb480242SMintz, Yuval 28539c8517c4STomer Tayar mfw_resc_info.res_id = qed_mcp_get_mfw_res_id(p_in_params->res_id); 28549c8517c4STomer Tayar if (mfw_resc_info.res_id == RESOURCE_NUM_INVALID) { 28559c8517c4STomer Tayar DP_ERR(p_hwfn, 28569c8517c4STomer Tayar "Failed to match resource %d [%s] with the MFW resources\n", 28579c8517c4STomer Tayar p_in_params->res_id, 28589c8517c4STomer Tayar qed_hw_get_resc_name(p_in_params->res_id)); 28599c8517c4STomer Tayar return -EINVAL; 28609c8517c4STomer Tayar } 28619c8517c4STomer Tayar 28629c8517c4STomer Tayar switch (p_in_params->cmd) { 28639c8517c4STomer Tayar case DRV_MSG_SET_RESOURCE_VALUE_MSG: 28649c8517c4STomer Tayar mfw_resc_info.size = p_in_params->resc_max_val; 28659c8517c4STomer Tayar /* Fallthrough */ 28669c8517c4STomer Tayar case DRV_MSG_GET_RESOURCE_ALLOC_MSG: 28679c8517c4STomer Tayar break; 28689c8517c4STomer Tayar default: 28699c8517c4STomer Tayar DP_ERR(p_hwfn, "Unexpected resource alloc command [0x%08x]\n", 28709c8517c4STomer Tayar p_in_params->cmd); 28719c8517c4STomer Tayar return -EINVAL; 28729c8517c4STomer Tayar } 28739c8517c4STomer Tayar 28749c8517c4STomer Tayar memset(&mb_params, 0, sizeof(mb_params)); 28759c8517c4STomer Tayar mb_params.cmd = p_in_params->cmd; 28769c8517c4STomer Tayar mb_params.param = QED_RESC_ALLOC_VERSION; 28779c8517c4STomer Tayar mb_params.p_data_src = &mfw_resc_info; 28789c8517c4STomer Tayar mb_params.data_src_size = sizeof(mfw_resc_info); 28799c8517c4STomer Tayar mb_params.p_data_dst = mb_params.p_data_src; 28809c8517c4STomer Tayar mb_params.data_dst_size = mb_params.data_src_size; 28819c8517c4STomer Tayar 28829c8517c4STomer Tayar DP_VERBOSE(p_hwfn, 28839c8517c4STomer Tayar QED_MSG_SP, 28849c8517c4STomer Tayar "Resource message request: cmd 0x%08x, res_id %d [%s], hsi_version %d.%d, val 0x%x\n", 28859c8517c4STomer Tayar p_in_params->cmd, 28869c8517c4STomer Tayar p_in_params->res_id, 28879c8517c4STomer Tayar qed_hw_get_resc_name(p_in_params->res_id), 28889c8517c4STomer Tayar QED_MFW_GET_FIELD(mb_params.param, 28899c8517c4STomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR), 28909c8517c4STomer Tayar QED_MFW_GET_FIELD(mb_params.param, 28919c8517c4STomer Tayar DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR), 28929c8517c4STomer Tayar p_in_params->resc_max_val); 28939c8517c4STomer Tayar 28942edbff8dSTomer Tayar rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); 28952edbff8dSTomer Tayar if (rc) 28962edbff8dSTomer Tayar return rc; 28972edbff8dSTomer Tayar 28989c8517c4STomer Tayar p_out_params->mcp_resp = mb_params.mcp_resp; 28999c8517c4STomer Tayar p_out_params->mcp_param = mb_params.mcp_param; 29009c8517c4STomer Tayar p_out_params->resc_num = mfw_resc_info.size; 29019c8517c4STomer Tayar p_out_params->resc_start = mfw_resc_info.offset; 29029c8517c4STomer Tayar p_out_params->vf_resc_num = mfw_resc_info.vf_size; 29039c8517c4STomer Tayar p_out_params->vf_resc_start = mfw_resc_info.vf_offset; 29049c8517c4STomer Tayar p_out_params->flags = mfw_resc_info.flags; 29052edbff8dSTomer Tayar 29062edbff8dSTomer Tayar DP_VERBOSE(p_hwfn, 29072edbff8dSTomer Tayar QED_MSG_SP, 29089c8517c4STomer Tayar "Resource message response: mfw_hsi_version %d.%d, num 0x%x, start 0x%x, vf_num 0x%x, vf_start 0x%x, flags 0x%08x\n", 29099c8517c4STomer Tayar QED_MFW_GET_FIELD(p_out_params->mcp_param, 29109c8517c4STomer Tayar FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR), 29119c8517c4STomer Tayar QED_MFW_GET_FIELD(p_out_params->mcp_param, 29129c8517c4STomer Tayar FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR), 29139c8517c4STomer Tayar p_out_params->resc_num, 29149c8517c4STomer Tayar p_out_params->resc_start, 29159c8517c4STomer Tayar p_out_params->vf_resc_num, 29169c8517c4STomer Tayar p_out_params->vf_resc_start, p_out_params->flags); 29179c8517c4STomer Tayar 29189c8517c4STomer Tayar return 0; 29199c8517c4STomer Tayar } 29209c8517c4STomer Tayar 29219c8517c4STomer Tayar int 29229c8517c4STomer Tayar qed_mcp_set_resc_max_val(struct qed_hwfn *p_hwfn, 29239c8517c4STomer Tayar struct qed_ptt *p_ptt, 29249c8517c4STomer Tayar enum qed_resources res_id, 29259c8517c4STomer Tayar u32 resc_max_val, u32 *p_mcp_resp) 29269c8517c4STomer Tayar { 29279c8517c4STomer Tayar struct qed_resc_alloc_out_params out_params; 29289c8517c4STomer Tayar struct qed_resc_alloc_in_params in_params; 29299c8517c4STomer Tayar int rc; 29309c8517c4STomer Tayar 29319c8517c4STomer Tayar memset(&in_params, 0, sizeof(in_params)); 29329c8517c4STomer Tayar in_params.cmd = DRV_MSG_SET_RESOURCE_VALUE_MSG; 29339c8517c4STomer Tayar in_params.res_id = res_id; 29349c8517c4STomer Tayar in_params.resc_max_val = resc_max_val; 29359c8517c4STomer Tayar memset(&out_params, 0, sizeof(out_params)); 29369c8517c4STomer Tayar rc = qed_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params, 29379c8517c4STomer Tayar &out_params); 29389c8517c4STomer Tayar if (rc) 29399c8517c4STomer Tayar return rc; 29409c8517c4STomer Tayar 29419c8517c4STomer Tayar *p_mcp_resp = out_params.mcp_resp; 29429c8517c4STomer Tayar 29439c8517c4STomer Tayar return 0; 29449c8517c4STomer Tayar } 29459c8517c4STomer Tayar 29469c8517c4STomer Tayar int 29479c8517c4STomer Tayar qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn, 29489c8517c4STomer Tayar struct qed_ptt *p_ptt, 29499c8517c4STomer Tayar enum qed_resources res_id, 29509c8517c4STomer Tayar u32 *p_mcp_resp, u32 *p_resc_num, u32 *p_resc_start) 29519c8517c4STomer Tayar { 29529c8517c4STomer Tayar struct qed_resc_alloc_out_params out_params; 29539c8517c4STomer Tayar struct qed_resc_alloc_in_params in_params; 29549c8517c4STomer Tayar int rc; 29559c8517c4STomer Tayar 29569c8517c4STomer Tayar memset(&in_params, 0, sizeof(in_params)); 29579c8517c4STomer Tayar in_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG; 29589c8517c4STomer Tayar in_params.res_id = res_id; 29599c8517c4STomer Tayar memset(&out_params, 0, sizeof(out_params)); 29609c8517c4STomer Tayar rc = qed_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params, 29619c8517c4STomer Tayar &out_params); 29629c8517c4STomer Tayar if (rc) 29639c8517c4STomer Tayar return rc; 29649c8517c4STomer Tayar 29659c8517c4STomer Tayar *p_mcp_resp = out_params.mcp_resp; 29669c8517c4STomer Tayar 29679c8517c4STomer Tayar if (*p_mcp_resp == FW_MSG_CODE_RESOURCE_ALLOC_OK) { 29689c8517c4STomer Tayar *p_resc_num = out_params.resc_num; 29699c8517c4STomer Tayar *p_resc_start = out_params.resc_start; 29709c8517c4STomer Tayar } 29712edbff8dSTomer Tayar 29722edbff8dSTomer Tayar return 0; 29732edbff8dSTomer Tayar } 297418a69e36SMintz, Yuval 297518a69e36SMintz, Yuval int qed_mcp_initiate_pf_flr(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 297618a69e36SMintz, Yuval { 297718a69e36SMintz, Yuval u32 mcp_resp, mcp_param; 297818a69e36SMintz, Yuval 297918a69e36SMintz, Yuval return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_INITIATE_PF_FLR, 0, 298018a69e36SMintz, Yuval &mcp_resp, &mcp_param); 298118a69e36SMintz, Yuval } 298295691c9cSTomer Tayar 298395691c9cSTomer Tayar static int qed_mcp_resource_cmd(struct qed_hwfn *p_hwfn, 298495691c9cSTomer Tayar struct qed_ptt *p_ptt, 298595691c9cSTomer Tayar u32 param, u32 *p_mcp_resp, u32 *p_mcp_param) 298695691c9cSTomer Tayar { 298795691c9cSTomer Tayar int rc; 298895691c9cSTomer Tayar 298995691c9cSTomer Tayar rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_RESOURCE_CMD, param, 299095691c9cSTomer Tayar p_mcp_resp, p_mcp_param); 299195691c9cSTomer Tayar if (rc) 299295691c9cSTomer Tayar return rc; 299395691c9cSTomer Tayar 299495691c9cSTomer Tayar if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED) { 299595691c9cSTomer Tayar DP_INFO(p_hwfn, 299695691c9cSTomer Tayar "The resource command is unsupported by the MFW\n"); 299795691c9cSTomer Tayar return -EINVAL; 299895691c9cSTomer Tayar } 299995691c9cSTomer Tayar 300095691c9cSTomer Tayar if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) { 300195691c9cSTomer Tayar u8 opcode = QED_MFW_GET_FIELD(param, RESOURCE_CMD_REQ_OPCODE); 300295691c9cSTomer Tayar 300395691c9cSTomer Tayar DP_NOTICE(p_hwfn, 300495691c9cSTomer Tayar "The resource command is unknown to the MFW [param 0x%08x, opcode %d]\n", 300595691c9cSTomer Tayar param, opcode); 300695691c9cSTomer Tayar return -EINVAL; 300795691c9cSTomer Tayar } 300895691c9cSTomer Tayar 300995691c9cSTomer Tayar return rc; 301095691c9cSTomer Tayar } 301195691c9cSTomer Tayar 3012bf774d14SYueHaibing static int 301395691c9cSTomer Tayar __qed_mcp_resc_lock(struct qed_hwfn *p_hwfn, 301495691c9cSTomer Tayar struct qed_ptt *p_ptt, 301595691c9cSTomer Tayar struct qed_resc_lock_params *p_params) 301695691c9cSTomer Tayar { 301795691c9cSTomer Tayar u32 param = 0, mcp_resp, mcp_param; 301895691c9cSTomer Tayar u8 opcode; 301995691c9cSTomer Tayar int rc; 302095691c9cSTomer Tayar 302195691c9cSTomer Tayar switch (p_params->timeout) { 302295691c9cSTomer Tayar case QED_MCP_RESC_LOCK_TO_DEFAULT: 302395691c9cSTomer Tayar opcode = RESOURCE_OPCODE_REQ; 302495691c9cSTomer Tayar p_params->timeout = 0; 302595691c9cSTomer Tayar break; 302695691c9cSTomer Tayar case QED_MCP_RESC_LOCK_TO_NONE: 302795691c9cSTomer Tayar opcode = RESOURCE_OPCODE_REQ_WO_AGING; 302895691c9cSTomer Tayar p_params->timeout = 0; 302995691c9cSTomer Tayar break; 303095691c9cSTomer Tayar default: 303195691c9cSTomer Tayar opcode = RESOURCE_OPCODE_REQ_W_AGING; 303295691c9cSTomer Tayar break; 303395691c9cSTomer Tayar } 303495691c9cSTomer Tayar 303595691c9cSTomer Tayar QED_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource); 303695691c9cSTomer Tayar QED_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode); 303795691c9cSTomer Tayar QED_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, p_params->timeout); 303895691c9cSTomer Tayar 303995691c9cSTomer Tayar DP_VERBOSE(p_hwfn, 304095691c9cSTomer Tayar QED_MSG_SP, 304195691c9cSTomer Tayar "Resource lock request: param 0x%08x [age %d, opcode %d, resource %d]\n", 304295691c9cSTomer Tayar param, p_params->timeout, opcode, p_params->resource); 304395691c9cSTomer Tayar 304495691c9cSTomer Tayar /* Attempt to acquire the resource */ 304595691c9cSTomer Tayar rc = qed_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp, &mcp_param); 304695691c9cSTomer Tayar if (rc) 304795691c9cSTomer Tayar return rc; 304895691c9cSTomer Tayar 304995691c9cSTomer Tayar /* Analyze the response */ 305095691c9cSTomer Tayar p_params->owner = QED_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OWNER); 305195691c9cSTomer Tayar opcode = QED_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE); 305295691c9cSTomer Tayar 305395691c9cSTomer Tayar DP_VERBOSE(p_hwfn, 305495691c9cSTomer Tayar QED_MSG_SP, 305595691c9cSTomer Tayar "Resource lock response: mcp_param 0x%08x [opcode %d, owner %d]\n", 305695691c9cSTomer Tayar mcp_param, opcode, p_params->owner); 305795691c9cSTomer Tayar 305895691c9cSTomer Tayar switch (opcode) { 305995691c9cSTomer Tayar case RESOURCE_OPCODE_GNT: 306095691c9cSTomer Tayar p_params->b_granted = true; 306195691c9cSTomer Tayar break; 306295691c9cSTomer Tayar case RESOURCE_OPCODE_BUSY: 306395691c9cSTomer Tayar p_params->b_granted = false; 306495691c9cSTomer Tayar break; 306595691c9cSTomer Tayar default: 306695691c9cSTomer Tayar DP_NOTICE(p_hwfn, 306795691c9cSTomer Tayar "Unexpected opcode in resource lock response [mcp_param 0x%08x, opcode %d]\n", 306895691c9cSTomer Tayar mcp_param, opcode); 306995691c9cSTomer Tayar return -EINVAL; 307095691c9cSTomer Tayar } 307195691c9cSTomer Tayar 307295691c9cSTomer Tayar return 0; 307395691c9cSTomer Tayar } 307495691c9cSTomer Tayar 307595691c9cSTomer Tayar int 307695691c9cSTomer Tayar qed_mcp_resc_lock(struct qed_hwfn *p_hwfn, 307795691c9cSTomer Tayar struct qed_ptt *p_ptt, struct qed_resc_lock_params *p_params) 307895691c9cSTomer Tayar { 307995691c9cSTomer Tayar u32 retry_cnt = 0; 308095691c9cSTomer Tayar int rc; 308195691c9cSTomer Tayar 308295691c9cSTomer Tayar do { 308395691c9cSTomer Tayar /* No need for an interval before the first iteration */ 308495691c9cSTomer Tayar if (retry_cnt) { 308595691c9cSTomer Tayar if (p_params->sleep_b4_retry) { 308695691c9cSTomer Tayar u16 retry_interval_in_ms = 308795691c9cSTomer Tayar DIV_ROUND_UP(p_params->retry_interval, 308895691c9cSTomer Tayar 1000); 308995691c9cSTomer Tayar 309095691c9cSTomer Tayar msleep(retry_interval_in_ms); 309195691c9cSTomer Tayar } else { 309295691c9cSTomer Tayar udelay(p_params->retry_interval); 309395691c9cSTomer Tayar } 309495691c9cSTomer Tayar } 309595691c9cSTomer Tayar 309695691c9cSTomer Tayar rc = __qed_mcp_resc_lock(p_hwfn, p_ptt, p_params); 309795691c9cSTomer Tayar if (rc) 309895691c9cSTomer Tayar return rc; 309995691c9cSTomer Tayar 310095691c9cSTomer Tayar if (p_params->b_granted) 310195691c9cSTomer Tayar break; 310295691c9cSTomer Tayar } while (retry_cnt++ < p_params->retry_num); 310395691c9cSTomer Tayar 310495691c9cSTomer Tayar return 0; 310595691c9cSTomer Tayar } 310695691c9cSTomer Tayar 310795691c9cSTomer Tayar int 310895691c9cSTomer Tayar qed_mcp_resc_unlock(struct qed_hwfn *p_hwfn, 310995691c9cSTomer Tayar struct qed_ptt *p_ptt, 311095691c9cSTomer Tayar struct qed_resc_unlock_params *p_params) 311195691c9cSTomer Tayar { 311295691c9cSTomer Tayar u32 param = 0, mcp_resp, mcp_param; 311395691c9cSTomer Tayar u8 opcode; 311495691c9cSTomer Tayar int rc; 311595691c9cSTomer Tayar 311695691c9cSTomer Tayar opcode = p_params->b_force ? RESOURCE_OPCODE_FORCE_RELEASE 311795691c9cSTomer Tayar : RESOURCE_OPCODE_RELEASE; 311895691c9cSTomer Tayar QED_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource); 311995691c9cSTomer Tayar QED_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode); 312095691c9cSTomer Tayar 312195691c9cSTomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 312295691c9cSTomer Tayar "Resource unlock request: param 0x%08x [opcode %d, resource %d]\n", 312395691c9cSTomer Tayar param, opcode, p_params->resource); 312495691c9cSTomer Tayar 312595691c9cSTomer Tayar /* Attempt to release the resource */ 312695691c9cSTomer Tayar rc = qed_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp, &mcp_param); 312795691c9cSTomer Tayar if (rc) 312895691c9cSTomer Tayar return rc; 312995691c9cSTomer Tayar 313095691c9cSTomer Tayar /* Analyze the response */ 313195691c9cSTomer Tayar opcode = QED_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE); 313295691c9cSTomer Tayar 313395691c9cSTomer Tayar DP_VERBOSE(p_hwfn, QED_MSG_SP, 313495691c9cSTomer Tayar "Resource unlock response: mcp_param 0x%08x [opcode %d]\n", 313595691c9cSTomer Tayar mcp_param, opcode); 313695691c9cSTomer Tayar 313795691c9cSTomer Tayar switch (opcode) { 313895691c9cSTomer Tayar case RESOURCE_OPCODE_RELEASED_PREVIOUS: 313995691c9cSTomer Tayar DP_INFO(p_hwfn, 314095691c9cSTomer Tayar "Resource unlock request for an already released resource [%d]\n", 314195691c9cSTomer Tayar p_params->resource); 314295691c9cSTomer Tayar /* Fallthrough */ 314395691c9cSTomer Tayar case RESOURCE_OPCODE_RELEASED: 314495691c9cSTomer Tayar p_params->b_released = true; 314595691c9cSTomer Tayar break; 314695691c9cSTomer Tayar case RESOURCE_OPCODE_WRONG_OWNER: 314795691c9cSTomer Tayar p_params->b_released = false; 314895691c9cSTomer Tayar break; 314995691c9cSTomer Tayar default: 315095691c9cSTomer Tayar DP_NOTICE(p_hwfn, 315195691c9cSTomer Tayar "Unexpected opcode in resource unlock response [mcp_param 0x%08x, opcode %d]\n", 315295691c9cSTomer Tayar mcp_param, opcode); 315395691c9cSTomer Tayar return -EINVAL; 315495691c9cSTomer Tayar } 315595691c9cSTomer Tayar 315695691c9cSTomer Tayar return 0; 315795691c9cSTomer Tayar } 3158f470f22cSsudarsana.kalluru@cavium.com 3159f470f22cSsudarsana.kalluru@cavium.com void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock, 3160f470f22cSsudarsana.kalluru@cavium.com struct qed_resc_unlock_params *p_unlock, 3161f470f22cSsudarsana.kalluru@cavium.com enum qed_resc_lock 3162f470f22cSsudarsana.kalluru@cavium.com resource, bool b_is_permanent) 3163f470f22cSsudarsana.kalluru@cavium.com { 3164f470f22cSsudarsana.kalluru@cavium.com if (p_lock) { 3165f470f22cSsudarsana.kalluru@cavium.com memset(p_lock, 0, sizeof(*p_lock)); 3166f470f22cSsudarsana.kalluru@cavium.com 3167f470f22cSsudarsana.kalluru@cavium.com /* Permanent resources don't require aging, and there's no 3168f470f22cSsudarsana.kalluru@cavium.com * point in trying to acquire them more than once since it's 3169f470f22cSsudarsana.kalluru@cavium.com * unexpected another entity would release them. 3170f470f22cSsudarsana.kalluru@cavium.com */ 3171f470f22cSsudarsana.kalluru@cavium.com if (b_is_permanent) { 3172f470f22cSsudarsana.kalluru@cavium.com p_lock->timeout = QED_MCP_RESC_LOCK_TO_NONE; 3173f470f22cSsudarsana.kalluru@cavium.com } else { 3174f470f22cSsudarsana.kalluru@cavium.com p_lock->retry_num = QED_MCP_RESC_LOCK_RETRY_CNT_DFLT; 3175f470f22cSsudarsana.kalluru@cavium.com p_lock->retry_interval = 3176f470f22cSsudarsana.kalluru@cavium.com QED_MCP_RESC_LOCK_RETRY_VAL_DFLT; 3177f470f22cSsudarsana.kalluru@cavium.com p_lock->sleep_b4_retry = true; 3178f470f22cSsudarsana.kalluru@cavium.com } 3179f470f22cSsudarsana.kalluru@cavium.com 3180f470f22cSsudarsana.kalluru@cavium.com p_lock->resource = resource; 3181f470f22cSsudarsana.kalluru@cavium.com } 3182f470f22cSsudarsana.kalluru@cavium.com 3183f470f22cSsudarsana.kalluru@cavium.com if (p_unlock) { 3184f470f22cSsudarsana.kalluru@cavium.com memset(p_unlock, 0, sizeof(*p_unlock)); 3185f470f22cSsudarsana.kalluru@cavium.com p_unlock->resource = resource; 3186f470f22cSsudarsana.kalluru@cavium.com } 3187f470f22cSsudarsana.kalluru@cavium.com } 3188645874e5SSudarsana Reddy Kalluru 3189645874e5SSudarsana Reddy Kalluru int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 3190645874e5SSudarsana Reddy Kalluru { 3191645874e5SSudarsana Reddy Kalluru u32 mcp_resp; 3192645874e5SSudarsana Reddy Kalluru int rc; 3193645874e5SSudarsana Reddy Kalluru 3194645874e5SSudarsana Reddy Kalluru rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT, 3195645874e5SSudarsana Reddy Kalluru 0, &mcp_resp, &p_hwfn->mcp_info->capabilities); 3196645874e5SSudarsana Reddy Kalluru if (!rc) 3197645874e5SSudarsana Reddy Kalluru DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_PROBE), 3198645874e5SSudarsana Reddy Kalluru "MFW supported features: %08x\n", 3199645874e5SSudarsana Reddy Kalluru p_hwfn->mcp_info->capabilities); 3200645874e5SSudarsana Reddy Kalluru 3201645874e5SSudarsana Reddy Kalluru return rc; 3202645874e5SSudarsana Reddy Kalluru } 3203645874e5SSudarsana Reddy Kalluru 3204645874e5SSudarsana Reddy Kalluru int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 3205645874e5SSudarsana Reddy Kalluru { 3206645874e5SSudarsana Reddy Kalluru u32 mcp_resp, mcp_param, features; 3207645874e5SSudarsana Reddy Kalluru 3208645874e5SSudarsana Reddy Kalluru features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE; 3209645874e5SSudarsana Reddy Kalluru 3210645874e5SSudarsana Reddy Kalluru return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT, 3211645874e5SSudarsana Reddy Kalluru features, &mcp_resp, &mcp_param); 3212645874e5SSudarsana Reddy Kalluru } 3213