162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term 562306a36Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This software is available to you under a choice of one of two 862306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 962306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 1062306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 1162306a36Sopenharmony_ci * BSD license below: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1462306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1562306a36Sopenharmony_ci * are met: 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1862306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1962306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 2062306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 2162306a36Sopenharmony_ci * the documentation and/or other materials provided with the 2262306a36Sopenharmony_ci * distribution. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 2562306a36Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2662306a36Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2762306a36Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 2862306a36Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2962306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3062306a36Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 3162306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 3262306a36Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 3362306a36Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 3462306a36Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * Description: Slow Path Operators 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define dev_fmt(fmt) "QPLIB: " fmt 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include <linux/interrupt.h> 4262306a36Sopenharmony_ci#include <linux/spinlock.h> 4362306a36Sopenharmony_ci#include <linux/sched.h> 4462306a36Sopenharmony_ci#include <linux/pci.h> 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include "roce_hsi.h" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#include "qplib_res.h" 4962306a36Sopenharmony_ci#include "qplib_rcfw.h" 5062306a36Sopenharmony_ci#include "qplib_sp.h" 5162306a36Sopenharmony_ci#include "qplib_tlv.h" 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciconst struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 5462306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0 } }; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Device */ 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic bool bnxt_qplib_is_atomic_cap(struct bnxt_qplib_rcfw *rcfw) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci u16 pcie_ctl2 = 0; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (!bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx)) 6362306a36Sopenharmony_ci return false; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci pcie_capability_read_word(rcfw->pdev, PCI_EXP_DEVCTL2, &pcie_ctl2); 6662306a36Sopenharmony_ci return (pcie_ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, 7062306a36Sopenharmony_ci char *fw_ver) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct creq_query_version_resp resp = {}; 7362306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 7462306a36Sopenharmony_ci struct cmdq_query_version req = {}; 7562306a36Sopenharmony_ci int rc; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 7862306a36Sopenharmony_ci CMDQ_BASE_OPCODE_QUERY_VERSION, 7962306a36Sopenharmony_ci sizeof(req)); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), sizeof(resp), 0); 8262306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 8362306a36Sopenharmony_ci if (rc) 8462306a36Sopenharmony_ci return; 8562306a36Sopenharmony_ci fw_ver[0] = resp.fw_maj; 8662306a36Sopenharmony_ci fw_ver[1] = resp.fw_minor; 8762306a36Sopenharmony_ci fw_ver[2] = resp.fw_bld; 8862306a36Sopenharmony_ci fw_ver[3] = resp.fw_rsvd; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ciint bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, 9262306a36Sopenharmony_ci struct bnxt_qplib_dev_attr *attr) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct creq_query_func_resp resp = {}; 9562306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 9662306a36Sopenharmony_ci struct creq_query_func_resp_sb *sb; 9762306a36Sopenharmony_ci struct bnxt_qplib_rcfw_sbuf sbuf; 9862306a36Sopenharmony_ci struct cmdq_query_func req = {}; 9962306a36Sopenharmony_ci u8 *tqm_alloc; 10062306a36Sopenharmony_ci int i, rc; 10162306a36Sopenharmony_ci u32 temp; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 10462306a36Sopenharmony_ci CMDQ_BASE_OPCODE_QUERY_FUNC, 10562306a36Sopenharmony_ci sizeof(req)); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci sbuf.size = ALIGN(sizeof(*sb), BNXT_QPLIB_CMDQE_UNITS); 10862306a36Sopenharmony_ci sbuf.sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf.size, 10962306a36Sopenharmony_ci &sbuf.dma_addr, GFP_KERNEL); 11062306a36Sopenharmony_ci if (!sbuf.sb) 11162306a36Sopenharmony_ci return -ENOMEM; 11262306a36Sopenharmony_ci sb = sbuf.sb; 11362306a36Sopenharmony_ci req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; 11462306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), 11562306a36Sopenharmony_ci sizeof(resp), 0); 11662306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 11762306a36Sopenharmony_ci if (rc) 11862306a36Sopenharmony_ci goto bail; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Extract the context from the side buffer */ 12162306a36Sopenharmony_ci attr->max_qp = le32_to_cpu(sb->max_qp); 12262306a36Sopenharmony_ci /* max_qp value reported by FW doesn't include the QP1 */ 12362306a36Sopenharmony_ci attr->max_qp += 1; 12462306a36Sopenharmony_ci attr->max_qp_rd_atom = 12562306a36Sopenharmony_ci sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 12662306a36Sopenharmony_ci BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; 12762306a36Sopenharmony_ci attr->max_qp_init_rd_atom = 12862306a36Sopenharmony_ci sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 12962306a36Sopenharmony_ci BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; 13062306a36Sopenharmony_ci attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * 128 WQEs needs to be reserved for the HW (8916). Prevent 13362306a36Sopenharmony_ci * reporting the max number 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1; 13662306a36Sopenharmony_ci attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx) ? 13762306a36Sopenharmony_ci 6 : sb->max_sge; 13862306a36Sopenharmony_ci attr->max_cq = le32_to_cpu(sb->max_cq); 13962306a36Sopenharmony_ci attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 14062306a36Sopenharmony_ci attr->max_cq_sges = attr->max_qp_sges; 14162306a36Sopenharmony_ci attr->max_mr = le32_to_cpu(sb->max_mr); 14262306a36Sopenharmony_ci attr->max_mw = le32_to_cpu(sb->max_mw); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 14562306a36Sopenharmony_ci attr->max_pd = 64 * 1024; 14662306a36Sopenharmony_ci attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 14762306a36Sopenharmony_ci attr->max_ah = le32_to_cpu(sb->max_ah); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci attr->max_srq = le16_to_cpu(sb->max_srq); 15062306a36Sopenharmony_ci attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 15162306a36Sopenharmony_ci attr->max_srq_sges = sb->max_srq_sge; 15262306a36Sopenharmony_ci attr->max_pkey = 1; 15362306a36Sopenharmony_ci attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 15462306a36Sopenharmony_ci attr->l2_db_size = (sb->l2_db_space_size + 1) * 15562306a36Sopenharmony_ci (0x01 << RCFW_DBR_BASE_PAGE_SHIFT); 15662306a36Sopenharmony_ci attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED; 15762306a36Sopenharmony_ci attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci bnxt_qplib_query_version(rcfw, attr->fw_ver); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 16262306a36Sopenharmony_ci temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 16362306a36Sopenharmony_ci tqm_alloc = (u8 *)&temp; 16462306a36Sopenharmony_ci attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 16562306a36Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 16662306a36Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 16762306a36Sopenharmony_ci attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (rcfw->res->cctx->hwrm_intf_ver >= HWRM_VERSION_DEV_ATTR_MAX_DPI) 17162306a36Sopenharmony_ci attr->max_dpi = le32_to_cpu(sb->max_dpi); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci attr->is_atomic = bnxt_qplib_is_atomic_cap(rcfw); 17462306a36Sopenharmony_cibail: 17562306a36Sopenharmony_ci dma_free_coherent(&rcfw->pdev->dev, sbuf.size, 17662306a36Sopenharmony_ci sbuf.sb, sbuf.dma_addr); 17762306a36Sopenharmony_ci return rc; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciint bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res, 18162306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw, 18262306a36Sopenharmony_ci struct bnxt_qplib_ctx *ctx) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct creq_set_func_resources_resp resp = {}; 18562306a36Sopenharmony_ci struct cmdq_set_func_resources req = {}; 18662306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 18762306a36Sopenharmony_ci int rc; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 19062306a36Sopenharmony_ci CMDQ_BASE_OPCODE_SET_FUNC_RESOURCES, 19162306a36Sopenharmony_ci sizeof(req)); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci req.number_of_qp = cpu_to_le32(ctx->qpc_count); 19462306a36Sopenharmony_ci req.number_of_mrw = cpu_to_le32(ctx->mrw_count); 19562306a36Sopenharmony_ci req.number_of_srq = cpu_to_le32(ctx->srqc_count); 19662306a36Sopenharmony_ci req.number_of_cq = cpu_to_le32(ctx->cq_count); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf); 19962306a36Sopenharmony_ci req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf); 20062306a36Sopenharmony_ci req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf); 20162306a36Sopenharmony_ci req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf); 20262306a36Sopenharmony_ci req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 20562306a36Sopenharmony_ci sizeof(resp), 0); 20662306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 20762306a36Sopenharmony_ci if (rc) { 20862306a36Sopenharmony_ci dev_err(&res->pdev->dev, "Failed to set function resources\n"); 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci return rc; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* SGID */ 21462306a36Sopenharmony_ciint bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 21562306a36Sopenharmony_ci struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 21662306a36Sopenharmony_ci struct bnxt_qplib_gid *gid) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci if (index >= sgid_tbl->max) { 21962306a36Sopenharmony_ci dev_err(&res->pdev->dev, 22062306a36Sopenharmony_ci "Index %d exceeded SGID table max (%d)\n", 22162306a36Sopenharmony_ci index, sgid_tbl->max); 22262306a36Sopenharmony_ci return -EINVAL; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid)); 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciint bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 22962306a36Sopenharmony_ci struct bnxt_qplib_gid *gid, u16 vlan_id, bool update) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 23262306a36Sopenharmony_ci struct bnxt_qplib_res, 23362306a36Sopenharmony_ci sgid_tbl); 23462306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 23562306a36Sopenharmony_ci int index; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* Do we need a sgid_lock here? */ 23862306a36Sopenharmony_ci if (!sgid_tbl->active) { 23962306a36Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table has no active entries\n"); 24062306a36Sopenharmony_ci return -ENOMEM; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci for (index = 0; index < sgid_tbl->max; index++) { 24362306a36Sopenharmony_ci if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) && 24462306a36Sopenharmony_ci vlan_id == sgid_tbl->tbl[index].vlan_id) 24562306a36Sopenharmony_ci break; 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci if (index == sgid_tbl->max) { 24862306a36Sopenharmony_ci dev_warn(&res->pdev->dev, "GID not found in the SGID table\n"); 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci /* Remove GID from the SGID table */ 25262306a36Sopenharmony_ci if (update) { 25362306a36Sopenharmony_ci struct creq_delete_gid_resp resp = {}; 25462306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 25562306a36Sopenharmony_ci struct cmdq_delete_gid req = {}; 25662306a36Sopenharmony_ci int rc; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 25962306a36Sopenharmony_ci CMDQ_BASE_OPCODE_DELETE_GID, 26062306a36Sopenharmony_ci sizeof(req)); 26162306a36Sopenharmony_ci if (sgid_tbl->hw_id[index] == 0xFFFF) { 26262306a36Sopenharmony_ci dev_err(&res->pdev->dev, 26362306a36Sopenharmony_ci "GID entry contains an invalid HW id\n"); 26462306a36Sopenharmony_ci return -EINVAL; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 26762306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 26862306a36Sopenharmony_ci sizeof(resp), 0); 26962306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 27062306a36Sopenharmony_ci if (rc) 27162306a36Sopenharmony_ci return rc; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero, 27462306a36Sopenharmony_ci sizeof(bnxt_qplib_gid_zero)); 27562306a36Sopenharmony_ci sgid_tbl->tbl[index].vlan_id = 0xFFFF; 27662306a36Sopenharmony_ci sgid_tbl->vlan[index] = 0; 27762306a36Sopenharmony_ci sgid_tbl->active--; 27862306a36Sopenharmony_ci dev_dbg(&res->pdev->dev, 27962306a36Sopenharmony_ci "SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n", 28062306a36Sopenharmony_ci index, sgid_tbl->hw_id[index], sgid_tbl->active); 28162306a36Sopenharmony_ci sgid_tbl->hw_id[index] = (u16)-1; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* unlock */ 28462306a36Sopenharmony_ci return 0; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciint bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 28862306a36Sopenharmony_ci struct bnxt_qplib_gid *gid, const u8 *smac, 28962306a36Sopenharmony_ci u16 vlan_id, bool update, u32 *index) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 29262306a36Sopenharmony_ci struct bnxt_qplib_res, 29362306a36Sopenharmony_ci sgid_tbl); 29462306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 29562306a36Sopenharmony_ci int i, free_idx; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* Do we need a sgid_lock here? */ 29862306a36Sopenharmony_ci if (sgid_tbl->active == sgid_tbl->max) { 29962306a36Sopenharmony_ci dev_err(&res->pdev->dev, "SGID table is full\n"); 30062306a36Sopenharmony_ci return -ENOMEM; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci free_idx = sgid_tbl->max; 30362306a36Sopenharmony_ci for (i = 0; i < sgid_tbl->max; i++) { 30462306a36Sopenharmony_ci if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) && 30562306a36Sopenharmony_ci sgid_tbl->tbl[i].vlan_id == vlan_id) { 30662306a36Sopenharmony_ci dev_dbg(&res->pdev->dev, 30762306a36Sopenharmony_ci "SGID entry already exist in entry %d!\n", i); 30862306a36Sopenharmony_ci *index = i; 30962306a36Sopenharmony_ci return -EALREADY; 31062306a36Sopenharmony_ci } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 31162306a36Sopenharmony_ci sizeof(bnxt_qplib_gid_zero)) && 31262306a36Sopenharmony_ci free_idx == sgid_tbl->max) { 31362306a36Sopenharmony_ci free_idx = i; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci if (free_idx == sgid_tbl->max) { 31762306a36Sopenharmony_ci dev_err(&res->pdev->dev, 31862306a36Sopenharmony_ci "SGID table is FULL but count is not MAX??\n"); 31962306a36Sopenharmony_ci return -ENOMEM; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci if (update) { 32262306a36Sopenharmony_ci struct creq_add_gid_resp resp = {}; 32362306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 32462306a36Sopenharmony_ci struct cmdq_add_gid req = {}; 32562306a36Sopenharmony_ci int rc; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 32862306a36Sopenharmony_ci CMDQ_BASE_OPCODE_ADD_GID, 32962306a36Sopenharmony_ci sizeof(req)); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 33262306a36Sopenharmony_ci req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 33362306a36Sopenharmony_ci req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 33462306a36Sopenharmony_ci req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 33562306a36Sopenharmony_ci /* 33662306a36Sopenharmony_ci * driver should ensure that all RoCE traffic is always VLAN 33762306a36Sopenharmony_ci * tagged if RoCE traffic is running on non-zero VLAN ID or 33862306a36Sopenharmony_ci * RoCE traffic is running on non-zero Priority. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci if ((vlan_id != 0xFFFF) || res->prio) { 34162306a36Sopenharmony_ci if (vlan_id != 0xFFFF) 34262306a36Sopenharmony_ci req.vlan = cpu_to_le16 34362306a36Sopenharmony_ci (vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK); 34462306a36Sopenharmony_ci req.vlan |= cpu_to_le16 34562306a36Sopenharmony_ci (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 34662306a36Sopenharmony_ci CMDQ_ADD_GID_VLAN_VLAN_EN); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* MAC in network format */ 35062306a36Sopenharmony_ci req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 35162306a36Sopenharmony_ci req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 35262306a36Sopenharmony_ci req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 35562306a36Sopenharmony_ci sizeof(resp), 0); 35662306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 35762306a36Sopenharmony_ci if (rc) 35862306a36Sopenharmony_ci return rc; 35962306a36Sopenharmony_ci sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci /* Add GID to the sgid_tbl */ 36262306a36Sopenharmony_ci memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 36362306a36Sopenharmony_ci sgid_tbl->tbl[free_idx].vlan_id = vlan_id; 36462306a36Sopenharmony_ci sgid_tbl->active++; 36562306a36Sopenharmony_ci if (vlan_id != 0xFFFF) 36662306a36Sopenharmony_ci sgid_tbl->vlan[free_idx] = 1; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci dev_dbg(&res->pdev->dev, 36962306a36Sopenharmony_ci "SGID added hw_id[0x%x] = 0x%x active = 0x%x\n", 37062306a36Sopenharmony_ci free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci *index = free_idx; 37362306a36Sopenharmony_ci /* unlock */ 37462306a36Sopenharmony_ci return 0; 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciint bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 37862306a36Sopenharmony_ci struct bnxt_qplib_gid *gid, u16 gid_idx, 37962306a36Sopenharmony_ci const u8 *smac) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 38262306a36Sopenharmony_ci struct bnxt_qplib_res, 38362306a36Sopenharmony_ci sgid_tbl); 38462306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 38562306a36Sopenharmony_ci struct creq_modify_gid_resp resp = {}; 38662306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 38762306a36Sopenharmony_ci struct cmdq_modify_gid req = {}; 38862306a36Sopenharmony_ci int rc; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 39162306a36Sopenharmony_ci CMDQ_BASE_OPCODE_MODIFY_GID, 39262306a36Sopenharmony_ci sizeof(req)); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 39562306a36Sopenharmony_ci req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 39662306a36Sopenharmony_ci req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 39762306a36Sopenharmony_ci req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 39862306a36Sopenharmony_ci if (res->prio) { 39962306a36Sopenharmony_ci req.vlan |= cpu_to_le16 40062306a36Sopenharmony_ci (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 40162306a36Sopenharmony_ci CMDQ_ADD_GID_VLAN_VLAN_EN); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* MAC in network format */ 40562306a36Sopenharmony_ci req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 40662306a36Sopenharmony_ci req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 40762306a36Sopenharmony_ci req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci req.gid_index = cpu_to_le16(gid_idx); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 41262306a36Sopenharmony_ci sizeof(resp), 0); 41362306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 41462306a36Sopenharmony_ci return rc; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci/* AH */ 41862306a36Sopenharmony_ciint bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 41962306a36Sopenharmony_ci bool block) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 42262306a36Sopenharmony_ci struct creq_create_ah_resp resp = {}; 42362306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 42462306a36Sopenharmony_ci struct cmdq_create_ah req = {}; 42562306a36Sopenharmony_ci u32 temp32[4]; 42662306a36Sopenharmony_ci u16 temp16[3]; 42762306a36Sopenharmony_ci int rc; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 43062306a36Sopenharmony_ci CMDQ_BASE_OPCODE_CREATE_AH, 43162306a36Sopenharmony_ci sizeof(req)); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 43462306a36Sopenharmony_ci req.dgid[0] = cpu_to_le32(temp32[0]); 43562306a36Sopenharmony_ci req.dgid[1] = cpu_to_le32(temp32[1]); 43662306a36Sopenharmony_ci req.dgid[2] = cpu_to_le32(temp32[2]); 43762306a36Sopenharmony_ci req.dgid[3] = cpu_to_le32(temp32[3]); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci req.type = ah->nw_type; 44062306a36Sopenharmony_ci req.hop_limit = ah->hop_limit; 44162306a36Sopenharmony_ci req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 44262306a36Sopenharmony_ci req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 44362306a36Sopenharmony_ci CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 44462306a36Sopenharmony_ci CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 44562306a36Sopenharmony_ci req.pd_id = cpu_to_le32(ah->pd->id); 44662306a36Sopenharmony_ci req.traffic_class = ah->traffic_class; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* MAC in network format */ 44962306a36Sopenharmony_ci memcpy(temp16, ah->dmac, 6); 45062306a36Sopenharmony_ci req.dest_mac[0] = cpu_to_le16(temp16[0]); 45162306a36Sopenharmony_ci req.dest_mac[1] = cpu_to_le16(temp16[1]); 45262306a36Sopenharmony_ci req.dest_mac[2] = cpu_to_le16(temp16[2]); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 45562306a36Sopenharmony_ci sizeof(resp), block); 45662306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 45762306a36Sopenharmony_ci if (rc) 45862306a36Sopenharmony_ci return rc; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci ah->id = le32_to_cpu(resp.xid); 46162306a36Sopenharmony_ci return 0; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ciint bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 46562306a36Sopenharmony_ci bool block) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 46862306a36Sopenharmony_ci struct creq_destroy_ah_resp resp = {}; 46962306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 47062306a36Sopenharmony_ci struct cmdq_destroy_ah req = {}; 47162306a36Sopenharmony_ci int rc; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* Clean up the AH table in the device */ 47462306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 47562306a36Sopenharmony_ci CMDQ_BASE_OPCODE_DESTROY_AH, 47662306a36Sopenharmony_ci sizeof(req)); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci req.ah_cid = cpu_to_le32(ah->id); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 48162306a36Sopenharmony_ci sizeof(resp), block); 48262306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 48362306a36Sopenharmony_ci return rc; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/* MRW */ 48762306a36Sopenharmony_ciint bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct creq_deallocate_key_resp resp = {}; 49062306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 49162306a36Sopenharmony_ci struct cmdq_deallocate_key req = {}; 49262306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 49362306a36Sopenharmony_ci int rc; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (mrw->lkey == 0xFFFFFFFF) { 49662306a36Sopenharmony_ci dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n"); 49762306a36Sopenharmony_ci return 0; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 50162306a36Sopenharmony_ci CMDQ_BASE_OPCODE_DEALLOCATE_KEY, 50262306a36Sopenharmony_ci sizeof(req)); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci req.mrw_flags = mrw->type; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 50762306a36Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 50862306a36Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 50962306a36Sopenharmony_ci req.key = cpu_to_le32(mrw->rkey); 51062306a36Sopenharmony_ci else 51162306a36Sopenharmony_ci req.key = cpu_to_le32(mrw->lkey); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 51462306a36Sopenharmony_ci sizeof(resp), 0); 51562306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 51662306a36Sopenharmony_ci if (rc) 51762306a36Sopenharmony_ci return rc; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* Free the qplib's MRW memory */ 52062306a36Sopenharmony_ci if (mrw->hwq.max_elements) 52162306a36Sopenharmony_ci bnxt_qplib_free_hwq(res, &mrw->hwq); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return 0; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ciint bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 52962306a36Sopenharmony_ci struct creq_allocate_mrw_resp resp = {}; 53062306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 53162306a36Sopenharmony_ci struct cmdq_allocate_mrw req = {}; 53262306a36Sopenharmony_ci unsigned long tmp; 53362306a36Sopenharmony_ci int rc; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 53662306a36Sopenharmony_ci CMDQ_BASE_OPCODE_ALLOCATE_MRW, 53762306a36Sopenharmony_ci sizeof(req)); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci req.pd_id = cpu_to_le32(mrw->pd->id); 54062306a36Sopenharmony_ci req.mrw_flags = mrw->type; 54162306a36Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 54262306a36Sopenharmony_ci mrw->flags & BNXT_QPLIB_FR_PMR) || 54362306a36Sopenharmony_ci mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 54462306a36Sopenharmony_ci mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 54562306a36Sopenharmony_ci req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 54662306a36Sopenharmony_ci tmp = (unsigned long)mrw; 54762306a36Sopenharmony_ci req.mrw_handle = cpu_to_le64(tmp); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 55062306a36Sopenharmony_ci sizeof(resp), 0); 55162306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 55262306a36Sopenharmony_ci if (rc) 55362306a36Sopenharmony_ci return rc; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 55662306a36Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 55762306a36Sopenharmony_ci (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 55862306a36Sopenharmony_ci mrw->rkey = le32_to_cpu(resp.xid); 55962306a36Sopenharmony_ci else 56062306a36Sopenharmony_ci mrw->lkey = le32_to_cpu(resp.xid); 56162306a36Sopenharmony_ci return 0; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ciint bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 56562306a36Sopenharmony_ci bool block) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 56862306a36Sopenharmony_ci struct creq_deregister_mr_resp resp = {}; 56962306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 57062306a36Sopenharmony_ci struct cmdq_deregister_mr req = {}; 57162306a36Sopenharmony_ci int rc; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 57462306a36Sopenharmony_ci CMDQ_BASE_OPCODE_DEREGISTER_MR, 57562306a36Sopenharmony_ci sizeof(req)); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci req.lkey = cpu_to_le32(mrw->lkey); 57862306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 57962306a36Sopenharmony_ci sizeof(resp), block); 58062306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 58162306a36Sopenharmony_ci if (rc) 58262306a36Sopenharmony_ci return rc; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* Free the qplib's MR memory */ 58562306a36Sopenharmony_ci if (mrw->hwq.max_elements) { 58662306a36Sopenharmony_ci mrw->va = 0; 58762306a36Sopenharmony_ci mrw->total_size = 0; 58862306a36Sopenharmony_ci bnxt_qplib_free_hwq(res, &mrw->hwq); 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci return 0; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ciint bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 59562306a36Sopenharmony_ci struct ib_umem *umem, int num_pbls, u32 buf_pg_size) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci struct bnxt_qplib_rcfw *rcfw = res->rcfw; 59862306a36Sopenharmony_ci struct bnxt_qplib_hwq_attr hwq_attr = {}; 59962306a36Sopenharmony_ci struct bnxt_qplib_sg_info sginfo = {}; 60062306a36Sopenharmony_ci struct creq_register_mr_resp resp = {}; 60162306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 60262306a36Sopenharmony_ci struct cmdq_register_mr req = {}; 60362306a36Sopenharmony_ci int pages, rc; 60462306a36Sopenharmony_ci u32 pg_size; 60562306a36Sopenharmony_ci u16 level; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (num_pbls) { 60862306a36Sopenharmony_ci pages = roundup_pow_of_two(num_pbls); 60962306a36Sopenharmony_ci /* Allocate memory for the non-leaf pages to store buf ptrs. 61062306a36Sopenharmony_ci * Non-leaf pages always uses system PAGE_SIZE 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci /* Free the hwq if it already exist, must be a rereg */ 61362306a36Sopenharmony_ci if (mr->hwq.max_elements) 61462306a36Sopenharmony_ci bnxt_qplib_free_hwq(res, &mr->hwq); 61562306a36Sopenharmony_ci hwq_attr.res = res; 61662306a36Sopenharmony_ci hwq_attr.depth = pages; 61762306a36Sopenharmony_ci hwq_attr.stride = sizeof(dma_addr_t); 61862306a36Sopenharmony_ci hwq_attr.type = HWQ_TYPE_MR; 61962306a36Sopenharmony_ci hwq_attr.sginfo = &sginfo; 62062306a36Sopenharmony_ci hwq_attr.sginfo->umem = umem; 62162306a36Sopenharmony_ci hwq_attr.sginfo->npages = pages; 62262306a36Sopenharmony_ci hwq_attr.sginfo->pgsize = buf_pg_size; 62362306a36Sopenharmony_ci hwq_attr.sginfo->pgshft = ilog2(buf_pg_size); 62462306a36Sopenharmony_ci rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr); 62562306a36Sopenharmony_ci if (rc) { 62662306a36Sopenharmony_ci dev_err(&res->pdev->dev, 62762306a36Sopenharmony_ci "SP: Reg MR memory allocation failed\n"); 62862306a36Sopenharmony_ci return -ENOMEM; 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 63362306a36Sopenharmony_ci CMDQ_BASE_OPCODE_REGISTER_MR, 63462306a36Sopenharmony_ci sizeof(req)); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* Configure the request */ 63762306a36Sopenharmony_ci if (mr->hwq.level == PBL_LVL_MAX) { 63862306a36Sopenharmony_ci /* No PBL provided, just use system PAGE_SIZE */ 63962306a36Sopenharmony_ci level = 0; 64062306a36Sopenharmony_ci req.pbl = 0; 64162306a36Sopenharmony_ci pg_size = PAGE_SIZE; 64262306a36Sopenharmony_ci } else { 64362306a36Sopenharmony_ci level = mr->hwq.level; 64462306a36Sopenharmony_ci req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE; 64762306a36Sopenharmony_ci req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 64862306a36Sopenharmony_ci ((ilog2(pg_size) << 64962306a36Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 65062306a36Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 65162306a36Sopenharmony_ci req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) << 65262306a36Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) & 65362306a36Sopenharmony_ci CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK)); 65462306a36Sopenharmony_ci req.access = (mr->flags & 0xFFFF); 65562306a36Sopenharmony_ci req.va = cpu_to_le64(mr->va); 65662306a36Sopenharmony_ci req.key = cpu_to_le32(mr->lkey); 65762306a36Sopenharmony_ci req.mr_size = cpu_to_le64(mr->total_size); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), 66062306a36Sopenharmony_ci sizeof(resp), 0); 66162306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 66262306a36Sopenharmony_ci if (rc) 66362306a36Sopenharmony_ci goto fail; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci return 0; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cifail: 66862306a36Sopenharmony_ci if (mr->hwq.max_elements) 66962306a36Sopenharmony_ci bnxt_qplib_free_hwq(res, &mr->hwq); 67062306a36Sopenharmony_ci return rc; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ciint bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 67462306a36Sopenharmony_ci struct bnxt_qplib_frpl *frpl, 67562306a36Sopenharmony_ci int max_pg_ptrs) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci struct bnxt_qplib_hwq_attr hwq_attr = {}; 67862306a36Sopenharmony_ci struct bnxt_qplib_sg_info sginfo = {}; 67962306a36Sopenharmony_ci int pg_ptrs, pages, rc; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* Re-calculate the max to fit the HWQ allocation model */ 68262306a36Sopenharmony_ci pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 68362306a36Sopenharmony_ci pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 68462306a36Sopenharmony_ci if (!pages) 68562306a36Sopenharmony_ci pages++; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci if (pages > MAX_PBL_LVL_1_PGS) 68862306a36Sopenharmony_ci return -ENOMEM; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci sginfo.pgsize = PAGE_SIZE; 69162306a36Sopenharmony_ci sginfo.nopte = true; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci hwq_attr.res = res; 69462306a36Sopenharmony_ci hwq_attr.depth = pg_ptrs; 69562306a36Sopenharmony_ci hwq_attr.stride = PAGE_SIZE; 69662306a36Sopenharmony_ci hwq_attr.sginfo = &sginfo; 69762306a36Sopenharmony_ci hwq_attr.type = HWQ_TYPE_CTX; 69862306a36Sopenharmony_ci rc = bnxt_qplib_alloc_init_hwq(&frpl->hwq, &hwq_attr); 69962306a36Sopenharmony_ci if (!rc) 70062306a36Sopenharmony_ci frpl->max_pg_ptrs = pg_ptrs; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci return rc; 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ciint bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 70662306a36Sopenharmony_ci struct bnxt_qplib_frpl *frpl) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci bnxt_qplib_free_hwq(res, &frpl->hwq); 70962306a36Sopenharmony_ci return 0; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ciint bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw, 71362306a36Sopenharmony_ci struct bnxt_qplib_roce_stats *stats) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct creq_query_roce_stats_resp resp = {}; 71662306a36Sopenharmony_ci struct creq_query_roce_stats_resp_sb *sb; 71762306a36Sopenharmony_ci struct cmdq_query_roce_stats req = {}; 71862306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 71962306a36Sopenharmony_ci struct bnxt_qplib_rcfw_sbuf sbuf; 72062306a36Sopenharmony_ci int rc; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 72362306a36Sopenharmony_ci CMDQ_BASE_OPCODE_QUERY_ROCE_STATS, 72462306a36Sopenharmony_ci sizeof(req)); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci sbuf.size = ALIGN(sizeof(*sb), BNXT_QPLIB_CMDQE_UNITS); 72762306a36Sopenharmony_ci sbuf.sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf.size, 72862306a36Sopenharmony_ci &sbuf.dma_addr, GFP_KERNEL); 72962306a36Sopenharmony_ci if (!sbuf.sb) 73062306a36Sopenharmony_ci return -ENOMEM; 73162306a36Sopenharmony_ci sb = sbuf.sb; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; 73462306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), 73562306a36Sopenharmony_ci sizeof(resp), 0); 73662306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 73762306a36Sopenharmony_ci if (rc) 73862306a36Sopenharmony_ci goto bail; 73962306a36Sopenharmony_ci /* Extract the context from the side buffer */ 74062306a36Sopenharmony_ci stats->to_retransmits = le64_to_cpu(sb->to_retransmits); 74162306a36Sopenharmony_ci stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); 74262306a36Sopenharmony_ci stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded); 74362306a36Sopenharmony_ci stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); 74462306a36Sopenharmony_ci stats->missing_resp = le64_to_cpu(sb->missing_resp); 74562306a36Sopenharmony_ci stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err); 74662306a36Sopenharmony_ci stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err); 74762306a36Sopenharmony_ci stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err); 74862306a36Sopenharmony_ci stats->local_protection_err = le64_to_cpu(sb->local_protection_err); 74962306a36Sopenharmony_ci stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err); 75062306a36Sopenharmony_ci stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err); 75162306a36Sopenharmony_ci stats->remote_access_err = le64_to_cpu(sb->remote_access_err); 75262306a36Sopenharmony_ci stats->remote_op_err = le64_to_cpu(sb->remote_op_err); 75362306a36Sopenharmony_ci stats->dup_req = le64_to_cpu(sb->dup_req); 75462306a36Sopenharmony_ci stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max); 75562306a36Sopenharmony_ci stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch); 75662306a36Sopenharmony_ci stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe); 75762306a36Sopenharmony_ci stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err); 75862306a36Sopenharmony_ci stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey); 75962306a36Sopenharmony_ci stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err); 76062306a36Sopenharmony_ci stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm); 76162306a36Sopenharmony_ci stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err); 76262306a36Sopenharmony_ci stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey); 76362306a36Sopenharmony_ci stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err); 76462306a36Sopenharmony_ci stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm); 76562306a36Sopenharmony_ci stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err); 76662306a36Sopenharmony_ci stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow); 76762306a36Sopenharmony_ci stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode); 76862306a36Sopenharmony_ci stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic); 76962306a36Sopenharmony_ci stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err); 77062306a36Sopenharmony_ci stats->res_mem_error = le64_to_cpu(sb->res_mem_error); 77162306a36Sopenharmony_ci stats->res_srq_err = le64_to_cpu(sb->res_srq_err); 77262306a36Sopenharmony_ci stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err); 77362306a36Sopenharmony_ci stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey); 77462306a36Sopenharmony_ci stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err); 77562306a36Sopenharmony_ci stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err); 77662306a36Sopenharmony_ci stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err); 77762306a36Sopenharmony_ci stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err); 77862306a36Sopenharmony_ci stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err); 77962306a36Sopenharmony_ci if (!rcfw->init_oos_stats) { 78062306a36Sopenharmony_ci rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 78162306a36Sopenharmony_ci rcfw->init_oos_stats = 1; 78262306a36Sopenharmony_ci } else { 78362306a36Sopenharmony_ci stats->res_oos_drop_count += 78462306a36Sopenharmony_ci (le64_to_cpu(sb->res_oos_drop_count) - 78562306a36Sopenharmony_ci rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK; 78662306a36Sopenharmony_ci rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cibail: 79062306a36Sopenharmony_ci dma_free_coherent(&rcfw->pdev->dev, sbuf.size, 79162306a36Sopenharmony_ci sbuf.sb, sbuf.dma_addr); 79262306a36Sopenharmony_ci return rc; 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ciint bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid, 79662306a36Sopenharmony_ci struct bnxt_qplib_ext_stat *estat) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci struct creq_query_roce_stats_ext_resp resp = {}; 79962306a36Sopenharmony_ci struct creq_query_roce_stats_ext_resp_sb *sb; 80062306a36Sopenharmony_ci struct cmdq_query_roce_stats_ext req = {}; 80162306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 80262306a36Sopenharmony_ci struct bnxt_qplib_rcfw_sbuf sbuf; 80362306a36Sopenharmony_ci int rc; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci sbuf.size = ALIGN(sizeof(*sb), BNXT_QPLIB_CMDQE_UNITS); 80662306a36Sopenharmony_ci sbuf.sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf.size, 80762306a36Sopenharmony_ci &sbuf.dma_addr, GFP_KERNEL); 80862306a36Sopenharmony_ci if (!sbuf.sb) 80962306a36Sopenharmony_ci return -ENOMEM; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci sb = sbuf.sb; 81262306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, 81362306a36Sopenharmony_ci CMDQ_QUERY_ROCE_STATS_EXT_OPCODE_QUERY_ROCE_STATS, 81462306a36Sopenharmony_ci sizeof(req)); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; 81762306a36Sopenharmony_ci req.resp_addr = cpu_to_le64(sbuf.dma_addr); 81862306a36Sopenharmony_ci req.function_id = cpu_to_le32(fid); 81962306a36Sopenharmony_ci req.flags = cpu_to_le16(CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_FUNCTION_ID); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), 82262306a36Sopenharmony_ci sizeof(resp), 0); 82362306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); 82462306a36Sopenharmony_ci if (rc) 82562306a36Sopenharmony_ci goto bail; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci estat->tx_atomic_req = le64_to_cpu(sb->tx_atomic_req_pkts); 82862306a36Sopenharmony_ci estat->tx_read_req = le64_to_cpu(sb->tx_read_req_pkts); 82962306a36Sopenharmony_ci estat->tx_read_res = le64_to_cpu(sb->tx_read_res_pkts); 83062306a36Sopenharmony_ci estat->tx_write_req = le64_to_cpu(sb->tx_write_req_pkts); 83162306a36Sopenharmony_ci estat->tx_send_req = le64_to_cpu(sb->tx_send_req_pkts); 83262306a36Sopenharmony_ci estat->tx_roce_pkts = le64_to_cpu(sb->tx_roce_pkts); 83362306a36Sopenharmony_ci estat->tx_roce_bytes = le64_to_cpu(sb->tx_roce_bytes); 83462306a36Sopenharmony_ci estat->rx_atomic_req = le64_to_cpu(sb->rx_atomic_req_pkts); 83562306a36Sopenharmony_ci estat->rx_read_req = le64_to_cpu(sb->rx_read_req_pkts); 83662306a36Sopenharmony_ci estat->rx_read_res = le64_to_cpu(sb->rx_read_res_pkts); 83762306a36Sopenharmony_ci estat->rx_write_req = le64_to_cpu(sb->rx_write_req_pkts); 83862306a36Sopenharmony_ci estat->rx_send_req = le64_to_cpu(sb->rx_send_req_pkts); 83962306a36Sopenharmony_ci estat->rx_roce_pkts = le64_to_cpu(sb->rx_roce_pkts); 84062306a36Sopenharmony_ci estat->rx_roce_bytes = le64_to_cpu(sb->rx_roce_bytes); 84162306a36Sopenharmony_ci estat->rx_roce_good_pkts = le64_to_cpu(sb->rx_roce_good_pkts); 84262306a36Sopenharmony_ci estat->rx_roce_good_bytes = le64_to_cpu(sb->rx_roce_good_bytes); 84362306a36Sopenharmony_ci estat->rx_out_of_buffer = le64_to_cpu(sb->rx_out_of_buffer_pkts); 84462306a36Sopenharmony_ci estat->rx_out_of_sequence = le64_to_cpu(sb->rx_out_of_sequence_pkts); 84562306a36Sopenharmony_ci estat->tx_cnp = le64_to_cpu(sb->tx_cnp_pkts); 84662306a36Sopenharmony_ci estat->rx_cnp = le64_to_cpu(sb->rx_cnp_pkts); 84762306a36Sopenharmony_ci estat->rx_ecn_marked = le64_to_cpu(sb->rx_ecn_marked_pkts); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cibail: 85062306a36Sopenharmony_ci dma_free_coherent(&rcfw->pdev->dev, sbuf.size, 85162306a36Sopenharmony_ci sbuf.sb, sbuf.dma_addr); 85262306a36Sopenharmony_ci return rc; 85362306a36Sopenharmony_ci} 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic void bnxt_qplib_fill_cc_gen1(struct cmdq_modify_roce_cc_gen1_tlv *ext_req, 85662306a36Sopenharmony_ci struct bnxt_qplib_cc_param_ext *cc_ext) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci ext_req->modify_mask = cpu_to_le64(cc_ext->ext_mask); 85962306a36Sopenharmony_ci cc_ext->ext_mask = 0; 86062306a36Sopenharmony_ci ext_req->inactivity_th_hi = cpu_to_le16(cc_ext->inact_th_hi); 86162306a36Sopenharmony_ci ext_req->min_time_between_cnps = cpu_to_le16(cc_ext->min_delta_cnp); 86262306a36Sopenharmony_ci ext_req->init_cp = cpu_to_le16(cc_ext->init_cp); 86362306a36Sopenharmony_ci ext_req->tr_update_mode = cc_ext->tr_update_mode; 86462306a36Sopenharmony_ci ext_req->tr_update_cycles = cc_ext->tr_update_cyls; 86562306a36Sopenharmony_ci ext_req->fr_num_rtts = cc_ext->fr_rtt; 86662306a36Sopenharmony_ci ext_req->ai_rate_increase = cc_ext->ai_rate_incr; 86762306a36Sopenharmony_ci ext_req->reduction_relax_rtts_th = cpu_to_le16(cc_ext->rr_rtt_th); 86862306a36Sopenharmony_ci ext_req->additional_relax_cr_th = cpu_to_le16(cc_ext->ar_cr_th); 86962306a36Sopenharmony_ci ext_req->cr_min_th = cpu_to_le16(cc_ext->cr_min_th); 87062306a36Sopenharmony_ci ext_req->bw_avg_weight = cc_ext->bw_avg_weight; 87162306a36Sopenharmony_ci ext_req->actual_cr_factor = cc_ext->cr_factor; 87262306a36Sopenharmony_ci ext_req->max_cp_cr_th = cpu_to_le16(cc_ext->cr_th_max_cp); 87362306a36Sopenharmony_ci ext_req->cp_bias_en = cc_ext->cp_bias_en; 87462306a36Sopenharmony_ci ext_req->cp_bias = cc_ext->cp_bias; 87562306a36Sopenharmony_ci ext_req->cnp_ecn = cc_ext->cnp_ecn; 87662306a36Sopenharmony_ci ext_req->rtt_jitter_en = cc_ext->rtt_jitter_en; 87762306a36Sopenharmony_ci ext_req->link_bytes_per_usec = cpu_to_le16(cc_ext->bytes_per_usec); 87862306a36Sopenharmony_ci ext_req->reset_cc_cr_th = cpu_to_le16(cc_ext->cc_cr_reset_th); 87962306a36Sopenharmony_ci ext_req->cr_width = cc_ext->cr_width; 88062306a36Sopenharmony_ci ext_req->quota_period_min = cc_ext->min_quota; 88162306a36Sopenharmony_ci ext_req->quota_period_max = cc_ext->max_quota; 88262306a36Sopenharmony_ci ext_req->quota_period_abs_max = cc_ext->abs_max_quota; 88362306a36Sopenharmony_ci ext_req->tr_lower_bound = cpu_to_le16(cc_ext->tr_lb); 88462306a36Sopenharmony_ci ext_req->cr_prob_factor = cc_ext->cr_prob_fac; 88562306a36Sopenharmony_ci ext_req->tr_prob_factor = cc_ext->tr_prob_fac; 88662306a36Sopenharmony_ci ext_req->fairness_cr_th = cpu_to_le16(cc_ext->fair_cr_th); 88762306a36Sopenharmony_ci ext_req->red_div = cc_ext->red_div; 88862306a36Sopenharmony_ci ext_req->cnp_ratio_th = cc_ext->cnp_ratio_th; 88962306a36Sopenharmony_ci ext_req->exp_ai_rtts = cpu_to_le16(cc_ext->ai_ext_rtt); 89062306a36Sopenharmony_ci ext_req->exp_ai_cr_cp_ratio = cc_ext->exp_crcp_ratio; 89162306a36Sopenharmony_ci ext_req->use_rate_table = cc_ext->low_rate_en; 89262306a36Sopenharmony_ci ext_req->cp_exp_update_th = cpu_to_le16(cc_ext->cpcr_update_th); 89362306a36Sopenharmony_ci ext_req->high_exp_ai_rtts_th1 = cpu_to_le16(cc_ext->ai_rtt_th1); 89462306a36Sopenharmony_ci ext_req->high_exp_ai_rtts_th2 = cpu_to_le16(cc_ext->ai_rtt_th2); 89562306a36Sopenharmony_ci ext_req->actual_cr_cong_free_rtts_th = cpu_to_le16(cc_ext->cf_rtt_th); 89662306a36Sopenharmony_ci ext_req->severe_cong_cr_th1 = cpu_to_le16(cc_ext->sc_cr_th1); 89762306a36Sopenharmony_ci ext_req->severe_cong_cr_th2 = cpu_to_le16(cc_ext->sc_cr_th2); 89862306a36Sopenharmony_ci ext_req->link64B_per_rtt = cpu_to_le32(cc_ext->l64B_per_rtt); 89962306a36Sopenharmony_ci ext_req->cc_ack_bytes = cc_ext->cc_ack_bytes; 90062306a36Sopenharmony_ci} 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ciint bnxt_qplib_modify_cc(struct bnxt_qplib_res *res, 90362306a36Sopenharmony_ci struct bnxt_qplib_cc_param *cc_param) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci struct bnxt_qplib_tlv_modify_cc_req tlv_req = {}; 90662306a36Sopenharmony_ci struct creq_modify_roce_cc_resp resp = {}; 90762306a36Sopenharmony_ci struct bnxt_qplib_cmdqmsg msg = {}; 90862306a36Sopenharmony_ci struct cmdq_modify_roce_cc *req; 90962306a36Sopenharmony_ci int req_size; 91062306a36Sopenharmony_ci void *cmd; 91162306a36Sopenharmony_ci int rc; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci /* Prepare the older base command */ 91462306a36Sopenharmony_ci req = &tlv_req.base_req; 91562306a36Sopenharmony_ci cmd = req; 91662306a36Sopenharmony_ci req_size = sizeof(*req); 91762306a36Sopenharmony_ci bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)req, CMDQ_BASE_OPCODE_MODIFY_ROCE_CC, 91862306a36Sopenharmony_ci sizeof(*req)); 91962306a36Sopenharmony_ci req->modify_mask = cpu_to_le32(cc_param->mask); 92062306a36Sopenharmony_ci req->enable_cc = cc_param->enable; 92162306a36Sopenharmony_ci req->g = cc_param->g; 92262306a36Sopenharmony_ci req->num_phases_per_state = cc_param->nph_per_state; 92362306a36Sopenharmony_ci req->time_per_phase = cc_param->time_pph; 92462306a36Sopenharmony_ci req->pkts_per_phase = cc_param->pkts_pph; 92562306a36Sopenharmony_ci req->init_cr = cpu_to_le16(cc_param->init_cr); 92662306a36Sopenharmony_ci req->init_tr = cpu_to_le16(cc_param->init_tr); 92762306a36Sopenharmony_ci req->tos_dscp_tos_ecn = (cc_param->tos_dscp << CMDQ_MODIFY_ROCE_CC_TOS_DSCP_SFT) | 92862306a36Sopenharmony_ci (cc_param->tos_ecn & CMDQ_MODIFY_ROCE_CC_TOS_ECN_MASK); 92962306a36Sopenharmony_ci req->alt_vlan_pcp = cc_param->alt_vlan_pcp; 93062306a36Sopenharmony_ci req->alt_tos_dscp = cpu_to_le16(cc_param->alt_tos_dscp); 93162306a36Sopenharmony_ci req->rtt = cpu_to_le16(cc_param->rtt); 93262306a36Sopenharmony_ci req->tcp_cp = cpu_to_le16(cc_param->tcp_cp); 93362306a36Sopenharmony_ci req->cc_mode = cc_param->cc_mode; 93462306a36Sopenharmony_ci req->inactivity_th = cpu_to_le16(cc_param->inact_th); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci /* For chip gen P5 onwards fill extended cmd and header */ 93762306a36Sopenharmony_ci if (bnxt_qplib_is_chip_gen_p5(res->cctx)) { 93862306a36Sopenharmony_ci struct roce_tlv *hdr; 93962306a36Sopenharmony_ci u32 payload; 94062306a36Sopenharmony_ci u32 chunks; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci cmd = &tlv_req; 94362306a36Sopenharmony_ci req_size = sizeof(tlv_req); 94462306a36Sopenharmony_ci /* Prepare primary tlv header */ 94562306a36Sopenharmony_ci hdr = &tlv_req.tlv_hdr; 94662306a36Sopenharmony_ci chunks = CHUNKS(sizeof(struct bnxt_qplib_tlv_modify_cc_req)); 94762306a36Sopenharmony_ci payload = sizeof(struct cmdq_modify_roce_cc); 94862306a36Sopenharmony_ci __roce_1st_tlv_prep(hdr, chunks, payload, true); 94962306a36Sopenharmony_ci /* Prepare secondary tlv header */ 95062306a36Sopenharmony_ci hdr = (struct roce_tlv *)&tlv_req.ext_req; 95162306a36Sopenharmony_ci payload = sizeof(struct cmdq_modify_roce_cc_gen1_tlv) - 95262306a36Sopenharmony_ci sizeof(struct roce_tlv); 95362306a36Sopenharmony_ci __roce_ext_tlv_prep(hdr, TLV_TYPE_MODIFY_ROCE_CC_GEN1, payload, false, true); 95462306a36Sopenharmony_ci bnxt_qplib_fill_cc_gen1(&tlv_req.ext_req, &cc_param->cc_ext); 95562306a36Sopenharmony_ci } 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci bnxt_qplib_fill_cmdqmsg(&msg, cmd, &resp, NULL, req_size, 95862306a36Sopenharmony_ci sizeof(resp), 0); 95962306a36Sopenharmony_ci rc = bnxt_qplib_rcfw_send_message(res->rcfw, &msg); 96062306a36Sopenharmony_ci return rc; 96162306a36Sopenharmony_ci} 962