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