18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term 58c2ecf20Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 88c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 98c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 108c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 118c2ecf20Sopenharmony_ci * BSD license below: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 148c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 158c2ecf20Sopenharmony_ci * are met: 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 188c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 198c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 208c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 218c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 228c2ecf20Sopenharmony_ci * distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 258c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 268c2ecf20Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 278c2ecf20Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 298c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 308c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 318c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 328c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 338c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 348c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * Description: Slow Path Operators 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define dev_fmt(fmt) "QPLIB: " fmt 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 428c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 438c2ecf20Sopenharmony_ci#include <linux/sched.h> 448c2ecf20Sopenharmony_ci#include <linux/pci.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include "roce_hsi.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include "qplib_res.h" 498c2ecf20Sopenharmony_ci#include "qplib_rcfw.h" 508c2ecf20Sopenharmony_ci#include "qplib_sp.h" 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciconst struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 538c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0 } }; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* Device */ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, 588c2ecf20Sopenharmony_ci char *fw_ver) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct cmdq_query_version req; 618c2ecf20Sopenharmony_ci struct creq_query_version_resp resp; 628c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 638c2ecf20Sopenharmony_ci int rc = 0; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, QUERY_VERSION, cmd_flags); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 688c2ecf20Sopenharmony_ci (void *)&resp, NULL, 0); 698c2ecf20Sopenharmony_ci if (rc) 708c2ecf20Sopenharmony_ci return; 718c2ecf20Sopenharmony_ci fw_ver[0] = resp.fw_maj; 728c2ecf20Sopenharmony_ci fw_ver[1] = resp.fw_minor; 738c2ecf20Sopenharmony_ci fw_ver[2] = resp.fw_bld; 748c2ecf20Sopenharmony_ci fw_ver[3] = resp.fw_rsvd; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciint bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, 788c2ecf20Sopenharmony_ci struct bnxt_qplib_dev_attr *attr, bool vf) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct cmdq_query_func req; 818c2ecf20Sopenharmony_ci struct creq_query_func_resp resp; 828c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw_sbuf *sbuf; 838c2ecf20Sopenharmony_ci struct creq_query_func_resp_sb *sb; 848c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 858c2ecf20Sopenharmony_ci u32 temp; 868c2ecf20Sopenharmony_ci u8 *tqm_alloc; 878c2ecf20Sopenharmony_ci int i, rc = 0; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 928c2ecf20Sopenharmony_ci if (!sbuf) { 938c2ecf20Sopenharmony_ci dev_err(&rcfw->pdev->dev, 948c2ecf20Sopenharmony_ci "SP: QUERY_FUNC alloc side buffer failed\n"); 958c2ecf20Sopenharmony_ci return -ENOMEM; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci sb = sbuf->sb; 998c2ecf20Sopenharmony_ci req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 1008c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 1018c2ecf20Sopenharmony_ci (void *)sbuf, 0); 1028c2ecf20Sopenharmony_ci if (rc) 1038c2ecf20Sopenharmony_ci goto bail; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Extract the context from the side buffer */ 1068c2ecf20Sopenharmony_ci attr->max_qp = le32_to_cpu(sb->max_qp); 1078c2ecf20Sopenharmony_ci /* max_qp value reported by FW for PF doesn't include the QP1 for PF */ 1088c2ecf20Sopenharmony_ci if (!vf) 1098c2ecf20Sopenharmony_ci attr->max_qp += 1; 1108c2ecf20Sopenharmony_ci attr->max_qp_rd_atom = 1118c2ecf20Sopenharmony_ci sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 1128c2ecf20Sopenharmony_ci BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; 1138c2ecf20Sopenharmony_ci attr->max_qp_init_rd_atom = 1148c2ecf20Sopenharmony_ci sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 1158c2ecf20Sopenharmony_ci BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; 1168c2ecf20Sopenharmony_ci attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); 1178c2ecf20Sopenharmony_ci /* 1188c2ecf20Sopenharmony_ci * 128 WQEs needs to be reserved for the HW (8916). Prevent 1198c2ecf20Sopenharmony_ci * reporting the max number 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ci attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS; 1228c2ecf20Sopenharmony_ci attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx) ? 1238c2ecf20Sopenharmony_ci 6 : sb->max_sge; 1248c2ecf20Sopenharmony_ci attr->max_cq = le32_to_cpu(sb->max_cq); 1258c2ecf20Sopenharmony_ci attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 1268c2ecf20Sopenharmony_ci attr->max_cq_sges = attr->max_qp_sges; 1278c2ecf20Sopenharmony_ci attr->max_mr = le32_to_cpu(sb->max_mr); 1288c2ecf20Sopenharmony_ci attr->max_mw = le32_to_cpu(sb->max_mw); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 1318c2ecf20Sopenharmony_ci attr->max_pd = 64 * 1024; 1328c2ecf20Sopenharmony_ci attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 1338c2ecf20Sopenharmony_ci attr->max_ah = le32_to_cpu(sb->max_ah); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci attr->max_srq = le16_to_cpu(sb->max_srq); 1368c2ecf20Sopenharmony_ci attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 1378c2ecf20Sopenharmony_ci attr->max_srq_sges = sb->max_srq_sge; 1388c2ecf20Sopenharmony_ci attr->max_pkey = le32_to_cpu(sb->max_pkeys); 1398c2ecf20Sopenharmony_ci /* 1408c2ecf20Sopenharmony_ci * Some versions of FW reports more than 0xFFFF. 1418c2ecf20Sopenharmony_ci * Restrict it for now to 0xFFFF to avoid 1428c2ecf20Sopenharmony_ci * reporting trucated value 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_ci if (attr->max_pkey > 0xFFFF) { 1458c2ecf20Sopenharmony_ci /* ib_port_attr::pkey_tbl_len is u16 */ 1468c2ecf20Sopenharmony_ci attr->max_pkey = 0xFFFF; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 1508c2ecf20Sopenharmony_ci attr->l2_db_size = (sb->l2_db_space_size + 1) * 1518c2ecf20Sopenharmony_ci (0x01 << RCFW_DBR_BASE_PAGE_SHIFT); 1528c2ecf20Sopenharmony_ci attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci bnxt_qplib_query_version(rcfw, attr->fw_ver); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 1578c2ecf20Sopenharmony_ci temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 1588c2ecf20Sopenharmony_ci tqm_alloc = (u8 *)&temp; 1598c2ecf20Sopenharmony_ci attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 1608c2ecf20Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 1618c2ecf20Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 1628c2ecf20Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci attr->is_atomic = false; 1668c2ecf20Sopenharmony_cibail: 1678c2ecf20Sopenharmony_ci bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 1688c2ecf20Sopenharmony_ci return rc; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciint bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res, 1728c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw, 1738c2ecf20Sopenharmony_ci struct bnxt_qplib_ctx *ctx) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct cmdq_set_func_resources req; 1768c2ecf20Sopenharmony_ci struct creq_set_func_resources_resp resp; 1778c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 1788c2ecf20Sopenharmony_ci int rc = 0; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci req.number_of_qp = cpu_to_le32(ctx->qpc_count); 1838c2ecf20Sopenharmony_ci req.number_of_mrw = cpu_to_le32(ctx->mrw_count); 1848c2ecf20Sopenharmony_ci req.number_of_srq = cpu_to_le32(ctx->srqc_count); 1858c2ecf20Sopenharmony_ci req.number_of_cq = cpu_to_le32(ctx->cq_count); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf); 1888c2ecf20Sopenharmony_ci req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf); 1898c2ecf20Sopenharmony_ci req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf); 1908c2ecf20Sopenharmony_ci req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf); 1918c2ecf20Sopenharmony_ci req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 1948c2ecf20Sopenharmony_ci (void *)&resp, 1958c2ecf20Sopenharmony_ci NULL, 0); 1968c2ecf20Sopenharmony_ci if (rc) { 1978c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "Failed to set function resources\n"); 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci return rc; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci/* SGID */ 2038c2ecf20Sopenharmony_ciint bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 2048c2ecf20Sopenharmony_ci struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 2058c2ecf20Sopenharmony_ci struct bnxt_qplib_gid *gid) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci if (index >= sgid_tbl->max) { 2088c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 2098c2ecf20Sopenharmony_ci "Index %d exceeded SGID table max (%d)\n", 2108c2ecf20Sopenharmony_ci index, sgid_tbl->max); 2118c2ecf20Sopenharmony_ci return -EINVAL; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid)); 2148c2ecf20Sopenharmony_ci return 0; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciint bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2188c2ecf20Sopenharmony_ci struct bnxt_qplib_gid *gid, u16 vlan_id, bool update) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2218c2ecf20Sopenharmony_ci struct bnxt_qplib_res, 2228c2ecf20Sopenharmony_ci sgid_tbl); 2238c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 2248c2ecf20Sopenharmony_ci int index; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (!sgid_tbl) { 2278c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci /* Do we need a sgid_lock here? */ 2318c2ecf20Sopenharmony_ci if (!sgid_tbl->active) { 2328c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table has no active entries\n"); 2338c2ecf20Sopenharmony_ci return -ENOMEM; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci for (index = 0; index < sgid_tbl->max; index++) { 2368c2ecf20Sopenharmony_ci if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) && 2378c2ecf20Sopenharmony_ci vlan_id == sgid_tbl->tbl[index].vlan_id) 2388c2ecf20Sopenharmony_ci break; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci if (index == sgid_tbl->max) { 2418c2ecf20Sopenharmony_ci dev_warn(&res->pdev->dev, "GID not found in the SGID table\n"); 2428c2ecf20Sopenharmony_ci return 0; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci /* Remove GID from the SGID table */ 2458c2ecf20Sopenharmony_ci if (update) { 2468c2ecf20Sopenharmony_ci struct cmdq_delete_gid req; 2478c2ecf20Sopenharmony_ci struct creq_delete_gid_resp resp; 2488c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 2498c2ecf20Sopenharmony_ci int rc; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); 2528c2ecf20Sopenharmony_ci if (sgid_tbl->hw_id[index] == 0xFFFF) { 2538c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 2548c2ecf20Sopenharmony_ci "GID entry contains an invalid HW id\n"); 2558c2ecf20Sopenharmony_ci return -EINVAL; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 2588c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 2598c2ecf20Sopenharmony_ci (void *)&resp, NULL, 0); 2608c2ecf20Sopenharmony_ci if (rc) 2618c2ecf20Sopenharmony_ci return rc; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero, 2648c2ecf20Sopenharmony_ci sizeof(bnxt_qplib_gid_zero)); 2658c2ecf20Sopenharmony_ci sgid_tbl->tbl[index].vlan_id = 0xFFFF; 2668c2ecf20Sopenharmony_ci sgid_tbl->vlan[index] = 0; 2678c2ecf20Sopenharmony_ci sgid_tbl->active--; 2688c2ecf20Sopenharmony_ci dev_dbg(&res->pdev->dev, 2698c2ecf20Sopenharmony_ci "SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n", 2708c2ecf20Sopenharmony_ci index, sgid_tbl->hw_id[index], sgid_tbl->active); 2718c2ecf20Sopenharmony_ci sgid_tbl->hw_id[index] = (u16)-1; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* unlock */ 2748c2ecf20Sopenharmony_ci return 0; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ciint bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2788c2ecf20Sopenharmony_ci struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id, 2798c2ecf20Sopenharmony_ci bool update, u32 *index) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2828c2ecf20Sopenharmony_ci struct bnxt_qplib_res, 2838c2ecf20Sopenharmony_ci sgid_tbl); 2848c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 2858c2ecf20Sopenharmony_ci int i, free_idx; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (!sgid_tbl) { 2888c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2898c2ecf20Sopenharmony_ci return -EINVAL; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci /* Do we need a sgid_lock here? */ 2928c2ecf20Sopenharmony_ci if (sgid_tbl->active == sgid_tbl->max) { 2938c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table is full\n"); 2948c2ecf20Sopenharmony_ci return -ENOMEM; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci free_idx = sgid_tbl->max; 2978c2ecf20Sopenharmony_ci for (i = 0; i < sgid_tbl->max; i++) { 2988c2ecf20Sopenharmony_ci if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) && 2998c2ecf20Sopenharmony_ci sgid_tbl->tbl[i].vlan_id == vlan_id) { 3008c2ecf20Sopenharmony_ci dev_dbg(&res->pdev->dev, 3018c2ecf20Sopenharmony_ci "SGID entry already exist in entry %d!\n", i); 3028c2ecf20Sopenharmony_ci *index = i; 3038c2ecf20Sopenharmony_ci return -EALREADY; 3048c2ecf20Sopenharmony_ci } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 3058c2ecf20Sopenharmony_ci sizeof(bnxt_qplib_gid_zero)) && 3068c2ecf20Sopenharmony_ci free_idx == sgid_tbl->max) { 3078c2ecf20Sopenharmony_ci free_idx = i; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci if (free_idx == sgid_tbl->max) { 3118c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 3128c2ecf20Sopenharmony_ci "SGID table is FULL but count is not MAX??\n"); 3138c2ecf20Sopenharmony_ci return -ENOMEM; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci if (update) { 3168c2ecf20Sopenharmony_ci struct cmdq_add_gid req; 3178c2ecf20Sopenharmony_ci struct creq_add_gid_resp resp; 3188c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 3198c2ecf20Sopenharmony_ci int rc; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, ADD_GID, cmd_flags); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3248c2ecf20Sopenharmony_ci req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3258c2ecf20Sopenharmony_ci req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3268c2ecf20Sopenharmony_ci req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3278c2ecf20Sopenharmony_ci /* 3288c2ecf20Sopenharmony_ci * driver should ensure that all RoCE traffic is always VLAN 3298c2ecf20Sopenharmony_ci * tagged if RoCE traffic is running on non-zero VLAN ID or 3308c2ecf20Sopenharmony_ci * RoCE traffic is running on non-zero Priority. 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_ci if ((vlan_id != 0xFFFF) || res->prio) { 3338c2ecf20Sopenharmony_ci if (vlan_id != 0xFFFF) 3348c2ecf20Sopenharmony_ci req.vlan = cpu_to_le16 3358c2ecf20Sopenharmony_ci (vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK); 3368c2ecf20Sopenharmony_ci req.vlan |= cpu_to_le16 3378c2ecf20Sopenharmony_ci (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3388c2ecf20Sopenharmony_ci CMDQ_ADD_GID_VLAN_VLAN_EN); 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* MAC in network format */ 3428c2ecf20Sopenharmony_ci req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3438c2ecf20Sopenharmony_ci req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3448c2ecf20Sopenharmony_ci req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 3478c2ecf20Sopenharmony_ci (void *)&resp, NULL, 0); 3488c2ecf20Sopenharmony_ci if (rc) 3498c2ecf20Sopenharmony_ci return rc; 3508c2ecf20Sopenharmony_ci sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci /* Add GID to the sgid_tbl */ 3538c2ecf20Sopenharmony_ci memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 3548c2ecf20Sopenharmony_ci sgid_tbl->tbl[free_idx].vlan_id = vlan_id; 3558c2ecf20Sopenharmony_ci sgid_tbl->active++; 3568c2ecf20Sopenharmony_ci if (vlan_id != 0xFFFF) 3578c2ecf20Sopenharmony_ci sgid_tbl->vlan[free_idx] = 1; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci dev_dbg(&res->pdev->dev, 3608c2ecf20Sopenharmony_ci "SGID added hw_id[0x%x] = 0x%x active = 0x%x\n", 3618c2ecf20Sopenharmony_ci free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci *index = free_idx; 3648c2ecf20Sopenharmony_ci /* unlock */ 3658c2ecf20Sopenharmony_ci return 0; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ciint bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 3698c2ecf20Sopenharmony_ci struct bnxt_qplib_gid *gid, u16 gid_idx, 3708c2ecf20Sopenharmony_ci u8 *smac) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 3738c2ecf20Sopenharmony_ci struct bnxt_qplib_res, 3748c2ecf20Sopenharmony_ci sgid_tbl); 3758c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 3768c2ecf20Sopenharmony_ci struct creq_modify_gid_resp resp; 3778c2ecf20Sopenharmony_ci struct cmdq_modify_gid req; 3788c2ecf20Sopenharmony_ci int rc; 3798c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, MODIFY_GID, cmd_flags); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3848c2ecf20Sopenharmony_ci req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3858c2ecf20Sopenharmony_ci req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3868c2ecf20Sopenharmony_ci req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3878c2ecf20Sopenharmony_ci if (res->prio) { 3888c2ecf20Sopenharmony_ci req.vlan |= cpu_to_le16 3898c2ecf20Sopenharmony_ci (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3908c2ecf20Sopenharmony_ci CMDQ_ADD_GID_VLAN_VLAN_EN); 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* MAC in network format */ 3948c2ecf20Sopenharmony_ci req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3958c2ecf20Sopenharmony_ci req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3968c2ecf20Sopenharmony_ci req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci req.gid_index = cpu_to_le16(gid_idx); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 4018c2ecf20Sopenharmony_ci (void *)&resp, NULL, 0); 4028c2ecf20Sopenharmony_ci return rc; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci/* pkeys */ 4068c2ecf20Sopenharmony_ciint bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, 4078c2ecf20Sopenharmony_ci struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index, 4088c2ecf20Sopenharmony_ci u16 *pkey) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci if (index == 0xFFFF) { 4118c2ecf20Sopenharmony_ci *pkey = 0xFFFF; 4128c2ecf20Sopenharmony_ci return 0; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci if (index >= pkey_tbl->max) { 4158c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 4168c2ecf20Sopenharmony_ci "Index %d exceeded PKEY table max (%d)\n", 4178c2ecf20Sopenharmony_ci index, pkey_tbl->max); 4188c2ecf20Sopenharmony_ci return -EINVAL; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey)); 4218c2ecf20Sopenharmony_ci return 0; 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ciint bnxt_qplib_del_pkey(struct bnxt_qplib_res *res, 4258c2ecf20Sopenharmony_ci struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4268c2ecf20Sopenharmony_ci bool update) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci int i, rc = 0; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (!pkey_tbl) { 4318c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4328c2ecf20Sopenharmony_ci return -EINVAL; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci /* Do we need a pkey_lock here? */ 4368c2ecf20Sopenharmony_ci if (!pkey_tbl->active) { 4378c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "PKEY table has no active entries\n"); 4388c2ecf20Sopenharmony_ci return -ENOMEM; 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci for (i = 0; i < pkey_tbl->max; i++) { 4418c2ecf20Sopenharmony_ci if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci if (i == pkey_tbl->max) { 4458c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 4468c2ecf20Sopenharmony_ci "PKEY 0x%04x not found in the pkey table\n", *pkey); 4478c2ecf20Sopenharmony_ci return -ENOMEM; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey)); 4508c2ecf20Sopenharmony_ci pkey_tbl->active--; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* unlock */ 4538c2ecf20Sopenharmony_ci return rc; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ciint bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, 4578c2ecf20Sopenharmony_ci struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4588c2ecf20Sopenharmony_ci bool update) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci int i, free_idx, rc = 0; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci if (!pkey_tbl) { 4638c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4648c2ecf20Sopenharmony_ci return -EINVAL; 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* Do we need a pkey_lock here? */ 4688c2ecf20Sopenharmony_ci if (pkey_tbl->active == pkey_tbl->max) { 4698c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, "PKEY table is full\n"); 4708c2ecf20Sopenharmony_ci return -ENOMEM; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci free_idx = pkey_tbl->max; 4738c2ecf20Sopenharmony_ci for (i = 0; i < pkey_tbl->max; i++) { 4748c2ecf20Sopenharmony_ci if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4758c2ecf20Sopenharmony_ci return -EALREADY; 4768c2ecf20Sopenharmony_ci else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max) 4778c2ecf20Sopenharmony_ci free_idx = i; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci if (free_idx == pkey_tbl->max) { 4808c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 4818c2ecf20Sopenharmony_ci "PKEY table is FULL but count is not MAX??\n"); 4828c2ecf20Sopenharmony_ci return -ENOMEM; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci /* Add PKEY to the pkey_tbl */ 4858c2ecf20Sopenharmony_ci memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey)); 4868c2ecf20Sopenharmony_ci pkey_tbl->active++; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* unlock */ 4898c2ecf20Sopenharmony_ci return rc; 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci/* AH */ 4938c2ecf20Sopenharmony_ciint bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 4948c2ecf20Sopenharmony_ci bool block) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4978c2ecf20Sopenharmony_ci struct cmdq_create_ah req; 4988c2ecf20Sopenharmony_ci struct creq_create_ah_resp resp; 4998c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 5008c2ecf20Sopenharmony_ci u32 temp32[4]; 5018c2ecf20Sopenharmony_ci u16 temp16[3]; 5028c2ecf20Sopenharmony_ci int rc; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 5078c2ecf20Sopenharmony_ci req.dgid[0] = cpu_to_le32(temp32[0]); 5088c2ecf20Sopenharmony_ci req.dgid[1] = cpu_to_le32(temp32[1]); 5098c2ecf20Sopenharmony_ci req.dgid[2] = cpu_to_le32(temp32[2]); 5108c2ecf20Sopenharmony_ci req.dgid[3] = cpu_to_le32(temp32[3]); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci req.type = ah->nw_type; 5138c2ecf20Sopenharmony_ci req.hop_limit = ah->hop_limit; 5148c2ecf20Sopenharmony_ci req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 5158c2ecf20Sopenharmony_ci req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 5168c2ecf20Sopenharmony_ci CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 5178c2ecf20Sopenharmony_ci CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 5188c2ecf20Sopenharmony_ci req.pd_id = cpu_to_le32(ah->pd->id); 5198c2ecf20Sopenharmony_ci req.traffic_class = ah->traffic_class; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* MAC in network format */ 5228c2ecf20Sopenharmony_ci memcpy(temp16, ah->dmac, 6); 5238c2ecf20Sopenharmony_ci req.dest_mac[0] = cpu_to_le16(temp16[0]); 5248c2ecf20Sopenharmony_ci req.dest_mac[1] = cpu_to_le16(temp16[1]); 5258c2ecf20Sopenharmony_ci req.dest_mac[2] = cpu_to_le16(temp16[2]); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5288c2ecf20Sopenharmony_ci NULL, block); 5298c2ecf20Sopenharmony_ci if (rc) 5308c2ecf20Sopenharmony_ci return rc; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci ah->id = le32_to_cpu(resp.xid); 5338c2ecf20Sopenharmony_ci return 0; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_civoid bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 5378c2ecf20Sopenharmony_ci bool block) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5408c2ecf20Sopenharmony_ci struct cmdq_destroy_ah req; 5418c2ecf20Sopenharmony_ci struct creq_destroy_ah_resp resp; 5428c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* Clean up the AH table in the device */ 5458c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci req.ah_cid = cpu_to_le32(ah->id); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 5508c2ecf20Sopenharmony_ci block); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci/* MRW */ 5548c2ecf20Sopenharmony_ciint bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5578c2ecf20Sopenharmony_ci struct cmdq_deallocate_key req; 5588c2ecf20Sopenharmony_ci struct creq_deallocate_key_resp resp; 5598c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 5608c2ecf20Sopenharmony_ci int rc; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (mrw->lkey == 0xFFFFFFFF) { 5638c2ecf20Sopenharmony_ci dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n"); 5648c2ecf20Sopenharmony_ci return 0; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci req.mrw_flags = mrw->type; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 5728c2ecf20Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 5738c2ecf20Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 5748c2ecf20Sopenharmony_ci req.key = cpu_to_le32(mrw->rkey); 5758c2ecf20Sopenharmony_ci else 5768c2ecf20Sopenharmony_ci req.key = cpu_to_le32(mrw->lkey); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5798c2ecf20Sopenharmony_ci NULL, 0); 5808c2ecf20Sopenharmony_ci if (rc) 5818c2ecf20Sopenharmony_ci return rc; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* Free the qplib's MRW memory */ 5848c2ecf20Sopenharmony_ci if (mrw->hwq.max_elements) 5858c2ecf20Sopenharmony_ci bnxt_qplib_free_hwq(res, &mrw->hwq); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci return 0; 5888c2ecf20Sopenharmony_ci} 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5918c2ecf20Sopenharmony_ci{ 5928c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5938c2ecf20Sopenharmony_ci struct cmdq_allocate_mrw req; 5948c2ecf20Sopenharmony_ci struct creq_allocate_mrw_resp resp; 5958c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 5968c2ecf20Sopenharmony_ci unsigned long tmp; 5978c2ecf20Sopenharmony_ci int rc; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci req.pd_id = cpu_to_le32(mrw->pd->id); 6028c2ecf20Sopenharmony_ci req.mrw_flags = mrw->type; 6038c2ecf20Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 6048c2ecf20Sopenharmony_ci mrw->flags & BNXT_QPLIB_FR_PMR) || 6058c2ecf20Sopenharmony_ci mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 6068c2ecf20Sopenharmony_ci mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 6078c2ecf20Sopenharmony_ci req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 6088c2ecf20Sopenharmony_ci tmp = (unsigned long)mrw; 6098c2ecf20Sopenharmony_ci req.mrw_handle = cpu_to_le64(tmp); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 6128c2ecf20Sopenharmony_ci (void *)&resp, NULL, 0); 6138c2ecf20Sopenharmony_ci if (rc) 6148c2ecf20Sopenharmony_ci return rc; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 6178c2ecf20Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 6188c2ecf20Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 6198c2ecf20Sopenharmony_ci mrw->rkey = le32_to_cpu(resp.xid); 6208c2ecf20Sopenharmony_ci else 6218c2ecf20Sopenharmony_ci mrw->lkey = le32_to_cpu(resp.xid); 6228c2ecf20Sopenharmony_ci return 0; 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ciint bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 6268c2ecf20Sopenharmony_ci bool block) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6298c2ecf20Sopenharmony_ci struct cmdq_deregister_mr req; 6308c2ecf20Sopenharmony_ci struct creq_deregister_mr_resp resp; 6318c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 6328c2ecf20Sopenharmony_ci int rc; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci req.lkey = cpu_to_le32(mrw->lkey); 6378c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 6388c2ecf20Sopenharmony_ci (void *)&resp, NULL, block); 6398c2ecf20Sopenharmony_ci if (rc) 6408c2ecf20Sopenharmony_ci return rc; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* Free the qplib's MR memory */ 6438c2ecf20Sopenharmony_ci if (mrw->hwq.max_elements) { 6448c2ecf20Sopenharmony_ci mrw->va = 0; 6458c2ecf20Sopenharmony_ci mrw->total_size = 0; 6468c2ecf20Sopenharmony_ci bnxt_qplib_free_hwq(res, &mrw->hwq); 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci return 0; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ciint bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 6538c2ecf20Sopenharmony_ci struct ib_umem *umem, int num_pbls, u32 buf_pg_size) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6568c2ecf20Sopenharmony_ci struct bnxt_qplib_hwq_attr hwq_attr = {}; 6578c2ecf20Sopenharmony_ci struct bnxt_qplib_sg_info sginfo = {}; 6588c2ecf20Sopenharmony_ci struct creq_register_mr_resp resp; 6598c2ecf20Sopenharmony_ci struct cmdq_register_mr req; 6608c2ecf20Sopenharmony_ci u16 cmd_flags = 0, level; 6618c2ecf20Sopenharmony_ci int pages, rc, pg_ptrs; 6628c2ecf20Sopenharmony_ci u32 pg_size; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (num_pbls) { 6658c2ecf20Sopenharmony_ci /* Allocate memory for the non-leaf pages to store buf ptrs. 6668c2ecf20Sopenharmony_ci * Non-leaf pages always uses system PAGE_SIZE 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_ci pg_ptrs = roundup_pow_of_two(num_pbls); 6698c2ecf20Sopenharmony_ci pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 6708c2ecf20Sopenharmony_ci if (!pages) 6718c2ecf20Sopenharmony_ci pages++; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (pages > MAX_PBL_LVL_1_PGS) { 6748c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 6758c2ecf20Sopenharmony_ci "SP: Reg MR: pages requested (0x%x) exceeded max (0x%x)\n", 6768c2ecf20Sopenharmony_ci pages, MAX_PBL_LVL_1_PGS); 6778c2ecf20Sopenharmony_ci return -ENOMEM; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci /* Free the hwq if it already exist, must be a rereg */ 6808c2ecf20Sopenharmony_ci if (mr->hwq.max_elements) 6818c2ecf20Sopenharmony_ci bnxt_qplib_free_hwq(res, &mr->hwq); 6828c2ecf20Sopenharmony_ci hwq_attr.res = res; 6838c2ecf20Sopenharmony_ci hwq_attr.depth = pages; 6848c2ecf20Sopenharmony_ci hwq_attr.stride = sizeof(dma_addr_t); 6858c2ecf20Sopenharmony_ci hwq_attr.type = HWQ_TYPE_MR; 6868c2ecf20Sopenharmony_ci hwq_attr.sginfo = &sginfo; 6878c2ecf20Sopenharmony_ci hwq_attr.sginfo->umem = umem; 6888c2ecf20Sopenharmony_ci hwq_attr.sginfo->npages = pages; 6898c2ecf20Sopenharmony_ci hwq_attr.sginfo->pgsize = buf_pg_size; 6908c2ecf20Sopenharmony_ci hwq_attr.sginfo->pgshft = ilog2(buf_pg_size); 6918c2ecf20Sopenharmony_ci rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr); 6928c2ecf20Sopenharmony_ci if (rc) { 6938c2ecf20Sopenharmony_ci dev_err(&res->pdev->dev, 6948c2ecf20Sopenharmony_ci "SP: Reg MR memory allocation failed\n"); 6958c2ecf20Sopenharmony_ci return -ENOMEM; 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* Configure the request */ 7028c2ecf20Sopenharmony_ci if (mr->hwq.level == PBL_LVL_MAX) { 7038c2ecf20Sopenharmony_ci /* No PBL provided, just use system PAGE_SIZE */ 7048c2ecf20Sopenharmony_ci level = 0; 7058c2ecf20Sopenharmony_ci req.pbl = 0; 7068c2ecf20Sopenharmony_ci pg_size = PAGE_SIZE; 7078c2ecf20Sopenharmony_ci } else { 7088c2ecf20Sopenharmony_ci level = mr->hwq.level; 7098c2ecf20Sopenharmony_ci req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE; 7128c2ecf20Sopenharmony_ci req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 7138c2ecf20Sopenharmony_ci ((ilog2(pg_size) << 7148c2ecf20Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 7158c2ecf20Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 7168c2ecf20Sopenharmony_ci req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) << 7178c2ecf20Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) & 7188c2ecf20Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK)); 7198c2ecf20Sopenharmony_ci req.access = (mr->flags & 0xFFFF); 7208c2ecf20Sopenharmony_ci req.va = cpu_to_le64(mr->va); 7218c2ecf20Sopenharmony_ci req.key = cpu_to_le32(mr->lkey); 7228c2ecf20Sopenharmony_ci req.mr_size = cpu_to_le64(mr->total_size); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 7258c2ecf20Sopenharmony_ci (void *)&resp, NULL, false); 7268c2ecf20Sopenharmony_ci if (rc) 7278c2ecf20Sopenharmony_ci goto fail; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci return 0; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cifail: 7328c2ecf20Sopenharmony_ci if (mr->hwq.max_elements) 7338c2ecf20Sopenharmony_ci bnxt_qplib_free_hwq(res, &mr->hwq); 7348c2ecf20Sopenharmony_ci return rc; 7358c2ecf20Sopenharmony_ci} 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 7388c2ecf20Sopenharmony_ci struct bnxt_qplib_frpl *frpl, 7398c2ecf20Sopenharmony_ci int max_pg_ptrs) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci struct bnxt_qplib_hwq_attr hwq_attr = {}; 7428c2ecf20Sopenharmony_ci struct bnxt_qplib_sg_info sginfo = {}; 7438c2ecf20Sopenharmony_ci int pg_ptrs, pages, rc; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* Re-calculate the max to fit the HWQ allocation model */ 7468c2ecf20Sopenharmony_ci pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 7478c2ecf20Sopenharmony_ci pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 7488c2ecf20Sopenharmony_ci if (!pages) 7498c2ecf20Sopenharmony_ci pages++; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (pages > MAX_PBL_LVL_1_PGS) 7528c2ecf20Sopenharmony_ci return -ENOMEM; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci sginfo.pgsize = PAGE_SIZE; 7558c2ecf20Sopenharmony_ci sginfo.nopte = true; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci hwq_attr.res = res; 7588c2ecf20Sopenharmony_ci hwq_attr.depth = pg_ptrs; 7598c2ecf20Sopenharmony_ci hwq_attr.stride = PAGE_SIZE; 7608c2ecf20Sopenharmony_ci hwq_attr.sginfo = &sginfo; 7618c2ecf20Sopenharmony_ci hwq_attr.type = HWQ_TYPE_CTX; 7628c2ecf20Sopenharmony_ci rc = bnxt_qplib_alloc_init_hwq(&frpl->hwq, &hwq_attr); 7638c2ecf20Sopenharmony_ci if (!rc) 7648c2ecf20Sopenharmony_ci frpl->max_pg_ptrs = pg_ptrs; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci return rc; 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ciint bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 7708c2ecf20Sopenharmony_ci struct bnxt_qplib_frpl *frpl) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci bnxt_qplib_free_hwq(res, &frpl->hwq); 7738c2ecf20Sopenharmony_ci return 0; 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ciint bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 7798c2ecf20Sopenharmony_ci struct cmdq_map_tc_to_cos req; 7808c2ecf20Sopenharmony_ci struct creq_map_tc_to_cos_resp resp; 7818c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); 7848c2ecf20Sopenharmony_ci req.cos0 = cpu_to_le16(cids[0]); 7858c2ecf20Sopenharmony_ci req.cos1 = cpu_to_le16(cids[1]); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci return bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 7888c2ecf20Sopenharmony_ci NULL, 0); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ciint bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw, 7928c2ecf20Sopenharmony_ci struct bnxt_qplib_roce_stats *stats) 7938c2ecf20Sopenharmony_ci{ 7948c2ecf20Sopenharmony_ci struct cmdq_query_roce_stats req; 7958c2ecf20Sopenharmony_ci struct creq_query_roce_stats_resp resp; 7968c2ecf20Sopenharmony_ci struct bnxt_qplib_rcfw_sbuf *sbuf; 7978c2ecf20Sopenharmony_ci struct creq_query_roce_stats_resp_sb *sb; 7988c2ecf20Sopenharmony_ci u16 cmd_flags = 0; 7998c2ecf20Sopenharmony_ci int rc = 0; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci RCFW_CMD_PREP(req, QUERY_ROCE_STATS, cmd_flags); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 8048c2ecf20Sopenharmony_ci if (!sbuf) { 8058c2ecf20Sopenharmony_ci dev_err(&rcfw->pdev->dev, 8068c2ecf20Sopenharmony_ci "SP: QUERY_ROCE_STATS alloc side buffer failed\n"); 8078c2ecf20Sopenharmony_ci return -ENOMEM; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci sb = sbuf->sb; 8118c2ecf20Sopenharmony_ci req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 8128c2ecf20Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 8138c2ecf20Sopenharmony_ci (void *)sbuf, 0); 8148c2ecf20Sopenharmony_ci if (rc) 8158c2ecf20Sopenharmony_ci goto bail; 8168c2ecf20Sopenharmony_ci /* Extract the context from the side buffer */ 8178c2ecf20Sopenharmony_ci stats->to_retransmits = le64_to_cpu(sb->to_retransmits); 8188c2ecf20Sopenharmony_ci stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); 8198c2ecf20Sopenharmony_ci stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded); 8208c2ecf20Sopenharmony_ci stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); 8218c2ecf20Sopenharmony_ci stats->missing_resp = le64_to_cpu(sb->missing_resp); 8228c2ecf20Sopenharmony_ci stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err); 8238c2ecf20Sopenharmony_ci stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err); 8248c2ecf20Sopenharmony_ci stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err); 8258c2ecf20Sopenharmony_ci stats->local_protection_err = le64_to_cpu(sb->local_protection_err); 8268c2ecf20Sopenharmony_ci stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err); 8278c2ecf20Sopenharmony_ci stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err); 8288c2ecf20Sopenharmony_ci stats->remote_access_err = le64_to_cpu(sb->remote_access_err); 8298c2ecf20Sopenharmony_ci stats->remote_op_err = le64_to_cpu(sb->remote_op_err); 8308c2ecf20Sopenharmony_ci stats->dup_req = le64_to_cpu(sb->dup_req); 8318c2ecf20Sopenharmony_ci stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max); 8328c2ecf20Sopenharmony_ci stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch); 8338c2ecf20Sopenharmony_ci stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe); 8348c2ecf20Sopenharmony_ci stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err); 8358c2ecf20Sopenharmony_ci stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey); 8368c2ecf20Sopenharmony_ci stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err); 8378c2ecf20Sopenharmony_ci stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm); 8388c2ecf20Sopenharmony_ci stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err); 8398c2ecf20Sopenharmony_ci stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey); 8408c2ecf20Sopenharmony_ci stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err); 8418c2ecf20Sopenharmony_ci stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm); 8428c2ecf20Sopenharmony_ci stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err); 8438c2ecf20Sopenharmony_ci stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow); 8448c2ecf20Sopenharmony_ci stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode); 8458c2ecf20Sopenharmony_ci stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic); 8468c2ecf20Sopenharmony_ci stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err); 8478c2ecf20Sopenharmony_ci stats->res_mem_error = le64_to_cpu(sb->res_mem_error); 8488c2ecf20Sopenharmony_ci stats->res_srq_err = le64_to_cpu(sb->res_srq_err); 8498c2ecf20Sopenharmony_ci stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err); 8508c2ecf20Sopenharmony_ci stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey); 8518c2ecf20Sopenharmony_ci stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err); 8528c2ecf20Sopenharmony_ci stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err); 8538c2ecf20Sopenharmony_ci stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err); 8548c2ecf20Sopenharmony_ci stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err); 8558c2ecf20Sopenharmony_ci stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err); 8568c2ecf20Sopenharmony_ci if (!rcfw->init_oos_stats) { 8578c2ecf20Sopenharmony_ci rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 8588c2ecf20Sopenharmony_ci rcfw->init_oos_stats = 1; 8598c2ecf20Sopenharmony_ci } else { 8608c2ecf20Sopenharmony_ci stats->res_oos_drop_count += 8618c2ecf20Sopenharmony_ci (le64_to_cpu(sb->res_oos_drop_count) - 8628c2ecf20Sopenharmony_ci rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK; 8638c2ecf20Sopenharmony_ci rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_cibail: 8678c2ecf20Sopenharmony_ci bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 8688c2ecf20Sopenharmony_ci return rc; 8698c2ecf20Sopenharmony_ci} 870