xref: /linux/drivers/infiniband/hw/bnxt_re/qplib_sp.c (revision 316dd282)
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 	 */
1219152e0b7SEddie Wai 	attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS;
1221ac5a404SSelvin Xavier 	attr->max_qp_sges = sb->max_sge;
1231ac5a404SSelvin Xavier 	attr->max_cq = le32_to_cpu(sb->max_cq);
1241ac5a404SSelvin Xavier 	attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
1251ac5a404SSelvin Xavier 	attr->max_cq_sges = attr->max_qp_sges;
1261ac5a404SSelvin Xavier 	attr->max_mr = le32_to_cpu(sb->max_mr);
1271ac5a404SSelvin Xavier 	attr->max_mw = le32_to_cpu(sb->max_mw);
1281ac5a404SSelvin Xavier 
1291ac5a404SSelvin Xavier 	attr->max_mr_size = le64_to_cpu(sb->max_mr_size);
1301ac5a404SSelvin Xavier 	attr->max_pd = 64 * 1024;
1311ac5a404SSelvin Xavier 	attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp);
1321ac5a404SSelvin Xavier 	attr->max_ah = le32_to_cpu(sb->max_ah);
1331ac5a404SSelvin Xavier 
1341ac5a404SSelvin Xavier 	attr->max_fmr = le32_to_cpu(sb->max_fmr);
1351ac5a404SSelvin Xavier 	attr->max_map_per_fmr = sb->max_map_per_fmr;
1361ac5a404SSelvin Xavier 
1371ac5a404SSelvin Xavier 	attr->max_srq = le16_to_cpu(sb->max_srq);
1381ac5a404SSelvin Xavier 	attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1;
1391ac5a404SSelvin Xavier 	attr->max_srq_sges = sb->max_srq_sge;
1401ac5a404SSelvin Xavier 	/* Bono only reports 1 PKEY for now, but it can support > 1 */
1411ac5a404SSelvin Xavier 	attr->max_pkey = le32_to_cpu(sb->max_pkeys);
1421ac5a404SSelvin Xavier 
1431ac5a404SSelvin Xavier 	attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
144c354dff0SDevesh Sharma 	attr->l2_db_size = (sb->l2_db_space_size + 1) *
145c354dff0SDevesh Sharma 			    (0x01 << RCFW_DBR_BASE_PAGE_SHIFT);
1461ac5a404SSelvin Xavier 	attr->max_sgid = le32_to_cpu(sb->max_gid);
1471ac5a404SSelvin Xavier 
1482fc68543SSelvin Xavier 	bnxt_qplib_query_version(rcfw, attr->fw_ver);
1491ac5a404SSelvin Xavier 
1501ac5a404SSelvin Xavier 	for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) {
1511ac5a404SSelvin Xavier 		temp = le32_to_cpu(sb->tqm_alloc_reqs[i]);
1521ac5a404SSelvin Xavier 		tqm_alloc = (u8 *)&temp;
1531ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4] = *tqm_alloc;
1541ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc);
1551ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
1561ac5a404SSelvin Xavier 		attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
1571ac5a404SSelvin Xavier 	}
158cc1ec769SDevesh Sharma 
15963231585SGustavo A. R. Silva 	attr->is_atomic = false;
160cc1ec769SDevesh Sharma bail:
161cc1ec769SDevesh Sharma 	bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
162cc1ec769SDevesh Sharma 	return rc;
1631ac5a404SSelvin Xavier }
1641ac5a404SSelvin Xavier 
165ccd9d0d3SSelvin Xavier int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
166ccd9d0d3SSelvin Xavier 				  struct bnxt_qplib_rcfw *rcfw,
167ccd9d0d3SSelvin Xavier 				  struct bnxt_qplib_ctx *ctx)
168ccd9d0d3SSelvin Xavier {
169ccd9d0d3SSelvin Xavier 	struct cmdq_set_func_resources req;
170ccd9d0d3SSelvin Xavier 	struct creq_set_func_resources_resp resp;
171ccd9d0d3SSelvin Xavier 	u16 cmd_flags = 0;
172ccd9d0d3SSelvin Xavier 	int rc = 0;
173ccd9d0d3SSelvin Xavier 
174ccd9d0d3SSelvin Xavier 	RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags);
175ccd9d0d3SSelvin Xavier 
176ccd9d0d3SSelvin Xavier 	req.number_of_qp = cpu_to_le32(ctx->qpc_count);
177ccd9d0d3SSelvin Xavier 	req.number_of_mrw = cpu_to_le32(ctx->mrw_count);
178ccd9d0d3SSelvin Xavier 	req.number_of_srq =  cpu_to_le32(ctx->srqc_count);
179ccd9d0d3SSelvin Xavier 	req.number_of_cq = cpu_to_le32(ctx->cq_count);
180ccd9d0d3SSelvin Xavier 
181ccd9d0d3SSelvin Xavier 	req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
182ccd9d0d3SSelvin Xavier 	req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
183ccd9d0d3SSelvin Xavier 	req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
184ccd9d0d3SSelvin Xavier 	req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf);
185ccd9d0d3SSelvin Xavier 	req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf);
186ccd9d0d3SSelvin Xavier 
187ccd9d0d3SSelvin Xavier 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
188ccd9d0d3SSelvin Xavier 					  (void *)&resp,
189ccd9d0d3SSelvin Xavier 					  NULL, 0);
190ccd9d0d3SSelvin Xavier 	if (rc) {
19108920b8fSJoe Perches 		dev_err(&res->pdev->dev, "Failed to set function resources\n");
192ccd9d0d3SSelvin Xavier 	}
193ccd9d0d3SSelvin Xavier 	return rc;
194ccd9d0d3SSelvin Xavier }
195ccd9d0d3SSelvin Xavier 
1961ac5a404SSelvin Xavier /* SGID */
1971ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
1981ac5a404SSelvin Xavier 			struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
1991ac5a404SSelvin Xavier 			struct bnxt_qplib_gid *gid)
2001ac5a404SSelvin Xavier {
201474e5a86SDan Carpenter 	if (index >= sgid_tbl->max) {
2021ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
20308920b8fSJoe Perches 			"Index %d exceeded SGID table max (%d)\n",
2041ac5a404SSelvin Xavier 			index, sgid_tbl->max);
2051ac5a404SSelvin Xavier 		return -EINVAL;
2061ac5a404SSelvin Xavier 	}
2071ac5a404SSelvin Xavier 	memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid));
2081ac5a404SSelvin Xavier 	return 0;
2091ac5a404SSelvin Xavier }
2101ac5a404SSelvin Xavier 
2111ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
2121ac5a404SSelvin Xavier 			struct bnxt_qplib_gid *gid, bool update)
2131ac5a404SSelvin Xavier {
2141ac5a404SSelvin Xavier 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
2151ac5a404SSelvin Xavier 						   struct bnxt_qplib_res,
2161ac5a404SSelvin Xavier 						   sgid_tbl);
2171ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
2181ac5a404SSelvin Xavier 	int index;
2191ac5a404SSelvin Xavier 
2201ac5a404SSelvin Xavier 	if (!sgid_tbl) {
22108920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table not allocated\n");
2221ac5a404SSelvin Xavier 		return -EINVAL;
2231ac5a404SSelvin Xavier 	}
2241ac5a404SSelvin Xavier 	/* Do we need a sgid_lock here? */
2251ac5a404SSelvin Xavier 	if (!sgid_tbl->active) {
22608920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table has no active entries\n");
2271ac5a404SSelvin Xavier 		return -ENOMEM;
2281ac5a404SSelvin Xavier 	}
2291ac5a404SSelvin Xavier 	for (index = 0; index < sgid_tbl->max; index++) {
2301ac5a404SSelvin Xavier 		if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid)))
2311ac5a404SSelvin Xavier 			break;
2321ac5a404SSelvin Xavier 	}
2331ac5a404SSelvin Xavier 	if (index == sgid_tbl->max) {
23408920b8fSJoe Perches 		dev_warn(&res->pdev->dev, "GID not found in the SGID table\n");
2351ac5a404SSelvin Xavier 		return 0;
2361ac5a404SSelvin Xavier 	}
2371ac5a404SSelvin Xavier 	/* Remove GID from the SGID table */
2381ac5a404SSelvin Xavier 	if (update) {
2391ac5a404SSelvin Xavier 		struct cmdq_delete_gid req;
240cc1ec769SDevesh Sharma 		struct creq_delete_gid_resp resp;
2411ac5a404SSelvin Xavier 		u16 cmd_flags = 0;
242cc1ec769SDevesh Sharma 		int rc;
2431ac5a404SSelvin Xavier 
2441ac5a404SSelvin Xavier 		RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
2451ac5a404SSelvin Xavier 		if (sgid_tbl->hw_id[index] == 0xFFFF) {
2461ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
24708920b8fSJoe Perches 				"GID entry contains an invalid HW id\n");
2481ac5a404SSelvin Xavier 			return -EINVAL;
2491ac5a404SSelvin Xavier 		}
2501ac5a404SSelvin Xavier 		req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
251cc1ec769SDevesh Sharma 		rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
252cc1ec769SDevesh Sharma 						  (void *)&resp, NULL, 0);
253cc1ec769SDevesh Sharma 		if (rc)
254cc1ec769SDevesh Sharma 			return rc;
2551ac5a404SSelvin Xavier 	}
2561ac5a404SSelvin Xavier 	memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
2571ac5a404SSelvin Xavier 	       sizeof(bnxt_qplib_gid_zero));
2585fac5b1bSKalesh AP 	sgid_tbl->vlan[index] = 0;
2591ac5a404SSelvin Xavier 	sgid_tbl->active--;
2601ac5a404SSelvin Xavier 	dev_dbg(&res->pdev->dev,
26108920b8fSJoe Perches 		"SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n",
2621ac5a404SSelvin Xavier 		 index, sgid_tbl->hw_id[index], sgid_tbl->active);
2631ac5a404SSelvin Xavier 	sgid_tbl->hw_id[index] = (u16)-1;
2641ac5a404SSelvin Xavier 
2651ac5a404SSelvin Xavier 	/* unlock */
2661ac5a404SSelvin Xavier 	return 0;
2671ac5a404SSelvin Xavier }
2681ac5a404SSelvin Xavier 
2691ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
2701ac5a404SSelvin Xavier 			struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id,
2711ac5a404SSelvin Xavier 			bool update, u32 *index)
2721ac5a404SSelvin Xavier {
2731ac5a404SSelvin Xavier 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
2741ac5a404SSelvin Xavier 						   struct bnxt_qplib_res,
2751ac5a404SSelvin Xavier 						   sgid_tbl);
2761ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
277cc1ec769SDevesh Sharma 	int i, free_idx;
2781ac5a404SSelvin Xavier 
2791ac5a404SSelvin Xavier 	if (!sgid_tbl) {
28008920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table not allocated\n");
2811ac5a404SSelvin Xavier 		return -EINVAL;
2821ac5a404SSelvin Xavier 	}
2831ac5a404SSelvin Xavier 	/* Do we need a sgid_lock here? */
2841ac5a404SSelvin Xavier 	if (sgid_tbl->active == sgid_tbl->max) {
28508920b8fSJoe Perches 		dev_err(&res->pdev->dev, "SGID table is full\n");
2861ac5a404SSelvin Xavier 		return -ENOMEM;
2871ac5a404SSelvin Xavier 	}
2881ac5a404SSelvin Xavier 	free_idx = sgid_tbl->max;
2891ac5a404SSelvin Xavier 	for (i = 0; i < sgid_tbl->max; i++) {
2901ac5a404SSelvin Xavier 		if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) {
2911ac5a404SSelvin Xavier 			dev_dbg(&res->pdev->dev,
29208920b8fSJoe Perches 				"SGID entry already exist in entry %d!\n", i);
2931ac5a404SSelvin Xavier 			*index = i;
2941ac5a404SSelvin Xavier 			return -EALREADY;
2951ac5a404SSelvin Xavier 		} else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
2961ac5a404SSelvin Xavier 				   sizeof(bnxt_qplib_gid_zero)) &&
2971ac5a404SSelvin Xavier 			   free_idx == sgid_tbl->max) {
2981ac5a404SSelvin Xavier 			free_idx = i;
2991ac5a404SSelvin Xavier 		}
3001ac5a404SSelvin Xavier 	}
3011ac5a404SSelvin Xavier 	if (free_idx == sgid_tbl->max) {
3021ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
30308920b8fSJoe Perches 			"SGID table is FULL but count is not MAX??\n");
3041ac5a404SSelvin Xavier 		return -ENOMEM;
3051ac5a404SSelvin Xavier 	}
3061ac5a404SSelvin Xavier 	if (update) {
3071ac5a404SSelvin Xavier 		struct cmdq_add_gid req;
308cc1ec769SDevesh Sharma 		struct creq_add_gid_resp resp;
3091ac5a404SSelvin Xavier 		u16 cmd_flags = 0;
310cc1ec769SDevesh Sharma 		int rc;
3111ac5a404SSelvin Xavier 
3121ac5a404SSelvin Xavier 		RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
3131ac5a404SSelvin Xavier 
3145fac5b1bSKalesh AP 		req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]);
3155fac5b1bSKalesh AP 		req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]);
3165fac5b1bSKalesh AP 		req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]);
3175fac5b1bSKalesh AP 		req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]);
3185fac5b1bSKalesh AP 		/*
3195fac5b1bSKalesh AP 		 * driver should ensure that all RoCE traffic is always VLAN
3205fac5b1bSKalesh AP 		 * tagged if RoCE traffic is running on non-zero VLAN ID or
3215fac5b1bSKalesh AP 		 * RoCE traffic is running on non-zero Priority.
3225fac5b1bSKalesh AP 		 */
3235fac5b1bSKalesh AP 		if ((vlan_id != 0xFFFF) || res->prio) {
3241ac5a404SSelvin Xavier 			if (vlan_id != 0xFFFF)
3255fac5b1bSKalesh AP 				req.vlan = cpu_to_le16
3265fac5b1bSKalesh AP 				(vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK);
3275fac5b1bSKalesh AP 			req.vlan |= cpu_to_le16
3285fac5b1bSKalesh AP 					(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 |
3291ac5a404SSelvin Xavier 					 CMDQ_ADD_GID_VLAN_VLAN_EN);
3305fac5b1bSKalesh AP 		}
3311ac5a404SSelvin Xavier 
3321ac5a404SSelvin Xavier 		/* MAC in network format */
3335fac5b1bSKalesh AP 		req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]);
3345fac5b1bSKalesh AP 		req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]);
3355fac5b1bSKalesh AP 		req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]);
3361ac5a404SSelvin Xavier 
337cc1ec769SDevesh Sharma 		rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
338cc1ec769SDevesh Sharma 						  (void *)&resp, NULL, 0);
339cc1ec769SDevesh Sharma 		if (rc)
340cc1ec769SDevesh Sharma 			return rc;
341cc1ec769SDevesh Sharma 		sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid);
3421ac5a404SSelvin Xavier 	}
3431ac5a404SSelvin Xavier 	/* Add GID to the sgid_tbl */
3441ac5a404SSelvin Xavier 	memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
3451ac5a404SSelvin Xavier 	sgid_tbl->active++;
3465fac5b1bSKalesh AP 	if (vlan_id != 0xFFFF)
3475fac5b1bSKalesh AP 		sgid_tbl->vlan[free_idx] = 1;
3485fac5b1bSKalesh AP 
3491ac5a404SSelvin Xavier 	dev_dbg(&res->pdev->dev,
35008920b8fSJoe Perches 		"SGID added hw_id[0x%x] = 0x%x active = 0x%x\n",
3511ac5a404SSelvin Xavier 		 free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active);
3521ac5a404SSelvin Xavier 
3531ac5a404SSelvin Xavier 	*index = free_idx;
3541ac5a404SSelvin Xavier 	/* unlock */
355cc1ec769SDevesh Sharma 	return 0;
3561ac5a404SSelvin Xavier }
3571ac5a404SSelvin Xavier 
3585fac5b1bSKalesh AP int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
3595fac5b1bSKalesh AP 			   struct bnxt_qplib_gid *gid, u16 gid_idx,
3605fac5b1bSKalesh AP 			   u8 *smac)
3615fac5b1bSKalesh AP {
3625fac5b1bSKalesh AP 	struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
3635fac5b1bSKalesh AP 						   struct bnxt_qplib_res,
3645fac5b1bSKalesh AP 						   sgid_tbl);
3655fac5b1bSKalesh AP 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
3665fac5b1bSKalesh AP 	struct creq_modify_gid_resp resp;
3675fac5b1bSKalesh AP 	struct cmdq_modify_gid req;
3685fac5b1bSKalesh AP 	int rc;
3695fac5b1bSKalesh AP 	u16 cmd_flags = 0;
3705fac5b1bSKalesh AP 
3715fac5b1bSKalesh AP 	RCFW_CMD_PREP(req, MODIFY_GID, cmd_flags);
3725fac5b1bSKalesh AP 
3735fac5b1bSKalesh AP 	req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]);
3745fac5b1bSKalesh AP 	req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]);
3755fac5b1bSKalesh AP 	req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]);
3765fac5b1bSKalesh AP 	req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]);
3775fac5b1bSKalesh AP 	if (res->prio) {
3785fac5b1bSKalesh AP 		req.vlan |= cpu_to_le16
3795fac5b1bSKalesh AP 			(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 |
3805fac5b1bSKalesh AP 			 CMDQ_ADD_GID_VLAN_VLAN_EN);
3815fac5b1bSKalesh AP 	}
3825fac5b1bSKalesh AP 
3835fac5b1bSKalesh AP 	/* MAC in network format */
3845fac5b1bSKalesh AP 	req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]);
3855fac5b1bSKalesh AP 	req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]);
3865fac5b1bSKalesh AP 	req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]);
3875fac5b1bSKalesh AP 
3885fac5b1bSKalesh AP 	req.gid_index = cpu_to_le16(gid_idx);
3895fac5b1bSKalesh AP 
3905fac5b1bSKalesh AP 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
3915fac5b1bSKalesh AP 					  (void *)&resp, NULL, 0);
3925fac5b1bSKalesh AP 	return rc;
3935fac5b1bSKalesh AP }
3945fac5b1bSKalesh AP 
3951ac5a404SSelvin Xavier /* pkeys */
3961ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res,
3971ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index,
3981ac5a404SSelvin Xavier 			u16 *pkey)
3991ac5a404SSelvin Xavier {
4001ac5a404SSelvin Xavier 	if (index == 0xFFFF) {
4011ac5a404SSelvin Xavier 		*pkey = 0xFFFF;
4021ac5a404SSelvin Xavier 		return 0;
4031ac5a404SSelvin Xavier 	}
404474e5a86SDan Carpenter 	if (index >= pkey_tbl->max) {
4051ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
40608920b8fSJoe Perches 			"Index %d exceeded PKEY table max (%d)\n",
4071ac5a404SSelvin Xavier 			index, pkey_tbl->max);
4081ac5a404SSelvin Xavier 		return -EINVAL;
4091ac5a404SSelvin Xavier 	}
4101ac5a404SSelvin Xavier 	memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey));
4111ac5a404SSelvin Xavier 	return 0;
4121ac5a404SSelvin Xavier }
4131ac5a404SSelvin Xavier 
4141ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res,
4151ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
4161ac5a404SSelvin Xavier 			bool update)
4171ac5a404SSelvin Xavier {
4181ac5a404SSelvin Xavier 	int i, rc = 0;
4191ac5a404SSelvin Xavier 
4201ac5a404SSelvin Xavier 	if (!pkey_tbl) {
42108920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table not allocated\n");
4221ac5a404SSelvin Xavier 		return -EINVAL;
4231ac5a404SSelvin Xavier 	}
4241ac5a404SSelvin Xavier 
4251ac5a404SSelvin Xavier 	/* Do we need a pkey_lock here? */
4261ac5a404SSelvin Xavier 	if (!pkey_tbl->active) {
42708920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table has no active entries\n");
4281ac5a404SSelvin Xavier 		return -ENOMEM;
4291ac5a404SSelvin Xavier 	}
4301ac5a404SSelvin Xavier 	for (i = 0; i < pkey_tbl->max; i++) {
4311ac5a404SSelvin Xavier 		if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
4321ac5a404SSelvin Xavier 			break;
4331ac5a404SSelvin Xavier 	}
4341ac5a404SSelvin Xavier 	if (i == pkey_tbl->max) {
4351ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
43608920b8fSJoe Perches 			"PKEY 0x%04x not found in the pkey table\n", *pkey);
4371ac5a404SSelvin Xavier 		return -ENOMEM;
4381ac5a404SSelvin Xavier 	}
4391ac5a404SSelvin Xavier 	memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey));
4401ac5a404SSelvin Xavier 	pkey_tbl->active--;
4411ac5a404SSelvin Xavier 
4421ac5a404SSelvin Xavier 	/* unlock */
4431ac5a404SSelvin Xavier 	return rc;
4441ac5a404SSelvin Xavier }
4451ac5a404SSelvin Xavier 
4461ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res,
4471ac5a404SSelvin Xavier 			struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
4481ac5a404SSelvin Xavier 			bool update)
4491ac5a404SSelvin Xavier {
4501ac5a404SSelvin Xavier 	int i, free_idx, rc = 0;
4511ac5a404SSelvin Xavier 
4521ac5a404SSelvin Xavier 	if (!pkey_tbl) {
45308920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table not allocated\n");
4541ac5a404SSelvin Xavier 		return -EINVAL;
4551ac5a404SSelvin Xavier 	}
4561ac5a404SSelvin Xavier 
4571ac5a404SSelvin Xavier 	/* Do we need a pkey_lock here? */
4581ac5a404SSelvin Xavier 	if (pkey_tbl->active == pkey_tbl->max) {
45908920b8fSJoe Perches 		dev_err(&res->pdev->dev, "PKEY table is full\n");
4601ac5a404SSelvin Xavier 		return -ENOMEM;
4611ac5a404SSelvin Xavier 	}
4621ac5a404SSelvin Xavier 	free_idx = pkey_tbl->max;
4631ac5a404SSelvin Xavier 	for (i = 0; i < pkey_tbl->max; i++) {
4641ac5a404SSelvin Xavier 		if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey)))
4651ac5a404SSelvin Xavier 			return -EALREADY;
4661ac5a404SSelvin Xavier 		else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max)
4671ac5a404SSelvin Xavier 			free_idx = i;
4681ac5a404SSelvin Xavier 	}
4691ac5a404SSelvin Xavier 	if (free_idx == pkey_tbl->max) {
4701ac5a404SSelvin Xavier 		dev_err(&res->pdev->dev,
47108920b8fSJoe Perches 			"PKEY table is FULL but count is not MAX??\n");
4721ac5a404SSelvin Xavier 		return -ENOMEM;
4731ac5a404SSelvin Xavier 	}
4741ac5a404SSelvin Xavier 	/* Add PKEY to the pkey_tbl */
4751ac5a404SSelvin Xavier 	memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey));
4761ac5a404SSelvin Xavier 	pkey_tbl->active++;
4771ac5a404SSelvin Xavier 
4781ac5a404SSelvin Xavier 	/* unlock */
4791ac5a404SSelvin Xavier 	return rc;
4801ac5a404SSelvin Xavier }
4811ac5a404SSelvin Xavier 
4821ac5a404SSelvin Xavier /* AH */
4831ac5a404SSelvin Xavier int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
4841ac5a404SSelvin Xavier {
4851ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
4861ac5a404SSelvin Xavier 	struct cmdq_create_ah req;
487cc1ec769SDevesh Sharma 	struct creq_create_ah_resp resp;
4881ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
4891ac5a404SSelvin Xavier 	u32 temp32[4];
4901ac5a404SSelvin Xavier 	u16 temp16[3];
491cc1ec769SDevesh Sharma 	int rc;
4921ac5a404SSelvin Xavier 
4931ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
4941ac5a404SSelvin Xavier 
4951ac5a404SSelvin Xavier 	memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid));
4961ac5a404SSelvin Xavier 	req.dgid[0] = cpu_to_le32(temp32[0]);
4971ac5a404SSelvin Xavier 	req.dgid[1] = cpu_to_le32(temp32[1]);
4981ac5a404SSelvin Xavier 	req.dgid[2] = cpu_to_le32(temp32[2]);
4991ac5a404SSelvin Xavier 	req.dgid[3] = cpu_to_le32(temp32[3]);
5001ac5a404SSelvin Xavier 
5011ac5a404SSelvin Xavier 	req.type = ah->nw_type;
5021ac5a404SSelvin Xavier 	req.hop_limit = ah->hop_limit;
5031ac5a404SSelvin Xavier 	req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]);
5041ac5a404SSelvin Xavier 	req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label &
5051ac5a404SSelvin Xavier 					CMDQ_CREATE_AH_FLOW_LABEL_MASK) |
5061ac5a404SSelvin Xavier 					CMDQ_CREATE_AH_DEST_VLAN_ID_MASK);
5071ac5a404SSelvin Xavier 	req.pd_id = cpu_to_le32(ah->pd->id);
5081ac5a404SSelvin Xavier 	req.traffic_class = ah->traffic_class;
5091ac5a404SSelvin Xavier 
5101ac5a404SSelvin Xavier 	/* MAC in network format */
5111ac5a404SSelvin Xavier 	memcpy(temp16, ah->dmac, 6);
5121ac5a404SSelvin Xavier 	req.dest_mac[0] = cpu_to_le16(temp16[0]);
5131ac5a404SSelvin Xavier 	req.dest_mac[1] = cpu_to_le16(temp16[1]);
5141ac5a404SSelvin Xavier 	req.dest_mac[2] = cpu_to_le16(temp16[2]);
5151ac5a404SSelvin Xavier 
516cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
5171ac5a404SSelvin Xavier 					  NULL, 1);
518cc1ec769SDevesh Sharma 	if (rc)
519cc1ec769SDevesh Sharma 		return rc;
520cc1ec769SDevesh Sharma 
521cc1ec769SDevesh Sharma 	ah->id = le32_to_cpu(resp.xid);
5221ac5a404SSelvin Xavier 	return 0;
5231ac5a404SSelvin Xavier }
5241ac5a404SSelvin Xavier 
5251ac5a404SSelvin Xavier int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
5261ac5a404SSelvin Xavier {
5271ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5281ac5a404SSelvin Xavier 	struct cmdq_destroy_ah req;
529cc1ec769SDevesh Sharma 	struct creq_destroy_ah_resp resp;
5301ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
531cc1ec769SDevesh Sharma 	int rc;
5321ac5a404SSelvin Xavier 
5331ac5a404SSelvin Xavier 	/* Clean up the AH table in the device */
5341ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
5351ac5a404SSelvin Xavier 
5361ac5a404SSelvin Xavier 	req.ah_cid = cpu_to_le32(ah->id);
5371ac5a404SSelvin Xavier 
538cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
5391ac5a404SSelvin Xavier 					  NULL, 1);
540cc1ec769SDevesh Sharma 	if (rc)
541cc1ec769SDevesh Sharma 		return rc;
5421ac5a404SSelvin Xavier 	return 0;
5431ac5a404SSelvin Xavier }
5441ac5a404SSelvin Xavier 
5451ac5a404SSelvin Xavier /* MRW */
5461ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
5471ac5a404SSelvin Xavier {
5481ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5491ac5a404SSelvin Xavier 	struct cmdq_deallocate_key req;
550cc1ec769SDevesh Sharma 	struct creq_deallocate_key_resp resp;
5511ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
552cc1ec769SDevesh Sharma 	int rc;
5531ac5a404SSelvin Xavier 
5541ac5a404SSelvin Xavier 	if (mrw->lkey == 0xFFFFFFFF) {
55508920b8fSJoe Perches 		dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n");
5561ac5a404SSelvin Xavier 		return 0;
5571ac5a404SSelvin Xavier 	}
5581ac5a404SSelvin Xavier 
5591ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags);
5601ac5a404SSelvin Xavier 
5611ac5a404SSelvin Xavier 	req.mrw_flags = mrw->type;
5621ac5a404SSelvin Xavier 
5631ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
5641ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
5651ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
5661ac5a404SSelvin Xavier 		req.key = cpu_to_le32(mrw->rkey);
5671ac5a404SSelvin Xavier 	else
5681ac5a404SSelvin Xavier 		req.key = cpu_to_le32(mrw->lkey);
5691ac5a404SSelvin Xavier 
570cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
5711ac5a404SSelvin Xavier 					  NULL, 0);
572cc1ec769SDevesh Sharma 	if (rc)
573cc1ec769SDevesh Sharma 		return rc;
574cc1ec769SDevesh Sharma 
5751ac5a404SSelvin Xavier 	/* Free the qplib's MRW memory */
5761ac5a404SSelvin Xavier 	if (mrw->hwq.max_elements)
5771ac5a404SSelvin Xavier 		bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
5781ac5a404SSelvin Xavier 
5791ac5a404SSelvin Xavier 	return 0;
5801ac5a404SSelvin Xavier }
5811ac5a404SSelvin Xavier 
5821ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
5831ac5a404SSelvin Xavier {
5841ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
5851ac5a404SSelvin Xavier 	struct cmdq_allocate_mrw req;
586cc1ec769SDevesh Sharma 	struct creq_allocate_mrw_resp resp;
5871ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
5881ac5a404SSelvin Xavier 	unsigned long tmp;
589cc1ec769SDevesh Sharma 	int rc;
5901ac5a404SSelvin Xavier 
5911ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
5921ac5a404SSelvin Xavier 
5931ac5a404SSelvin Xavier 	req.pd_id = cpu_to_le32(mrw->pd->id);
5941ac5a404SSelvin Xavier 	req.mrw_flags = mrw->type;
5951ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR &&
5961ac5a404SSelvin Xavier 	     mrw->flags & BNXT_QPLIB_FR_PMR) ||
5971ac5a404SSelvin Xavier 	    mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
5981ac5a404SSelvin Xavier 	    mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
5991ac5a404SSelvin Xavier 		req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY;
6001ac5a404SSelvin Xavier 	tmp = (unsigned long)mrw;
6011ac5a404SSelvin Xavier 	req.mrw_handle = cpu_to_le64(tmp);
6021ac5a404SSelvin Xavier 
603cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
604cc1ec769SDevesh Sharma 					  (void *)&resp, NULL, 0);
605cc1ec769SDevesh Sharma 	if (rc)
606cc1ec769SDevesh Sharma 		return rc;
607cc1ec769SDevesh Sharma 
6081ac5a404SSelvin Xavier 	if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
6091ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
6101ac5a404SSelvin Xavier 	    (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
611cc1ec769SDevesh Sharma 		mrw->rkey = le32_to_cpu(resp.xid);
6121ac5a404SSelvin Xavier 	else
613cc1ec769SDevesh Sharma 		mrw->lkey = le32_to_cpu(resp.xid);
6141ac5a404SSelvin Xavier 	return 0;
6151ac5a404SSelvin Xavier }
6161ac5a404SSelvin Xavier 
6171ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
6181ac5a404SSelvin Xavier 			 bool block)
6191ac5a404SSelvin Xavier {
6201ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
6211ac5a404SSelvin Xavier 	struct cmdq_deregister_mr req;
622cc1ec769SDevesh Sharma 	struct creq_deregister_mr_resp resp;
6231ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
6241ac5a404SSelvin Xavier 	int rc;
6251ac5a404SSelvin Xavier 
6261ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
6271ac5a404SSelvin Xavier 
6281ac5a404SSelvin Xavier 	req.lkey = cpu_to_le32(mrw->lkey);
629cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
630cc1ec769SDevesh Sharma 					  (void *)&resp, NULL, block);
631cc1ec769SDevesh Sharma 	if (rc)
632cc1ec769SDevesh Sharma 		return rc;
6331ac5a404SSelvin Xavier 
6341ac5a404SSelvin Xavier 	/* Free the qplib's MR memory */
6351ac5a404SSelvin Xavier 	if (mrw->hwq.max_elements) {
6361ac5a404SSelvin Xavier 		mrw->va = 0;
6371ac5a404SSelvin Xavier 		mrw->total_size = 0;
6381ac5a404SSelvin Xavier 		bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
6391ac5a404SSelvin Xavier 	}
6401ac5a404SSelvin Xavier 
6411ac5a404SSelvin Xavier 	return 0;
6421ac5a404SSelvin Xavier }
6431ac5a404SSelvin Xavier 
6441ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
645872f3578SSomnath Kotur 		      u64 *pbl_tbl, int num_pbls, bool block, u32 buf_pg_size)
6461ac5a404SSelvin Xavier {
6471ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
6481ac5a404SSelvin Xavier 	struct cmdq_register_mr req;
649cc1ec769SDevesh Sharma 	struct creq_register_mr_resp resp;
6501ac5a404SSelvin Xavier 	u16 cmd_flags = 0, level;
6511ac5a404SSelvin Xavier 	int pg_ptrs, pages, i, rc;
6521ac5a404SSelvin Xavier 	dma_addr_t **pbl_ptr;
6531ac5a404SSelvin Xavier 	u32 pg_size;
6541ac5a404SSelvin Xavier 
6551ac5a404SSelvin Xavier 	if (num_pbls) {
656872f3578SSomnath Kotur 		/* Allocate memory for the non-leaf pages to store buf ptrs.
657872f3578SSomnath Kotur 		 * Non-leaf pages always uses system PAGE_SIZE
658872f3578SSomnath Kotur 		 */
6591ac5a404SSelvin Xavier 		pg_ptrs = roundup_pow_of_two(num_pbls);
6601ac5a404SSelvin Xavier 		pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
6611ac5a404SSelvin Xavier 		if (!pages)
6621ac5a404SSelvin Xavier 			pages++;
6631ac5a404SSelvin Xavier 
6641ac5a404SSelvin Xavier 		if (pages > MAX_PBL_LVL_1_PGS) {
6651ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
66608920b8fSJoe Perches 				"SP: Reg MR pages requested (0x%x) exceeded max (0x%x)\n",
6671ac5a404SSelvin Xavier 				pages, MAX_PBL_LVL_1_PGS);
6681ac5a404SSelvin Xavier 			return -ENOMEM;
6691ac5a404SSelvin Xavier 		}
6701ac5a404SSelvin Xavier 		/* Free the hwq if it already exist, must be a rereg */
6711ac5a404SSelvin Xavier 		if (mr->hwq.max_elements)
6721ac5a404SSelvin Xavier 			bnxt_qplib_free_hwq(res->pdev, &mr->hwq);
6731ac5a404SSelvin Xavier 
6741ac5a404SSelvin Xavier 		mr->hwq.max_elements = pages;
675872f3578SSomnath Kotur 		/* Use system PAGE_SIZE */
6761ac5a404SSelvin Xavier 		rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0,
6771ac5a404SSelvin Xavier 					       &mr->hwq.max_elements,
6781ac5a404SSelvin Xavier 					       PAGE_SIZE, 0, PAGE_SIZE,
6791ac5a404SSelvin Xavier 					       HWQ_TYPE_CTX);
6801ac5a404SSelvin Xavier 		if (rc) {
6811ac5a404SSelvin Xavier 			dev_err(&res->pdev->dev,
68208920b8fSJoe Perches 				"SP: Reg MR memory allocation failed\n");
6831ac5a404SSelvin Xavier 			return -ENOMEM;
6841ac5a404SSelvin Xavier 		}
6851ac5a404SSelvin Xavier 		/* Write to the hwq */
6861ac5a404SSelvin Xavier 		pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr;
6871ac5a404SSelvin Xavier 		for (i = 0; i < num_pbls; i++)
6881ac5a404SSelvin Xavier 			pbl_ptr[PTR_PG(i)][PTR_IDX(i)] =
6891ac5a404SSelvin Xavier 				(pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID;
6901ac5a404SSelvin Xavier 	}
6911ac5a404SSelvin Xavier 
6921ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags);
6931ac5a404SSelvin Xavier 
6941ac5a404SSelvin Xavier 	/* Configure the request */
6951ac5a404SSelvin Xavier 	if (mr->hwq.level == PBL_LVL_MAX) {
696872f3578SSomnath Kotur 		/* No PBL provided, just use system PAGE_SIZE */
6971ac5a404SSelvin Xavier 		level = 0;
6981ac5a404SSelvin Xavier 		req.pbl = 0;
6991ac5a404SSelvin Xavier 		pg_size = PAGE_SIZE;
7001ac5a404SSelvin Xavier 	} else {
7011ac5a404SSelvin Xavier 		level = mr->hwq.level + 1;
7021ac5a404SSelvin Xavier 		req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]);
7031ac5a404SSelvin Xavier 	}
704872f3578SSomnath Kotur 	pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE;
7051ac5a404SSelvin Xavier 	req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) |
7061ac5a404SSelvin Xavier 			       ((ilog2(pg_size) <<
7071ac5a404SSelvin Xavier 				 CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) &
7081ac5a404SSelvin Xavier 				CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK);
709872f3578SSomnath Kotur 	req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
710872f3578SSomnath Kotur 				 CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
711872f3578SSomnath Kotur 				CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
7121ac5a404SSelvin Xavier 	req.access = (mr->flags & 0xFFFF);
7131ac5a404SSelvin Xavier 	req.va = cpu_to_le64(mr->va);
7141ac5a404SSelvin Xavier 	req.key = cpu_to_le32(mr->lkey);
7151ac5a404SSelvin Xavier 	req.mr_size = cpu_to_le64(mr->total_size);
7161ac5a404SSelvin Xavier 
717cc1ec769SDevesh Sharma 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
718cc1ec769SDevesh Sharma 					  (void *)&resp, NULL, block);
719cc1ec769SDevesh Sharma 	if (rc)
7201ac5a404SSelvin Xavier 		goto fail;
721cc1ec769SDevesh Sharma 
7221ac5a404SSelvin Xavier 	return 0;
7231ac5a404SSelvin Xavier 
7241ac5a404SSelvin Xavier fail:
7251ac5a404SSelvin Xavier 	if (mr->hwq.max_elements)
7261ac5a404SSelvin Xavier 		bnxt_qplib_free_hwq(res->pdev, &mr->hwq);
7271ac5a404SSelvin Xavier 	return rc;
7281ac5a404SSelvin Xavier }
7291ac5a404SSelvin Xavier 
7301ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res,
7311ac5a404SSelvin Xavier 					struct bnxt_qplib_frpl *frpl,
7321ac5a404SSelvin Xavier 					int max_pg_ptrs)
7331ac5a404SSelvin Xavier {
7341ac5a404SSelvin Xavier 	int pg_ptrs, pages, rc;
7351ac5a404SSelvin Xavier 
7361ac5a404SSelvin Xavier 	/* Re-calculate the max to fit the HWQ allocation model */
7371ac5a404SSelvin Xavier 	pg_ptrs = roundup_pow_of_two(max_pg_ptrs);
7381ac5a404SSelvin Xavier 	pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT;
7391ac5a404SSelvin Xavier 	if (!pages)
7401ac5a404SSelvin Xavier 		pages++;
7411ac5a404SSelvin Xavier 
7421ac5a404SSelvin Xavier 	if (pages > MAX_PBL_LVL_1_PGS)
7431ac5a404SSelvin Xavier 		return -ENOMEM;
7441ac5a404SSelvin Xavier 
7451ac5a404SSelvin Xavier 	frpl->hwq.max_elements = pages;
7461ac5a404SSelvin Xavier 	rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0,
7471ac5a404SSelvin Xavier 				       &frpl->hwq.max_elements, PAGE_SIZE, 0,
7481ac5a404SSelvin Xavier 				       PAGE_SIZE, HWQ_TYPE_CTX);
7491ac5a404SSelvin Xavier 	if (!rc)
7501ac5a404SSelvin Xavier 		frpl->max_pg_ptrs = pg_ptrs;
7511ac5a404SSelvin Xavier 
7521ac5a404SSelvin Xavier 	return rc;
7531ac5a404SSelvin Xavier }
7541ac5a404SSelvin Xavier 
7551ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res,
7561ac5a404SSelvin Xavier 				       struct bnxt_qplib_frpl *frpl)
7571ac5a404SSelvin Xavier {
7581ac5a404SSelvin Xavier 	bnxt_qplib_free_hwq(res->pdev, &frpl->hwq);
7591ac5a404SSelvin Xavier 	return 0;
7601ac5a404SSelvin Xavier }
7611ac5a404SSelvin Xavier 
7621ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
7631ac5a404SSelvin Xavier {
7641ac5a404SSelvin Xavier 	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
7651ac5a404SSelvin Xavier 	struct cmdq_map_tc_to_cos req;
766cc1ec769SDevesh Sharma 	struct creq_map_tc_to_cos_resp resp;
7671ac5a404SSelvin Xavier 	u16 cmd_flags = 0;
7681ac5a404SSelvin Xavier 
7691ac5a404SSelvin Xavier 	RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
7701ac5a404SSelvin Xavier 	req.cos0 = cpu_to_le16(cids[0]);
7711ac5a404SSelvin Xavier 	req.cos1 = cpu_to_le16(cids[1]);
7721ac5a404SSelvin Xavier 
7736dfa8ae6SBart Van Assche 	bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL,
7746dfa8ae6SBart Van Assche 				     0);
7751ac5a404SSelvin Xavier 	return 0;
7761ac5a404SSelvin Xavier }
77789f81008SSelvin Xavier 
77889f81008SSelvin Xavier int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw,
77989f81008SSelvin Xavier 			      struct bnxt_qplib_roce_stats *stats)
78089f81008SSelvin Xavier {
78189f81008SSelvin Xavier 	struct cmdq_query_roce_stats req;
78289f81008SSelvin Xavier 	struct creq_query_roce_stats_resp resp;
78389f81008SSelvin Xavier 	struct bnxt_qplib_rcfw_sbuf *sbuf;
78489f81008SSelvin Xavier 	struct creq_query_roce_stats_resp_sb *sb;
78589f81008SSelvin Xavier 	u16 cmd_flags = 0;
78689f81008SSelvin Xavier 	int rc = 0;
78789f81008SSelvin Xavier 
78889f81008SSelvin Xavier 	RCFW_CMD_PREP(req, QUERY_ROCE_STATS, cmd_flags);
78989f81008SSelvin Xavier 
79089f81008SSelvin Xavier 	sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
79189f81008SSelvin Xavier 	if (!sbuf) {
79289f81008SSelvin Xavier 		dev_err(&rcfw->pdev->dev,
79308920b8fSJoe Perches 			"SP: QUERY_ROCE_STATS alloc side buffer failed\n");
79489f81008SSelvin Xavier 		return -ENOMEM;
79589f81008SSelvin Xavier 	}
79689f81008SSelvin Xavier 
79789f81008SSelvin Xavier 	sb = sbuf->sb;
79889f81008SSelvin Xavier 	req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
79989f81008SSelvin Xavier 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
80089f81008SSelvin Xavier 					  (void *)sbuf, 0);
80189f81008SSelvin Xavier 	if (rc)
80289f81008SSelvin Xavier 		goto bail;
80389f81008SSelvin Xavier 	/* Extract the context from the side buffer */
80489f81008SSelvin Xavier 	stats->to_retransmits = le64_to_cpu(sb->to_retransmits);
80589f81008SSelvin Xavier 	stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd);
80689f81008SSelvin Xavier 	stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded);
80789f81008SSelvin Xavier 	stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd);
80889f81008SSelvin Xavier 	stats->missing_resp = le64_to_cpu(sb->missing_resp);
80989f81008SSelvin Xavier 	stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err);
81089f81008SSelvin Xavier 	stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err);
81189f81008SSelvin Xavier 	stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err);
81289f81008SSelvin Xavier 	stats->local_protection_err = le64_to_cpu(sb->local_protection_err);
81389f81008SSelvin Xavier 	stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err);
81489f81008SSelvin Xavier 	stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err);
81589f81008SSelvin Xavier 	stats->remote_access_err = le64_to_cpu(sb->remote_access_err);
81689f81008SSelvin Xavier 	stats->remote_op_err = le64_to_cpu(sb->remote_op_err);
81789f81008SSelvin Xavier 	stats->dup_req = le64_to_cpu(sb->dup_req);
81889f81008SSelvin Xavier 	stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max);
81989f81008SSelvin Xavier 	stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch);
82089f81008SSelvin Xavier 	stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe);
82189f81008SSelvin Xavier 	stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err);
82289f81008SSelvin Xavier 	stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey);
82389f81008SSelvin Xavier 	stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err);
82489f81008SSelvin Xavier 	stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm);
82589f81008SSelvin Xavier 	stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err);
82689f81008SSelvin Xavier 	stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey);
82789f81008SSelvin Xavier 	stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err);
82889f81008SSelvin Xavier 	stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm);
82989f81008SSelvin Xavier 	stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err);
83089f81008SSelvin Xavier 	stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow);
83189f81008SSelvin Xavier 	stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode);
83289f81008SSelvin Xavier 	stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic);
83389f81008SSelvin Xavier 	stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err);
83489f81008SSelvin Xavier 	stats->res_mem_error = le64_to_cpu(sb->res_mem_error);
83589f81008SSelvin Xavier 	stats->res_srq_err = le64_to_cpu(sb->res_srq_err);
83689f81008SSelvin Xavier 	stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err);
83789f81008SSelvin Xavier 	stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey);
83889f81008SSelvin Xavier 	stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err);
83989f81008SSelvin Xavier 	stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err);
84089f81008SSelvin Xavier 	stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err);
84189f81008SSelvin Xavier 	stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err);
84289f81008SSelvin Xavier 	stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err);
843*316dd282SSelvin Xavier 	if (!rcfw->init_oos_stats) {
844*316dd282SSelvin Xavier 		rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count);
845*316dd282SSelvin Xavier 		rcfw->init_oos_stats = 1;
846*316dd282SSelvin Xavier 	} else {
847*316dd282SSelvin Xavier 		stats->res_oos_drop_count +=
848*316dd282SSelvin Xavier 				(le64_to_cpu(sb->res_oos_drop_count) -
849*316dd282SSelvin Xavier 				 rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK;
850*316dd282SSelvin Xavier 		rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count);
851*316dd282SSelvin Xavier 	}
852*316dd282SSelvin Xavier 
85389f81008SSelvin Xavier bail:
85489f81008SSelvin Xavier 	bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
85589f81008SSelvin Xavier 	return rc;
85689f81008SSelvin Xavier }
857