xref: /linux/drivers/infiniband/hw/bnxt_re/qplib_sp.c (revision f6919d56)
11ac5a404SSelvin Xavier /*
21ac5a404SSelvin Xavier  * Broadcom NetXtreme-E RoCE driver.
31ac5a404SSelvin Xavier  *
41ac5a404SSelvin Xavier  * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
51ac5a404SSelvin Xavier  * Broadcom refers to Broadcom Limited and/or its subsidiaries.
61ac5a404SSelvin Xavier  *
71ac5a404SSelvin Xavier  * This software is available to you under a choice of one of two
81ac5a404SSelvin Xavier  * licenses.  You may choose to be licensed under the terms of the GNU
91ac5a404SSelvin Xavier  * General Public License (GPL) Version 2, available from the file
101ac5a404SSelvin Xavier  * COPYING in the main directory of this source tree, or the
111ac5a404SSelvin Xavier  * BSD license below:
121ac5a404SSelvin Xavier  *
131ac5a404SSelvin Xavier  * Redistribution and use in source and binary forms, with or without
141ac5a404SSelvin Xavier  * modification, are permitted provided that the following conditions
151ac5a404SSelvin Xavier  * are met:
161ac5a404SSelvin Xavier  *
171ac5a404SSelvin Xavier  * 1. Redistributions of source code must retain the above copyright
181ac5a404SSelvin Xavier  *    notice, this list of conditions and the following disclaimer.
191ac5a404SSelvin Xavier  * 2. Redistributions in binary form must reproduce the above copyright
201ac5a404SSelvin Xavier  *    notice, this list of conditions and the following disclaimer in
211ac5a404SSelvin Xavier  *    the documentation and/or other materials provided with the
221ac5a404SSelvin Xavier  *    distribution.
231ac5a404SSelvin Xavier  *
241ac5a404SSelvin Xavier  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
251ac5a404SSelvin Xavier  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
261ac5a404SSelvin Xavier  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
271ac5a404SSelvin Xavier  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
281ac5a404SSelvin Xavier  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
291ac5a404SSelvin Xavier  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
301ac5a404SSelvin Xavier  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
311ac5a404SSelvin Xavier  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
321ac5a404SSelvin Xavier  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
331ac5a404SSelvin Xavier  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
341ac5a404SSelvin Xavier  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351ac5a404SSelvin Xavier  *
361ac5a404SSelvin Xavier  * Description: Slow Path Operators
371ac5a404SSelvin Xavier  */
381ac5a404SSelvin Xavier 
3908920b8fSJoe Perches #define dev_fmt(fmt) "QPLIB: " fmt
4008920b8fSJoe Perches 
411ac5a404SSelvin Xavier #include <linux/interrupt.h>
421ac5a404SSelvin Xavier #include <linux/spinlock.h>
431ac5a404SSelvin Xavier #include <linux/sched.h>
441ac5a404SSelvin Xavier #include <linux/pci.h>
451ac5a404SSelvin Xavier 
461ac5a404SSelvin Xavier #include "roce_hsi.h"
471ac5a404SSelvin Xavier 
481ac5a404SSelvin Xavier #include "qplib_res.h"
491ac5a404SSelvin Xavier #include "qplib_rcfw.h"
501ac5a404SSelvin Xavier #include "qplib_sp.h"
511ac5a404SSelvin Xavier 
521ac5a404SSelvin Xavier const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0,
531ac5a404SSelvin Xavier 						     0, 0, 0, 0, 0, 0, 0, 0 } };
541ac5a404SSelvin Xavier 
551ac5a404SSelvin Xavier /* Device */
56254cd259SDevesh Sharma 
572fc68543SSelvin Xavier static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw,
582fc68543SSelvin Xavier 				     char *fw_ver)
592fc68543SSelvin Xavier {
602fc68543SSelvin Xavier 	struct cmdq_query_version req;
612fc68543SSelvin Xavier 	struct creq_query_version_resp resp;
622fc68543SSelvin Xavier 	u16 cmd_flags = 0;
632fc68543SSelvin Xavier 	int rc = 0;
642fc68543SSelvin Xavier 
652fc68543SSelvin Xavier 	RCFW_CMD_PREP(req, QUERY_VERSION, cmd_flags);
662fc68543SSelvin Xavier 
672fc68543SSelvin Xavier 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
682fc68543SSelvin Xavier 					  (void *)&resp, NULL, 0);
692fc68543SSelvin Xavier 	if (rc)
702fc68543SSelvin Xavier 		return;
712fc68543SSelvin Xavier 	fw_ver[0] = resp.fw_maj;
722fc68543SSelvin Xavier 	fw_ver[1] = resp.fw_minor;
732fc68543SSelvin Xavier 	fw_ver[2] = resp.fw_bld;
742fc68543SSelvin Xavier 	fw_ver[3] = resp.fw_rsvd;
752fc68543SSelvin Xavier }
762fc68543SSelvin Xavier 
771ac5a404SSelvin Xavier int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
78ccd9d0d3SSelvin Xavier 			    struct bnxt_qplib_dev_attr *attr, bool vf)
791ac5a404SSelvin Xavier {
801ac5a404SSelvin Xavier 	struct cmdq_query_func req;
81cc1ec769SDevesh Sharma 	struct creq_query_func_resp resp;
82cc1ec769SDevesh Sharma 	struct bnxt_qplib_rcfw_sbuf *sbuf;
831ac5a404SSelvin Xavier 	struct creq_query_func_resp_sb *sb;
841ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
851ac5a404SSelvin Xavier 	u32 temp;
861ac5a404SSelvin Xavier 	u8 *tqm_alloc;
87cc1ec769SDevesh Sharma 	int i, rc = 0;
881ac5a404SSelvin Xavier 
891ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags);
901ac5a404SSelvin Xavier 
91cc1ec769SDevesh Sharma 	sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
92cc1ec769SDevesh Sharma 	if (!sbuf) {
931ac5a404SSelvin Xavier 		dev_err(&rcfw->pdev->dev,
9408920b8fSJoe Perches 			"SP: QUERY_FUNC alloc side buffer failed\n");
95cc1ec769SDevesh Sharma 		return -ENOMEM;
961ac5a404SSelvin Xavier 	}
97cc1ec769SDevesh Sharma 
98cc1ec769SDevesh Sharma 	sb = sbuf->sb;
99cc1ec769SDevesh Sharma 	req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
100cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
101cc1ec769SDevesh Sharma 					  (void *)sbuf, 0);
102cc1ec769SDevesh Sharma 	if (rc)
103cc1ec769SDevesh Sharma 		goto bail;
104cc1ec769SDevesh Sharma 
1051ac5a404SSelvin Xavier 	/* Extract the context from the side buffer */
1061ac5a404SSelvin Xavier 	attr->max_qp = le32_to_cpu(sb->max_qp);
10758d4a671SSelvin Xavier 	/* max_qp value reported by FW for PF doesn't include the QP1 for PF */
108ccd9d0d3SSelvin Xavier 	if (!vf)
10958d4a671SSelvin Xavier 		attr->max_qp += 1;
1101ac5a404SSelvin Xavier 	attr->max_qp_rd_atom =
1111ac5a404SSelvin Xavier 		sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
1121ac5a404SSelvin Xavier 		BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom;
1131ac5a404SSelvin Xavier 	attr->max_qp_init_rd_atom =
1141ac5a404SSelvin Xavier 		sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
1151ac5a404SSelvin Xavier 		BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
1161ac5a404SSelvin Xavier 	attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
1179152e0b7SEddie Wai 	/*
1189152e0b7SEddie Wai 	 * 128 WQEs needs to be reserved for the HW (8916). Prevent
1199152e0b7SEddie Wai 	 * reporting the max number
1209152e0b7SEddie Wai 	 */
121c63e1c4dSSelvin Xavier 	attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
12237f91cffSDevesh Sharma 	attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx) ?
12337f91cffSDevesh Sharma 			    6 : sb->max_sge;
1241ac5a404SSelvin Xavier 	attr->max_cq = le32_to_cpu(sb->max_cq);
1251ac5a404SSelvin Xavier 	attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
1261ac5a404SSelvin Xavier 	attr->max_cq_sges = attr->max_qp_sges;
1271ac5a404SSelvin Xavier 	attr->max_mr = le32_to_cpu(sb->max_mr);
1281ac5a404SSelvin Xavier 	attr->max_mw = le32_to_cpu(sb->max_mw);
1291ac5a404SSelvin Xavier 
1301ac5a404SSelvin Xavier 	attr->max_mr_size = le64_to_cpu(sb->max_mr_size);
1311ac5a404SSelvin Xavier 	attr->max_pd = 64 * 1024;
1321ac5a404SSelvin Xavier 	attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp);
1331ac5a404SSelvin Xavier 	attr->max_ah = le32_to_cpu(sb->max_ah);
1341ac5a404SSelvin Xavier 
1351ac5a404SSelvin Xavier 	attr->max_srq = le16_to_cpu(sb->max_srq);
1361ac5a404SSelvin Xavier 	attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1;
1371ac5a404SSelvin Xavier 	attr->max_srq_sges = sb->max_srq_sge;
1381ac5a404SSelvin Xavier 	attr->max_pkey = le32_to_cpu(sb->max_pkeys);
139854a2020SDevesh Sharma 	/*
140854a2020SDevesh Sharma 	 * Some versions of FW reports more than 0xFFFF.
141854a2020SDevesh Sharma 	 * Restrict it for now to 0xFFFF to avoid
142854a2020SDevesh Sharma 	 * reporting trucated value
143854a2020SDevesh Sharma 	 */
144854a2020SDevesh Sharma 	if (attr->max_pkey > 0xFFFF) {
145854a2020SDevesh Sharma 		/* ib_port_attr::pkey_tbl_len is u16 */
146854a2020SDevesh Sharma 		attr->max_pkey = 0xFFFF;
147854a2020SDevesh Sharma 	}
1481ac5a404SSelvin Xavier 
1491ac5a404SSelvin Xavier 	attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
150c354dff0SDevesh Sharma 	attr->l2_db_size = (sb->l2_db_space_size + 1) *
151c354dff0SDevesh Sharma 			    (0x01 << RCFW_DBR_BASE_PAGE_SHIFT);
152847b9788SNaresh Kumar PBS 	attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED;
1531ac5a404SSelvin Xavier 
1542fc68543SSelvin Xavier 	bnxt_qplib_query_version(rcfw, attr->fw_ver);
1551ac5a404SSelvin Xavier 
1561ac5a404SSelvin Xavier 	for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) {
1571ac5a404SSelvin Xavier 		temp = le32_to_cpu(sb->tqm_alloc_reqs[i]);
1581ac5a404SSelvin Xavier 		tqm_alloc = (u8 *)&temp;
1591ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4] = *tqm_alloc;
1601ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc);
1611ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
1621ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
1631ac5a404SSelvin Xavier 	}
164cc1ec769SDevesh Sharma 
16563231585SGustavo A. R. Silva 	attr->is_atomic = false;
166cc1ec769SDevesh Sharma bail:
167cc1ec769SDevesh Sharma 	bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
168cc1ec769SDevesh Sharma 	return rc;
1691ac5a404SSelvin Xavier }
1701ac5a404SSelvin Xavier 
171ccd9d0d3SSelvin Xavier int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
172ccd9d0d3SSelvin Xavier 				  struct bnxt_qplib_rcfw *rcfw,
173ccd9d0d3SSelvin Xavier 				  struct bnxt_qplib_ctx *ctx)
174ccd9d0d3SSelvin Xavier {
175ccd9d0d3SSelvin Xavier 	struct cmdq_set_func_resources req;
176ccd9d0d3SSelvin Xavier 	struct creq_set_func_resources_resp resp;
177ccd9d0d3SSelvin Xavier 	u16 cmd_flags = 0;
178ccd9d0d3SSelvin Xavier 	int rc = 0;
179ccd9d0d3SSelvin Xavier 
180ccd9d0d3SSelvin Xavier 	RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags);
181ccd9d0d3SSelvin Xavier 
182ccd9d0d3SSelvin Xavier 	req.number_of_qp = cpu_to_le32(ctx->qpc_count);
183ccd9d0d3SSelvin Xavier 	req.number_of_mrw = cpu_to_le32(ctx->mrw_count);
184ccd9d0d3SSelvin Xavier 	req.number_of_srq =  cpu_to_le32(ctx->srqc_count);
185ccd9d0d3SSelvin Xavier 	req.number_of_cq = cpu_to_le32(ctx->cq_count);
186ccd9d0d3SSelvin Xavier 
187ccd9d0d3SSelvin Xavier 	req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
188ccd9d0d3SSelvin Xavier 	req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
189ccd9d0d3SSelvin Xavier 	req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
190ccd9d0d3SSelvin Xavier 	req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf);
191ccd9d0d3SSelvin Xavier 	req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf);
192ccd9d0d3SSelvin Xavier 
193ccd9d0d3SSelvin Xavier 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
194ccd9d0d3SSelvin Xavier 					  (void *)&resp,
195ccd9d0d3SSelvin Xavier 					  NULL, 0);
196ccd9d0d3SSelvin Xavier 	if (rc) {
19708920b8fSJoe Perches 		dev_err(&res->pdev->dev, "Failed to set function resources\n");
198ccd9d0d3SSelvin Xavier 	}
199ccd9d0d3SSelvin Xavier 	return rc;
200ccd9d0d3SSelvin Xavier }
201ccd9d0d3SSelvin Xavier 
2021ac5a404SSelvin Xavier /* SGID */
2031ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
2041ac5a404SSelvin Xavier 			struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
2051ac5a404SSelvin Xavier 			struct bnxt_qplib_gid *gid)
2061ac5a404SSelvin Xavier {
207474e5a86SDan Carpenter 	if (index >= sgid_tbl->max) {
2081ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
20908920b8fSJoe Perches 			"Index %d exceeded SGID table max (%d)\n",
2101ac5a404SSelvin Xavier 			index, sgid_tbl->max);
2111ac5a404SSelvin Xavier 		return -EINVAL;
2121ac5a404SSelvin Xavier 	}
213c56b593dSSelvin Xavier 	memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid));
2141ac5a404SSelvin Xavier 	return 0;
2151ac5a404SSelvin Xavier }
2161ac5a404SSelvin Xavier 
2171ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
218c56b593dSSelvin Xavier 			struct bnxt_qplib_gid *gid, u16 vlan_id, bool update)
2191ac5a404SSelvin Xavier {
2201ac5a404SSelvin Xavier 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
2211ac5a404SSelvin Xavier 						   struct bnxt_qplib_res,
2221ac5a404SSelvin Xavier 						   sgid_tbl);
2231ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
2241ac5a404SSelvin Xavier 	int index;
2251ac5a404SSelvin Xavier 
2261ac5a404SSelvin Xavier 	if (!sgid_tbl) {
22708920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table not allocated\n");
2281ac5a404SSelvin Xavier 		return -EINVAL;
2291ac5a404SSelvin Xavier 	}
2301ac5a404SSelvin Xavier 	/* Do we need a sgid_lock here? */
2311ac5a404SSelvin Xavier 	if (!sgid_tbl->active) {
23208920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table has no active entries\n");
2331ac5a404SSelvin Xavier 		return -ENOMEM;
2341ac5a404SSelvin Xavier 	}
2351ac5a404SSelvin Xavier 	for (index = 0; index < sgid_tbl->max; index++) {
236c56b593dSSelvin Xavier 		if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) &&
237c56b593dSSelvin Xavier 		    vlan_id == sgid_tbl->tbl[index].vlan_id)
2381ac5a404SSelvin Xavier 			break;
2391ac5a404SSelvin Xavier 	}
2401ac5a404SSelvin Xavier 	if (index == sgid_tbl->max) {
24108920b8fSJoe Perches 		dev_warn(&res->pdev->dev, "GID not found in the SGID table\n");
2421ac5a404SSelvin Xavier 		return 0;
2431ac5a404SSelvin Xavier 	}
2441ac5a404SSelvin Xavier 	/* Remove GID from the SGID table */
2451ac5a404SSelvin Xavier 	if (update) {
2461ac5a404SSelvin Xavier 		struct cmdq_delete_gid req;
247cc1ec769SDevesh Sharma 		struct creq_delete_gid_resp resp;
2481ac5a404SSelvin Xavier 		u16 cmd_flags = 0;
249cc1ec769SDevesh Sharma 		int rc;
2501ac5a404SSelvin Xavier 
2511ac5a404SSelvin Xavier 		RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
2521ac5a404SSelvin Xavier 		if (sgid_tbl->hw_id[index] == 0xFFFF) {
2531ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
25408920b8fSJoe Perches 				"GID entry contains an invalid HW id\n");
2551ac5a404SSelvin Xavier 			return -EINVAL;
2561ac5a404SSelvin Xavier 		}
2571ac5a404SSelvin Xavier 		req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
258cc1ec769SDevesh Sharma 		rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
259cc1ec769SDevesh Sharma 						  (void *)&resp, NULL, 0);
260cc1ec769SDevesh Sharma 		if (rc)
261cc1ec769SDevesh Sharma 			return rc;
2621ac5a404SSelvin Xavier 	}
263c56b593dSSelvin Xavier 	memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero,
2641ac5a404SSelvin Xavier 	       sizeof(bnxt_qplib_gid_zero));
265c56b593dSSelvin Xavier 	sgid_tbl->tbl[index].vlan_id = 0xFFFF;
2665fac5b1bSKalesh AP 	sgid_tbl->vlan[index] = 0;
2671ac5a404SSelvin Xavier 	sgid_tbl->active--;
2681ac5a404SSelvin Xavier 	dev_dbg(&res->pdev->dev,
26908920b8fSJoe Perches 		"SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n",
2701ac5a404SSelvin Xavier 		 index, sgid_tbl->hw_id[index], sgid_tbl->active);
2711ac5a404SSelvin Xavier 	sgid_tbl->hw_id[index] = (u16)-1;
2721ac5a404SSelvin Xavier 
2731ac5a404SSelvin Xavier 	/* unlock */
2741ac5a404SSelvin Xavier 	return 0;
2751ac5a404SSelvin Xavier }
2761ac5a404SSelvin Xavier 
2771ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
2781ac5a404SSelvin Xavier 			struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id,
2791ac5a404SSelvin Xavier 			bool update, u32 *index)
2801ac5a404SSelvin Xavier {
2811ac5a404SSelvin Xavier 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
2821ac5a404SSelvin Xavier 						   struct bnxt_qplib_res,
2831ac5a404SSelvin Xavier 						   sgid_tbl);
2841ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
285cc1ec769SDevesh Sharma 	int i, free_idx;
2861ac5a404SSelvin Xavier 
2871ac5a404SSelvin Xavier 	if (!sgid_tbl) {
28808920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table not allocated\n");
2891ac5a404SSelvin Xavier 		return -EINVAL;
2901ac5a404SSelvin Xavier 	}
2911ac5a404SSelvin Xavier 	/* Do we need a sgid_lock here? */
2921ac5a404SSelvin Xavier 	if (sgid_tbl->active == sgid_tbl->max) {
29308920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table is full\n");
2941ac5a404SSelvin Xavier 		return -ENOMEM;
2951ac5a404SSelvin Xavier 	}
2961ac5a404SSelvin Xavier 	free_idx = sgid_tbl->max;
2971ac5a404SSelvin Xavier 	for (i = 0; i < sgid_tbl->max; i++) {
298c56b593dSSelvin Xavier 		if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) &&
299c56b593dSSelvin Xavier 		    sgid_tbl->tbl[i].vlan_id == vlan_id) {
3001ac5a404SSelvin Xavier 			dev_dbg(&res->pdev->dev,
30108920b8fSJoe Perches 				"SGID entry already exist in entry %d!\n", i);
3021ac5a404SSelvin Xavier 			*index = i;
3031ac5a404SSelvin Xavier 			return -EALREADY;
3041ac5a404SSelvin Xavier 		} else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
3051ac5a404SSelvin Xavier 				   sizeof(bnxt_qplib_gid_zero)) &&
3061ac5a404SSelvin Xavier 			   free_idx == sgid_tbl->max) {
3071ac5a404SSelvin Xavier 			free_idx = i;
3081ac5a404SSelvin Xavier 		}
3091ac5a404SSelvin Xavier 	}
3101ac5a404SSelvin Xavier 	if (free_idx == sgid_tbl->max) {
3111ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
31208920b8fSJoe Perches 			"SGID table is FULL but count is not MAX??\n");
3131ac5a404SSelvin Xavier 		return -ENOMEM;
3141ac5a404SSelvin Xavier 	}
3151ac5a404SSelvin Xavier 	if (update) {
3161ac5a404SSelvin Xavier 		struct cmdq_add_gid req;
317cc1ec769SDevesh Sharma 		struct creq_add_gid_resp resp;
3181ac5a404SSelvin Xavier 		u16 cmd_flags = 0;
319cc1ec769SDevesh Sharma 		int rc;
3201ac5a404SSelvin Xavier 
3211ac5a404SSelvin Xavier 		RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
3221ac5a404SSelvin Xavier 
3235fac5b1bSKalesh AP 		req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]);
3245fac5b1bSKalesh AP 		req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]);
3255fac5b1bSKalesh AP 		req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]);
3265fac5b1bSKalesh AP 		req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]);
3275fac5b1bSKalesh AP 		/*
3285fac5b1bSKalesh AP 		 * driver should ensure that all RoCE traffic is always VLAN
3295fac5b1bSKalesh AP 		 * tagged if RoCE traffic is running on non-zero VLAN ID or
3305fac5b1bSKalesh AP 		 * RoCE traffic is running on non-zero Priority.
3315fac5b1bSKalesh AP 		 */
3325fac5b1bSKalesh AP 		if ((vlan_id != 0xFFFF) || res->prio) {
3331ac5a404SSelvin Xavier 			if (vlan_id != 0xFFFF)
3345fac5b1bSKalesh AP 				req.vlan = cpu_to_le16
3355fac5b1bSKalesh AP 				(vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK);
3365fac5b1bSKalesh AP 			req.vlan |= cpu_to_le16
3375fac5b1bSKalesh AP 					(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 |
3381ac5a404SSelvin Xavier 					 CMDQ_ADD_GID_VLAN_VLAN_EN);
3395fac5b1bSKalesh AP 		}
3401ac5a404SSelvin Xavier 
3411ac5a404SSelvin Xavier 		/* MAC in network format */
3425fac5b1bSKalesh AP 		req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]);
3435fac5b1bSKalesh AP 		req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]);
3445fac5b1bSKalesh AP 		req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]);
3451ac5a404SSelvin Xavier 
346cc1ec769SDevesh Sharma 		rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
347cc1ec769SDevesh Sharma 						  (void *)&resp, NULL, 0);
348cc1ec769SDevesh Sharma 		if (rc)
349cc1ec769SDevesh Sharma 			return rc;
350cc1ec769SDevesh Sharma 		sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid);
3511ac5a404SSelvin Xavier 	}
3521ac5a404SSelvin Xavier 	/* Add GID to the sgid_tbl */
3531ac5a404SSelvin Xavier 	memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
354c56b593dSSelvin Xavier 	sgid_tbl->tbl[free_idx].vlan_id = vlan_id;
3551ac5a404SSelvin Xavier 	sgid_tbl->active++;
3565fac5b1bSKalesh AP 	if (vlan_id != 0xFFFF)
3575fac5b1bSKalesh AP 		sgid_tbl->vlan[free_idx] = 1;
3585fac5b1bSKalesh AP 
3591ac5a404SSelvin Xavier 	dev_dbg(&res->pdev->dev,
36008920b8fSJoe Perches 		"SGID added hw_id[0x%x] = 0x%x active = 0x%x\n",
3611ac5a404SSelvin Xavier 		 free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active);
3621ac5a404SSelvin Xavier 
3631ac5a404SSelvin Xavier 	*index = free_idx;
3641ac5a404SSelvin Xavier 	/* unlock */
365cc1ec769SDevesh Sharma 	return 0;
3661ac5a404SSelvin Xavier }
3671ac5a404SSelvin Xavier 
3685fac5b1bSKalesh AP int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
3695fac5b1bSKalesh AP 			   struct bnxt_qplib_gid *gid, u16 gid_idx,
3705fac5b1bSKalesh AP 			   u8 *smac)
3715fac5b1bSKalesh AP {
3725fac5b1bSKalesh AP 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
3735fac5b1bSKalesh AP 						   struct bnxt_qplib_res,
3745fac5b1bSKalesh AP 						   sgid_tbl);
3755fac5b1bSKalesh AP 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
3765fac5b1bSKalesh AP 	struct creq_modify_gid_resp resp;
3775fac5b1bSKalesh AP 	struct cmdq_modify_gid req;
3785fac5b1bSKalesh AP 	int rc;
3795fac5b1bSKalesh AP 	u16 cmd_flags = 0;
3805fac5b1bSKalesh AP 
3815fac5b1bSKalesh AP 	RCFW_CMD_PREP(req, MODIFY_GID, cmd_flags);
3825fac5b1bSKalesh AP 
3835fac5b1bSKalesh AP 	req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]);
3845fac5b1bSKalesh AP 	req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]);
3855fac5b1bSKalesh AP 	req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]);
3865fac5b1bSKalesh AP 	req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]);
3875fac5b1bSKalesh AP 	if (res->prio) {
3885fac5b1bSKalesh AP 		req.vlan |= cpu_to_le16
3895fac5b1bSKalesh AP 			(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 |
3905fac5b1bSKalesh AP 			 CMDQ_ADD_GID_VLAN_VLAN_EN);
3915fac5b1bSKalesh AP 	}
3925fac5b1bSKalesh AP 
3935fac5b1bSKalesh AP 	/* MAC in network format */
3945fac5b1bSKalesh AP 	req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]);
3955fac5b1bSKalesh AP 	req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]);
3965fac5b1bSKalesh AP 	req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]);
3975fac5b1bSKalesh AP 
3985fac5b1bSKalesh AP 	req.gid_index = cpu_to_le16(gid_idx);
3995fac5b1bSKalesh AP 
4005fac5b1bSKalesh AP 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
4015fac5b1bSKalesh AP 					  (void *)&resp, NULL, 0);
4025fac5b1bSKalesh AP 	return rc;
4035fac5b1bSKalesh AP }
4045fac5b1bSKalesh AP 
4051ac5a404SSelvin Xavier /* pkeys */
4061ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res,
4071ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index,
4081ac5a404SSelvin Xavier 			u16 *pkey)
4091ac5a404SSelvin Xavier {
4101ac5a404SSelvin Xavier 	if (index == 0xFFFF) {
4111ac5a404SSelvin Xavier 		*pkey = 0xFFFF;
4121ac5a404SSelvin Xavier 		return 0;
4131ac5a404SSelvin Xavier 	}
414474e5a86SDan Carpenter 	if (index >= pkey_tbl->max) {
4151ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
41608920b8fSJoe Perches 			"Index %d exceeded PKEY table max (%d)\n",
4171ac5a404SSelvin Xavier 			index, pkey_tbl->max);
4181ac5a404SSelvin Xavier 		return -EINVAL;
4191ac5a404SSelvin Xavier 	}
4201ac5a404SSelvin Xavier 	memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey));
4211ac5a404SSelvin Xavier 	return 0;
4221ac5a404SSelvin Xavier }
4231ac5a404SSelvin Xavier 
4241ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res,
4251ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
4261ac5a404SSelvin Xavier 			bool update)
4271ac5a404SSelvin Xavier {
4281ac5a404SSelvin Xavier 	int i, rc = 0;
4291ac5a404SSelvin Xavier 
4301ac5a404SSelvin Xavier 	if (!pkey_tbl) {
43108920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table not allocated\n");
4321ac5a404SSelvin Xavier 		return -EINVAL;
4331ac5a404SSelvin Xavier 	}
4341ac5a404SSelvin Xavier 
4351ac5a404SSelvin Xavier 	/* Do we need a pkey_lock here? */
4361ac5a404SSelvin Xavier 	if (!pkey_tbl->active) {
43708920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table has no active entries\n");
4381ac5a404SSelvin Xavier 		return -ENOMEM;
4391ac5a404SSelvin Xavier 	}
4401ac5a404SSelvin Xavier 	for (i = 0; i < pkey_tbl->max; i++) {
4411ac5a404SSelvin Xavier 		if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
4421ac5a404SSelvin Xavier 			break;
4431ac5a404SSelvin Xavier 	}
4441ac5a404SSelvin Xavier 	if (i == pkey_tbl->max) {
4451ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
44608920b8fSJoe Perches 			"PKEY 0x%04x not found in the pkey table\n", *pkey);
4471ac5a404SSelvin Xavier 		return -ENOMEM;
4481ac5a404SSelvin Xavier 	}
4491ac5a404SSelvin Xavier 	memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey));
4501ac5a404SSelvin Xavier 	pkey_tbl->active--;
4511ac5a404SSelvin Xavier 
4521ac5a404SSelvin Xavier 	/* unlock */
4531ac5a404SSelvin Xavier 	return rc;
4541ac5a404SSelvin Xavier }
4551ac5a404SSelvin Xavier 
4561ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res,
4571ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
4581ac5a404SSelvin Xavier 			bool update)
4591ac5a404SSelvin Xavier {
4601ac5a404SSelvin Xavier 	int i, free_idx, rc = 0;
4611ac5a404SSelvin Xavier 
4621ac5a404SSelvin Xavier 	if (!pkey_tbl) {
46308920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table not allocated\n");
4641ac5a404SSelvin Xavier 		return -EINVAL;
4651ac5a404SSelvin Xavier 	}
4661ac5a404SSelvin Xavier 
4671ac5a404SSelvin Xavier 	/* Do we need a pkey_lock here? */
4681ac5a404SSelvin Xavier 	if (pkey_tbl->active == pkey_tbl->max) {
46908920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table is full\n");
4701ac5a404SSelvin Xavier 		return -ENOMEM;
4711ac5a404SSelvin Xavier 	}
4721ac5a404SSelvin Xavier 	free_idx = pkey_tbl->max;
4731ac5a404SSelvin Xavier 	for (i = 0; i < pkey_tbl->max; i++) {
4741ac5a404SSelvin Xavier 		if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
4751ac5a404SSelvin Xavier 			return -EALREADY;
4761ac5a404SSelvin Xavier 		else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max)
4771ac5a404SSelvin Xavier 			free_idx = i;
4781ac5a404SSelvin Xavier 	}
4791ac5a404SSelvin Xavier 	if (free_idx == pkey_tbl->max) {
4801ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
48108920b8fSJoe Perches 			"PKEY table is FULL but count is not MAX??\n");
4821ac5a404SSelvin Xavier 		return -ENOMEM;
4831ac5a404SSelvin Xavier 	}
4841ac5a404SSelvin Xavier 	/* Add PKEY to the pkey_tbl */
4851ac5a404SSelvin Xavier 	memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey));
4861ac5a404SSelvin Xavier 	pkey_tbl->active++;
4871ac5a404SSelvin Xavier 
4881ac5a404SSelvin Xavier 	/* unlock */
4891ac5a404SSelvin Xavier 	return rc;
4901ac5a404SSelvin Xavier }
4911ac5a404SSelvin Xavier 
4921ac5a404SSelvin Xavier /* AH */
49390e3edd8SGal Pressman int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
49490e3edd8SGal Pressman 			 bool block)
4951ac5a404SSelvin Xavier {
4961ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
4971ac5a404SSelvin Xavier 	struct cmdq_create_ah req;
498cc1ec769SDevesh Sharma 	struct creq_create_ah_resp resp;
4991ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
5001ac5a404SSelvin Xavier 	u32 temp32[4];
5011ac5a404SSelvin Xavier 	u16 temp16[3];
502cc1ec769SDevesh Sharma 	int rc;
5031ac5a404SSelvin Xavier 
5041ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
5051ac5a404SSelvin Xavier 
5061ac5a404SSelvin Xavier 	memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid));
5071ac5a404SSelvin Xavier 	req.dgid[0] = cpu_to_le32(temp32[0]);
5081ac5a404SSelvin Xavier 	req.dgid[1] = cpu_to_le32(temp32[1]);
5091ac5a404SSelvin Xavier 	req.dgid[2] = cpu_to_le32(temp32[2]);
5101ac5a404SSelvin Xavier 	req.dgid[3] = cpu_to_le32(temp32[3]);
5111ac5a404SSelvin Xavier 
5121ac5a404SSelvin Xavier 	req.type = ah->nw_type;
5131ac5a404SSelvin Xavier 	req.hop_limit = ah->hop_limit;
5141ac5a404SSelvin Xavier 	req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]);
5151ac5a404SSelvin Xavier 	req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label &
5161ac5a404SSelvin Xavier 					CMDQ_CREATE_AH_FLOW_LABEL_MASK) |
5171ac5a404SSelvin Xavier 					CMDQ_CREATE_AH_DEST_VLAN_ID_MASK);
5181ac5a404SSelvin Xavier 	req.pd_id = cpu_to_le32(ah->pd->id);
5191ac5a404SSelvin Xavier 	req.traffic_class = ah->traffic_class;
5201ac5a404SSelvin Xavier 
5211ac5a404SSelvin Xavier 	/* MAC in network format */
5221ac5a404SSelvin Xavier 	memcpy(temp16, ah->dmac, 6);
5231ac5a404SSelvin Xavier 	req.dest_mac[0] = cpu_to_le16(temp16[0]);
5241ac5a404SSelvin Xavier 	req.dest_mac[1] = cpu_to_le16(temp16[1]);
5251ac5a404SSelvin Xavier 	req.dest_mac[2] = cpu_to_le16(temp16[2]);
5261ac5a404SSelvin Xavier 
527cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
52890e3edd8SGal Pressman 					  NULL, block);
529cc1ec769SDevesh Sharma 	if (rc)
530cc1ec769SDevesh Sharma 		return rc;
531cc1ec769SDevesh Sharma 
532cc1ec769SDevesh Sharma 	ah->id = le32_to_cpu(resp.xid);
5331ac5a404SSelvin Xavier 	return 0;
5341ac5a404SSelvin Xavier }
5351ac5a404SSelvin Xavier 
536d3456914SLeon Romanovsky void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
53750c582deSGal Pressman 			   bool block)
5381ac5a404SSelvin Xavier {
5391ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5401ac5a404SSelvin Xavier 	struct cmdq_destroy_ah req;
541cc1ec769SDevesh Sharma 	struct creq_destroy_ah_resp resp;
5421ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
5431ac5a404SSelvin Xavier 
5441ac5a404SSelvin Xavier 	/* Clean up the AH table in the device */
5451ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
5461ac5a404SSelvin Xavier 
5471ac5a404SSelvin Xavier 	req.ah_cid = cpu_to_le32(ah->id);
5481ac5a404SSelvin Xavier 
549d3456914SLeon Romanovsky 	bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL,
550d3456914SLeon Romanovsky 				     block);
5511ac5a404SSelvin Xavier }
5521ac5a404SSelvin Xavier 
5531ac5a404SSelvin Xavier /* MRW */
5541ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
5551ac5a404SSelvin Xavier {
5561ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5571ac5a404SSelvin Xavier 	struct cmdq_deallocate_key req;
558cc1ec769SDevesh Sharma 	struct creq_deallocate_key_resp resp;
5591ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
560cc1ec769SDevesh Sharma 	int rc;
5611ac5a404SSelvin Xavier 
5621ac5a404SSelvin Xavier 	if (mrw->lkey == 0xFFFFFFFF) {
56308920b8fSJoe Perches 		dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n");
5641ac5a404SSelvin Xavier 		return 0;
5651ac5a404SSelvin Xavier 	}
5661ac5a404SSelvin Xavier 
5671ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags);
5681ac5a404SSelvin Xavier 
5691ac5a404SSelvin Xavier 	req.mrw_flags = mrw->type;
5701ac5a404SSelvin Xavier 
5711ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
5721ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
5731ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
5741ac5a404SSelvin Xavier 		req.key = cpu_to_le32(mrw->rkey);
5751ac5a404SSelvin Xavier 	else
5761ac5a404SSelvin Xavier 		req.key = cpu_to_le32(mrw->lkey);
5771ac5a404SSelvin Xavier 
578cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
5791ac5a404SSelvin Xavier 					  NULL, 0);
580cc1ec769SDevesh Sharma 	if (rc)
581cc1ec769SDevesh Sharma 		return rc;
582cc1ec769SDevesh Sharma 
5831ac5a404SSelvin Xavier 	/* Free the qplib's MRW memory */
5841ac5a404SSelvin Xavier 	if (mrw->hwq.max_elements)
5850c4dcd60SDevesh Sharma 		bnxt_qplib_free_hwq(res, &mrw->hwq);
5861ac5a404SSelvin Xavier 
5871ac5a404SSelvin Xavier 	return 0;
5881ac5a404SSelvin Xavier }
5891ac5a404SSelvin Xavier 
5901ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
5911ac5a404SSelvin Xavier {
5921ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5931ac5a404SSelvin Xavier 	struct cmdq_allocate_mrw req;
594cc1ec769SDevesh Sharma 	struct creq_allocate_mrw_resp resp;
5951ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
5961ac5a404SSelvin Xavier 	unsigned long tmp;
597cc1ec769SDevesh Sharma 	int rc;
5981ac5a404SSelvin Xavier 
5991ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
6001ac5a404SSelvin Xavier 
6011ac5a404SSelvin Xavier 	req.pd_id = cpu_to_le32(mrw->pd->id);
6021ac5a404SSelvin Xavier 	req.mrw_flags = mrw->type;
6031ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR &&
6041ac5a404SSelvin Xavier 	     mrw->flags & BNXT_QPLIB_FR_PMR) ||
6051ac5a404SSelvin Xavier 	    mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
6061ac5a404SSelvin Xavier 	    mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
6071ac5a404SSelvin Xavier 		req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY;
6081ac5a404SSelvin Xavier 	tmp = (unsigned long)mrw;
6091ac5a404SSelvin Xavier 	req.mrw_handle = cpu_to_le64(tmp);
6101ac5a404SSelvin Xavier 
611cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
612cc1ec769SDevesh Sharma 					  (void *)&resp, NULL, 0);
613cc1ec769SDevesh Sharma 	if (rc)
614cc1ec769SDevesh Sharma 		return rc;
615cc1ec769SDevesh Sharma 
6161ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
6171ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
6181ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
619cc1ec769SDevesh Sharma 		mrw->rkey = le32_to_cpu(resp.xid);
6201ac5a404SSelvin Xavier 	else
621cc1ec769SDevesh Sharma 		mrw->lkey = le32_to_cpu(resp.xid);
6221ac5a404SSelvin Xavier 	return 0;
6231ac5a404SSelvin Xavier }
6241ac5a404SSelvin Xavier 
6251ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
6261ac5a404SSelvin Xavier 			 bool block)
6271ac5a404SSelvin Xavier {
6281ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
6291ac5a404SSelvin Xavier 	struct cmdq_deregister_mr req;
630cc1ec769SDevesh Sharma 	struct creq_deregister_mr_resp resp;
6311ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
6321ac5a404SSelvin Xavier 	int rc;
6331ac5a404SSelvin Xavier 
6341ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
6351ac5a404SSelvin Xavier 
6361ac5a404SSelvin Xavier 	req.lkey = cpu_to_le32(mrw->lkey);
637cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
638cc1ec769SDevesh Sharma 					  (void *)&resp, NULL, block);
639cc1ec769SDevesh Sharma 	if (rc)
640cc1ec769SDevesh Sharma 		return rc;
6411ac5a404SSelvin Xavier 
6421ac5a404SSelvin Xavier 	/* Free the qplib's MR memory */
6431ac5a404SSelvin Xavier 	if (mrw->hwq.max_elements) {
6441ac5a404SSelvin Xavier 		mrw->va = 0;
6451ac5a404SSelvin Xavier 		mrw->total_size = 0;
6460c4dcd60SDevesh Sharma 		bnxt_qplib_free_hwq(res, &mrw->hwq);
6471ac5a404SSelvin Xavier 	}
6481ac5a404SSelvin Xavier 
6491ac5a404SSelvin Xavier 	return 0;
6501ac5a404SSelvin Xavier }
6511ac5a404SSelvin Xavier 
6521ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
653*f6919d56SSelvin Xavier 		      struct ib_umem *umem, int num_pbls, u32 buf_pg_size)
6541ac5a404SSelvin Xavier {
6551ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
6560c4dcd60SDevesh Sharma 	struct bnxt_qplib_hwq_attr hwq_attr = {};
6570c4dcd60SDevesh Sharma 	struct bnxt_qplib_sg_info sginfo = {};
658cc1ec769SDevesh Sharma 	struct creq_register_mr_resp resp;
6590c4dcd60SDevesh Sharma 	struct cmdq_register_mr req;
6600c4dcd60SDevesh Sharma 	u16 cmd_flags = 0, level;
661*f6919d56SSelvin Xavier 	int pages, rc, pg_ptrs;
6621ac5a404SSelvin Xavier 	u32 pg_size;
6631ac5a404SSelvin Xavier 
6641ac5a404SSelvin Xavier 	if (num_pbls) {
665872f3578SSomnath Kotur 		/* Allocate memory for the non-leaf pages to store buf ptrs.
666872f3578SSomnath Kotur 		 * Non-leaf pages always uses system PAGE_SIZE
667872f3578SSomnath Kotur 		 */
6681ac5a404SSelvin Xavier 		pg_ptrs = roundup_pow_of_two(num_pbls);
6691ac5a404SSelvin Xavier 		pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
6701ac5a404SSelvin Xavier 		if (!pages)
6711ac5a404SSelvin Xavier 			pages++;
6721ac5a404SSelvin Xavier 
6731ac5a404SSelvin Xavier 		if (pages > MAX_PBL_LVL_1_PGS) {
6741ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
6750c4dcd60SDevesh Sharma 				"SP: Reg MR: pages requested (0x%x) exceeded max (0x%x)\n",
6761ac5a404SSelvin Xavier 				pages, MAX_PBL_LVL_1_PGS);
6771ac5a404SSelvin Xavier 			return -ENOMEM;
6781ac5a404SSelvin Xavier 		}
6791ac5a404SSelvin Xavier 		/* Free the hwq if it already exist, must be a rereg */
6801ac5a404SSelvin Xavier 		if (mr->hwq.max_elements)
6810c4dcd60SDevesh Sharma 			bnxt_qplib_free_hwq(res, &mr->hwq);
682872f3578SSomnath Kotur 		/* Use system PAGE_SIZE */
6830c4dcd60SDevesh Sharma 		hwq_attr.res = res;
6840c4dcd60SDevesh Sharma 		hwq_attr.depth = pages;
685*f6919d56SSelvin Xavier 		hwq_attr.stride = buf_pg_size;
6860c4dcd60SDevesh Sharma 		hwq_attr.type = HWQ_TYPE_MR;
6870c4dcd60SDevesh Sharma 		hwq_attr.sginfo = &sginfo;
688*f6919d56SSelvin Xavier 		hwq_attr.sginfo->umem = umem;
6890c4dcd60SDevesh Sharma 		hwq_attr.sginfo->npages = pages;
6900c4dcd60SDevesh Sharma 		hwq_attr.sginfo->pgsize = PAGE_SIZE;
6910c4dcd60SDevesh Sharma 		hwq_attr.sginfo->pgshft = PAGE_SHIFT;
6920c4dcd60SDevesh Sharma 		rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr);
6931ac5a404SSelvin Xavier 		if (rc) {
6941ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
69508920b8fSJoe Perches 				"SP: Reg MR memory allocation failed\n");
6961ac5a404SSelvin Xavier 			return -ENOMEM;
6971ac5a404SSelvin Xavier 		}
6981ac5a404SSelvin Xavier 	}
6991ac5a404SSelvin Xavier 
7001ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags);
7011ac5a404SSelvin Xavier 
7021ac5a404SSelvin Xavier 	/* Configure the request */
7031ac5a404SSelvin Xavier 	if (mr->hwq.level == PBL_LVL_MAX) {
704872f3578SSomnath Kotur 		/* No PBL provided, just use system PAGE_SIZE */
7051ac5a404SSelvin Xavier 		level = 0;
7061ac5a404SSelvin Xavier 		req.pbl = 0;
7071ac5a404SSelvin Xavier 		pg_size = PAGE_SIZE;
7081ac5a404SSelvin Xavier 	} else {
709*f6919d56SSelvin Xavier 		level = mr->hwq.level;
7101ac5a404SSelvin Xavier 		req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]);
7111ac5a404SSelvin Xavier 	}
712872f3578SSomnath Kotur 	pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE;
7131ac5a404SSelvin Xavier 	req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) |
7141ac5a404SSelvin Xavier 			       ((ilog2(pg_size) <<
7151ac5a404SSelvin Xavier 				 CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) &
7161ac5a404SSelvin Xavier 				CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK);
717872f3578SSomnath Kotur 	req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
718872f3578SSomnath Kotur 				 CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
719872f3578SSomnath Kotur 				CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
7201ac5a404SSelvin Xavier 	req.access = (mr->flags & 0xFFFF);
7211ac5a404SSelvin Xavier 	req.va = cpu_to_le64(mr->va);
7221ac5a404SSelvin Xavier 	req.key = cpu_to_le32(mr->lkey);
7231ac5a404SSelvin Xavier 	req.mr_size = cpu_to_le64(mr->total_size);
7241ac5a404SSelvin Xavier 
725cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
726*f6919d56SSelvin Xavier 					  (void *)&resp, NULL, false);
727cc1ec769SDevesh Sharma 	if (rc)
7281ac5a404SSelvin Xavier 		goto fail;
729cc1ec769SDevesh Sharma 
7301ac5a404SSelvin Xavier 	return 0;
7311ac5a404SSelvin Xavier 
7321ac5a404SSelvin Xavier fail:
7331ac5a404SSelvin Xavier 	if (mr->hwq.max_elements)
7340c4dcd60SDevesh Sharma 		bnxt_qplib_free_hwq(res, &mr->hwq);
7351ac5a404SSelvin Xavier 	return rc;
7361ac5a404SSelvin Xavier }
7371ac5a404SSelvin Xavier 
7381ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res,
7391ac5a404SSelvin Xavier 					struct bnxt_qplib_frpl *frpl,
7401ac5a404SSelvin Xavier 					int max_pg_ptrs)
7411ac5a404SSelvin Xavier {
7420c4dcd60SDevesh Sharma 	struct bnxt_qplib_hwq_attr hwq_attr = {};
7430c4dcd60SDevesh Sharma 	struct bnxt_qplib_sg_info sginfo = {};
7441ac5a404SSelvin Xavier 	int pg_ptrs, pages, rc;
7451ac5a404SSelvin Xavier 
7461ac5a404SSelvin Xavier 	/* Re-calculate the max to fit the HWQ allocation model */
7471ac5a404SSelvin Xavier 	pg_ptrs = roundup_pow_of_two(max_pg_ptrs);
7481ac5a404SSelvin Xavier 	pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
7491ac5a404SSelvin Xavier 	if (!pages)
7501ac5a404SSelvin Xavier 		pages++;
7511ac5a404SSelvin Xavier 
7521ac5a404SSelvin Xavier 	if (pages > MAX_PBL_LVL_1_PGS)
7531ac5a404SSelvin Xavier 		return -ENOMEM;
7541ac5a404SSelvin Xavier 
7550c4dcd60SDevesh Sharma 	sginfo.pgsize = PAGE_SIZE;
7560c4dcd60SDevesh Sharma 	sginfo.nopte = true;
7570c4dcd60SDevesh Sharma 
7580c4dcd60SDevesh Sharma 	hwq_attr.res = res;
7590c4dcd60SDevesh Sharma 	hwq_attr.depth = pg_ptrs;
7600c4dcd60SDevesh Sharma 	hwq_attr.stride = PAGE_SIZE;
7610c4dcd60SDevesh Sharma 	hwq_attr.sginfo = &sginfo;
7620c4dcd60SDevesh Sharma 	hwq_attr.type = HWQ_TYPE_CTX;
7630c4dcd60SDevesh Sharma 	rc = bnxt_qplib_alloc_init_hwq(&frpl->hwq, &hwq_attr);
7641ac5a404SSelvin Xavier 	if (!rc)
7651ac5a404SSelvin Xavier 		frpl->max_pg_ptrs = pg_ptrs;
7661ac5a404SSelvin Xavier 
7671ac5a404SSelvin Xavier 	return rc;
7681ac5a404SSelvin Xavier }
7691ac5a404SSelvin Xavier 
7701ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res,
7711ac5a404SSelvin Xavier 				       struct bnxt_qplib_frpl *frpl)
7721ac5a404SSelvin Xavier {
7730c4dcd60SDevesh Sharma 	bnxt_qplib_free_hwq(res, &frpl->hwq);
7741ac5a404SSelvin Xavier 	return 0;
7751ac5a404SSelvin Xavier }
7761ac5a404SSelvin Xavier 
7771ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
7781ac5a404SSelvin Xavier {
7791ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
7801ac5a404SSelvin Xavier 	struct cmdq_map_tc_to_cos req;
781cc1ec769SDevesh Sharma 	struct creq_map_tc_to_cos_resp resp;
7821ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
7831ac5a404SSelvin Xavier 
7841ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
7851ac5a404SSelvin Xavier 	req.cos0 = cpu_to_le16(cids[0]);
7861ac5a404SSelvin Xavier 	req.cos1 = cpu_to_le16(cids[1]);
7871ac5a404SSelvin Xavier 
78894edd87aSAditya Pakki 	return bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
78994edd87aSAditya Pakki 						NULL, 0);
7901ac5a404SSelvin Xavier }
79189f81008SSelvin Xavier 
79289f81008SSelvin Xavier int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw,
79389f81008SSelvin Xavier 			      struct bnxt_qplib_roce_stats *stats)
79489f81008SSelvin Xavier {
79589f81008SSelvin Xavier 	struct cmdq_query_roce_stats req;
79689f81008SSelvin Xavier 	struct creq_query_roce_stats_resp resp;
79789f81008SSelvin Xavier 	struct bnxt_qplib_rcfw_sbuf *sbuf;
79889f81008SSelvin Xavier 	struct creq_query_roce_stats_resp_sb *sb;
79989f81008SSelvin Xavier 	u16 cmd_flags = 0;
80089f81008SSelvin Xavier 	int rc = 0;
80189f81008SSelvin Xavier 
80289f81008SSelvin Xavier 	RCFW_CMD_PREP(req, QUERY_ROCE_STATS, cmd_flags);
80389f81008SSelvin Xavier 
80489f81008SSelvin Xavier 	sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
80589f81008SSelvin Xavier 	if (!sbuf) {
80689f81008SSelvin Xavier 		dev_err(&rcfw->pdev->dev,
80708920b8fSJoe Perches 			"SP: QUERY_ROCE_STATS alloc side buffer failed\n");
80889f81008SSelvin Xavier 		return -ENOMEM;
80989f81008SSelvin Xavier 	}
81089f81008SSelvin Xavier 
81189f81008SSelvin Xavier 	sb = sbuf->sb;
81289f81008SSelvin Xavier 	req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
81389f81008SSelvin Xavier 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
81489f81008SSelvin Xavier 					  (void *)sbuf, 0);
81589f81008SSelvin Xavier 	if (rc)
81689f81008SSelvin Xavier 		goto bail;
81789f81008SSelvin Xavier 	/* Extract the context from the side buffer */
81889f81008SSelvin Xavier 	stats->to_retransmits = le64_to_cpu(sb->to_retransmits);
81989f81008SSelvin Xavier 	stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd);
82089f81008SSelvin Xavier 	stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded);
82189f81008SSelvin Xavier 	stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd);
82289f81008SSelvin Xavier 	stats->missing_resp = le64_to_cpu(sb->missing_resp);
82389f81008SSelvin Xavier 	stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err);
82489f81008SSelvin Xavier 	stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err);
82589f81008SSelvin Xavier 	stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err);
82689f81008SSelvin Xavier 	stats->local_protection_err = le64_to_cpu(sb->local_protection_err);
82789f81008SSelvin Xavier 	stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err);
82889f81008SSelvin Xavier 	stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err);
82989f81008SSelvin Xavier 	stats->remote_access_err = le64_to_cpu(sb->remote_access_err);
83089f81008SSelvin Xavier 	stats->remote_op_err = le64_to_cpu(sb->remote_op_err);
83189f81008SSelvin Xavier 	stats->dup_req = le64_to_cpu(sb->dup_req);
83289f81008SSelvin Xavier 	stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max);
83389f81008SSelvin Xavier 	stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch);
83489f81008SSelvin Xavier 	stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe);
83589f81008SSelvin Xavier 	stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err);
83689f81008SSelvin Xavier 	stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey);
83789f81008SSelvin Xavier 	stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err);
83889f81008SSelvin Xavier 	stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm);
83989f81008SSelvin Xavier 	stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err);
84089f81008SSelvin Xavier 	stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey);
84189f81008SSelvin Xavier 	stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err);
84289f81008SSelvin Xavier 	stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm);
84389f81008SSelvin Xavier 	stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err);
84489f81008SSelvin Xavier 	stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow);
84589f81008SSelvin Xavier 	stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode);
84689f81008SSelvin Xavier 	stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic);
84789f81008SSelvin Xavier 	stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err);
84889f81008SSelvin Xavier 	stats->res_mem_error = le64_to_cpu(sb->res_mem_error);
84989f81008SSelvin Xavier 	stats->res_srq_err = le64_to_cpu(sb->res_srq_err);
85089f81008SSelvin Xavier 	stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err);
85189f81008SSelvin Xavier 	stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey);
85289f81008SSelvin Xavier 	stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err);
85389f81008SSelvin Xavier 	stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err);
85489f81008SSelvin Xavier 	stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err);
85589f81008SSelvin Xavier 	stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err);
85689f81008SSelvin Xavier 	stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err);
857316dd282SSelvin Xavier 	if (!rcfw->init_oos_stats) {
858316dd282SSelvin Xavier 		rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count);
859316dd282SSelvin Xavier 		rcfw->init_oos_stats = 1;
860316dd282SSelvin Xavier 	} else {
861316dd282SSelvin Xavier 		stats->res_oos_drop_count +=
862316dd282SSelvin Xavier 				(le64_to_cpu(sb->res_oos_drop_count) -
863316dd282SSelvin Xavier 				 rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK;
864316dd282SSelvin Xavier 		rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count);
865316dd282SSelvin Xavier 	}
866316dd282SSelvin Xavier 
86789f81008SSelvin Xavier bail:
86889f81008SSelvin Xavier 	bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
86989f81008SSelvin Xavier 	return rc;
87089f81008SSelvin Xavier }
871