18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
58c2ecf20Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
88c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
98c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
108c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
118c2ecf20Sopenharmony_ci * BSD license below:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
148c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
158c2ecf20Sopenharmony_ci * are met:
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
198c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
208c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
218c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
228c2ecf20Sopenharmony_ci *    distribution.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
258c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
268c2ecf20Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
278c2ecf20Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
298c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
308c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
318c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
328c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
338c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
348c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * Description: IB Verbs interpreter
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
408c2ecf20Sopenharmony_ci#include <linux/types.h>
418c2ecf20Sopenharmony_ci#include <linux/pci.h>
428c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
438c2ecf20Sopenharmony_ci#include <linux/if_ether.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h>
468c2ecf20Sopenharmony_ci#include <rdma/ib_user_verbs.h>
478c2ecf20Sopenharmony_ci#include <rdma/ib_umem.h>
488c2ecf20Sopenharmony_ci#include <rdma/ib_addr.h>
498c2ecf20Sopenharmony_ci#include <rdma/ib_mad.h>
508c2ecf20Sopenharmony_ci#include <rdma/ib_cache.h>
518c2ecf20Sopenharmony_ci#include <rdma/uverbs_ioctl.h>
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#include "bnxt_ulp.h"
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#include "roce_hsi.h"
568c2ecf20Sopenharmony_ci#include "qplib_res.h"
578c2ecf20Sopenharmony_ci#include "qplib_sp.h"
588c2ecf20Sopenharmony_ci#include "qplib_fp.h"
598c2ecf20Sopenharmony_ci#include "qplib_rcfw.h"
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#include "bnxt_re.h"
628c2ecf20Sopenharmony_ci#include "ib_verbs.h"
638c2ecf20Sopenharmony_ci#include <rdma/bnxt_re-abi.h>
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int __from_ib_access_flags(int iflags)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	int qflags = 0;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_LOCAL_WRITE)
708c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
718c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_READ)
728c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
738c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_WRITE)
748c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
758c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_ATOMIC)
768c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
778c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_MW_BIND)
788c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
798c2ecf20Sopenharmony_ci	if (iflags & IB_ZERO_BASED)
808c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
818c2ecf20Sopenharmony_ci	if (iflags & IB_ACCESS_ON_DEMAND)
828c2ecf20Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
838c2ecf20Sopenharmony_ci	return qflags;
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic enum ib_access_flags __to_ib_access_flags(int qflags)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	enum ib_access_flags iflags = 0;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
918c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_LOCAL_WRITE;
928c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
938c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_WRITE;
948c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
958c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_READ;
968c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
978c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_ATOMIC;
988c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
998c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_MW_BIND;
1008c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
1018c2ecf20Sopenharmony_ci		iflags |= IB_ZERO_BASED;
1028c2ecf20Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
1038c2ecf20Sopenharmony_ci		iflags |= IB_ACCESS_ON_DEMAND;
1048c2ecf20Sopenharmony_ci	return iflags;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
1088c2ecf20Sopenharmony_ci			     struct bnxt_qplib_sge *sg_list, int num)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	int i, total = 0;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
1138c2ecf20Sopenharmony_ci		sg_list[i].addr = ib_sg_list[i].addr;
1148c2ecf20Sopenharmony_ci		sg_list[i].lkey = ib_sg_list[i].lkey;
1158c2ecf20Sopenharmony_ci		sg_list[i].size = ib_sg_list[i].length;
1168c2ecf20Sopenharmony_ci		total += sg_list[i].size;
1178c2ecf20Sopenharmony_ci	}
1188c2ecf20Sopenharmony_ci	return total;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/* Device */
1228c2ecf20Sopenharmony_ciint bnxt_re_query_device(struct ib_device *ibdev,
1238c2ecf20Sopenharmony_ci			 struct ib_device_attr *ib_attr,
1248c2ecf20Sopenharmony_ci			 struct ib_udata *udata)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
1278c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	memset(ib_attr, 0, sizeof(*ib_attr));
1308c2ecf20Sopenharmony_ci	memcpy(&ib_attr->fw_ver, dev_attr->fw_ver,
1318c2ecf20Sopenharmony_ci	       min(sizeof(dev_attr->fw_ver),
1328c2ecf20Sopenharmony_ci		   sizeof(ib_attr->fw_ver)));
1338c2ecf20Sopenharmony_ci	bnxt_qplib_get_guid(rdev->netdev->dev_addr,
1348c2ecf20Sopenharmony_ci			    (u8 *)&ib_attr->sys_image_guid);
1358c2ecf20Sopenharmony_ci	ib_attr->max_mr_size = BNXT_RE_MAX_MR_SIZE;
1368c2ecf20Sopenharmony_ci	ib_attr->page_size_cap = BNXT_RE_PAGE_SIZE_4K | BNXT_RE_PAGE_SIZE_2M;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
1398c2ecf20Sopenharmony_ci	ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
1408c2ecf20Sopenharmony_ci	ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
1418c2ecf20Sopenharmony_ci	ib_attr->max_qp = dev_attr->max_qp;
1428c2ecf20Sopenharmony_ci	ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
1438c2ecf20Sopenharmony_ci	ib_attr->device_cap_flags =
1448c2ecf20Sopenharmony_ci				    IB_DEVICE_CURR_QP_STATE_MOD
1458c2ecf20Sopenharmony_ci				    | IB_DEVICE_RC_RNR_NAK_GEN
1468c2ecf20Sopenharmony_ci				    | IB_DEVICE_SHUTDOWN_PORT
1478c2ecf20Sopenharmony_ci				    | IB_DEVICE_SYS_IMAGE_GUID
1488c2ecf20Sopenharmony_ci				    | IB_DEVICE_LOCAL_DMA_LKEY
1498c2ecf20Sopenharmony_ci				    | IB_DEVICE_RESIZE_MAX_WR
1508c2ecf20Sopenharmony_ci				    | IB_DEVICE_PORT_ACTIVE_EVENT
1518c2ecf20Sopenharmony_ci				    | IB_DEVICE_N_NOTIFY_CQ
1528c2ecf20Sopenharmony_ci				    | IB_DEVICE_MEM_WINDOW
1538c2ecf20Sopenharmony_ci				    | IB_DEVICE_MEM_WINDOW_TYPE_2B
1548c2ecf20Sopenharmony_ci				    | IB_DEVICE_MEM_MGT_EXTENSIONS;
1558c2ecf20Sopenharmony_ci	ib_attr->max_send_sge = dev_attr->max_qp_sges;
1568c2ecf20Sopenharmony_ci	ib_attr->max_recv_sge = dev_attr->max_qp_sges;
1578c2ecf20Sopenharmony_ci	ib_attr->max_sge_rd = dev_attr->max_qp_sges;
1588c2ecf20Sopenharmony_ci	ib_attr->max_cq = dev_attr->max_cq;
1598c2ecf20Sopenharmony_ci	ib_attr->max_cqe = dev_attr->max_cq_wqes;
1608c2ecf20Sopenharmony_ci	ib_attr->max_mr = dev_attr->max_mr;
1618c2ecf20Sopenharmony_ci	ib_attr->max_pd = dev_attr->max_pd;
1628c2ecf20Sopenharmony_ci	ib_attr->max_qp_rd_atom = dev_attr->max_qp_rd_atom;
1638c2ecf20Sopenharmony_ci	ib_attr->max_qp_init_rd_atom = dev_attr->max_qp_init_rd_atom;
1648c2ecf20Sopenharmony_ci	ib_attr->atomic_cap = IB_ATOMIC_NONE;
1658c2ecf20Sopenharmony_ci	ib_attr->masked_atomic_cap = IB_ATOMIC_NONE;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	ib_attr->max_ee_rd_atom = 0;
1688c2ecf20Sopenharmony_ci	ib_attr->max_res_rd_atom = 0;
1698c2ecf20Sopenharmony_ci	ib_attr->max_ee_init_rd_atom = 0;
1708c2ecf20Sopenharmony_ci	ib_attr->max_ee = 0;
1718c2ecf20Sopenharmony_ci	ib_attr->max_rdd = 0;
1728c2ecf20Sopenharmony_ci	ib_attr->max_mw = dev_attr->max_mw;
1738c2ecf20Sopenharmony_ci	ib_attr->max_raw_ipv6_qp = 0;
1748c2ecf20Sopenharmony_ci	ib_attr->max_raw_ethy_qp = dev_attr->max_raw_ethy_qp;
1758c2ecf20Sopenharmony_ci	ib_attr->max_mcast_grp = 0;
1768c2ecf20Sopenharmony_ci	ib_attr->max_mcast_qp_attach = 0;
1778c2ecf20Sopenharmony_ci	ib_attr->max_total_mcast_qp_attach = 0;
1788c2ecf20Sopenharmony_ci	ib_attr->max_ah = dev_attr->max_ah;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	ib_attr->max_srq = dev_attr->max_srq;
1818c2ecf20Sopenharmony_ci	ib_attr->max_srq_wr = dev_attr->max_srq_wqes;
1828c2ecf20Sopenharmony_ci	ib_attr->max_srq_sge = dev_attr->max_srq_sges;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	ib_attr->max_fast_reg_page_list_len = MAX_PBL_LVL_1_PGS;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ib_attr->max_pkeys = 1;
1878c2ecf20Sopenharmony_ci	ib_attr->local_ca_ack_delay = BNXT_RE_DEFAULT_ACK_DELAY;
1888c2ecf20Sopenharmony_ci	return 0;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* Port */
1928c2ecf20Sopenharmony_ciint bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
1938c2ecf20Sopenharmony_ci		       struct ib_port_attr *port_attr)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
1968c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	memset(port_attr, 0, sizeof(*port_attr));
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	if (netif_running(rdev->netdev) && netif_carrier_ok(rdev->netdev)) {
2018c2ecf20Sopenharmony_ci		port_attr->state = IB_PORT_ACTIVE;
2028c2ecf20Sopenharmony_ci		port_attr->phys_state = IB_PORT_PHYS_STATE_LINK_UP;
2038c2ecf20Sopenharmony_ci	} else {
2048c2ecf20Sopenharmony_ci		port_attr->state = IB_PORT_DOWN;
2058c2ecf20Sopenharmony_ci		port_attr->phys_state = IB_PORT_PHYS_STATE_DISABLED;
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci	port_attr->max_mtu = IB_MTU_4096;
2088c2ecf20Sopenharmony_ci	port_attr->active_mtu = iboe_get_mtu(rdev->netdev->mtu);
2098c2ecf20Sopenharmony_ci	port_attr->gid_tbl_len = dev_attr->max_sgid;
2108c2ecf20Sopenharmony_ci	port_attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP |
2118c2ecf20Sopenharmony_ci				    IB_PORT_DEVICE_MGMT_SUP |
2128c2ecf20Sopenharmony_ci				    IB_PORT_VENDOR_CLASS_SUP;
2138c2ecf20Sopenharmony_ci	port_attr->ip_gids = true;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	port_attr->max_msg_sz = (u32)BNXT_RE_MAX_MR_SIZE_LOW;
2168c2ecf20Sopenharmony_ci	port_attr->bad_pkey_cntr = 0;
2178c2ecf20Sopenharmony_ci	port_attr->qkey_viol_cntr = 0;
2188c2ecf20Sopenharmony_ci	port_attr->pkey_tbl_len = dev_attr->max_pkey;
2198c2ecf20Sopenharmony_ci	port_attr->lid = 0;
2208c2ecf20Sopenharmony_ci	port_attr->sm_lid = 0;
2218c2ecf20Sopenharmony_ci	port_attr->lmc = 0;
2228c2ecf20Sopenharmony_ci	port_attr->max_vl_num = 4;
2238c2ecf20Sopenharmony_ci	port_attr->sm_sl = 0;
2248c2ecf20Sopenharmony_ci	port_attr->subnet_timeout = 0;
2258c2ecf20Sopenharmony_ci	port_attr->init_type_reply = 0;
2268c2ecf20Sopenharmony_ci	port_attr->active_speed = rdev->active_speed;
2278c2ecf20Sopenharmony_ci	port_attr->active_width = rdev->active_width;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	return 0;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ciint bnxt_re_get_port_immutable(struct ib_device *ibdev, u8 port_num,
2338c2ecf20Sopenharmony_ci			       struct ib_port_immutable *immutable)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	struct ib_port_attr port_attr;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	if (bnxt_re_query_port(ibdev, port_num, &port_attr))
2388c2ecf20Sopenharmony_ci		return -EINVAL;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	immutable->pkey_tbl_len = port_attr.pkey_tbl_len;
2418c2ecf20Sopenharmony_ci	immutable->gid_tbl_len = port_attr.gid_tbl_len;
2428c2ecf20Sopenharmony_ci	immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
2438c2ecf20Sopenharmony_ci	immutable->core_cap_flags |= RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP;
2448c2ecf20Sopenharmony_ci	immutable->max_mad_size = IB_MGMT_MAD_SIZE;
2458c2ecf20Sopenharmony_ci	return 0;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_civoid bnxt_re_query_fw_str(struct ib_device *ibdev, char *str)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%d.%d",
2538c2ecf20Sopenharmony_ci		 rdev->dev_attr.fw_ver[0], rdev->dev_attr.fw_ver[1],
2548c2ecf20Sopenharmony_ci		 rdev->dev_attr.fw_ver[2], rdev->dev_attr.fw_ver[3]);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ciint bnxt_re_query_pkey(struct ib_device *ibdev, u8 port_num,
2588c2ecf20Sopenharmony_ci		       u16 index, u16 *pkey)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* Ignore port_num */
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	memset(pkey, 0, sizeof(*pkey));
2658c2ecf20Sopenharmony_ci	return bnxt_qplib_get_pkey(&rdev->qplib_res,
2668c2ecf20Sopenharmony_ci				   &rdev->qplib_res.pkey_tbl, index, pkey);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ciint bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num,
2708c2ecf20Sopenharmony_ci		      int index, union ib_gid *gid)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
2738c2ecf20Sopenharmony_ci	int rc = 0;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* Ignore port_num */
2768c2ecf20Sopenharmony_ci	memset(gid, 0, sizeof(*gid));
2778c2ecf20Sopenharmony_ci	rc = bnxt_qplib_get_sgid(&rdev->qplib_res,
2788c2ecf20Sopenharmony_ci				 &rdev->qplib_res.sgid_tbl, index,
2798c2ecf20Sopenharmony_ci				 (struct bnxt_qplib_gid *)gid);
2808c2ecf20Sopenharmony_ci	return rc;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ciint bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	int rc = 0;
2868c2ecf20Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
2878c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
2888c2ecf20Sopenharmony_ci	struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
2898c2ecf20Sopenharmony_ci	struct bnxt_qplib_gid *gid_to_del;
2908c2ecf20Sopenharmony_ci	u16 vlan_id = 0xFFFF;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	/* Delete the entry from the hardware */
2938c2ecf20Sopenharmony_ci	ctx = *context;
2948c2ecf20Sopenharmony_ci	if (!ctx)
2958c2ecf20Sopenharmony_ci		return -EINVAL;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	if (sgid_tbl && sgid_tbl->active) {
2988c2ecf20Sopenharmony_ci		if (ctx->idx >= sgid_tbl->max)
2998c2ecf20Sopenharmony_ci			return -EINVAL;
3008c2ecf20Sopenharmony_ci		gid_to_del = &sgid_tbl->tbl[ctx->idx].gid;
3018c2ecf20Sopenharmony_ci		vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id;
3028c2ecf20Sopenharmony_ci		/* DEL_GID is called in WQ context(netdevice_event_work_handler)
3038c2ecf20Sopenharmony_ci		 * or via the ib_unregister_device path. In the former case QP1
3048c2ecf20Sopenharmony_ci		 * may not be destroyed yet, in which case just return as FW
3058c2ecf20Sopenharmony_ci		 * needs that entry to be present and will fail it's deletion.
3068c2ecf20Sopenharmony_ci		 * We could get invoked again after QP1 is destroyed OR get an
3078c2ecf20Sopenharmony_ci		 * ADD_GID call with a different GID value for the same index
3088c2ecf20Sopenharmony_ci		 * where we issue MODIFY_GID cmd to update the GID entry -- TBD
3098c2ecf20Sopenharmony_ci		 */
3108c2ecf20Sopenharmony_ci		if (ctx->idx == 0 &&
3118c2ecf20Sopenharmony_ci		    rdma_link_local_addr((struct in6_addr *)gid_to_del) &&
3128c2ecf20Sopenharmony_ci		    ctx->refcnt == 1 && rdev->gsi_ctx.gsi_sqp) {
3138c2ecf20Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
3148c2ecf20Sopenharmony_ci				  "Trying to delete GID0 while QP1 is alive\n");
3158c2ecf20Sopenharmony_ci			return -EFAULT;
3168c2ecf20Sopenharmony_ci		}
3178c2ecf20Sopenharmony_ci		ctx->refcnt--;
3188c2ecf20Sopenharmony_ci		if (!ctx->refcnt) {
3198c2ecf20Sopenharmony_ci			rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
3208c2ecf20Sopenharmony_ci						 vlan_id,  true);
3218c2ecf20Sopenharmony_ci			if (rc) {
3228c2ecf20Sopenharmony_ci				ibdev_err(&rdev->ibdev,
3238c2ecf20Sopenharmony_ci					  "Failed to remove GID: %#x", rc);
3248c2ecf20Sopenharmony_ci			} else {
3258c2ecf20Sopenharmony_ci				ctx_tbl = sgid_tbl->ctx;
3268c2ecf20Sopenharmony_ci				ctx_tbl[ctx->idx] = NULL;
3278c2ecf20Sopenharmony_ci				kfree(ctx);
3288c2ecf20Sopenharmony_ci			}
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci	} else {
3318c2ecf20Sopenharmony_ci		return -EINVAL;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci	return rc;
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ciint bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	int rc;
3398c2ecf20Sopenharmony_ci	u32 tbl_idx = 0;
3408c2ecf20Sopenharmony_ci	u16 vlan_id = 0xFFFF;
3418c2ecf20Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
3428c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
3438c2ecf20Sopenharmony_ci	struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL);
3468c2ecf20Sopenharmony_ci	if (rc)
3478c2ecf20Sopenharmony_ci		return rc;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid,
3508c2ecf20Sopenharmony_ci				 rdev->qplib_res.netdev->dev_addr,
3518c2ecf20Sopenharmony_ci				 vlan_id, true, &tbl_idx);
3528c2ecf20Sopenharmony_ci	if (rc == -EALREADY) {
3538c2ecf20Sopenharmony_ci		ctx_tbl = sgid_tbl->ctx;
3548c2ecf20Sopenharmony_ci		ctx_tbl[tbl_idx]->refcnt++;
3558c2ecf20Sopenharmony_ci		*context = ctx_tbl[tbl_idx];
3568c2ecf20Sopenharmony_ci		return 0;
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	if (rc < 0) {
3608c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to add GID: %#x", rc);
3618c2ecf20Sopenharmony_ci		return rc;
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
3658c2ecf20Sopenharmony_ci	if (!ctx)
3668c2ecf20Sopenharmony_ci		return -ENOMEM;
3678c2ecf20Sopenharmony_ci	ctx_tbl = sgid_tbl->ctx;
3688c2ecf20Sopenharmony_ci	ctx->idx = tbl_idx;
3698c2ecf20Sopenharmony_ci	ctx->refcnt = 1;
3708c2ecf20Sopenharmony_ci	ctx_tbl[tbl_idx] = ctx;
3718c2ecf20Sopenharmony_ci	*context = ctx;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	return rc;
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_cienum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
3778c2ecf20Sopenharmony_ci					    u8 port_num)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	return IB_LINK_LAYER_ETHERNET;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci#define	BNXT_RE_FENCE_PBL_SIZE	DIV_ROUND_UP(BNXT_RE_FENCE_BYTES, PAGE_SIZE)
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic void bnxt_re_create_fence_wqe(struct bnxt_re_pd *pd)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
3878c2ecf20Sopenharmony_ci	struct ib_mr *ib_mr = &fence->mr->ib_mr;
3888c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe *wqe = &fence->bind_wqe;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	memset(wqe, 0, sizeof(*wqe));
3918c2ecf20Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW;
3928c2ecf20Sopenharmony_ci	wqe->wr_id = BNXT_QPLIB_FENCE_WRID;
3938c2ecf20Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
3948c2ecf20Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
3958c2ecf20Sopenharmony_ci	wqe->bind.zero_based = false;
3968c2ecf20Sopenharmony_ci	wqe->bind.parent_l_key = ib_mr->lkey;
3978c2ecf20Sopenharmony_ci	wqe->bind.va = (u64)(unsigned long)fence->va;
3988c2ecf20Sopenharmony_ci	wqe->bind.length = fence->size;
3998c2ecf20Sopenharmony_ci	wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ);
4008c2ecf20Sopenharmony_ci	wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* Save the initial rkey in fence structure for now;
4038c2ecf20Sopenharmony_ci	 * wqe->bind.r_key will be set at (re)bind time.
4048c2ecf20Sopenharmony_ci	 */
4058c2ecf20Sopenharmony_ci	fence->bind_rkey = ib_inc_rkey(fence->mw->rkey);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic int bnxt_re_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp,
4118c2ecf20Sopenharmony_ci					     qplib_qp);
4128c2ecf20Sopenharmony_ci	struct ib_pd *ib_pd = qp->ib_qp.pd;
4138c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
4148c2ecf20Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
4158c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe;
4168c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
4178c2ecf20Sopenharmony_ci	int rc;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	memcpy(&wqe, fence_wqe, sizeof(wqe));
4208c2ecf20Sopenharmony_ci	wqe.bind.r_key = fence->bind_rkey;
4218c2ecf20Sopenharmony_ci	fence->bind_rkey = ib_inc_rkey(fence->bind_rkey);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	ibdev_dbg(&qp->rdev->ibdev,
4248c2ecf20Sopenharmony_ci		  "Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n",
4258c2ecf20Sopenharmony_ci		wqe.bind.r_key, qp->qplib_qp.id, pd);
4268c2ecf20Sopenharmony_ci	rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
4278c2ecf20Sopenharmony_ci	if (rc) {
4288c2ecf20Sopenharmony_ci		ibdev_err(&qp->rdev->ibdev, "Failed to bind fence-WQE\n");
4298c2ecf20Sopenharmony_ci		return rc;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	return rc;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic void bnxt_re_destroy_fence_mr(struct bnxt_re_pd *pd)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
4398c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
4408c2ecf20Sopenharmony_ci	struct device *dev = &rdev->en_dev->pdev->dev;
4418c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = fence->mr;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	if (fence->mw) {
4448c2ecf20Sopenharmony_ci		bnxt_re_dealloc_mw(fence->mw);
4458c2ecf20Sopenharmony_ci		fence->mw = NULL;
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci	if (mr) {
4488c2ecf20Sopenharmony_ci		if (mr->ib_mr.rkey)
4498c2ecf20Sopenharmony_ci			bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr,
4508c2ecf20Sopenharmony_ci					     true);
4518c2ecf20Sopenharmony_ci		if (mr->ib_mr.lkey)
4528c2ecf20Sopenharmony_ci			bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
4538c2ecf20Sopenharmony_ci		kfree(mr);
4548c2ecf20Sopenharmony_ci		fence->mr = NULL;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci	if (fence->dma_addr) {
4578c2ecf20Sopenharmony_ci		dma_unmap_single(dev, fence->dma_addr, BNXT_RE_FENCE_BYTES,
4588c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
4598c2ecf20Sopenharmony_ci		fence->dma_addr = 0;
4608c2ecf20Sopenharmony_ci	}
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cistatic int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND;
4668c2ecf20Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
4678c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
4688c2ecf20Sopenharmony_ci	struct device *dev = &rdev->en_dev->pdev->dev;
4698c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = NULL;
4708c2ecf20Sopenharmony_ci	dma_addr_t dma_addr = 0;
4718c2ecf20Sopenharmony_ci	struct ib_mw *mw;
4728c2ecf20Sopenharmony_ci	int rc;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	dma_addr = dma_map_single(dev, fence->va, BNXT_RE_FENCE_BYTES,
4758c2ecf20Sopenharmony_ci				  DMA_BIDIRECTIONAL);
4768c2ecf20Sopenharmony_ci	rc = dma_mapping_error(dev, dma_addr);
4778c2ecf20Sopenharmony_ci	if (rc) {
4788c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to dma-map fence-MR-mem\n");
4798c2ecf20Sopenharmony_ci		rc = -EIO;
4808c2ecf20Sopenharmony_ci		fence->dma_addr = 0;
4818c2ecf20Sopenharmony_ci		goto fail;
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci	fence->dma_addr = dma_addr;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	/* Allocate a MR */
4868c2ecf20Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
4878c2ecf20Sopenharmony_ci	if (!mr) {
4888c2ecf20Sopenharmony_ci		rc = -ENOMEM;
4898c2ecf20Sopenharmony_ci		goto fail;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci	fence->mr = mr;
4928c2ecf20Sopenharmony_ci	mr->rdev = rdev;
4938c2ecf20Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
4948c2ecf20Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
4958c2ecf20Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
4968c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
4978c2ecf20Sopenharmony_ci	if (rc) {
4988c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to alloc fence-HW-MR\n");
4998c2ecf20Sopenharmony_ci		goto fail;
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* Register MR */
5038c2ecf20Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
5048c2ecf20Sopenharmony_ci	mr->qplib_mr.va = (u64)(unsigned long)fence->va;
5058c2ecf20Sopenharmony_ci	mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
5068c2ecf20Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, NULL,
5078c2ecf20Sopenharmony_ci			       BNXT_RE_FENCE_PBL_SIZE, PAGE_SIZE);
5088c2ecf20Sopenharmony_ci	if (rc) {
5098c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to register fence-MR\n");
5108c2ecf20Sopenharmony_ci		goto fail;
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.rkey;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	/* Create a fence MW only for kernel consumers */
5158c2ecf20Sopenharmony_ci	mw = bnxt_re_alloc_mw(&pd->ib_pd, IB_MW_TYPE_1, NULL);
5168c2ecf20Sopenharmony_ci	if (IS_ERR(mw)) {
5178c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
5188c2ecf20Sopenharmony_ci			  "Failed to create fence-MW for PD: %p\n", pd);
5198c2ecf20Sopenharmony_ci		rc = PTR_ERR(mw);
5208c2ecf20Sopenharmony_ci		goto fail;
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci	fence->mw = mw;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	bnxt_re_create_fence_wqe(pd);
5258c2ecf20Sopenharmony_ci	return 0;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cifail:
5288c2ecf20Sopenharmony_ci	bnxt_re_destroy_fence_mr(pd);
5298c2ecf20Sopenharmony_ci	return rc;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci/* Protection Domains */
5338c2ecf20Sopenharmony_ciint bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata)
5348c2ecf20Sopenharmony_ci{
5358c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
5368c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	bnxt_re_destroy_fence_mr(pd);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (pd->qplib_pd.id)
5418c2ecf20Sopenharmony_ci		bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
5428c2ecf20Sopenharmony_ci				      &pd->qplib_pd);
5438c2ecf20Sopenharmony_ci	return 0;
5448c2ecf20Sopenharmony_ci}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ciint bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	struct ib_device *ibdev = ibpd->device;
5498c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
5508c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *ucntx = rdma_udata_to_drv_context(
5518c2ecf20Sopenharmony_ci		udata, struct bnxt_re_ucontext, ib_uctx);
5528c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ibpd, struct bnxt_re_pd, ib_pd);
5538c2ecf20Sopenharmony_ci	int rc;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	pd->rdev = rdev;
5568c2ecf20Sopenharmony_ci	if (bnxt_qplib_alloc_pd(&rdev->qplib_res.pd_tbl, &pd->qplib_pd)) {
5578c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate HW PD");
5588c2ecf20Sopenharmony_ci		rc = -ENOMEM;
5598c2ecf20Sopenharmony_ci		goto fail;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (udata) {
5638c2ecf20Sopenharmony_ci		struct bnxt_re_pd_resp resp;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci		if (!ucntx->dpi.dbr) {
5668c2ecf20Sopenharmony_ci			/* Allocate DPI in alloc_pd to avoid failing of
5678c2ecf20Sopenharmony_ci			 * ibv_devinfo and family of application when DPIs
5688c2ecf20Sopenharmony_ci			 * are depleted.
5698c2ecf20Sopenharmony_ci			 */
5708c2ecf20Sopenharmony_ci			if (bnxt_qplib_alloc_dpi(&rdev->qplib_res.dpi_tbl,
5718c2ecf20Sopenharmony_ci						 &ucntx->dpi, ucntx)) {
5728c2ecf20Sopenharmony_ci				rc = -ENOMEM;
5738c2ecf20Sopenharmony_ci				goto dbfail;
5748c2ecf20Sopenharmony_ci			}
5758c2ecf20Sopenharmony_ci		}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci		resp.pdid = pd->qplib_pd.id;
5788c2ecf20Sopenharmony_ci		/* Still allow mapping this DBR to the new user PD. */
5798c2ecf20Sopenharmony_ci		resp.dpi = ucntx->dpi.dpi;
5808c2ecf20Sopenharmony_ci		resp.dbr = (u64)ucntx->dpi.umdbr;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
5838c2ecf20Sopenharmony_ci		if (rc) {
5848c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
5858c2ecf20Sopenharmony_ci				  "Failed to copy user response\n");
5868c2ecf20Sopenharmony_ci			goto dbfail;
5878c2ecf20Sopenharmony_ci		}
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (!udata)
5918c2ecf20Sopenharmony_ci		if (bnxt_re_create_fence_mr(pd))
5928c2ecf20Sopenharmony_ci			ibdev_warn(&rdev->ibdev,
5938c2ecf20Sopenharmony_ci				   "Failed to create Fence-MR\n");
5948c2ecf20Sopenharmony_ci	return 0;
5958c2ecf20Sopenharmony_cidbfail:
5968c2ecf20Sopenharmony_ci	bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
5978c2ecf20Sopenharmony_ci			      &pd->qplib_pd);
5988c2ecf20Sopenharmony_cifail:
5998c2ecf20Sopenharmony_ci	return rc;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci/* Address Handles */
6038c2ecf20Sopenharmony_ciint bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)
6048c2ecf20Sopenharmony_ci{
6058c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
6068c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = ah->rdev;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah,
6098c2ecf20Sopenharmony_ci			      !(flags & RDMA_DESTROY_AH_SLEEPABLE));
6108c2ecf20Sopenharmony_ci	return 0;
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype)
6148c2ecf20Sopenharmony_ci{
6158c2ecf20Sopenharmony_ci	u8 nw_type;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	switch (ntype) {
6188c2ecf20Sopenharmony_ci	case RDMA_NETWORK_IPV4:
6198c2ecf20Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V2IPV4;
6208c2ecf20Sopenharmony_ci		break;
6218c2ecf20Sopenharmony_ci	case RDMA_NETWORK_IPV6:
6228c2ecf20Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V2IPV6;
6238c2ecf20Sopenharmony_ci		break;
6248c2ecf20Sopenharmony_ci	default:
6258c2ecf20Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V1;
6268c2ecf20Sopenharmony_ci		break;
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci	return nw_type;
6298c2ecf20Sopenharmony_ci}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ciint bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_ah_init_attr *init_attr,
6328c2ecf20Sopenharmony_ci		      struct ib_udata *udata)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	struct ib_pd *ib_pd = ib_ah->pd;
6358c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
6368c2ecf20Sopenharmony_ci	struct rdma_ah_attr *ah_attr = init_attr->ah_attr;
6378c2ecf20Sopenharmony_ci	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
6388c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
6398c2ecf20Sopenharmony_ci	const struct ib_gid_attr *sgid_attr;
6408c2ecf20Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx;
6418c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
6428c2ecf20Sopenharmony_ci	u8 nw_type;
6438c2ecf20Sopenharmony_ci	int rc;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) {
6468c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to alloc AH: GRH not set");
6478c2ecf20Sopenharmony_ci		return -EINVAL;
6488c2ecf20Sopenharmony_ci	}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	ah->rdev = rdev;
6518c2ecf20Sopenharmony_ci	ah->qplib_ah.pd = &pd->qplib_pd;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	/* Supply the configuration for the HW */
6548c2ecf20Sopenharmony_ci	memcpy(ah->qplib_ah.dgid.data, grh->dgid.raw,
6558c2ecf20Sopenharmony_ci	       sizeof(union ib_gid));
6568c2ecf20Sopenharmony_ci	sgid_attr = grh->sgid_attr;
6578c2ecf20Sopenharmony_ci	/* Get the HW context of the GID. The reference
6588c2ecf20Sopenharmony_ci	 * of GID table entry is already taken by the caller.
6598c2ecf20Sopenharmony_ci	 */
6608c2ecf20Sopenharmony_ci	ctx = rdma_read_gid_hw_context(sgid_attr);
6618c2ecf20Sopenharmony_ci	ah->qplib_ah.sgid_index = ctx->idx;
6628c2ecf20Sopenharmony_ci	ah->qplib_ah.host_sgid_index = grh->sgid_index;
6638c2ecf20Sopenharmony_ci	ah->qplib_ah.traffic_class = grh->traffic_class;
6648c2ecf20Sopenharmony_ci	ah->qplib_ah.flow_label = grh->flow_label;
6658c2ecf20Sopenharmony_ci	ah->qplib_ah.hop_limit = grh->hop_limit;
6668c2ecf20Sopenharmony_ci	ah->qplib_ah.sl = rdma_ah_get_sl(ah_attr);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	/* Get network header type for this GID */
6698c2ecf20Sopenharmony_ci	nw_type = rdma_gid_attr_network_type(sgid_attr);
6708c2ecf20Sopenharmony_ci	ah->qplib_ah.nw_type = bnxt_re_stack_to_dev_nw_type(nw_type);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	memcpy(ah->qplib_ah.dmac, ah_attr->roce.dmac, ETH_ALEN);
6738c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah,
6748c2ecf20Sopenharmony_ci				  !(init_attr->flags &
6758c2ecf20Sopenharmony_ci				    RDMA_CREATE_AH_SLEEPABLE));
6768c2ecf20Sopenharmony_ci	if (rc) {
6778c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate HW AH");
6788c2ecf20Sopenharmony_ci		return rc;
6798c2ecf20Sopenharmony_ci	}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* Write AVID to shared page. */
6828c2ecf20Sopenharmony_ci	if (udata) {
6838c2ecf20Sopenharmony_ci		struct bnxt_re_ucontext *uctx = rdma_udata_to_drv_context(
6848c2ecf20Sopenharmony_ci			udata, struct bnxt_re_ucontext, ib_uctx);
6858c2ecf20Sopenharmony_ci		unsigned long flag;
6868c2ecf20Sopenharmony_ci		u32 *wrptr;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci		spin_lock_irqsave(&uctx->sh_lock, flag);
6898c2ecf20Sopenharmony_ci		wrptr = (u32 *)(uctx->shpg + BNXT_RE_AVID_OFFT);
6908c2ecf20Sopenharmony_ci		*wrptr = ah->qplib_ah.id;
6918c2ecf20Sopenharmony_ci		wmb(); /* make sure cache is updated. */
6928c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&uctx->sh_lock, flag);
6938c2ecf20Sopenharmony_ci	}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	return 0;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ciint bnxt_re_modify_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	return 0;
7018c2ecf20Sopenharmony_ci}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ciint bnxt_re_query_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	ah_attr->type = ib_ah->type;
7088c2ecf20Sopenharmony_ci	rdma_ah_set_sl(ah_attr, ah->qplib_ah.sl);
7098c2ecf20Sopenharmony_ci	memcpy(ah_attr->roce.dmac, ah->qplib_ah.dmac, ETH_ALEN);
7108c2ecf20Sopenharmony_ci	rdma_ah_set_grh(ah_attr, NULL, 0,
7118c2ecf20Sopenharmony_ci			ah->qplib_ah.host_sgid_index,
7128c2ecf20Sopenharmony_ci			0, ah->qplib_ah.traffic_class);
7138c2ecf20Sopenharmony_ci	rdma_ah_set_dgid_raw(ah_attr, ah->qplib_ah.dgid.data);
7148c2ecf20Sopenharmony_ci	rdma_ah_set_port_num(ah_attr, 1);
7158c2ecf20Sopenharmony_ci	rdma_ah_set_static_rate(ah_attr, 0);
7168c2ecf20Sopenharmony_ci	return 0;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ciunsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp)
7208c2ecf20Sopenharmony_ci	__acquires(&qp->scq->cq_lock) __acquires(&qp->rcq->cq_lock)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	unsigned long flags;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	spin_lock_irqsave(&qp->scq->cq_lock, flags);
7258c2ecf20Sopenharmony_ci	if (qp->rcq != qp->scq)
7268c2ecf20Sopenharmony_ci		spin_lock(&qp->rcq->cq_lock);
7278c2ecf20Sopenharmony_ci	else
7288c2ecf20Sopenharmony_ci		__acquire(&qp->rcq->cq_lock);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	return flags;
7318c2ecf20Sopenharmony_ci}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_civoid bnxt_re_unlock_cqs(struct bnxt_re_qp *qp,
7348c2ecf20Sopenharmony_ci			unsigned long flags)
7358c2ecf20Sopenharmony_ci	__releases(&qp->scq->cq_lock) __releases(&qp->rcq->cq_lock)
7368c2ecf20Sopenharmony_ci{
7378c2ecf20Sopenharmony_ci	if (qp->rcq != qp->scq)
7388c2ecf20Sopenharmony_ci		spin_unlock(&qp->rcq->cq_lock);
7398c2ecf20Sopenharmony_ci	else
7408c2ecf20Sopenharmony_ci		__release(&qp->rcq->cq_lock);
7418c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&qp->scq->cq_lock, flags);
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	struct bnxt_re_qp *gsi_sqp;
7478c2ecf20Sopenharmony_ci	struct bnxt_re_ah *gsi_sah;
7488c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
7498c2ecf20Sopenharmony_ci	int rc = 0;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	rdev = qp->rdev;
7528c2ecf20Sopenharmony_ci	gsi_sqp = rdev->gsi_ctx.gsi_sqp;
7538c2ecf20Sopenharmony_ci	gsi_sah = rdev->gsi_ctx.gsi_sah;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	ibdev_dbg(&rdev->ibdev, "Destroy the shadow AH\n");
7568c2ecf20Sopenharmony_ci	bnxt_qplib_destroy_ah(&rdev->qplib_res,
7578c2ecf20Sopenharmony_ci			      &gsi_sah->qplib_ah,
7588c2ecf20Sopenharmony_ci			      true);
7598c2ecf20Sopenharmony_ci	bnxt_qplib_clean_qp(&qp->qplib_qp);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	ibdev_dbg(&rdev->ibdev, "Destroy the shadow QP\n");
7628c2ecf20Sopenharmony_ci	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &gsi_sqp->qplib_qp);
7638c2ecf20Sopenharmony_ci	if (rc) {
7648c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Destroy Shadow QP failed");
7658c2ecf20Sopenharmony_ci		goto fail;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci	bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	/* remove from active qp list */
7708c2ecf20Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
7718c2ecf20Sopenharmony_ci	list_del(&gsi_sqp->list);
7728c2ecf20Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
7738c2ecf20Sopenharmony_ci	atomic_dec(&rdev->qp_count);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	kfree(rdev->gsi_ctx.sqp_tbl);
7768c2ecf20Sopenharmony_ci	kfree(gsi_sah);
7778c2ecf20Sopenharmony_ci	kfree(gsi_sqp);
7788c2ecf20Sopenharmony_ci	rdev->gsi_ctx.gsi_sqp = NULL;
7798c2ecf20Sopenharmony_ci	rdev->gsi_ctx.gsi_sah = NULL;
7808c2ecf20Sopenharmony_ci	rdev->gsi_ctx.sqp_tbl = NULL;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	return 0;
7838c2ecf20Sopenharmony_cifail:
7848c2ecf20Sopenharmony_ci	return rc;
7858c2ecf20Sopenharmony_ci}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci/* Queue Pairs */
7888c2ecf20Sopenharmony_ciint bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
7898c2ecf20Sopenharmony_ci{
7908c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
7918c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
7928c2ecf20Sopenharmony_ci	unsigned int flags;
7938c2ecf20Sopenharmony_ci	int rc;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
7988c2ecf20Sopenharmony_ci	if (rc) {
7998c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to destroy HW QP");
8008c2ecf20Sopenharmony_ci		return rc;
8018c2ecf20Sopenharmony_ci	}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if (rdma_is_kernel_res(&qp->ib_qp.res)) {
8048c2ecf20Sopenharmony_ci		flags = bnxt_re_lock_cqs(qp);
8058c2ecf20Sopenharmony_ci		bnxt_qplib_clean_qp(&qp->qplib_qp);
8068c2ecf20Sopenharmony_ci		bnxt_re_unlock_cqs(qp, flags);
8078c2ecf20Sopenharmony_ci	}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
8128c2ecf20Sopenharmony_ci		rc = bnxt_re_destroy_gsi_sqp(qp);
8138c2ecf20Sopenharmony_ci		if (rc)
8148c2ecf20Sopenharmony_ci			goto sh_fail;
8158c2ecf20Sopenharmony_ci	}
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
8188c2ecf20Sopenharmony_ci	list_del(&qp->list);
8198c2ecf20Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
8208c2ecf20Sopenharmony_ci	atomic_dec(&rdev->qp_count);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	ib_umem_release(qp->rumem);
8238c2ecf20Sopenharmony_ci	ib_umem_release(qp->sumem);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	kfree(qp);
8268c2ecf20Sopenharmony_ci	return 0;
8278c2ecf20Sopenharmony_cish_fail:
8288c2ecf20Sopenharmony_ci	return rc;
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_cistatic u8 __from_ib_qp_type(enum ib_qp_type type)
8328c2ecf20Sopenharmony_ci{
8338c2ecf20Sopenharmony_ci	switch (type) {
8348c2ecf20Sopenharmony_ci	case IB_QPT_GSI:
8358c2ecf20Sopenharmony_ci		return CMDQ_CREATE_QP1_TYPE_GSI;
8368c2ecf20Sopenharmony_ci	case IB_QPT_RC:
8378c2ecf20Sopenharmony_ci		return CMDQ_CREATE_QP_TYPE_RC;
8388c2ecf20Sopenharmony_ci	case IB_QPT_UD:
8398c2ecf20Sopenharmony_ci		return CMDQ_CREATE_QP_TYPE_UD;
8408c2ecf20Sopenharmony_ci	default:
8418c2ecf20Sopenharmony_ci		return IB_QPT_MAX;
8428c2ecf20Sopenharmony_ci	}
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic u16 bnxt_re_setup_rwqe_size(struct bnxt_qplib_qp *qplqp,
8468c2ecf20Sopenharmony_ci				   int rsge, int max)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
8498c2ecf20Sopenharmony_ci		rsge = max;
8508c2ecf20Sopenharmony_ci	return bnxt_re_get_rwqe_size(rsge);
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_cistatic u16 bnxt_re_get_wqe_size(int ilsize, int nsge)
8548c2ecf20Sopenharmony_ci{
8558c2ecf20Sopenharmony_ci	u16 wqe_size, calc_ils;
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci	wqe_size = bnxt_re_get_swqe_size(nsge);
8588c2ecf20Sopenharmony_ci	if (ilsize) {
8598c2ecf20Sopenharmony_ci		calc_ils = sizeof(struct sq_send_hdr) + ilsize;
8608c2ecf20Sopenharmony_ci		wqe_size = max_t(u16, calc_ils, wqe_size);
8618c2ecf20Sopenharmony_ci		wqe_size = ALIGN(wqe_size, sizeof(struct sq_send_hdr));
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci	return wqe_size;
8648c2ecf20Sopenharmony_ci}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_cistatic int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp,
8678c2ecf20Sopenharmony_ci				   struct ib_qp_init_attr *init_attr)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
8708c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
8718c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
8728c2ecf20Sopenharmony_ci	struct bnxt_qplib_q *sq;
8738c2ecf20Sopenharmony_ci	int align, ilsize;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	rdev = qp->rdev;
8768c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
8778c2ecf20Sopenharmony_ci	sq = &qplqp->sq;
8788c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	align = sizeof(struct sq_send_hdr);
8818c2ecf20Sopenharmony_ci	ilsize = ALIGN(init_attr->cap.max_inline_data, align);
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
8848c2ecf20Sopenharmony_ci	if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
8858c2ecf20Sopenharmony_ci		return -EINVAL;
8868c2ecf20Sopenharmony_ci	/* For gen p4 and gen p5 backward compatibility mode
8878c2ecf20Sopenharmony_ci	 * wqe size is fixed to 128 bytes
8888c2ecf20Sopenharmony_ci	 */
8898c2ecf20Sopenharmony_ci	if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) &&
8908c2ecf20Sopenharmony_ci			qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
8918c2ecf20Sopenharmony_ci		sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	if (init_attr->cap.max_inline_data) {
8948c2ecf20Sopenharmony_ci		qplqp->max_inline_data = sq->wqe_size -
8958c2ecf20Sopenharmony_ci			sizeof(struct sq_send_hdr);
8968c2ecf20Sopenharmony_ci		init_attr->cap.max_inline_data = qplqp->max_inline_data;
8978c2ecf20Sopenharmony_ci		if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
8988c2ecf20Sopenharmony_ci			sq->max_sge = qplqp->max_inline_data /
8998c2ecf20Sopenharmony_ci				sizeof(struct sq_sge);
9008c2ecf20Sopenharmony_ci	}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	return 0;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
9068c2ecf20Sopenharmony_ci				struct bnxt_re_qp *qp, struct ib_udata *udata)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplib_qp;
9098c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *cntx;
9108c2ecf20Sopenharmony_ci	struct bnxt_re_qp_req ureq;
9118c2ecf20Sopenharmony_ci	int bytes = 0, psn_sz;
9128c2ecf20Sopenharmony_ci	struct ib_umem *umem;
9138c2ecf20Sopenharmony_ci	int psn_nume;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	qplib_qp = &qp->qplib_qp;
9168c2ecf20Sopenharmony_ci	cntx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext,
9178c2ecf20Sopenharmony_ci					 ib_uctx);
9188c2ecf20Sopenharmony_ci	if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
9198c2ecf20Sopenharmony_ci		return -EFAULT;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	bytes = (qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size);
9228c2ecf20Sopenharmony_ci	/* Consider mapping PSN search memory only for RC QPs. */
9238c2ecf20Sopenharmony_ci	if (qplib_qp->type == CMDQ_CREATE_QP_TYPE_RC) {
9248c2ecf20Sopenharmony_ci		psn_sz = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ?
9258c2ecf20Sopenharmony_ci						   sizeof(struct sq_psn_search_ext) :
9268c2ecf20Sopenharmony_ci						   sizeof(struct sq_psn_search);
9278c2ecf20Sopenharmony_ci		psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
9288c2ecf20Sopenharmony_ci			    qplib_qp->sq.max_wqe :
9298c2ecf20Sopenharmony_ci			    ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) /
9308c2ecf20Sopenharmony_ci			      sizeof(struct bnxt_qplib_sge));
9318c2ecf20Sopenharmony_ci		bytes += (psn_nume * psn_sz);
9328c2ecf20Sopenharmony_ci	}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	bytes = PAGE_ALIGN(bytes);
9358c2ecf20Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes,
9368c2ecf20Sopenharmony_ci			   IB_ACCESS_LOCAL_WRITE);
9378c2ecf20Sopenharmony_ci	if (IS_ERR(umem))
9388c2ecf20Sopenharmony_ci		return PTR_ERR(umem);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	qp->sumem = umem;
9418c2ecf20Sopenharmony_ci	qplib_qp->sq.sg_info.umem = umem;
9428c2ecf20Sopenharmony_ci	qplib_qp->sq.sg_info.pgsize = PAGE_SIZE;
9438c2ecf20Sopenharmony_ci	qplib_qp->sq.sg_info.pgshft = PAGE_SHIFT;
9448c2ecf20Sopenharmony_ci	qplib_qp->qp_handle = ureq.qp_handle;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	if (!qp->qplib_qp.srq) {
9478c2ecf20Sopenharmony_ci		bytes = (qplib_qp->rq.max_wqe * qplib_qp->rq.wqe_size);
9488c2ecf20Sopenharmony_ci		bytes = PAGE_ALIGN(bytes);
9498c2ecf20Sopenharmony_ci		umem = ib_umem_get(&rdev->ibdev, ureq.qprva, bytes,
9508c2ecf20Sopenharmony_ci				   IB_ACCESS_LOCAL_WRITE);
9518c2ecf20Sopenharmony_ci		if (IS_ERR(umem))
9528c2ecf20Sopenharmony_ci			goto rqfail;
9538c2ecf20Sopenharmony_ci		qp->rumem = umem;
9548c2ecf20Sopenharmony_ci		qplib_qp->rq.sg_info.umem = umem;
9558c2ecf20Sopenharmony_ci		qplib_qp->rq.sg_info.pgsize = PAGE_SIZE;
9568c2ecf20Sopenharmony_ci		qplib_qp->rq.sg_info.pgshft = PAGE_SHIFT;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	qplib_qp->dpi = &cntx->dpi;
9608c2ecf20Sopenharmony_ci	return 0;
9618c2ecf20Sopenharmony_cirqfail:
9628c2ecf20Sopenharmony_ci	ib_umem_release(qp->sumem);
9638c2ecf20Sopenharmony_ci	qp->sumem = NULL;
9648c2ecf20Sopenharmony_ci	memset(&qplib_qp->sq.sg_info, 0, sizeof(qplib_qp->sq.sg_info));
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	return PTR_ERR(umem);
9678c2ecf20Sopenharmony_ci}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_cistatic struct bnxt_re_ah *bnxt_re_create_shadow_qp_ah
9708c2ecf20Sopenharmony_ci				(struct bnxt_re_pd *pd,
9718c2ecf20Sopenharmony_ci				 struct bnxt_qplib_res *qp1_res,
9728c2ecf20Sopenharmony_ci				 struct bnxt_qplib_qp *qp1_qp)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
9758c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah;
9768c2ecf20Sopenharmony_ci	union ib_gid sgid;
9778c2ecf20Sopenharmony_ci	int rc;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	ah = kzalloc(sizeof(*ah), GFP_KERNEL);
9808c2ecf20Sopenharmony_ci	if (!ah)
9818c2ecf20Sopenharmony_ci		return NULL;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	ah->rdev = rdev;
9848c2ecf20Sopenharmony_ci	ah->qplib_ah.pd = &pd->qplib_pd;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	rc = bnxt_re_query_gid(&rdev->ibdev, 1, 0, &sgid);
9878c2ecf20Sopenharmony_ci	if (rc)
9888c2ecf20Sopenharmony_ci		goto fail;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	/* supply the dgid data same as sgid */
9918c2ecf20Sopenharmony_ci	memcpy(ah->qplib_ah.dgid.data, &sgid.raw,
9928c2ecf20Sopenharmony_ci	       sizeof(union ib_gid));
9938c2ecf20Sopenharmony_ci	ah->qplib_ah.sgid_index = 0;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	ah->qplib_ah.traffic_class = 0;
9968c2ecf20Sopenharmony_ci	ah->qplib_ah.flow_label = 0;
9978c2ecf20Sopenharmony_ci	ah->qplib_ah.hop_limit = 1;
9988c2ecf20Sopenharmony_ci	ah->qplib_ah.sl = 0;
9998c2ecf20Sopenharmony_ci	/* Have DMAC same as SMAC */
10008c2ecf20Sopenharmony_ci	ether_addr_copy(ah->qplib_ah.dmac, rdev->netdev->dev_addr);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah, false);
10038c2ecf20Sopenharmony_ci	if (rc) {
10048c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
10058c2ecf20Sopenharmony_ci			  "Failed to allocate HW AH for Shadow QP");
10068c2ecf20Sopenharmony_ci		goto fail;
10078c2ecf20Sopenharmony_ci	}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	return ah;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_cifail:
10128c2ecf20Sopenharmony_ci	kfree(ah);
10138c2ecf20Sopenharmony_ci	return NULL;
10148c2ecf20Sopenharmony_ci}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_cistatic struct bnxt_re_qp *bnxt_re_create_shadow_qp
10178c2ecf20Sopenharmony_ci				(struct bnxt_re_pd *pd,
10188c2ecf20Sopenharmony_ci				 struct bnxt_qplib_res *qp1_res,
10198c2ecf20Sopenharmony_ci				 struct bnxt_qplib_qp *qp1_qp)
10208c2ecf20Sopenharmony_ci{
10218c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
10228c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp;
10238c2ecf20Sopenharmony_ci	int rc;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
10268c2ecf20Sopenharmony_ci	if (!qp)
10278c2ecf20Sopenharmony_ci		return NULL;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	qp->rdev = rdev;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	/* Initialize the shadow QP structure from the QP1 values */
10328c2ecf20Sopenharmony_ci	ether_addr_copy(qp->qplib_qp.smac, rdev->netdev->dev_addr);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	qp->qplib_qp.pd = &pd->qplib_pd;
10358c2ecf20Sopenharmony_ci	qp->qplib_qp.qp_handle = (u64)(unsigned long)(&qp->qplib_qp);
10368c2ecf20Sopenharmony_ci	qp->qplib_qp.type = IB_QPT_UD;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	qp->qplib_qp.max_inline_data = 0;
10398c2ecf20Sopenharmony_ci	qp->qplib_qp.sig_type = true;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	/* Shadow QP SQ depth should be same as QP1 RQ depth */
10428c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6);
10438c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
10448c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.max_sge = 2;
10458c2ecf20Sopenharmony_ci	/* Q full delta can be 1 since it is internal QP */
10468c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.q_full_delta = 1;
10478c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.sg_info.pgsize = PAGE_SIZE;
10488c2ecf20Sopenharmony_ci	qp->qplib_qp.sq.sg_info.pgshft = PAGE_SHIFT;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	qp->qplib_qp.scq = qp1_qp->scq;
10518c2ecf20Sopenharmony_ci	qp->qplib_qp.rcq = qp1_qp->rcq;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6);
10548c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
10558c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
10568c2ecf20Sopenharmony_ci	/* Q full delta can be 1 since it is internal QP */
10578c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.q_full_delta = 1;
10588c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.sg_info.pgsize = PAGE_SIZE;
10598c2ecf20Sopenharmony_ci	qp->qplib_qp.rq.sg_info.pgshft = PAGE_SHIFT;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	qp->qplib_qp.mtu = qp1_qp->mtu;
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	qp->qplib_qp.sq_hdr_buf_size = 0;
10648c2ecf20Sopenharmony_ci	qp->qplib_qp.rq_hdr_buf_size = BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6;
10658c2ecf20Sopenharmony_ci	qp->qplib_qp.dpi = &rdev->dpi_privileged;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_qp(qp1_res, &qp->qplib_qp);
10688c2ecf20Sopenharmony_ci	if (rc)
10698c2ecf20Sopenharmony_ci		goto fail;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	spin_lock_init(&qp->sq_lock);
10728c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qp->list);
10738c2ecf20Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
10748c2ecf20Sopenharmony_ci	list_add_tail(&qp->list, &rdev->qp_list);
10758c2ecf20Sopenharmony_ci	atomic_inc(&rdev->qp_count);
10768c2ecf20Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
10778c2ecf20Sopenharmony_ci	return qp;
10788c2ecf20Sopenharmony_cifail:
10798c2ecf20Sopenharmony_ci	kfree(qp);
10808c2ecf20Sopenharmony_ci	return NULL;
10818c2ecf20Sopenharmony_ci}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_cistatic int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
10848c2ecf20Sopenharmony_ci				struct ib_qp_init_attr *init_attr)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
10878c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
10888c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
10898c2ecf20Sopenharmony_ci	struct bnxt_qplib_q *rq;
10908c2ecf20Sopenharmony_ci	int entries;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	rdev = qp->rdev;
10938c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
10948c2ecf20Sopenharmony_ci	rq = &qplqp->rq;
10958c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	if (init_attr->srq) {
10988c2ecf20Sopenharmony_ci		struct bnxt_re_srq *srq;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci		srq = container_of(init_attr->srq, struct bnxt_re_srq, ib_srq);
11018c2ecf20Sopenharmony_ci		if (!srq) {
11028c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "SRQ not found");
11038c2ecf20Sopenharmony_ci			return -EINVAL;
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci		qplqp->srq = &srq->qplib_srq;
11068c2ecf20Sopenharmony_ci		rq->max_wqe = 0;
11078c2ecf20Sopenharmony_ci	} else {
11088c2ecf20Sopenharmony_ci		rq->max_sge = init_attr->cap.max_recv_sge;
11098c2ecf20Sopenharmony_ci		if (rq->max_sge > dev_attr->max_qp_sges)
11108c2ecf20Sopenharmony_ci			rq->max_sge = dev_attr->max_qp_sges;
11118c2ecf20Sopenharmony_ci		init_attr->cap.max_recv_sge = rq->max_sge;
11128c2ecf20Sopenharmony_ci		rq->wqe_size = bnxt_re_setup_rwqe_size(qplqp, rq->max_sge,
11138c2ecf20Sopenharmony_ci						       dev_attr->max_qp_sges);
11148c2ecf20Sopenharmony_ci		/* Allocate 1 more than what's provided so posting max doesn't
11158c2ecf20Sopenharmony_ci		 * mean empty.
11168c2ecf20Sopenharmony_ci		 */
11178c2ecf20Sopenharmony_ci		entries = roundup_pow_of_two(init_attr->cap.max_recv_wr + 1);
11188c2ecf20Sopenharmony_ci		rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1);
11198c2ecf20Sopenharmony_ci		rq->q_full_delta = 0;
11208c2ecf20Sopenharmony_ci		rq->sg_info.pgsize = PAGE_SIZE;
11218c2ecf20Sopenharmony_ci		rq->sg_info.pgshft = PAGE_SHIFT;
11228c2ecf20Sopenharmony_ci	}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	return 0;
11258c2ecf20Sopenharmony_ci}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_cistatic void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp)
11288c2ecf20Sopenharmony_ci{
11298c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
11308c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
11318c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	rdev = qp->rdev;
11348c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
11358c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
11388c2ecf20Sopenharmony_ci		qplqp->rq.max_sge = dev_attr->max_qp_sges;
11398c2ecf20Sopenharmony_ci		if (qplqp->rq.max_sge > dev_attr->max_qp_sges)
11408c2ecf20Sopenharmony_ci			qplqp->rq.max_sge = dev_attr->max_qp_sges;
11418c2ecf20Sopenharmony_ci		qplqp->rq.max_sge = 6;
11428c2ecf20Sopenharmony_ci	}
11438c2ecf20Sopenharmony_ci}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_cistatic int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
11468c2ecf20Sopenharmony_ci				struct ib_qp_init_attr *init_attr,
11478c2ecf20Sopenharmony_ci				struct ib_udata *udata)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
11508c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
11518c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
11528c2ecf20Sopenharmony_ci	struct bnxt_qplib_q *sq;
11538c2ecf20Sopenharmony_ci	int entries;
11548c2ecf20Sopenharmony_ci	int diff;
11558c2ecf20Sopenharmony_ci	int rc;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	rdev = qp->rdev;
11588c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
11598c2ecf20Sopenharmony_ci	sq = &qplqp->sq;
11608c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	sq->max_sge = init_attr->cap.max_send_sge;
11638c2ecf20Sopenharmony_ci	if (sq->max_sge > dev_attr->max_qp_sges) {
11648c2ecf20Sopenharmony_ci		sq->max_sge = dev_attr->max_qp_sges;
11658c2ecf20Sopenharmony_ci		init_attr->cap.max_send_sge = sq->max_sge;
11668c2ecf20Sopenharmony_ci	}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	rc = bnxt_re_setup_swqe_size(qp, init_attr);
11698c2ecf20Sopenharmony_ci	if (rc)
11708c2ecf20Sopenharmony_ci		return rc;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	entries = init_attr->cap.max_send_wr;
11738c2ecf20Sopenharmony_ci	/* Allocate 128 + 1 more than what's provided */
11748c2ecf20Sopenharmony_ci	diff = (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ?
11758c2ecf20Sopenharmony_ci		0 : BNXT_QPLIB_RESERVED_QP_WRS;
11768c2ecf20Sopenharmony_ci	entries = roundup_pow_of_two(entries + diff + 1);
11778c2ecf20Sopenharmony_ci	sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1);
11788c2ecf20Sopenharmony_ci	sq->q_full_delta = diff + 1;
11798c2ecf20Sopenharmony_ci	/*
11808c2ecf20Sopenharmony_ci	 * Reserving one slot for Phantom WQE. Application can
11818c2ecf20Sopenharmony_ci	 * post one extra entry in this case. But allowing this to avoid
11828c2ecf20Sopenharmony_ci	 * unexpected Queue full condition
11838c2ecf20Sopenharmony_ci	 */
11848c2ecf20Sopenharmony_ci	qplqp->sq.q_full_delta -= 1;
11858c2ecf20Sopenharmony_ci	qplqp->sq.sg_info.pgsize = PAGE_SIZE;
11868c2ecf20Sopenharmony_ci	qplqp->sq.sg_info.pgshft = PAGE_SHIFT;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	return 0;
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_cistatic void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp,
11928c2ecf20Sopenharmony_ci				       struct ib_qp_init_attr *init_attr)
11938c2ecf20Sopenharmony_ci{
11948c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
11958c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
11968c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
11978c2ecf20Sopenharmony_ci	int entries;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	rdev = qp->rdev;
12008c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
12018c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
12048c2ecf20Sopenharmony_ci		entries = roundup_pow_of_two(init_attr->cap.max_send_wr + 1);
12058c2ecf20Sopenharmony_ci		qplqp->sq.max_wqe = min_t(u32, entries,
12068c2ecf20Sopenharmony_ci					  dev_attr->max_qp_wqes + 1);
12078c2ecf20Sopenharmony_ci		qplqp->sq.q_full_delta = qplqp->sq.max_wqe -
12088c2ecf20Sopenharmony_ci			init_attr->cap.max_send_wr;
12098c2ecf20Sopenharmony_ci		qplqp->sq.max_sge++; /* Need one extra sge to put UD header */
12108c2ecf20Sopenharmony_ci		if (qplqp->sq.max_sge > dev_attr->max_qp_sges)
12118c2ecf20Sopenharmony_ci			qplqp->sq.max_sge = dev_attr->max_qp_sges;
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_cistatic int bnxt_re_init_qp_type(struct bnxt_re_dev *rdev,
12168c2ecf20Sopenharmony_ci				struct ib_qp_init_attr *init_attr)
12178c2ecf20Sopenharmony_ci{
12188c2ecf20Sopenharmony_ci	struct bnxt_qplib_chip_ctx *chip_ctx;
12198c2ecf20Sopenharmony_ci	int qptype;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	chip_ctx = rdev->chip_ctx;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	qptype = __from_ib_qp_type(init_attr->qp_type);
12248c2ecf20Sopenharmony_ci	if (qptype == IB_QPT_MAX) {
12258c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "QP type 0x%x not supported", qptype);
12268c2ecf20Sopenharmony_ci		qptype = -EOPNOTSUPP;
12278c2ecf20Sopenharmony_ci		goto out;
12288c2ecf20Sopenharmony_ci	}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (bnxt_qplib_is_chip_gen_p5(chip_ctx) &&
12318c2ecf20Sopenharmony_ci	    init_attr->qp_type == IB_QPT_GSI)
12328c2ecf20Sopenharmony_ci		qptype = CMDQ_CREATE_QP_TYPE_GSI;
12338c2ecf20Sopenharmony_ciout:
12348c2ecf20Sopenharmony_ci	return qptype;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
12388c2ecf20Sopenharmony_ci				struct ib_qp_init_attr *init_attr,
12398c2ecf20Sopenharmony_ci				struct ib_udata *udata)
12408c2ecf20Sopenharmony_ci{
12418c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
12428c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
12438c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
12448c2ecf20Sopenharmony_ci	struct bnxt_re_cq *cq;
12458c2ecf20Sopenharmony_ci	int rc = 0, qptype;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	rdev = qp->rdev;
12488c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
12498c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	/* Setup misc params */
12528c2ecf20Sopenharmony_ci	ether_addr_copy(qplqp->smac, rdev->netdev->dev_addr);
12538c2ecf20Sopenharmony_ci	qplqp->pd = &pd->qplib_pd;
12548c2ecf20Sopenharmony_ci	qplqp->qp_handle = (u64)qplqp;
12558c2ecf20Sopenharmony_ci	qplqp->max_inline_data = init_attr->cap.max_inline_data;
12568c2ecf20Sopenharmony_ci	qplqp->sig_type = ((init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ?
12578c2ecf20Sopenharmony_ci			    true : false);
12588c2ecf20Sopenharmony_ci	qptype = bnxt_re_init_qp_type(rdev, init_attr);
12598c2ecf20Sopenharmony_ci	if (qptype < 0) {
12608c2ecf20Sopenharmony_ci		rc = qptype;
12618c2ecf20Sopenharmony_ci		goto out;
12628c2ecf20Sopenharmony_ci	}
12638c2ecf20Sopenharmony_ci	qplqp->type = (u8)qptype;
12648c2ecf20Sopenharmony_ci	qplqp->wqe_mode = rdev->chip_ctx->modes.wqe_mode;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_RC) {
12678c2ecf20Sopenharmony_ci		qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom;
12688c2ecf20Sopenharmony_ci		qplqp->max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
12698c2ecf20Sopenharmony_ci	}
12708c2ecf20Sopenharmony_ci	qplqp->mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
12718c2ecf20Sopenharmony_ci	qplqp->dpi = &rdev->dpi_privileged; /* Doorbell page */
12728c2ecf20Sopenharmony_ci	if (init_attr->create_flags)
12738c2ecf20Sopenharmony_ci		ibdev_dbg(&rdev->ibdev,
12748c2ecf20Sopenharmony_ci			  "QP create flags 0x%x not supported",
12758c2ecf20Sopenharmony_ci			  init_attr->create_flags);
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	/* Setup CQs */
12788c2ecf20Sopenharmony_ci	if (init_attr->send_cq) {
12798c2ecf20Sopenharmony_ci		cq = container_of(init_attr->send_cq, struct bnxt_re_cq, ib_cq);
12808c2ecf20Sopenharmony_ci		if (!cq) {
12818c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Send CQ not found");
12828c2ecf20Sopenharmony_ci			rc = -EINVAL;
12838c2ecf20Sopenharmony_ci			goto out;
12848c2ecf20Sopenharmony_ci		}
12858c2ecf20Sopenharmony_ci		qplqp->scq = &cq->qplib_cq;
12868c2ecf20Sopenharmony_ci		qp->scq = cq;
12878c2ecf20Sopenharmony_ci	}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	if (init_attr->recv_cq) {
12908c2ecf20Sopenharmony_ci		cq = container_of(init_attr->recv_cq, struct bnxt_re_cq, ib_cq);
12918c2ecf20Sopenharmony_ci		if (!cq) {
12928c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Receive CQ not found");
12938c2ecf20Sopenharmony_ci			rc = -EINVAL;
12948c2ecf20Sopenharmony_ci			goto out;
12958c2ecf20Sopenharmony_ci		}
12968c2ecf20Sopenharmony_ci		qplqp->rcq = &cq->qplib_cq;
12978c2ecf20Sopenharmony_ci		qp->rcq = cq;
12988c2ecf20Sopenharmony_ci	}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	/* Setup RQ/SRQ */
13018c2ecf20Sopenharmony_ci	rc = bnxt_re_init_rq_attr(qp, init_attr);
13028c2ecf20Sopenharmony_ci	if (rc)
13038c2ecf20Sopenharmony_ci		goto out;
13048c2ecf20Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_GSI)
13058c2ecf20Sopenharmony_ci		bnxt_re_adjust_gsi_rq_attr(qp);
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	/* Setup SQ */
13088c2ecf20Sopenharmony_ci	rc = bnxt_re_init_sq_attr(qp, init_attr, udata);
13098c2ecf20Sopenharmony_ci	if (rc)
13108c2ecf20Sopenharmony_ci		goto out;
13118c2ecf20Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_GSI)
13128c2ecf20Sopenharmony_ci		bnxt_re_adjust_gsi_sq_attr(qp, init_attr);
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	if (udata) /* This will update DPI and qp_handle */
13158c2ecf20Sopenharmony_ci		rc = bnxt_re_init_user_qp(rdev, pd, qp, udata);
13168c2ecf20Sopenharmony_ciout:
13178c2ecf20Sopenharmony_ci	return rc;
13188c2ecf20Sopenharmony_ci}
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_cistatic int bnxt_re_create_shadow_gsi(struct bnxt_re_qp *qp,
13218c2ecf20Sopenharmony_ci				     struct bnxt_re_pd *pd)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_tbl = NULL;
13248c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
13258c2ecf20Sopenharmony_ci	struct bnxt_re_qp *sqp;
13268c2ecf20Sopenharmony_ci	struct bnxt_re_ah *sah;
13278c2ecf20Sopenharmony_ci	int rc = 0;
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	rdev = qp->rdev;
13308c2ecf20Sopenharmony_ci	/* Create a shadow QP to handle the QP1 traffic */
13318c2ecf20Sopenharmony_ci	sqp_tbl = kzalloc(sizeof(*sqp_tbl) * BNXT_RE_MAX_GSI_SQP_ENTRIES,
13328c2ecf20Sopenharmony_ci			  GFP_KERNEL);
13338c2ecf20Sopenharmony_ci	if (!sqp_tbl)
13348c2ecf20Sopenharmony_ci		return -ENOMEM;
13358c2ecf20Sopenharmony_ci	rdev->gsi_ctx.sqp_tbl = sqp_tbl;
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	sqp = bnxt_re_create_shadow_qp(pd, &rdev->qplib_res, &qp->qplib_qp);
13388c2ecf20Sopenharmony_ci	if (!sqp) {
13398c2ecf20Sopenharmony_ci		rc = -ENODEV;
13408c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create Shadow QP for QP1");
13418c2ecf20Sopenharmony_ci		goto out;
13428c2ecf20Sopenharmony_ci	}
13438c2ecf20Sopenharmony_ci	rdev->gsi_ctx.gsi_sqp = sqp;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	sqp->rcq = qp->rcq;
13468c2ecf20Sopenharmony_ci	sqp->scq = qp->scq;
13478c2ecf20Sopenharmony_ci	sah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res,
13488c2ecf20Sopenharmony_ci					  &qp->qplib_qp);
13498c2ecf20Sopenharmony_ci	if (!sah) {
13508c2ecf20Sopenharmony_ci		bnxt_qplib_destroy_qp(&rdev->qplib_res,
13518c2ecf20Sopenharmony_ci				      &sqp->qplib_qp);
13528c2ecf20Sopenharmony_ci		rc = -ENODEV;
13538c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
13548c2ecf20Sopenharmony_ci			  "Failed to create AH entry for ShadowQP");
13558c2ecf20Sopenharmony_ci		goto out;
13568c2ecf20Sopenharmony_ci	}
13578c2ecf20Sopenharmony_ci	rdev->gsi_ctx.gsi_sah = sah;
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	return 0;
13608c2ecf20Sopenharmony_ciout:
13618c2ecf20Sopenharmony_ci	kfree(sqp_tbl);
13628c2ecf20Sopenharmony_ci	return rc;
13638c2ecf20Sopenharmony_ci}
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_cistatic int bnxt_re_create_gsi_qp(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
13668c2ecf20Sopenharmony_ci				 struct ib_qp_init_attr *init_attr)
13678c2ecf20Sopenharmony_ci{
13688c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
13698c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
13708c2ecf20Sopenharmony_ci	int rc = 0;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	rdev = qp->rdev;
13738c2ecf20Sopenharmony_ci	qplqp = &qp->qplib_qp;
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	qplqp->rq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
13768c2ecf20Sopenharmony_ci	qplqp->sq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2;
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_qp1(&rdev->qplib_res, qplqp);
13798c2ecf20Sopenharmony_ci	if (rc) {
13808c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "create HW QP1 failed!");
13818c2ecf20Sopenharmony_ci		goto out;
13828c2ecf20Sopenharmony_ci	}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	rc = bnxt_re_create_shadow_gsi(qp, pd);
13858c2ecf20Sopenharmony_ciout:
13868c2ecf20Sopenharmony_ci	return rc;
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_cistatic bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
13908c2ecf20Sopenharmony_ci				   struct ib_qp_init_attr *init_attr,
13918c2ecf20Sopenharmony_ci				   struct bnxt_qplib_dev_attr *dev_attr)
13928c2ecf20Sopenharmony_ci{
13938c2ecf20Sopenharmony_ci	bool rc = true;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	if (init_attr->cap.max_send_wr > dev_attr->max_qp_wqes ||
13968c2ecf20Sopenharmony_ci	    init_attr->cap.max_recv_wr > dev_attr->max_qp_wqes ||
13978c2ecf20Sopenharmony_ci	    init_attr->cap.max_send_sge > dev_attr->max_qp_sges ||
13988c2ecf20Sopenharmony_ci	    init_attr->cap.max_recv_sge > dev_attr->max_qp_sges ||
13998c2ecf20Sopenharmony_ci	    init_attr->cap.max_inline_data > dev_attr->max_inline_data) {
14008c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
14018c2ecf20Sopenharmony_ci			  "Create QP failed - max exceeded! 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x",
14028c2ecf20Sopenharmony_ci			  init_attr->cap.max_send_wr, dev_attr->max_qp_wqes,
14038c2ecf20Sopenharmony_ci			  init_attr->cap.max_recv_wr, dev_attr->max_qp_wqes,
14048c2ecf20Sopenharmony_ci			  init_attr->cap.max_send_sge, dev_attr->max_qp_sges,
14058c2ecf20Sopenharmony_ci			  init_attr->cap.max_recv_sge, dev_attr->max_qp_sges,
14068c2ecf20Sopenharmony_ci			  init_attr->cap.max_inline_data,
14078c2ecf20Sopenharmony_ci			  dev_attr->max_inline_data);
14088c2ecf20Sopenharmony_ci		rc = false;
14098c2ecf20Sopenharmony_ci	}
14108c2ecf20Sopenharmony_ci	return rc;
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_cistruct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
14148c2ecf20Sopenharmony_ci				struct ib_qp_init_attr *qp_init_attr,
14158c2ecf20Sopenharmony_ci				struct ib_udata *udata)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
14188c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
14198c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
14208c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp;
14218c2ecf20Sopenharmony_ci	int rc;
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
14248c2ecf20Sopenharmony_ci	if (!rc) {
14258c2ecf20Sopenharmony_ci		rc = -EINVAL;
14268c2ecf20Sopenharmony_ci		goto exit;
14278c2ecf20Sopenharmony_ci	}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
14308c2ecf20Sopenharmony_ci	if (!qp) {
14318c2ecf20Sopenharmony_ci		rc = -ENOMEM;
14328c2ecf20Sopenharmony_ci		goto exit;
14338c2ecf20Sopenharmony_ci	}
14348c2ecf20Sopenharmony_ci	qp->rdev = rdev;
14358c2ecf20Sopenharmony_ci	rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
14368c2ecf20Sopenharmony_ci	if (rc)
14378c2ecf20Sopenharmony_ci		goto fail;
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	if (qp_init_attr->qp_type == IB_QPT_GSI &&
14408c2ecf20Sopenharmony_ci	    !(bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx))) {
14418c2ecf20Sopenharmony_ci		rc = bnxt_re_create_gsi_qp(qp, pd, qp_init_attr);
14428c2ecf20Sopenharmony_ci		if (rc == -ENODEV)
14438c2ecf20Sopenharmony_ci			goto qp_destroy;
14448c2ecf20Sopenharmony_ci		if (rc)
14458c2ecf20Sopenharmony_ci			goto fail;
14468c2ecf20Sopenharmony_ci	} else {
14478c2ecf20Sopenharmony_ci		rc = bnxt_qplib_create_qp(&rdev->qplib_res, &qp->qplib_qp);
14488c2ecf20Sopenharmony_ci		if (rc) {
14498c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to create HW QP");
14508c2ecf20Sopenharmony_ci			goto free_umem;
14518c2ecf20Sopenharmony_ci		}
14528c2ecf20Sopenharmony_ci		if (udata) {
14538c2ecf20Sopenharmony_ci			struct bnxt_re_qp_resp resp;
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci			resp.qpid = qp->qplib_qp.id;
14568c2ecf20Sopenharmony_ci			resp.rsvd = 0;
14578c2ecf20Sopenharmony_ci			rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
14588c2ecf20Sopenharmony_ci			if (rc) {
14598c2ecf20Sopenharmony_ci				ibdev_err(&rdev->ibdev, "Failed to copy QP udata");
14608c2ecf20Sopenharmony_ci				goto qp_destroy;
14618c2ecf20Sopenharmony_ci			}
14628c2ecf20Sopenharmony_ci		}
14638c2ecf20Sopenharmony_ci	}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	qp->ib_qp.qp_num = qp->qplib_qp.id;
14668c2ecf20Sopenharmony_ci	if (qp_init_attr->qp_type == IB_QPT_GSI)
14678c2ecf20Sopenharmony_ci		rdev->gsi_ctx.gsi_qp = qp;
14688c2ecf20Sopenharmony_ci	spin_lock_init(&qp->sq_lock);
14698c2ecf20Sopenharmony_ci	spin_lock_init(&qp->rq_lock);
14708c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qp->list);
14718c2ecf20Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
14728c2ecf20Sopenharmony_ci	list_add_tail(&qp->list, &rdev->qp_list);
14738c2ecf20Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
14748c2ecf20Sopenharmony_ci	atomic_inc(&rdev->qp_count);
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci	return &qp->ib_qp;
14778c2ecf20Sopenharmony_ciqp_destroy:
14788c2ecf20Sopenharmony_ci	bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
14798c2ecf20Sopenharmony_cifree_umem:
14808c2ecf20Sopenharmony_ci	ib_umem_release(qp->rumem);
14818c2ecf20Sopenharmony_ci	ib_umem_release(qp->sumem);
14828c2ecf20Sopenharmony_cifail:
14838c2ecf20Sopenharmony_ci	kfree(qp);
14848c2ecf20Sopenharmony_ciexit:
14858c2ecf20Sopenharmony_ci	return ERR_PTR(rc);
14868c2ecf20Sopenharmony_ci}
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_cistatic u8 __from_ib_qp_state(enum ib_qp_state state)
14898c2ecf20Sopenharmony_ci{
14908c2ecf20Sopenharmony_ci	switch (state) {
14918c2ecf20Sopenharmony_ci	case IB_QPS_RESET:
14928c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RESET;
14938c2ecf20Sopenharmony_ci	case IB_QPS_INIT:
14948c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_INIT;
14958c2ecf20Sopenharmony_ci	case IB_QPS_RTR:
14968c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RTR;
14978c2ecf20Sopenharmony_ci	case IB_QPS_RTS:
14988c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RTS;
14998c2ecf20Sopenharmony_ci	case IB_QPS_SQD:
15008c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_SQD;
15018c2ecf20Sopenharmony_ci	case IB_QPS_SQE:
15028c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_SQE;
15038c2ecf20Sopenharmony_ci	case IB_QPS_ERR:
15048c2ecf20Sopenharmony_ci	default:
15058c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_ERR;
15068c2ecf20Sopenharmony_ci	}
15078c2ecf20Sopenharmony_ci}
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_cistatic enum ib_qp_state __to_ib_qp_state(u8 state)
15108c2ecf20Sopenharmony_ci{
15118c2ecf20Sopenharmony_ci	switch (state) {
15128c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RESET:
15138c2ecf20Sopenharmony_ci		return IB_QPS_RESET;
15148c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_INIT:
15158c2ecf20Sopenharmony_ci		return IB_QPS_INIT;
15168c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RTR:
15178c2ecf20Sopenharmony_ci		return IB_QPS_RTR;
15188c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RTS:
15198c2ecf20Sopenharmony_ci		return IB_QPS_RTS;
15208c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_SQD:
15218c2ecf20Sopenharmony_ci		return IB_QPS_SQD;
15228c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_SQE:
15238c2ecf20Sopenharmony_ci		return IB_QPS_SQE;
15248c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_ERR:
15258c2ecf20Sopenharmony_ci	default:
15268c2ecf20Sopenharmony_ci		return IB_QPS_ERR;
15278c2ecf20Sopenharmony_ci	}
15288c2ecf20Sopenharmony_ci}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_cistatic u32 __from_ib_mtu(enum ib_mtu mtu)
15318c2ecf20Sopenharmony_ci{
15328c2ecf20Sopenharmony_ci	switch (mtu) {
15338c2ecf20Sopenharmony_ci	case IB_MTU_256:
15348c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_256;
15358c2ecf20Sopenharmony_ci	case IB_MTU_512:
15368c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_512;
15378c2ecf20Sopenharmony_ci	case IB_MTU_1024:
15388c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_1024;
15398c2ecf20Sopenharmony_ci	case IB_MTU_2048:
15408c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
15418c2ecf20Sopenharmony_ci	case IB_MTU_4096:
15428c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_4096;
15438c2ecf20Sopenharmony_ci	default:
15448c2ecf20Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
15458c2ecf20Sopenharmony_ci	}
15468c2ecf20Sopenharmony_ci}
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_cistatic enum ib_mtu __to_ib_mtu(u32 mtu)
15498c2ecf20Sopenharmony_ci{
15508c2ecf20Sopenharmony_ci	switch (mtu & CREQ_QUERY_QP_RESP_SB_PATH_MTU_MASK) {
15518c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_256:
15528c2ecf20Sopenharmony_ci		return IB_MTU_256;
15538c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_512:
15548c2ecf20Sopenharmony_ci		return IB_MTU_512;
15558c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_1024:
15568c2ecf20Sopenharmony_ci		return IB_MTU_1024;
15578c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_2048:
15588c2ecf20Sopenharmony_ci		return IB_MTU_2048;
15598c2ecf20Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_4096:
15608c2ecf20Sopenharmony_ci		return IB_MTU_4096;
15618c2ecf20Sopenharmony_ci	default:
15628c2ecf20Sopenharmony_ci		return IB_MTU_2048;
15638c2ecf20Sopenharmony_ci	}
15648c2ecf20Sopenharmony_ci}
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci/* Shared Receive Queues */
15678c2ecf20Sopenharmony_ciint bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata)
15688c2ecf20Sopenharmony_ci{
15698c2ecf20Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
15708c2ecf20Sopenharmony_ci					       ib_srq);
15718c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
15728c2ecf20Sopenharmony_ci	struct bnxt_qplib_srq *qplib_srq = &srq->qplib_srq;
15738c2ecf20Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	if (qplib_srq->cq)
15768c2ecf20Sopenharmony_ci		nq = qplib_srq->cq->nq;
15778c2ecf20Sopenharmony_ci	bnxt_qplib_destroy_srq(&rdev->qplib_res, qplib_srq);
15788c2ecf20Sopenharmony_ci	ib_umem_release(srq->umem);
15798c2ecf20Sopenharmony_ci	atomic_dec(&rdev->srq_count);
15808c2ecf20Sopenharmony_ci	if (nq)
15818c2ecf20Sopenharmony_ci		nq->budget--;
15828c2ecf20Sopenharmony_ci	return 0;
15838c2ecf20Sopenharmony_ci}
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_cistatic int bnxt_re_init_user_srq(struct bnxt_re_dev *rdev,
15868c2ecf20Sopenharmony_ci				 struct bnxt_re_pd *pd,
15878c2ecf20Sopenharmony_ci				 struct bnxt_re_srq *srq,
15888c2ecf20Sopenharmony_ci				 struct ib_udata *udata)
15898c2ecf20Sopenharmony_ci{
15908c2ecf20Sopenharmony_ci	struct bnxt_re_srq_req ureq;
15918c2ecf20Sopenharmony_ci	struct bnxt_qplib_srq *qplib_srq = &srq->qplib_srq;
15928c2ecf20Sopenharmony_ci	struct ib_umem *umem;
15938c2ecf20Sopenharmony_ci	int bytes = 0;
15948c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *cntx = rdma_udata_to_drv_context(
15958c2ecf20Sopenharmony_ci		udata, struct bnxt_re_ucontext, ib_uctx);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
15988c2ecf20Sopenharmony_ci		return -EFAULT;
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	bytes = (qplib_srq->max_wqe * qplib_srq->wqe_size);
16018c2ecf20Sopenharmony_ci	bytes = PAGE_ALIGN(bytes);
16028c2ecf20Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, ureq.srqva, bytes,
16038c2ecf20Sopenharmony_ci			   IB_ACCESS_LOCAL_WRITE);
16048c2ecf20Sopenharmony_ci	if (IS_ERR(umem))
16058c2ecf20Sopenharmony_ci		return PTR_ERR(umem);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci	srq->umem = umem;
16088c2ecf20Sopenharmony_ci	qplib_srq->sg_info.umem = umem;
16098c2ecf20Sopenharmony_ci	qplib_srq->sg_info.pgsize = PAGE_SIZE;
16108c2ecf20Sopenharmony_ci	qplib_srq->sg_info.pgshft = PAGE_SHIFT;
16118c2ecf20Sopenharmony_ci	qplib_srq->srq_handle = ureq.srq_handle;
16128c2ecf20Sopenharmony_ci	qplib_srq->dpi = &cntx->dpi;
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	return 0;
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ciint bnxt_re_create_srq(struct ib_srq *ib_srq,
16188c2ecf20Sopenharmony_ci		       struct ib_srq_init_attr *srq_init_attr,
16198c2ecf20Sopenharmony_ci		       struct ib_udata *udata)
16208c2ecf20Sopenharmony_ci{
16218c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
16228c2ecf20Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
16238c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
16248c2ecf20Sopenharmony_ci	struct bnxt_re_srq *srq;
16258c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd;
16268c2ecf20Sopenharmony_ci	struct ib_pd *ib_pd;
16278c2ecf20Sopenharmony_ci	int rc, entries;
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci	ib_pd = ib_srq->pd;
16308c2ecf20Sopenharmony_ci	pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
16318c2ecf20Sopenharmony_ci	rdev = pd->rdev;
16328c2ecf20Sopenharmony_ci	dev_attr = &rdev->dev_attr;
16338c2ecf20Sopenharmony_ci	srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq);
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	if (srq_init_attr->attr.max_wr >= dev_attr->max_srq_wqes) {
16368c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Create CQ failed - max exceeded");
16378c2ecf20Sopenharmony_ci		rc = -EINVAL;
16388c2ecf20Sopenharmony_ci		goto exit;
16398c2ecf20Sopenharmony_ci	}
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
16428c2ecf20Sopenharmony_ci		rc = -EOPNOTSUPP;
16438c2ecf20Sopenharmony_ci		goto exit;
16448c2ecf20Sopenharmony_ci	}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci	srq->rdev = rdev;
16478c2ecf20Sopenharmony_ci	srq->qplib_srq.pd = &pd->qplib_pd;
16488c2ecf20Sopenharmony_ci	srq->qplib_srq.dpi = &rdev->dpi_privileged;
16498c2ecf20Sopenharmony_ci	/* Allocate 1 more than what's provided so posting max doesn't
16508c2ecf20Sopenharmony_ci	 * mean empty
16518c2ecf20Sopenharmony_ci	 */
16528c2ecf20Sopenharmony_ci	entries = roundup_pow_of_two(srq_init_attr->attr.max_wr + 1);
16538c2ecf20Sopenharmony_ci	if (entries > dev_attr->max_srq_wqes + 1)
16548c2ecf20Sopenharmony_ci		entries = dev_attr->max_srq_wqes + 1;
16558c2ecf20Sopenharmony_ci	srq->qplib_srq.max_wqe = entries;
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	srq->qplib_srq.max_sge = srq_init_attr->attr.max_sge;
16588c2ecf20Sopenharmony_ci	 /* 128 byte wqe size for SRQ . So use max sges */
16598c2ecf20Sopenharmony_ci	srq->qplib_srq.wqe_size = bnxt_re_get_rwqe_size(dev_attr->max_srq_sges);
16608c2ecf20Sopenharmony_ci	srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit;
16618c2ecf20Sopenharmony_ci	srq->srq_limit = srq_init_attr->attr.srq_limit;
16628c2ecf20Sopenharmony_ci	srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0].ring_id;
16638c2ecf20Sopenharmony_ci	nq = &rdev->nq[0];
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	if (udata) {
16668c2ecf20Sopenharmony_ci		rc = bnxt_re_init_user_srq(rdev, pd, srq, udata);
16678c2ecf20Sopenharmony_ci		if (rc)
16688c2ecf20Sopenharmony_ci			goto fail;
16698c2ecf20Sopenharmony_ci	}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_srq(&rdev->qplib_res, &srq->qplib_srq);
16728c2ecf20Sopenharmony_ci	if (rc) {
16738c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Create HW SRQ failed!");
16748c2ecf20Sopenharmony_ci		goto fail;
16758c2ecf20Sopenharmony_ci	}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	if (udata) {
16788c2ecf20Sopenharmony_ci		struct bnxt_re_srq_resp resp;
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci		resp.srqid = srq->qplib_srq.id;
16818c2ecf20Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
16828c2ecf20Sopenharmony_ci		if (rc) {
16838c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "SRQ copy to udata failed!");
16848c2ecf20Sopenharmony_ci			bnxt_qplib_destroy_srq(&rdev->qplib_res,
16858c2ecf20Sopenharmony_ci					       &srq->qplib_srq);
16868c2ecf20Sopenharmony_ci			goto fail;
16878c2ecf20Sopenharmony_ci		}
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ci	if (nq)
16908c2ecf20Sopenharmony_ci		nq->budget++;
16918c2ecf20Sopenharmony_ci	atomic_inc(&rdev->srq_count);
16928c2ecf20Sopenharmony_ci	spin_lock_init(&srq->lock);
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	return 0;
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_cifail:
16978c2ecf20Sopenharmony_ci	ib_umem_release(srq->umem);
16988c2ecf20Sopenharmony_ciexit:
16998c2ecf20Sopenharmony_ci	return rc;
17008c2ecf20Sopenharmony_ci}
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ciint bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
17038c2ecf20Sopenharmony_ci		       enum ib_srq_attr_mask srq_attr_mask,
17048c2ecf20Sopenharmony_ci		       struct ib_udata *udata)
17058c2ecf20Sopenharmony_ci{
17068c2ecf20Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
17078c2ecf20Sopenharmony_ci					       ib_srq);
17088c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
17098c2ecf20Sopenharmony_ci	int rc;
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	switch (srq_attr_mask) {
17128c2ecf20Sopenharmony_ci	case IB_SRQ_MAX_WR:
17138c2ecf20Sopenharmony_ci		/* SRQ resize is not supported */
17148c2ecf20Sopenharmony_ci		break;
17158c2ecf20Sopenharmony_ci	case IB_SRQ_LIMIT:
17168c2ecf20Sopenharmony_ci		/* Change the SRQ threshold */
17178c2ecf20Sopenharmony_ci		if (srq_attr->srq_limit > srq->qplib_srq.max_wqe)
17188c2ecf20Sopenharmony_ci			return -EINVAL;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci		srq->qplib_srq.threshold = srq_attr->srq_limit;
17218c2ecf20Sopenharmony_ci		rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq);
17228c2ecf20Sopenharmony_ci		if (rc) {
17238c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Modify HW SRQ failed!");
17248c2ecf20Sopenharmony_ci			return rc;
17258c2ecf20Sopenharmony_ci		}
17268c2ecf20Sopenharmony_ci		/* On success, update the shadow */
17278c2ecf20Sopenharmony_ci		srq->srq_limit = srq_attr->srq_limit;
17288c2ecf20Sopenharmony_ci		/* No need to Build and send response back to udata */
17298c2ecf20Sopenharmony_ci		break;
17308c2ecf20Sopenharmony_ci	default:
17318c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
17328c2ecf20Sopenharmony_ci			  "Unsupported srq_attr_mask 0x%x", srq_attr_mask);
17338c2ecf20Sopenharmony_ci		return -EINVAL;
17348c2ecf20Sopenharmony_ci	}
17358c2ecf20Sopenharmony_ci	return 0;
17368c2ecf20Sopenharmony_ci}
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ciint bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr)
17398c2ecf20Sopenharmony_ci{
17408c2ecf20Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
17418c2ecf20Sopenharmony_ci					       ib_srq);
17428c2ecf20Sopenharmony_ci	struct bnxt_re_srq tsrq;
17438c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
17448c2ecf20Sopenharmony_ci	int rc;
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci	/* Get live SRQ attr */
17478c2ecf20Sopenharmony_ci	tsrq.qplib_srq.id = srq->qplib_srq.id;
17488c2ecf20Sopenharmony_ci	rc = bnxt_qplib_query_srq(&rdev->qplib_res, &tsrq.qplib_srq);
17498c2ecf20Sopenharmony_ci	if (rc) {
17508c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Query HW SRQ failed!");
17518c2ecf20Sopenharmony_ci		return rc;
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci	srq_attr->max_wr = srq->qplib_srq.max_wqe;
17548c2ecf20Sopenharmony_ci	srq_attr->max_sge = srq->qplib_srq.max_sge;
17558c2ecf20Sopenharmony_ci	srq_attr->srq_limit = tsrq.qplib_srq.threshold;
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	return 0;
17588c2ecf20Sopenharmony_ci}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ciint bnxt_re_post_srq_recv(struct ib_srq *ib_srq, const struct ib_recv_wr *wr,
17618c2ecf20Sopenharmony_ci			  const struct ib_recv_wr **bad_wr)
17628c2ecf20Sopenharmony_ci{
17638c2ecf20Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
17648c2ecf20Sopenharmony_ci					       ib_srq);
17658c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
17668c2ecf20Sopenharmony_ci	unsigned long flags;
17678c2ecf20Sopenharmony_ci	int rc = 0;
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	spin_lock_irqsave(&srq->lock, flags);
17708c2ecf20Sopenharmony_ci	while (wr) {
17718c2ecf20Sopenharmony_ci		/* Transcribe each ib_recv_wr to qplib_swqe */
17728c2ecf20Sopenharmony_ci		wqe.num_sge = wr->num_sge;
17738c2ecf20Sopenharmony_ci		bnxt_re_build_sgl(wr->sg_list, wqe.sg_list, wr->num_sge);
17748c2ecf20Sopenharmony_ci		wqe.wr_id = wr->wr_id;
17758c2ecf20Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci		rc = bnxt_qplib_post_srq_recv(&srq->qplib_srq, &wqe);
17788c2ecf20Sopenharmony_ci		if (rc) {
17798c2ecf20Sopenharmony_ci			*bad_wr = wr;
17808c2ecf20Sopenharmony_ci			break;
17818c2ecf20Sopenharmony_ci		}
17828c2ecf20Sopenharmony_ci		wr = wr->next;
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&srq->lock, flags);
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci	return rc;
17878c2ecf20Sopenharmony_ci}
17888c2ecf20Sopenharmony_cistatic int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev,
17898c2ecf20Sopenharmony_ci				    struct bnxt_re_qp *qp1_qp,
17908c2ecf20Sopenharmony_ci				    int qp_attr_mask)
17918c2ecf20Sopenharmony_ci{
17928c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = rdev->gsi_ctx.gsi_sqp;
17938c2ecf20Sopenharmony_ci	int rc = 0;
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_STATE) {
17968c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE;
17978c2ecf20Sopenharmony_ci		qp->qplib_qp.state = qp1_qp->qplib_qp.state;
17988c2ecf20Sopenharmony_ci	}
17998c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_PKEY_INDEX) {
18008c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
18018c2ecf20Sopenharmony_ci		qp->qplib_qp.pkey_index = qp1_qp->qplib_qp.pkey_index;
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_QKEY) {
18058c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
18068c2ecf20Sopenharmony_ci		/* Using a Random  QKEY */
18078c2ecf20Sopenharmony_ci		qp->qplib_qp.qkey = 0x81818181;
18088c2ecf20Sopenharmony_ci	}
18098c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_SQ_PSN) {
18108c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN;
18118c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.psn = qp1_qp->qplib_qp.sq.psn;
18128c2ecf20Sopenharmony_ci	}
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp);
18158c2ecf20Sopenharmony_ci	if (rc)
18168c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to modify Shadow QP for QP1");
18178c2ecf20Sopenharmony_ci	return rc;
18188c2ecf20Sopenharmony_ci}
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ciint bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
18218c2ecf20Sopenharmony_ci		      int qp_attr_mask, struct ib_udata *udata)
18228c2ecf20Sopenharmony_ci{
18238c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
18248c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
18258c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
18268c2ecf20Sopenharmony_ci	enum ib_qp_state curr_qp_state, new_qp_state;
18278c2ecf20Sopenharmony_ci	int rc, entries;
18288c2ecf20Sopenharmony_ci	unsigned int flags;
18298c2ecf20Sopenharmony_ci	u8 nw_type;
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	qp->qplib_qp.modify_flags = 0;
18328c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_STATE) {
18338c2ecf20Sopenharmony_ci		curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state);
18348c2ecf20Sopenharmony_ci		new_qp_state = qp_attr->qp_state;
18358c2ecf20Sopenharmony_ci		if (!ib_modify_qp_is_ok(curr_qp_state, new_qp_state,
18368c2ecf20Sopenharmony_ci					ib_qp->qp_type, qp_attr_mask)) {
18378c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
18388c2ecf20Sopenharmony_ci				  "Invalid attribute mask: %#x specified ",
18398c2ecf20Sopenharmony_ci				  qp_attr_mask);
18408c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
18418c2ecf20Sopenharmony_ci				  "for qpn: %#x type: %#x",
18428c2ecf20Sopenharmony_ci				  ib_qp->qp_num, ib_qp->qp_type);
18438c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
18448c2ecf20Sopenharmony_ci				  "curr_qp_state=0x%x, new_qp_state=0x%x\n",
18458c2ecf20Sopenharmony_ci				  curr_qp_state, new_qp_state);
18468c2ecf20Sopenharmony_ci			return -EINVAL;
18478c2ecf20Sopenharmony_ci		}
18488c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE;
18498c2ecf20Sopenharmony_ci		qp->qplib_qp.state = __from_ib_qp_state(qp_attr->qp_state);
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci		if (!qp->sumem &&
18528c2ecf20Sopenharmony_ci		    qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR) {
18538c2ecf20Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
18548c2ecf20Sopenharmony_ci				  "Move QP = %p to flush list\n", qp);
18558c2ecf20Sopenharmony_ci			flags = bnxt_re_lock_cqs(qp);
18568c2ecf20Sopenharmony_ci			bnxt_qplib_add_flush_qp(&qp->qplib_qp);
18578c2ecf20Sopenharmony_ci			bnxt_re_unlock_cqs(qp, flags);
18588c2ecf20Sopenharmony_ci		}
18598c2ecf20Sopenharmony_ci		if (!qp->sumem &&
18608c2ecf20Sopenharmony_ci		    qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_RESET) {
18618c2ecf20Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
18628c2ecf20Sopenharmony_ci				  "Move QP = %p out of flush list\n", qp);
18638c2ecf20Sopenharmony_ci			flags = bnxt_re_lock_cqs(qp);
18648c2ecf20Sopenharmony_ci			bnxt_qplib_clean_qp(&qp->qplib_qp);
18658c2ecf20Sopenharmony_ci			bnxt_re_unlock_cqs(qp, flags);
18668c2ecf20Sopenharmony_ci		}
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) {
18698c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
18708c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_EN_SQD_ASYNC_NOTIFY;
18718c2ecf20Sopenharmony_ci		qp->qplib_qp.en_sqd_async_notify = true;
18728c2ecf20Sopenharmony_ci	}
18738c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_ACCESS_FLAGS) {
18748c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS;
18758c2ecf20Sopenharmony_ci		qp->qplib_qp.access =
18768c2ecf20Sopenharmony_ci			__from_ib_access_flags(qp_attr->qp_access_flags);
18778c2ecf20Sopenharmony_ci		/* LOCAL_WRITE access must be set to allow RC receive */
18788c2ecf20Sopenharmony_ci		qp->qplib_qp.access |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
18798c2ecf20Sopenharmony_ci		/* Temp: Set all params on QP as of now */
18808c2ecf20Sopenharmony_ci		qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE;
18818c2ecf20Sopenharmony_ci		qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_READ;
18828c2ecf20Sopenharmony_ci	}
18838c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_PKEY_INDEX) {
18848c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
18858c2ecf20Sopenharmony_ci		qp->qplib_qp.pkey_index = qp_attr->pkey_index;
18868c2ecf20Sopenharmony_ci	}
18878c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_QKEY) {
18888c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
18898c2ecf20Sopenharmony_ci		qp->qplib_qp.qkey = qp_attr->qkey;
18908c2ecf20Sopenharmony_ci	}
18918c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_AV) {
18928c2ecf20Sopenharmony_ci		const struct ib_global_route *grh =
18938c2ecf20Sopenharmony_ci			rdma_ah_read_grh(&qp_attr->ah_attr);
18948c2ecf20Sopenharmony_ci		const struct ib_gid_attr *sgid_attr;
18958c2ecf20Sopenharmony_ci		struct bnxt_re_gid_ctx *ctx;
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_DGID |
18988c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_FLOW_LABEL |
18998c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX |
19008c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_HOP_LIMIT |
19018c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_TRAFFIC_CLASS |
19028c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_DEST_MAC |
19038c2ecf20Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID;
19048c2ecf20Sopenharmony_ci		memcpy(qp->qplib_qp.ah.dgid.data, grh->dgid.raw,
19058c2ecf20Sopenharmony_ci		       sizeof(qp->qplib_qp.ah.dgid.data));
19068c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.flow_label = grh->flow_label;
19078c2ecf20Sopenharmony_ci		sgid_attr = grh->sgid_attr;
19088c2ecf20Sopenharmony_ci		/* Get the HW context of the GID. The reference
19098c2ecf20Sopenharmony_ci		 * of GID table entry is already taken by the caller.
19108c2ecf20Sopenharmony_ci		 */
19118c2ecf20Sopenharmony_ci		ctx = rdma_read_gid_hw_context(sgid_attr);
19128c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.sgid_index = ctx->idx;
19138c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.host_sgid_index = grh->sgid_index;
19148c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.hop_limit = grh->hop_limit;
19158c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.traffic_class = grh->traffic_class;
19168c2ecf20Sopenharmony_ci		qp->qplib_qp.ah.sl = rdma_ah_get_sl(&qp_attr->ah_attr);
19178c2ecf20Sopenharmony_ci		ether_addr_copy(qp->qplib_qp.ah.dmac,
19188c2ecf20Sopenharmony_ci				qp_attr->ah_attr.roce.dmac);
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci		rc = rdma_read_gid_l2_fields(sgid_attr, NULL,
19218c2ecf20Sopenharmony_ci					     &qp->qplib_qp.smac[0]);
19228c2ecf20Sopenharmony_ci		if (rc)
19238c2ecf20Sopenharmony_ci			return rc;
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci		nw_type = rdma_gid_attr_network_type(sgid_attr);
19268c2ecf20Sopenharmony_ci		switch (nw_type) {
19278c2ecf20Sopenharmony_ci		case RDMA_NETWORK_IPV4:
19288c2ecf20Sopenharmony_ci			qp->qplib_qp.nw_type =
19298c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV4;
19308c2ecf20Sopenharmony_ci			break;
19318c2ecf20Sopenharmony_ci		case RDMA_NETWORK_IPV6:
19328c2ecf20Sopenharmony_ci			qp->qplib_qp.nw_type =
19338c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV6;
19348c2ecf20Sopenharmony_ci			break;
19358c2ecf20Sopenharmony_ci		default:
19368c2ecf20Sopenharmony_ci			qp->qplib_qp.nw_type =
19378c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV1;
19388c2ecf20Sopenharmony_ci			break;
19398c2ecf20Sopenharmony_ci		}
19408c2ecf20Sopenharmony_ci	}
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_PATH_MTU) {
19438c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19448c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
19458c2ecf20Sopenharmony_ci		qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
19468c2ecf20Sopenharmony_ci		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
19478c2ecf20Sopenharmony_ci	} else if (qp_attr->qp_state == IB_QPS_RTR) {
19488c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19498c2ecf20Sopenharmony_ci			CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
19508c2ecf20Sopenharmony_ci		qp->qplib_qp.path_mtu =
19518c2ecf20Sopenharmony_ci			__from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
19528c2ecf20Sopenharmony_ci		qp->qplib_qp.mtu =
19538c2ecf20Sopenharmony_ci			ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
19548c2ecf20Sopenharmony_ci	}
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_TIMEOUT) {
19578c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_TIMEOUT;
19588c2ecf20Sopenharmony_ci		qp->qplib_qp.timeout = qp_attr->timeout;
19598c2ecf20Sopenharmony_ci	}
19608c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_RETRY_CNT) {
19618c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19628c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RETRY_CNT;
19638c2ecf20Sopenharmony_ci		qp->qplib_qp.retry_cnt = qp_attr->retry_cnt;
19648c2ecf20Sopenharmony_ci	}
19658c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_RNR_RETRY) {
19668c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19678c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RNR_RETRY;
19688c2ecf20Sopenharmony_ci		qp->qplib_qp.rnr_retry = qp_attr->rnr_retry;
19698c2ecf20Sopenharmony_ci	}
19708c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_MIN_RNR_TIMER) {
19718c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19728c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER;
19738c2ecf20Sopenharmony_ci		qp->qplib_qp.min_rnr_timer = qp_attr->min_rnr_timer;
19748c2ecf20Sopenharmony_ci	}
19758c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_RQ_PSN) {
19768c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_RQ_PSN;
19778c2ecf20Sopenharmony_ci		qp->qplib_qp.rq.psn = qp_attr->rq_psn;
19788c2ecf20Sopenharmony_ci	}
19798c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
19808c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
19818c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_RD_ATOMIC;
19828c2ecf20Sopenharmony_ci		/* Cap the max_rd_atomic to device max */
19838c2ecf20Sopenharmony_ci		qp->qplib_qp.max_rd_atomic = min_t(u32, qp_attr->max_rd_atomic,
19848c2ecf20Sopenharmony_ci						   dev_attr->max_qp_rd_atom);
19858c2ecf20Sopenharmony_ci	}
19868c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_SQ_PSN) {
19878c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN;
19888c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.psn = qp_attr->sq_psn;
19898c2ecf20Sopenharmony_ci	}
19908c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
19918c2ecf20Sopenharmony_ci		if (qp_attr->max_dest_rd_atomic >
19928c2ecf20Sopenharmony_ci		    dev_attr->max_qp_init_rd_atom) {
19938c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
19948c2ecf20Sopenharmony_ci				  "max_dest_rd_atomic requested%d is > dev_max%d",
19958c2ecf20Sopenharmony_ci				  qp_attr->max_dest_rd_atomic,
19968c2ecf20Sopenharmony_ci				  dev_attr->max_qp_init_rd_atom);
19978c2ecf20Sopenharmony_ci			return -EINVAL;
19988c2ecf20Sopenharmony_ci		}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
20018c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_DEST_RD_ATOMIC;
20028c2ecf20Sopenharmony_ci		qp->qplib_qp.max_dest_rd_atomic = qp_attr->max_dest_rd_atomic;
20038c2ecf20Sopenharmony_ci	}
20048c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_CAP) {
20058c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
20068c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SIZE |
20078c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SIZE |
20088c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SGE |
20098c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SGE |
20108c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_INLINE_DATA;
20118c2ecf20Sopenharmony_ci		if ((qp_attr->cap.max_send_wr >= dev_attr->max_qp_wqes) ||
20128c2ecf20Sopenharmony_ci		    (qp_attr->cap.max_recv_wr >= dev_attr->max_qp_wqes) ||
20138c2ecf20Sopenharmony_ci		    (qp_attr->cap.max_send_sge >= dev_attr->max_qp_sges) ||
20148c2ecf20Sopenharmony_ci		    (qp_attr->cap.max_recv_sge >= dev_attr->max_qp_sges) ||
20158c2ecf20Sopenharmony_ci		    (qp_attr->cap.max_inline_data >=
20168c2ecf20Sopenharmony_ci						dev_attr->max_inline_data)) {
20178c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
20188c2ecf20Sopenharmony_ci				  "Create QP failed - max exceeded");
20198c2ecf20Sopenharmony_ci			return -EINVAL;
20208c2ecf20Sopenharmony_ci		}
20218c2ecf20Sopenharmony_ci		entries = roundup_pow_of_two(qp_attr->cap.max_send_wr);
20228c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
20238c2ecf20Sopenharmony_ci						dev_attr->max_qp_wqes + 1);
20248c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
20258c2ecf20Sopenharmony_ci						qp_attr->cap.max_send_wr;
20268c2ecf20Sopenharmony_ci		/*
20278c2ecf20Sopenharmony_ci		 * Reserving one slot for Phantom WQE. Some application can
20288c2ecf20Sopenharmony_ci		 * post one extra entry in this case. Allowing this to avoid
20298c2ecf20Sopenharmony_ci		 * unexpected Queue full condition
20308c2ecf20Sopenharmony_ci		 */
20318c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.q_full_delta -= 1;
20328c2ecf20Sopenharmony_ci		qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge;
20338c2ecf20Sopenharmony_ci		if (qp->qplib_qp.rq.max_wqe) {
20348c2ecf20Sopenharmony_ci			entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr);
20358c2ecf20Sopenharmony_ci			qp->qplib_qp.rq.max_wqe =
20368c2ecf20Sopenharmony_ci				min_t(u32, entries, dev_attr->max_qp_wqes + 1);
20378c2ecf20Sopenharmony_ci			qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
20388c2ecf20Sopenharmony_ci						       qp_attr->cap.max_recv_wr;
20398c2ecf20Sopenharmony_ci			qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
20408c2ecf20Sopenharmony_ci		} else {
20418c2ecf20Sopenharmony_ci			/* SRQ was used prior, just ignore the RQ caps */
20428c2ecf20Sopenharmony_ci		}
20438c2ecf20Sopenharmony_ci	}
20448c2ecf20Sopenharmony_ci	if (qp_attr_mask & IB_QP_DEST_QPN) {
20458c2ecf20Sopenharmony_ci		qp->qplib_qp.modify_flags |=
20468c2ecf20Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID;
20478c2ecf20Sopenharmony_ci		qp->qplib_qp.dest_qpn = qp_attr->dest_qp_num;
20488c2ecf20Sopenharmony_ci	}
20498c2ecf20Sopenharmony_ci	rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp);
20508c2ecf20Sopenharmony_ci	if (rc) {
20518c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to modify HW QP");
20528c2ecf20Sopenharmony_ci		return rc;
20538c2ecf20Sopenharmony_ci	}
20548c2ecf20Sopenharmony_ci	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp)
20558c2ecf20Sopenharmony_ci		rc = bnxt_re_modify_shadow_qp(rdev, qp, qp_attr_mask);
20568c2ecf20Sopenharmony_ci	return rc;
20578c2ecf20Sopenharmony_ci}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ciint bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
20608c2ecf20Sopenharmony_ci		     int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
20618c2ecf20Sopenharmony_ci{
20628c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
20638c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
20648c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *qplib_qp;
20658c2ecf20Sopenharmony_ci	int rc;
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	qplib_qp = kzalloc(sizeof(*qplib_qp), GFP_KERNEL);
20688c2ecf20Sopenharmony_ci	if (!qplib_qp)
20698c2ecf20Sopenharmony_ci		return -ENOMEM;
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	qplib_qp->id = qp->qplib_qp.id;
20728c2ecf20Sopenharmony_ci	qplib_qp->ah.host_sgid_index = qp->qplib_qp.ah.host_sgid_index;
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	rc = bnxt_qplib_query_qp(&rdev->qplib_res, qplib_qp);
20758c2ecf20Sopenharmony_ci	if (rc) {
20768c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to query HW QP");
20778c2ecf20Sopenharmony_ci		goto out;
20788c2ecf20Sopenharmony_ci	}
20798c2ecf20Sopenharmony_ci	qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state);
20808c2ecf20Sopenharmony_ci	qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state);
20818c2ecf20Sopenharmony_ci	qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0;
20828c2ecf20Sopenharmony_ci	qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access);
20838c2ecf20Sopenharmony_ci	qp_attr->pkey_index = qplib_qp->pkey_index;
20848c2ecf20Sopenharmony_ci	qp_attr->qkey = qplib_qp->qkey;
20858c2ecf20Sopenharmony_ci	qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
20868c2ecf20Sopenharmony_ci	rdma_ah_set_grh(&qp_attr->ah_attr, NULL, qplib_qp->ah.flow_label,
20878c2ecf20Sopenharmony_ci			qplib_qp->ah.host_sgid_index,
20888c2ecf20Sopenharmony_ci			qplib_qp->ah.hop_limit,
20898c2ecf20Sopenharmony_ci			qplib_qp->ah.traffic_class);
20908c2ecf20Sopenharmony_ci	rdma_ah_set_dgid_raw(&qp_attr->ah_attr, qplib_qp->ah.dgid.data);
20918c2ecf20Sopenharmony_ci	rdma_ah_set_sl(&qp_attr->ah_attr, qplib_qp->ah.sl);
20928c2ecf20Sopenharmony_ci	ether_addr_copy(qp_attr->ah_attr.roce.dmac, qplib_qp->ah.dmac);
20938c2ecf20Sopenharmony_ci	qp_attr->path_mtu = __to_ib_mtu(qplib_qp->path_mtu);
20948c2ecf20Sopenharmony_ci	qp_attr->timeout = qplib_qp->timeout;
20958c2ecf20Sopenharmony_ci	qp_attr->retry_cnt = qplib_qp->retry_cnt;
20968c2ecf20Sopenharmony_ci	qp_attr->rnr_retry = qplib_qp->rnr_retry;
20978c2ecf20Sopenharmony_ci	qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer;
20988c2ecf20Sopenharmony_ci	qp_attr->rq_psn = qplib_qp->rq.psn;
20998c2ecf20Sopenharmony_ci	qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic;
21008c2ecf20Sopenharmony_ci	qp_attr->sq_psn = qplib_qp->sq.psn;
21018c2ecf20Sopenharmony_ci	qp_attr->max_dest_rd_atomic = qplib_qp->max_dest_rd_atomic;
21028c2ecf20Sopenharmony_ci	qp_init_attr->sq_sig_type = qplib_qp->sig_type ? IB_SIGNAL_ALL_WR :
21038c2ecf20Sopenharmony_ci							 IB_SIGNAL_REQ_WR;
21048c2ecf20Sopenharmony_ci	qp_attr->dest_qp_num = qplib_qp->dest_qpn;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	qp_attr->cap.max_send_wr = qp->qplib_qp.sq.max_wqe;
21078c2ecf20Sopenharmony_ci	qp_attr->cap.max_send_sge = qp->qplib_qp.sq.max_sge;
21088c2ecf20Sopenharmony_ci	qp_attr->cap.max_recv_wr = qp->qplib_qp.rq.max_wqe;
21098c2ecf20Sopenharmony_ci	qp_attr->cap.max_recv_sge = qp->qplib_qp.rq.max_sge;
21108c2ecf20Sopenharmony_ci	qp_attr->cap.max_inline_data = qp->qplib_qp.max_inline_data;
21118c2ecf20Sopenharmony_ci	qp_init_attr->cap = qp_attr->cap;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ciout:
21148c2ecf20Sopenharmony_ci	kfree(qplib_qp);
21158c2ecf20Sopenharmony_ci	return rc;
21168c2ecf20Sopenharmony_ci}
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci/* Routine for sending QP1 packets for RoCE V1 an V2
21198c2ecf20Sopenharmony_ci */
21208c2ecf20Sopenharmony_cistatic int bnxt_re_build_qp1_send_v2(struct bnxt_re_qp *qp,
21218c2ecf20Sopenharmony_ci				     const struct ib_send_wr *wr,
21228c2ecf20Sopenharmony_ci				     struct bnxt_qplib_swqe *wqe,
21238c2ecf20Sopenharmony_ci				     int payload_size)
21248c2ecf20Sopenharmony_ci{
21258c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ud_wr(wr)->ah, struct bnxt_re_ah,
21268c2ecf20Sopenharmony_ci					     ib_ah);
21278c2ecf20Sopenharmony_ci	struct bnxt_qplib_ah *qplib_ah = &ah->qplib_ah;
21288c2ecf20Sopenharmony_ci	const struct ib_gid_attr *sgid_attr = ah->ib_ah.sgid_attr;
21298c2ecf20Sopenharmony_ci	struct bnxt_qplib_sge sge;
21308c2ecf20Sopenharmony_ci	u8 nw_type;
21318c2ecf20Sopenharmony_ci	u16 ether_type;
21328c2ecf20Sopenharmony_ci	union ib_gid dgid;
21338c2ecf20Sopenharmony_ci	bool is_eth = false;
21348c2ecf20Sopenharmony_ci	bool is_vlan = false;
21358c2ecf20Sopenharmony_ci	bool is_grh = false;
21368c2ecf20Sopenharmony_ci	bool is_udp = false;
21378c2ecf20Sopenharmony_ci	u8 ip_version = 0;
21388c2ecf20Sopenharmony_ci	u16 vlan_id = 0xFFFF;
21398c2ecf20Sopenharmony_ci	void *buf;
21408c2ecf20Sopenharmony_ci	int i, rc = 0;
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr));
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
21458c2ecf20Sopenharmony_ci	if (rc)
21468c2ecf20Sopenharmony_ci		return rc;
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	/* Get network header type for this GID */
21498c2ecf20Sopenharmony_ci	nw_type = rdma_gid_attr_network_type(sgid_attr);
21508c2ecf20Sopenharmony_ci	switch (nw_type) {
21518c2ecf20Sopenharmony_ci	case RDMA_NETWORK_IPV4:
21528c2ecf20Sopenharmony_ci		nw_type = BNXT_RE_ROCEV2_IPV4_PACKET;
21538c2ecf20Sopenharmony_ci		break;
21548c2ecf20Sopenharmony_ci	case RDMA_NETWORK_IPV6:
21558c2ecf20Sopenharmony_ci		nw_type = BNXT_RE_ROCEV2_IPV6_PACKET;
21568c2ecf20Sopenharmony_ci		break;
21578c2ecf20Sopenharmony_ci	default:
21588c2ecf20Sopenharmony_ci		nw_type = BNXT_RE_ROCE_V1_PACKET;
21598c2ecf20Sopenharmony_ci		break;
21608c2ecf20Sopenharmony_ci	}
21618c2ecf20Sopenharmony_ci	memcpy(&dgid.raw, &qplib_ah->dgid, 16);
21628c2ecf20Sopenharmony_ci	is_udp = sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP;
21638c2ecf20Sopenharmony_ci	if (is_udp) {
21648c2ecf20Sopenharmony_ci		if (ipv6_addr_v4mapped((struct in6_addr *)&sgid_attr->gid)) {
21658c2ecf20Sopenharmony_ci			ip_version = 4;
21668c2ecf20Sopenharmony_ci			ether_type = ETH_P_IP;
21678c2ecf20Sopenharmony_ci		} else {
21688c2ecf20Sopenharmony_ci			ip_version = 6;
21698c2ecf20Sopenharmony_ci			ether_type = ETH_P_IPV6;
21708c2ecf20Sopenharmony_ci		}
21718c2ecf20Sopenharmony_ci		is_grh = false;
21728c2ecf20Sopenharmony_ci	} else {
21738c2ecf20Sopenharmony_ci		ether_type = ETH_P_IBOE;
21748c2ecf20Sopenharmony_ci		is_grh = true;
21758c2ecf20Sopenharmony_ci	}
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci	is_eth = true;
21788c2ecf20Sopenharmony_ci	is_vlan = (vlan_id && (vlan_id < 0x1000)) ? true : false;
21798c2ecf20Sopenharmony_ci
21808c2ecf20Sopenharmony_ci	ib_ud_header_init(payload_size, !is_eth, is_eth, is_vlan, is_grh,
21818c2ecf20Sopenharmony_ci			  ip_version, is_udp, 0, &qp->qp1_hdr);
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	/* ETH */
21848c2ecf20Sopenharmony_ci	ether_addr_copy(qp->qp1_hdr.eth.dmac_h, ah->qplib_ah.dmac);
21858c2ecf20Sopenharmony_ci	ether_addr_copy(qp->qp1_hdr.eth.smac_h, qp->qplib_qp.smac);
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci	/* For vlan, check the sgid for vlan existence */
21888c2ecf20Sopenharmony_ci
21898c2ecf20Sopenharmony_ci	if (!is_vlan) {
21908c2ecf20Sopenharmony_ci		qp->qp1_hdr.eth.type = cpu_to_be16(ether_type);
21918c2ecf20Sopenharmony_ci	} else {
21928c2ecf20Sopenharmony_ci		qp->qp1_hdr.vlan.type = cpu_to_be16(ether_type);
21938c2ecf20Sopenharmony_ci		qp->qp1_hdr.vlan.tag = cpu_to_be16(vlan_id);
21948c2ecf20Sopenharmony_ci	}
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	if (is_grh || (ip_version == 6)) {
21978c2ecf20Sopenharmony_ci		memcpy(qp->qp1_hdr.grh.source_gid.raw, sgid_attr->gid.raw,
21988c2ecf20Sopenharmony_ci		       sizeof(sgid_attr->gid));
21998c2ecf20Sopenharmony_ci		memcpy(qp->qp1_hdr.grh.destination_gid.raw, qplib_ah->dgid.data,
22008c2ecf20Sopenharmony_ci		       sizeof(sgid_attr->gid));
22018c2ecf20Sopenharmony_ci		qp->qp1_hdr.grh.hop_limit     = qplib_ah->hop_limit;
22028c2ecf20Sopenharmony_ci	}
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci	if (ip_version == 4) {
22058c2ecf20Sopenharmony_ci		qp->qp1_hdr.ip4.tos = 0;
22068c2ecf20Sopenharmony_ci		qp->qp1_hdr.ip4.id = 0;
22078c2ecf20Sopenharmony_ci		qp->qp1_hdr.ip4.frag_off = htons(IP_DF);
22088c2ecf20Sopenharmony_ci		qp->qp1_hdr.ip4.ttl = qplib_ah->hop_limit;
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci		memcpy(&qp->qp1_hdr.ip4.saddr, sgid_attr->gid.raw + 12, 4);
22118c2ecf20Sopenharmony_ci		memcpy(&qp->qp1_hdr.ip4.daddr, qplib_ah->dgid.data + 12, 4);
22128c2ecf20Sopenharmony_ci		qp->qp1_hdr.ip4.check = ib_ud_ip4_csum(&qp->qp1_hdr);
22138c2ecf20Sopenharmony_ci	}
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	if (is_udp) {
22168c2ecf20Sopenharmony_ci		qp->qp1_hdr.udp.dport = htons(ROCE_V2_UDP_DPORT);
22178c2ecf20Sopenharmony_ci		qp->qp1_hdr.udp.sport = htons(0x8CD1);
22188c2ecf20Sopenharmony_ci		qp->qp1_hdr.udp.csum = 0;
22198c2ecf20Sopenharmony_ci	}
22208c2ecf20Sopenharmony_ci
22218c2ecf20Sopenharmony_ci	/* BTH */
22228c2ecf20Sopenharmony_ci	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
22238c2ecf20Sopenharmony_ci		qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
22248c2ecf20Sopenharmony_ci		qp->qp1_hdr.immediate_present = 1;
22258c2ecf20Sopenharmony_ci	} else {
22268c2ecf20Sopenharmony_ci		qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
22278c2ecf20Sopenharmony_ci	}
22288c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
22298c2ecf20Sopenharmony_ci		qp->qp1_hdr.bth.solicited_event = 1;
22308c2ecf20Sopenharmony_ci	/* pad_count */
22318c2ecf20Sopenharmony_ci	qp->qp1_hdr.bth.pad_count = (4 - payload_size) & 3;
22328c2ecf20Sopenharmony_ci
22338c2ecf20Sopenharmony_ci	/* P_key for QP1 is for all members */
22348c2ecf20Sopenharmony_ci	qp->qp1_hdr.bth.pkey = cpu_to_be16(0xFFFF);
22358c2ecf20Sopenharmony_ci	qp->qp1_hdr.bth.destination_qpn = IB_QP1;
22368c2ecf20Sopenharmony_ci	qp->qp1_hdr.bth.ack_req = 0;
22378c2ecf20Sopenharmony_ci	qp->send_psn++;
22388c2ecf20Sopenharmony_ci	qp->send_psn &= BTH_PSN_MASK;
22398c2ecf20Sopenharmony_ci	qp->qp1_hdr.bth.psn = cpu_to_be32(qp->send_psn);
22408c2ecf20Sopenharmony_ci	/* DETH */
22418c2ecf20Sopenharmony_ci	/* Use the priviledged Q_Key for QP1 */
22428c2ecf20Sopenharmony_ci	qp->qp1_hdr.deth.qkey = cpu_to_be32(IB_QP1_QKEY);
22438c2ecf20Sopenharmony_ci	qp->qp1_hdr.deth.source_qpn = IB_QP1;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci	/* Pack the QP1 to the transmit buffer */
22468c2ecf20Sopenharmony_ci	buf = bnxt_qplib_get_qp1_sq_buf(&qp->qplib_qp, &sge);
22478c2ecf20Sopenharmony_ci	if (buf) {
22488c2ecf20Sopenharmony_ci		ib_ud_header_pack(&qp->qp1_hdr, buf);
22498c2ecf20Sopenharmony_ci		for (i = wqe->num_sge; i; i--) {
22508c2ecf20Sopenharmony_ci			wqe->sg_list[i].addr = wqe->sg_list[i - 1].addr;
22518c2ecf20Sopenharmony_ci			wqe->sg_list[i].lkey = wqe->sg_list[i - 1].lkey;
22528c2ecf20Sopenharmony_ci			wqe->sg_list[i].size = wqe->sg_list[i - 1].size;
22538c2ecf20Sopenharmony_ci		}
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci		/*
22568c2ecf20Sopenharmony_ci		 * Max Header buf size for IPV6 RoCE V2 is 86,
22578c2ecf20Sopenharmony_ci		 * which is same as the QP1 SQ header buffer.
22588c2ecf20Sopenharmony_ci		 * Header buf size for IPV4 RoCE V2 can be 66.
22598c2ecf20Sopenharmony_ci		 * ETH(14) + VLAN(4)+ IP(20) + UDP (8) + BTH(20).
22608c2ecf20Sopenharmony_ci		 * Subtract 20 bytes from QP1 SQ header buf size
22618c2ecf20Sopenharmony_ci		 */
22628c2ecf20Sopenharmony_ci		if (is_udp && ip_version == 4)
22638c2ecf20Sopenharmony_ci			sge.size -= 20;
22648c2ecf20Sopenharmony_ci		/*
22658c2ecf20Sopenharmony_ci		 * Max Header buf size for RoCE V1 is 78.
22668c2ecf20Sopenharmony_ci		 * ETH(14) + VLAN(4) + GRH(40) + BTH(20).
22678c2ecf20Sopenharmony_ci		 * Subtract 8 bytes from QP1 SQ header buf size
22688c2ecf20Sopenharmony_ci		 */
22698c2ecf20Sopenharmony_ci		if (!is_udp)
22708c2ecf20Sopenharmony_ci			sge.size -= 8;
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci		/* Subtract 4 bytes for non vlan packets */
22738c2ecf20Sopenharmony_ci		if (!is_vlan)
22748c2ecf20Sopenharmony_ci			sge.size -= 4;
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci		wqe->sg_list[0].addr = sge.addr;
22778c2ecf20Sopenharmony_ci		wqe->sg_list[0].lkey = sge.lkey;
22788c2ecf20Sopenharmony_ci		wqe->sg_list[0].size = sge.size;
22798c2ecf20Sopenharmony_ci		wqe->num_sge++;
22808c2ecf20Sopenharmony_ci
22818c2ecf20Sopenharmony_ci	} else {
22828c2ecf20Sopenharmony_ci		ibdev_err(&qp->rdev->ibdev, "QP1 buffer is empty!");
22838c2ecf20Sopenharmony_ci		rc = -ENOMEM;
22848c2ecf20Sopenharmony_ci	}
22858c2ecf20Sopenharmony_ci	return rc;
22868c2ecf20Sopenharmony_ci}
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci/* For the MAD layer, it only provides the recv SGE the size of
22898c2ecf20Sopenharmony_ci * ib_grh + MAD datagram.  No Ethernet headers, Ethertype, BTH, DETH,
22908c2ecf20Sopenharmony_ci * nor RoCE iCRC.  The Cu+ solution must provide buffer for the entire
22918c2ecf20Sopenharmony_ci * receive packet (334 bytes) with no VLAN and then copy the GRH
22928c2ecf20Sopenharmony_ci * and the MAD datagram out to the provided SGE.
22938c2ecf20Sopenharmony_ci */
22948c2ecf20Sopenharmony_cistatic int bnxt_re_build_qp1_shadow_qp_recv(struct bnxt_re_qp *qp,
22958c2ecf20Sopenharmony_ci					    const struct ib_recv_wr *wr,
22968c2ecf20Sopenharmony_ci					    struct bnxt_qplib_swqe *wqe,
22978c2ecf20Sopenharmony_ci					    int payload_size)
22988c2ecf20Sopenharmony_ci{
22998c2ecf20Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry;
23008c2ecf20Sopenharmony_ci	struct bnxt_qplib_sge ref, sge;
23018c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
23028c2ecf20Sopenharmony_ci	u32 rq_prod_index;
23038c2ecf20Sopenharmony_ci
23048c2ecf20Sopenharmony_ci	rdev = qp->rdev;
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	rq_prod_index = bnxt_qplib_get_rq_prod_index(&qp->qplib_qp);
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	if (!bnxt_qplib_get_qp1_rq_buf(&qp->qplib_qp, &sge))
23098c2ecf20Sopenharmony_ci		return -ENOMEM;
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci	/* Create 1 SGE to receive the entire
23128c2ecf20Sopenharmony_ci	 * ethernet packet
23138c2ecf20Sopenharmony_ci	 */
23148c2ecf20Sopenharmony_ci	/* Save the reference from ULP */
23158c2ecf20Sopenharmony_ci	ref.addr = wqe->sg_list[0].addr;
23168c2ecf20Sopenharmony_ci	ref.lkey = wqe->sg_list[0].lkey;
23178c2ecf20Sopenharmony_ci	ref.size = wqe->sg_list[0].size;
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[rq_prod_index];
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	/* SGE 1 */
23228c2ecf20Sopenharmony_ci	wqe->sg_list[0].addr = sge.addr;
23238c2ecf20Sopenharmony_ci	wqe->sg_list[0].lkey = sge.lkey;
23248c2ecf20Sopenharmony_ci	wqe->sg_list[0].size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
23258c2ecf20Sopenharmony_ci	sge.size -= wqe->sg_list[0].size;
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	sqp_entry->sge.addr = ref.addr;
23288c2ecf20Sopenharmony_ci	sqp_entry->sge.lkey = ref.lkey;
23298c2ecf20Sopenharmony_ci	sqp_entry->sge.size = ref.size;
23308c2ecf20Sopenharmony_ci	/* Store the wrid for reporting completion */
23318c2ecf20Sopenharmony_ci	sqp_entry->wrid = wqe->wr_id;
23328c2ecf20Sopenharmony_ci	/* change the wqe->wrid to table index */
23338c2ecf20Sopenharmony_ci	wqe->wr_id = rq_prod_index;
23348c2ecf20Sopenharmony_ci	return 0;
23358c2ecf20Sopenharmony_ci}
23368c2ecf20Sopenharmony_ci
23378c2ecf20Sopenharmony_cistatic int is_ud_qp(struct bnxt_re_qp *qp)
23388c2ecf20Sopenharmony_ci{
23398c2ecf20Sopenharmony_ci	return (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD ||
23408c2ecf20Sopenharmony_ci		qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_GSI);
23418c2ecf20Sopenharmony_ci}
23428c2ecf20Sopenharmony_ci
23438c2ecf20Sopenharmony_cistatic int bnxt_re_build_send_wqe(struct bnxt_re_qp *qp,
23448c2ecf20Sopenharmony_ci				  const struct ib_send_wr *wr,
23458c2ecf20Sopenharmony_ci				  struct bnxt_qplib_swqe *wqe)
23468c2ecf20Sopenharmony_ci{
23478c2ecf20Sopenharmony_ci	struct bnxt_re_ah *ah = NULL;
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	if (is_ud_qp(qp)) {
23508c2ecf20Sopenharmony_ci		ah = container_of(ud_wr(wr)->ah, struct bnxt_re_ah, ib_ah);
23518c2ecf20Sopenharmony_ci		wqe->send.q_key = ud_wr(wr)->remote_qkey;
23528c2ecf20Sopenharmony_ci		wqe->send.dst_qp = ud_wr(wr)->remote_qpn;
23538c2ecf20Sopenharmony_ci		wqe->send.avid = ah->qplib_ah.id;
23548c2ecf20Sopenharmony_ci	}
23558c2ecf20Sopenharmony_ci	switch (wr->opcode) {
23568c2ecf20Sopenharmony_ci	case IB_WR_SEND:
23578c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND;
23588c2ecf20Sopenharmony_ci		break;
23598c2ecf20Sopenharmony_ci	case IB_WR_SEND_WITH_IMM:
23608c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM;
23618c2ecf20Sopenharmony_ci		wqe->send.imm_data = wr->ex.imm_data;
23628c2ecf20Sopenharmony_ci		break;
23638c2ecf20Sopenharmony_ci	case IB_WR_SEND_WITH_INV:
23648c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV;
23658c2ecf20Sopenharmony_ci		wqe->send.inv_key = wr->ex.invalidate_rkey;
23668c2ecf20Sopenharmony_ci		break;
23678c2ecf20Sopenharmony_ci	default:
23688c2ecf20Sopenharmony_ci		return -EINVAL;
23698c2ecf20Sopenharmony_ci	}
23708c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
23718c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
23728c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
23738c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
23748c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
23758c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
23768c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
23778c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE;
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	return 0;
23808c2ecf20Sopenharmony_ci}
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_cistatic int bnxt_re_build_rdma_wqe(const struct ib_send_wr *wr,
23838c2ecf20Sopenharmony_ci				  struct bnxt_qplib_swqe *wqe)
23848c2ecf20Sopenharmony_ci{
23858c2ecf20Sopenharmony_ci	switch (wr->opcode) {
23868c2ecf20Sopenharmony_ci	case IB_WR_RDMA_WRITE:
23878c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE;
23888c2ecf20Sopenharmony_ci		break;
23898c2ecf20Sopenharmony_ci	case IB_WR_RDMA_WRITE_WITH_IMM:
23908c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM;
23918c2ecf20Sopenharmony_ci		wqe->rdma.imm_data = wr->ex.imm_data;
23928c2ecf20Sopenharmony_ci		break;
23938c2ecf20Sopenharmony_ci	case IB_WR_RDMA_READ:
23948c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_READ;
23958c2ecf20Sopenharmony_ci		wqe->rdma.inv_key = wr->ex.invalidate_rkey;
23968c2ecf20Sopenharmony_ci		break;
23978c2ecf20Sopenharmony_ci	default:
23988c2ecf20Sopenharmony_ci		return -EINVAL;
23998c2ecf20Sopenharmony_ci	}
24008c2ecf20Sopenharmony_ci	wqe->rdma.remote_va = rdma_wr(wr)->remote_addr;
24018c2ecf20Sopenharmony_ci	wqe->rdma.r_key = rdma_wr(wr)->rkey;
24028c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
24038c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
24048c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
24058c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
24068c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
24078c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
24088c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
24098c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE;
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci	return 0;
24128c2ecf20Sopenharmony_ci}
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_cistatic int bnxt_re_build_atomic_wqe(const struct ib_send_wr *wr,
24158c2ecf20Sopenharmony_ci				    struct bnxt_qplib_swqe *wqe)
24168c2ecf20Sopenharmony_ci{
24178c2ecf20Sopenharmony_ci	switch (wr->opcode) {
24188c2ecf20Sopenharmony_ci	case IB_WR_ATOMIC_CMP_AND_SWP:
24198c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP;
24208c2ecf20Sopenharmony_ci		wqe->atomic.cmp_data = atomic_wr(wr)->compare_add;
24218c2ecf20Sopenharmony_ci		wqe->atomic.swap_data = atomic_wr(wr)->swap;
24228c2ecf20Sopenharmony_ci		break;
24238c2ecf20Sopenharmony_ci	case IB_WR_ATOMIC_FETCH_AND_ADD:
24248c2ecf20Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD;
24258c2ecf20Sopenharmony_ci		wqe->atomic.cmp_data = atomic_wr(wr)->compare_add;
24268c2ecf20Sopenharmony_ci		break;
24278c2ecf20Sopenharmony_ci	default:
24288c2ecf20Sopenharmony_ci		return -EINVAL;
24298c2ecf20Sopenharmony_ci	}
24308c2ecf20Sopenharmony_ci	wqe->atomic.remote_va = atomic_wr(wr)->remote_addr;
24318c2ecf20Sopenharmony_ci	wqe->atomic.r_key = atomic_wr(wr)->rkey;
24328c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
24338c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
24348c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
24358c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
24368c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
24378c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
24388c2ecf20Sopenharmony_ci	return 0;
24398c2ecf20Sopenharmony_ci}
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_cistatic int bnxt_re_build_inv_wqe(const struct ib_send_wr *wr,
24428c2ecf20Sopenharmony_ci				 struct bnxt_qplib_swqe *wqe)
24438c2ecf20Sopenharmony_ci{
24448c2ecf20Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_LOCAL_INV;
24458c2ecf20Sopenharmony_ci	wqe->local_inv.inv_l_key = wr->ex.invalidate_rkey;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci	/* Need unconditional fence for local invalidate
24488c2ecf20Sopenharmony_ci	 * opcode to work as expected.
24498c2ecf20Sopenharmony_ci	 */
24508c2ecf20Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
24538c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
24548c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
24558c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci	return 0;
24588c2ecf20Sopenharmony_ci}
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_cistatic int bnxt_re_build_reg_wqe(const struct ib_reg_wr *wr,
24618c2ecf20Sopenharmony_ci				 struct bnxt_qplib_swqe *wqe)
24628c2ecf20Sopenharmony_ci{
24638c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(wr->mr, struct bnxt_re_mr, ib_mr);
24648c2ecf20Sopenharmony_ci	struct bnxt_qplib_frpl *qplib_frpl = &mr->qplib_frpl;
24658c2ecf20Sopenharmony_ci	int access = wr->access;
24668c2ecf20Sopenharmony_ci
24678c2ecf20Sopenharmony_ci	wqe->frmr.pbl_ptr = (__le64 *)qplib_frpl->hwq.pbl_ptr[0];
24688c2ecf20Sopenharmony_ci	wqe->frmr.pbl_dma_ptr = qplib_frpl->hwq.pbl_dma_ptr[0];
24698c2ecf20Sopenharmony_ci	wqe->frmr.page_list = mr->pages;
24708c2ecf20Sopenharmony_ci	wqe->frmr.page_list_len = mr->npages;
24718c2ecf20Sopenharmony_ci	wqe->frmr.levels = qplib_frpl->hwq.level;
24728c2ecf20Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_REG_MR;
24738c2ecf20Sopenharmony_ci
24748c2ecf20Sopenharmony_ci	/* Need unconditional fence for reg_mr
24758c2ecf20Sopenharmony_ci	 * opcode to function as expected.
24768c2ecf20Sopenharmony_ci	 */
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
24798c2ecf20Sopenharmony_ci
24808c2ecf20Sopenharmony_ci	if (wr->wr.send_flags & IB_SEND_SIGNALED)
24818c2ecf20Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
24828c2ecf20Sopenharmony_ci
24838c2ecf20Sopenharmony_ci	if (access & IB_ACCESS_LOCAL_WRITE)
24848c2ecf20Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_LOCAL_WRITE;
24858c2ecf20Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_READ)
24868c2ecf20Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_READ;
24878c2ecf20Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_WRITE)
24888c2ecf20Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_WRITE;
24898c2ecf20Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_ATOMIC)
24908c2ecf20Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_ATOMIC;
24918c2ecf20Sopenharmony_ci	if (access & IB_ACCESS_MW_BIND)
24928c2ecf20Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_WINDOW_BIND;
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	wqe->frmr.l_key = wr->key;
24958c2ecf20Sopenharmony_ci	wqe->frmr.length = wr->mr->length;
24968c2ecf20Sopenharmony_ci	wqe->frmr.pbl_pg_sz_log = (wr->mr->page_size >> PAGE_SHIFT_4K) - 1;
24978c2ecf20Sopenharmony_ci	wqe->frmr.va = wr->mr->iova;
24988c2ecf20Sopenharmony_ci	return 0;
24998c2ecf20Sopenharmony_ci}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_cistatic int bnxt_re_copy_inline_data(struct bnxt_re_dev *rdev,
25028c2ecf20Sopenharmony_ci				    const struct ib_send_wr *wr,
25038c2ecf20Sopenharmony_ci				    struct bnxt_qplib_swqe *wqe)
25048c2ecf20Sopenharmony_ci{
25058c2ecf20Sopenharmony_ci	/*  Copy the inline data to the data  field */
25068c2ecf20Sopenharmony_ci	u8 *in_data;
25078c2ecf20Sopenharmony_ci	u32 i, sge_len;
25088c2ecf20Sopenharmony_ci	void *sge_addr;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	in_data = wqe->inline_data;
25118c2ecf20Sopenharmony_ci	for (i = 0; i < wr->num_sge; i++) {
25128c2ecf20Sopenharmony_ci		sge_addr = (void *)(unsigned long)
25138c2ecf20Sopenharmony_ci				wr->sg_list[i].addr;
25148c2ecf20Sopenharmony_ci		sge_len = wr->sg_list[i].length;
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci		if ((sge_len + wqe->inline_len) >
25178c2ecf20Sopenharmony_ci		    BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH) {
25188c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
25198c2ecf20Sopenharmony_ci				  "Inline data size requested > supported value");
25208c2ecf20Sopenharmony_ci			return -EINVAL;
25218c2ecf20Sopenharmony_ci		}
25228c2ecf20Sopenharmony_ci		sge_len = wr->sg_list[i].length;
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci		memcpy(in_data, sge_addr, sge_len);
25258c2ecf20Sopenharmony_ci		in_data += wr->sg_list[i].length;
25268c2ecf20Sopenharmony_ci		wqe->inline_len += wr->sg_list[i].length;
25278c2ecf20Sopenharmony_ci	}
25288c2ecf20Sopenharmony_ci	return wqe->inline_len;
25298c2ecf20Sopenharmony_ci}
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_cistatic int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev,
25328c2ecf20Sopenharmony_ci				   const struct ib_send_wr *wr,
25338c2ecf20Sopenharmony_ci				   struct bnxt_qplib_swqe *wqe)
25348c2ecf20Sopenharmony_ci{
25358c2ecf20Sopenharmony_ci	int payload_sz = 0;
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
25388c2ecf20Sopenharmony_ci		payload_sz = bnxt_re_copy_inline_data(rdev, wr, wqe);
25398c2ecf20Sopenharmony_ci	else
25408c2ecf20Sopenharmony_ci		payload_sz = bnxt_re_build_sgl(wr->sg_list, wqe->sg_list,
25418c2ecf20Sopenharmony_ci					       wqe->num_sge);
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_ci	return payload_sz;
25448c2ecf20Sopenharmony_ci}
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_cistatic void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp)
25478c2ecf20Sopenharmony_ci{
25488c2ecf20Sopenharmony_ci	if ((qp->ib_qp.qp_type == IB_QPT_UD ||
25498c2ecf20Sopenharmony_ci	     qp->ib_qp.qp_type == IB_QPT_GSI ||
25508c2ecf20Sopenharmony_ci	     qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) &&
25518c2ecf20Sopenharmony_ci	     qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) {
25528c2ecf20Sopenharmony_ci		int qp_attr_mask;
25538c2ecf20Sopenharmony_ci		struct ib_qp_attr qp_attr;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci		qp_attr_mask = IB_QP_STATE;
25568c2ecf20Sopenharmony_ci		qp_attr.qp_state = IB_QPS_RTS;
25578c2ecf20Sopenharmony_ci		bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL);
25588c2ecf20Sopenharmony_ci		qp->qplib_qp.wqe_cnt = 0;
25598c2ecf20Sopenharmony_ci	}
25608c2ecf20Sopenharmony_ci}
25618c2ecf20Sopenharmony_ci
25628c2ecf20Sopenharmony_cistatic int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
25638c2ecf20Sopenharmony_ci				       struct bnxt_re_qp *qp,
25648c2ecf20Sopenharmony_ci				       const struct ib_send_wr *wr)
25658c2ecf20Sopenharmony_ci{
25668c2ecf20Sopenharmony_ci	int rc = 0, payload_sz = 0;
25678c2ecf20Sopenharmony_ci	unsigned long flags;
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
25708c2ecf20Sopenharmony_ci	while (wr) {
25718c2ecf20Sopenharmony_ci		struct bnxt_qplib_swqe wqe = {};
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci		/* Common */
25748c2ecf20Sopenharmony_ci		wqe.num_sge = wr->num_sge;
25758c2ecf20Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.sq.max_sge) {
25768c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
25778c2ecf20Sopenharmony_ci				  "Limit exceeded for Send SGEs");
25788c2ecf20Sopenharmony_ci			rc = -EINVAL;
25798c2ecf20Sopenharmony_ci			goto bad;
25808c2ecf20Sopenharmony_ci		}
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci		payload_sz = bnxt_re_copy_wr_payload(qp->rdev, wr, &wqe);
25838c2ecf20Sopenharmony_ci		if (payload_sz < 0) {
25848c2ecf20Sopenharmony_ci			rc = -EINVAL;
25858c2ecf20Sopenharmony_ci			goto bad;
25868c2ecf20Sopenharmony_ci		}
25878c2ecf20Sopenharmony_ci		wqe.wr_id = wr->wr_id;
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_SEND;
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci		rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
25928c2ecf20Sopenharmony_ci		if (!rc)
25938c2ecf20Sopenharmony_ci			rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
25948c2ecf20Sopenharmony_cibad:
25958c2ecf20Sopenharmony_ci		if (rc) {
25968c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
25978c2ecf20Sopenharmony_ci				  "Post send failed opcode = %#x rc = %d",
25988c2ecf20Sopenharmony_ci				  wr->opcode, rc);
25998c2ecf20Sopenharmony_ci			break;
26008c2ecf20Sopenharmony_ci		}
26018c2ecf20Sopenharmony_ci		wr = wr->next;
26028c2ecf20Sopenharmony_ci	}
26038c2ecf20Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
26048c2ecf20Sopenharmony_ci	bnxt_ud_qp_hw_stall_workaround(qp);
26058c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
26068c2ecf20Sopenharmony_ci	return rc;
26078c2ecf20Sopenharmony_ci}
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ciint bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
26108c2ecf20Sopenharmony_ci		      const struct ib_send_wr **bad_wr)
26118c2ecf20Sopenharmony_ci{
26128c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
26138c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
26148c2ecf20Sopenharmony_ci	int rc = 0, payload_sz = 0;
26158c2ecf20Sopenharmony_ci	unsigned long flags;
26168c2ecf20Sopenharmony_ci
26178c2ecf20Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
26188c2ecf20Sopenharmony_ci	while (wr) {
26198c2ecf20Sopenharmony_ci		/* House keeping */
26208c2ecf20Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ci		/* Common */
26238c2ecf20Sopenharmony_ci		wqe.num_sge = wr->num_sge;
26248c2ecf20Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.sq.max_sge) {
26258c2ecf20Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
26268c2ecf20Sopenharmony_ci				  "Limit exceeded for Send SGEs");
26278c2ecf20Sopenharmony_ci			rc = -EINVAL;
26288c2ecf20Sopenharmony_ci			goto bad;
26298c2ecf20Sopenharmony_ci		}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_ci		payload_sz = bnxt_re_copy_wr_payload(qp->rdev, wr, &wqe);
26328c2ecf20Sopenharmony_ci		if (payload_sz < 0) {
26338c2ecf20Sopenharmony_ci			rc = -EINVAL;
26348c2ecf20Sopenharmony_ci			goto bad;
26358c2ecf20Sopenharmony_ci		}
26368c2ecf20Sopenharmony_ci		wqe.wr_id = wr->wr_id;
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci		switch (wr->opcode) {
26398c2ecf20Sopenharmony_ci		case IB_WR_SEND:
26408c2ecf20Sopenharmony_ci		case IB_WR_SEND_WITH_IMM:
26418c2ecf20Sopenharmony_ci			if (qp->qplib_qp.type == CMDQ_CREATE_QP1_TYPE_GSI) {
26428c2ecf20Sopenharmony_ci				rc = bnxt_re_build_qp1_send_v2(qp, wr, &wqe,
26438c2ecf20Sopenharmony_ci							       payload_sz);
26448c2ecf20Sopenharmony_ci				if (rc)
26458c2ecf20Sopenharmony_ci					goto bad;
26468c2ecf20Sopenharmony_ci				wqe.rawqp1.lflags |=
26478c2ecf20Sopenharmony_ci					SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
26488c2ecf20Sopenharmony_ci			}
26498c2ecf20Sopenharmony_ci			switch (wr->send_flags) {
26508c2ecf20Sopenharmony_ci			case IB_SEND_IP_CSUM:
26518c2ecf20Sopenharmony_ci				wqe.rawqp1.lflags |=
26528c2ecf20Sopenharmony_ci					SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
26538c2ecf20Sopenharmony_ci				break;
26548c2ecf20Sopenharmony_ci			default:
26558c2ecf20Sopenharmony_ci				break;
26568c2ecf20Sopenharmony_ci			}
26578c2ecf20Sopenharmony_ci			fallthrough;
26588c2ecf20Sopenharmony_ci		case IB_WR_SEND_WITH_INV:
26598c2ecf20Sopenharmony_ci			rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
26608c2ecf20Sopenharmony_ci			break;
26618c2ecf20Sopenharmony_ci		case IB_WR_RDMA_WRITE:
26628c2ecf20Sopenharmony_ci		case IB_WR_RDMA_WRITE_WITH_IMM:
26638c2ecf20Sopenharmony_ci		case IB_WR_RDMA_READ:
26648c2ecf20Sopenharmony_ci			rc = bnxt_re_build_rdma_wqe(wr, &wqe);
26658c2ecf20Sopenharmony_ci			break;
26668c2ecf20Sopenharmony_ci		case IB_WR_ATOMIC_CMP_AND_SWP:
26678c2ecf20Sopenharmony_ci		case IB_WR_ATOMIC_FETCH_AND_ADD:
26688c2ecf20Sopenharmony_ci			rc = bnxt_re_build_atomic_wqe(wr, &wqe);
26698c2ecf20Sopenharmony_ci			break;
26708c2ecf20Sopenharmony_ci		case IB_WR_RDMA_READ_WITH_INV:
26718c2ecf20Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
26728c2ecf20Sopenharmony_ci				  "RDMA Read with Invalidate is not supported");
26738c2ecf20Sopenharmony_ci			rc = -EINVAL;
26748c2ecf20Sopenharmony_ci			goto bad;
26758c2ecf20Sopenharmony_ci		case IB_WR_LOCAL_INV:
26768c2ecf20Sopenharmony_ci			rc = bnxt_re_build_inv_wqe(wr, &wqe);
26778c2ecf20Sopenharmony_ci			break;
26788c2ecf20Sopenharmony_ci		case IB_WR_REG_MR:
26798c2ecf20Sopenharmony_ci			rc = bnxt_re_build_reg_wqe(reg_wr(wr), &wqe);
26808c2ecf20Sopenharmony_ci			break;
26818c2ecf20Sopenharmony_ci		default:
26828c2ecf20Sopenharmony_ci			/* Unsupported WRs */
26838c2ecf20Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
26848c2ecf20Sopenharmony_ci				  "WR (%#x) is not supported", wr->opcode);
26858c2ecf20Sopenharmony_ci			rc = -EINVAL;
26868c2ecf20Sopenharmony_ci			goto bad;
26878c2ecf20Sopenharmony_ci		}
26888c2ecf20Sopenharmony_ci		if (!rc)
26898c2ecf20Sopenharmony_ci			rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
26908c2ecf20Sopenharmony_cibad:
26918c2ecf20Sopenharmony_ci		if (rc) {
26928c2ecf20Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
26938c2ecf20Sopenharmony_ci				  "post_send failed op:%#x qps = %#x rc = %d\n",
26948c2ecf20Sopenharmony_ci				  wr->opcode, qp->qplib_qp.state, rc);
26958c2ecf20Sopenharmony_ci			*bad_wr = wr;
26968c2ecf20Sopenharmony_ci			break;
26978c2ecf20Sopenharmony_ci		}
26988c2ecf20Sopenharmony_ci		wr = wr->next;
26998c2ecf20Sopenharmony_ci	}
27008c2ecf20Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
27018c2ecf20Sopenharmony_ci	bnxt_ud_qp_hw_stall_workaround(qp);
27028c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	return rc;
27058c2ecf20Sopenharmony_ci}
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_cistatic int bnxt_re_post_recv_shadow_qp(struct bnxt_re_dev *rdev,
27088c2ecf20Sopenharmony_ci				       struct bnxt_re_qp *qp,
27098c2ecf20Sopenharmony_ci				       const struct ib_recv_wr *wr)
27108c2ecf20Sopenharmony_ci{
27118c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
27128c2ecf20Sopenharmony_ci	int rc = 0;
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_ci	memset(&wqe, 0, sizeof(wqe));
27158c2ecf20Sopenharmony_ci	while (wr) {
27168c2ecf20Sopenharmony_ci		/* House keeping */
27178c2ecf20Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci		/* Common */
27208c2ecf20Sopenharmony_ci		wqe.num_sge = wr->num_sge;
27218c2ecf20Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.rq.max_sge) {
27228c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev,
27238c2ecf20Sopenharmony_ci				  "Limit exceeded for Receive SGEs");
27248c2ecf20Sopenharmony_ci			rc = -EINVAL;
27258c2ecf20Sopenharmony_ci			break;
27268c2ecf20Sopenharmony_ci		}
27278c2ecf20Sopenharmony_ci		bnxt_re_build_sgl(wr->sg_list, wqe.sg_list, wr->num_sge);
27288c2ecf20Sopenharmony_ci		wqe.wr_id = wr->wr_id;
27298c2ecf20Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_ci		rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe);
27328c2ecf20Sopenharmony_ci		if (rc)
27338c2ecf20Sopenharmony_ci			break;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci		wr = wr->next;
27368c2ecf20Sopenharmony_ci	}
27378c2ecf20Sopenharmony_ci	if (!rc)
27388c2ecf20Sopenharmony_ci		bnxt_qplib_post_recv_db(&qp->qplib_qp);
27398c2ecf20Sopenharmony_ci	return rc;
27408c2ecf20Sopenharmony_ci}
27418c2ecf20Sopenharmony_ci
27428c2ecf20Sopenharmony_ciint bnxt_re_post_recv(struct ib_qp *ib_qp, const struct ib_recv_wr *wr,
27438c2ecf20Sopenharmony_ci		      const struct ib_recv_wr **bad_wr)
27448c2ecf20Sopenharmony_ci{
27458c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
27468c2ecf20Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
27478c2ecf20Sopenharmony_ci	int rc = 0, payload_sz = 0;
27488c2ecf20Sopenharmony_ci	unsigned long flags;
27498c2ecf20Sopenharmony_ci	u32 count = 0;
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci	spin_lock_irqsave(&qp->rq_lock, flags);
27528c2ecf20Sopenharmony_ci	while (wr) {
27538c2ecf20Sopenharmony_ci		/* House keeping */
27548c2ecf20Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_ci		/* Common */
27578c2ecf20Sopenharmony_ci		wqe.num_sge = wr->num_sge;
27588c2ecf20Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.rq.max_sge) {
27598c2ecf20Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
27608c2ecf20Sopenharmony_ci				  "Limit exceeded for Receive SGEs");
27618c2ecf20Sopenharmony_ci			rc = -EINVAL;
27628c2ecf20Sopenharmony_ci			*bad_wr = wr;
27638c2ecf20Sopenharmony_ci			break;
27648c2ecf20Sopenharmony_ci		}
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ci		payload_sz = bnxt_re_build_sgl(wr->sg_list, wqe.sg_list,
27678c2ecf20Sopenharmony_ci					       wr->num_sge);
27688c2ecf20Sopenharmony_ci		wqe.wr_id = wr->wr_id;
27698c2ecf20Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci		if (ib_qp->qp_type == IB_QPT_GSI &&
27728c2ecf20Sopenharmony_ci		    qp->qplib_qp.type != CMDQ_CREATE_QP_TYPE_GSI)
27738c2ecf20Sopenharmony_ci			rc = bnxt_re_build_qp1_shadow_qp_recv(qp, wr, &wqe,
27748c2ecf20Sopenharmony_ci							      payload_sz);
27758c2ecf20Sopenharmony_ci		if (!rc)
27768c2ecf20Sopenharmony_ci			rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe);
27778c2ecf20Sopenharmony_ci		if (rc) {
27788c2ecf20Sopenharmony_ci			*bad_wr = wr;
27798c2ecf20Sopenharmony_ci			break;
27808c2ecf20Sopenharmony_ci		}
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci		/* Ring DB if the RQEs posted reaches a threshold value */
27838c2ecf20Sopenharmony_ci		if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) {
27848c2ecf20Sopenharmony_ci			bnxt_qplib_post_recv_db(&qp->qplib_qp);
27858c2ecf20Sopenharmony_ci			count = 0;
27868c2ecf20Sopenharmony_ci		}
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci		wr = wr->next;
27898c2ecf20Sopenharmony_ci	}
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci	if (count)
27928c2ecf20Sopenharmony_ci		bnxt_qplib_post_recv_db(&qp->qplib_qp);
27938c2ecf20Sopenharmony_ci
27948c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&qp->rq_lock, flags);
27958c2ecf20Sopenharmony_ci
27968c2ecf20Sopenharmony_ci	return rc;
27978c2ecf20Sopenharmony_ci}
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci/* Completion Queues */
28008c2ecf20Sopenharmony_ciint bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
28018c2ecf20Sopenharmony_ci{
28028c2ecf20Sopenharmony_ci	struct bnxt_re_cq *cq;
28038c2ecf20Sopenharmony_ci	struct bnxt_qplib_nq *nq;
28048c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
28078c2ecf20Sopenharmony_ci	rdev = cq->rdev;
28088c2ecf20Sopenharmony_ci	nq = cq->qplib_cq.nq;
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci	bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
28118c2ecf20Sopenharmony_ci	ib_umem_release(cq->umem);
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci	atomic_dec(&rdev->cq_count);
28148c2ecf20Sopenharmony_ci	nq->budget--;
28158c2ecf20Sopenharmony_ci	kfree(cq->cql);
28168c2ecf20Sopenharmony_ci	return 0;
28178c2ecf20Sopenharmony_ci}
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ciint bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
28208c2ecf20Sopenharmony_ci		      struct ib_udata *udata)
28218c2ecf20Sopenharmony_ci{
28228c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibcq->device, ibdev);
28238c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
28248c2ecf20Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ibcq, struct bnxt_re_cq, ib_cq);
28258c2ecf20Sopenharmony_ci	int rc, entries;
28268c2ecf20Sopenharmony_ci	int cqe = attr->cqe;
28278c2ecf20Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
28288c2ecf20Sopenharmony_ci	unsigned int nq_alloc_cnt;
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci	/* Validate CQ fields */
28318c2ecf20Sopenharmony_ci	if (cqe < 1 || cqe > dev_attr->max_cq_wqes) {
28328c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create CQ -max exceeded");
28338c2ecf20Sopenharmony_ci		return -EINVAL;
28348c2ecf20Sopenharmony_ci	}
28358c2ecf20Sopenharmony_ci
28368c2ecf20Sopenharmony_ci	cq->rdev = rdev;
28378c2ecf20Sopenharmony_ci	cq->qplib_cq.cq_handle = (u64)(unsigned long)(&cq->qplib_cq);
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	entries = roundup_pow_of_two(cqe + 1);
28408c2ecf20Sopenharmony_ci	if (entries > dev_attr->max_cq_wqes + 1)
28418c2ecf20Sopenharmony_ci		entries = dev_attr->max_cq_wqes + 1;
28428c2ecf20Sopenharmony_ci
28438c2ecf20Sopenharmony_ci	cq->qplib_cq.sg_info.pgsize = PAGE_SIZE;
28448c2ecf20Sopenharmony_ci	cq->qplib_cq.sg_info.pgshft = PAGE_SHIFT;
28458c2ecf20Sopenharmony_ci	if (udata) {
28468c2ecf20Sopenharmony_ci		struct bnxt_re_cq_req req;
28478c2ecf20Sopenharmony_ci		struct bnxt_re_ucontext *uctx = rdma_udata_to_drv_context(
28488c2ecf20Sopenharmony_ci			udata, struct bnxt_re_ucontext, ib_uctx);
28498c2ecf20Sopenharmony_ci		if (ib_copy_from_udata(&req, udata, sizeof(req))) {
28508c2ecf20Sopenharmony_ci			rc = -EFAULT;
28518c2ecf20Sopenharmony_ci			goto fail;
28528c2ecf20Sopenharmony_ci		}
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci		cq->umem = ib_umem_get(&rdev->ibdev, req.cq_va,
28558c2ecf20Sopenharmony_ci				       entries * sizeof(struct cq_base),
28568c2ecf20Sopenharmony_ci				       IB_ACCESS_LOCAL_WRITE);
28578c2ecf20Sopenharmony_ci		if (IS_ERR(cq->umem)) {
28588c2ecf20Sopenharmony_ci			rc = PTR_ERR(cq->umem);
28598c2ecf20Sopenharmony_ci			goto fail;
28608c2ecf20Sopenharmony_ci		}
28618c2ecf20Sopenharmony_ci		cq->qplib_cq.sg_info.umem = cq->umem;
28628c2ecf20Sopenharmony_ci		cq->qplib_cq.dpi = &uctx->dpi;
28638c2ecf20Sopenharmony_ci	} else {
28648c2ecf20Sopenharmony_ci		cq->max_cql = min_t(u32, entries, MAX_CQL_PER_POLL);
28658c2ecf20Sopenharmony_ci		cq->cql = kcalloc(cq->max_cql, sizeof(struct bnxt_qplib_cqe),
28668c2ecf20Sopenharmony_ci				  GFP_KERNEL);
28678c2ecf20Sopenharmony_ci		if (!cq->cql) {
28688c2ecf20Sopenharmony_ci			rc = -ENOMEM;
28698c2ecf20Sopenharmony_ci			goto fail;
28708c2ecf20Sopenharmony_ci		}
28718c2ecf20Sopenharmony_ci
28728c2ecf20Sopenharmony_ci		cq->qplib_cq.dpi = &rdev->dpi_privileged;
28738c2ecf20Sopenharmony_ci	}
28748c2ecf20Sopenharmony_ci	/*
28758c2ecf20Sopenharmony_ci	 * Allocating the NQ in a round robin fashion. nq_alloc_cnt is a
28768c2ecf20Sopenharmony_ci	 * used for getting the NQ index.
28778c2ecf20Sopenharmony_ci	 */
28788c2ecf20Sopenharmony_ci	nq_alloc_cnt = atomic_inc_return(&rdev->nq_alloc_cnt);
28798c2ecf20Sopenharmony_ci	nq = &rdev->nq[nq_alloc_cnt % (rdev->num_msix - 1)];
28808c2ecf20Sopenharmony_ci	cq->qplib_cq.max_wqe = entries;
28818c2ecf20Sopenharmony_ci	cq->qplib_cq.cnq_hw_ring_id = nq->ring_id;
28828c2ecf20Sopenharmony_ci	cq->qplib_cq.nq	= nq;
28838c2ecf20Sopenharmony_ci
28848c2ecf20Sopenharmony_ci	rc = bnxt_qplib_create_cq(&rdev->qplib_res, &cq->qplib_cq);
28858c2ecf20Sopenharmony_ci	if (rc) {
28868c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create HW CQ");
28878c2ecf20Sopenharmony_ci		goto fail;
28888c2ecf20Sopenharmony_ci	}
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci	cq->ib_cq.cqe = entries;
28918c2ecf20Sopenharmony_ci	cq->cq_period = cq->qplib_cq.period;
28928c2ecf20Sopenharmony_ci	nq->budget++;
28938c2ecf20Sopenharmony_ci
28948c2ecf20Sopenharmony_ci	atomic_inc(&rdev->cq_count);
28958c2ecf20Sopenharmony_ci	spin_lock_init(&cq->cq_lock);
28968c2ecf20Sopenharmony_ci
28978c2ecf20Sopenharmony_ci	if (udata) {
28988c2ecf20Sopenharmony_ci		struct bnxt_re_cq_resp resp;
28998c2ecf20Sopenharmony_ci
29008c2ecf20Sopenharmony_ci		resp.cqid = cq->qplib_cq.id;
29018c2ecf20Sopenharmony_ci		resp.tail = cq->qplib_cq.hwq.cons;
29028c2ecf20Sopenharmony_ci		resp.phase = cq->qplib_cq.period;
29038c2ecf20Sopenharmony_ci		resp.rsvd = 0;
29048c2ecf20Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
29058c2ecf20Sopenharmony_ci		if (rc) {
29068c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to copy CQ udata");
29078c2ecf20Sopenharmony_ci			bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
29088c2ecf20Sopenharmony_ci			goto c2fail;
29098c2ecf20Sopenharmony_ci		}
29108c2ecf20Sopenharmony_ci	}
29118c2ecf20Sopenharmony_ci
29128c2ecf20Sopenharmony_ci	return 0;
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_cic2fail:
29158c2ecf20Sopenharmony_ci	ib_umem_release(cq->umem);
29168c2ecf20Sopenharmony_cifail:
29178c2ecf20Sopenharmony_ci	kfree(cq->cql);
29188c2ecf20Sopenharmony_ci	return rc;
29198c2ecf20Sopenharmony_ci}
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_cistatic u8 __req_to_ib_wc_status(u8 qstatus)
29228c2ecf20Sopenharmony_ci{
29238c2ecf20Sopenharmony_ci	switch (qstatus) {
29248c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_OK:
29258c2ecf20Sopenharmony_ci		return IB_WC_SUCCESS;
29268c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_BAD_RESPONSE_ERR:
29278c2ecf20Sopenharmony_ci		return IB_WC_BAD_RESP_ERR;
29288c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_LENGTH_ERR:
29298c2ecf20Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
29308c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_QP_OPERATION_ERR:
29318c2ecf20Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
29328c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_PROTECTION_ERR:
29338c2ecf20Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
29348c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_MEMORY_MGT_OPERATION_ERR:
29358c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
29368c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_INVALID_REQUEST_ERR:
29378c2ecf20Sopenharmony_ci		return IB_WC_REM_INV_REQ_ERR;
29388c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_ACCESS_ERR:
29398c2ecf20Sopenharmony_ci		return IB_WC_REM_ACCESS_ERR;
29408c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_OPERATION_ERR:
29418c2ecf20Sopenharmony_ci		return IB_WC_REM_OP_ERR;
29428c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_RNR_NAK_RETRY_CNT_ERR:
29438c2ecf20Sopenharmony_ci		return IB_WC_RNR_RETRY_EXC_ERR;
29448c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_TRANSPORT_RETRY_CNT_ERR:
29458c2ecf20Sopenharmony_ci		return IB_WC_RETRY_EXC_ERR;
29468c2ecf20Sopenharmony_ci	case CQ_REQ_STATUS_WORK_REQUEST_FLUSHED_ERR:
29478c2ecf20Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
29488c2ecf20Sopenharmony_ci	default:
29498c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
29508c2ecf20Sopenharmony_ci	}
29518c2ecf20Sopenharmony_ci	return 0;
29528c2ecf20Sopenharmony_ci}
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_cistatic u8 __rawqp1_to_ib_wc_status(u8 qstatus)
29558c2ecf20Sopenharmony_ci{
29568c2ecf20Sopenharmony_ci	switch (qstatus) {
29578c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_OK:
29588c2ecf20Sopenharmony_ci		return IB_WC_SUCCESS;
29598c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_ACCESS_ERROR:
29608c2ecf20Sopenharmony_ci		return IB_WC_LOC_ACCESS_ERR;
29618c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_HW_LOCAL_LENGTH_ERR:
29628c2ecf20Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
29638c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_PROTECTION_ERR:
29648c2ecf20Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
29658c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_QP_OPERATION_ERR:
29668c2ecf20Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
29678c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_MEMORY_MGT_OPERATION_ERR:
29688c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
29698c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_WORK_REQUEST_FLUSHED_ERR:
29708c2ecf20Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
29718c2ecf20Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_HW_FLUSH_ERR:
29728c2ecf20Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
29738c2ecf20Sopenharmony_ci	default:
29748c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
29758c2ecf20Sopenharmony_ci	}
29768c2ecf20Sopenharmony_ci}
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_cistatic u8 __rc_to_ib_wc_status(u8 qstatus)
29798c2ecf20Sopenharmony_ci{
29808c2ecf20Sopenharmony_ci	switch (qstatus) {
29818c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_OK:
29828c2ecf20Sopenharmony_ci		return IB_WC_SUCCESS;
29838c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_ACCESS_ERROR:
29848c2ecf20Sopenharmony_ci		return IB_WC_LOC_ACCESS_ERR;
29858c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_LENGTH_ERR:
29868c2ecf20Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
29878c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_PROTECTION_ERR:
29888c2ecf20Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
29898c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_QP_OPERATION_ERR:
29908c2ecf20Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
29918c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_MEMORY_MGT_OPERATION_ERR:
29928c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
29938c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_REMOTE_INVALID_REQUEST_ERR:
29948c2ecf20Sopenharmony_ci		return IB_WC_REM_INV_REQ_ERR;
29958c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_WORK_REQUEST_FLUSHED_ERR:
29968c2ecf20Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
29978c2ecf20Sopenharmony_ci	case CQ_RES_RC_STATUS_HW_FLUSH_ERR:
29988c2ecf20Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
29998c2ecf20Sopenharmony_ci	default:
30008c2ecf20Sopenharmony_ci		return IB_WC_GENERAL_ERR;
30018c2ecf20Sopenharmony_ci	}
30028c2ecf20Sopenharmony_ci}
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_cistatic void bnxt_re_process_req_wc(struct ib_wc *wc, struct bnxt_qplib_cqe *cqe)
30058c2ecf20Sopenharmony_ci{
30068c2ecf20Sopenharmony_ci	switch (cqe->type) {
30078c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND:
30088c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_SEND;
30098c2ecf20Sopenharmony_ci		break;
30108c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM:
30118c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_SEND;
30128c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
30138c2ecf20Sopenharmony_ci		break;
30148c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV:
30158c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_SEND;
30168c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_INVALIDATE;
30178c2ecf20Sopenharmony_ci		break;
30188c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE:
30198c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_RDMA_WRITE;
30208c2ecf20Sopenharmony_ci		break;
30218c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM:
30228c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_RDMA_WRITE;
30238c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
30248c2ecf20Sopenharmony_ci		break;
30258c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_READ:
30268c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_RDMA_READ;
30278c2ecf20Sopenharmony_ci		break;
30288c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP:
30298c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_COMP_SWAP;
30308c2ecf20Sopenharmony_ci		break;
30318c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD:
30328c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_FETCH_ADD;
30338c2ecf20Sopenharmony_ci		break;
30348c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_LOCAL_INV:
30358c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_LOCAL_INV;
30368c2ecf20Sopenharmony_ci		break;
30378c2ecf20Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_REG_MR:
30388c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_REG_MR;
30398c2ecf20Sopenharmony_ci		break;
30408c2ecf20Sopenharmony_ci	default:
30418c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_SEND;
30428c2ecf20Sopenharmony_ci		break;
30438c2ecf20Sopenharmony_ci	}
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci	wc->status = __req_to_ib_wc_status(cqe->status);
30468c2ecf20Sopenharmony_ci}
30478c2ecf20Sopenharmony_ci
30488c2ecf20Sopenharmony_cistatic int bnxt_re_check_packet_type(u16 raweth_qp1_flags,
30498c2ecf20Sopenharmony_ci				     u16 raweth_qp1_flags2)
30508c2ecf20Sopenharmony_ci{
30518c2ecf20Sopenharmony_ci	bool is_ipv6 = false, is_ipv4 = false;
30528c2ecf20Sopenharmony_ci
30538c2ecf20Sopenharmony_ci	/* raweth_qp1_flags Bit 9-6 indicates itype */
30548c2ecf20Sopenharmony_ci	if ((raweth_qp1_flags & CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE)
30558c2ecf20Sopenharmony_ci	    != CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE)
30568c2ecf20Sopenharmony_ci		return -1;
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_ci	if (raweth_qp1_flags2 &
30598c2ecf20Sopenharmony_ci	    CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_CS_CALC &&
30608c2ecf20Sopenharmony_ci	    raweth_qp1_flags2 &
30618c2ecf20Sopenharmony_ci	    CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_L4_CS_CALC) {
30628c2ecf20Sopenharmony_ci		/* raweth_qp1_flags2 Bit 8 indicates ip_type. 0-v4 1 - v6 */
30638c2ecf20Sopenharmony_ci		(raweth_qp1_flags2 &
30648c2ecf20Sopenharmony_ci		 CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_TYPE) ?
30658c2ecf20Sopenharmony_ci			(is_ipv6 = true) : (is_ipv4 = true);
30668c2ecf20Sopenharmony_ci		return ((is_ipv6) ?
30678c2ecf20Sopenharmony_ci			 BNXT_RE_ROCEV2_IPV6_PACKET :
30688c2ecf20Sopenharmony_ci			 BNXT_RE_ROCEV2_IPV4_PACKET);
30698c2ecf20Sopenharmony_ci	} else {
30708c2ecf20Sopenharmony_ci		return BNXT_RE_ROCE_V1_PACKET;
30718c2ecf20Sopenharmony_ci	}
30728c2ecf20Sopenharmony_ci}
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_cistatic int bnxt_re_to_ib_nw_type(int nw_type)
30758c2ecf20Sopenharmony_ci{
30768c2ecf20Sopenharmony_ci	u8 nw_hdr_type = 0xFF;
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci	switch (nw_type) {
30798c2ecf20Sopenharmony_ci	case BNXT_RE_ROCE_V1_PACKET:
30808c2ecf20Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_ROCE_V1;
30818c2ecf20Sopenharmony_ci		break;
30828c2ecf20Sopenharmony_ci	case BNXT_RE_ROCEV2_IPV4_PACKET:
30838c2ecf20Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_IPV4;
30848c2ecf20Sopenharmony_ci		break;
30858c2ecf20Sopenharmony_ci	case BNXT_RE_ROCEV2_IPV6_PACKET:
30868c2ecf20Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_IPV6;
30878c2ecf20Sopenharmony_ci		break;
30888c2ecf20Sopenharmony_ci	}
30898c2ecf20Sopenharmony_ci	return nw_hdr_type;
30908c2ecf20Sopenharmony_ci}
30918c2ecf20Sopenharmony_ci
30928c2ecf20Sopenharmony_cistatic bool bnxt_re_is_loopback_packet(struct bnxt_re_dev *rdev,
30938c2ecf20Sopenharmony_ci				       void *rq_hdr_buf)
30948c2ecf20Sopenharmony_ci{
30958c2ecf20Sopenharmony_ci	u8 *tmp_buf = NULL;
30968c2ecf20Sopenharmony_ci	struct ethhdr *eth_hdr;
30978c2ecf20Sopenharmony_ci	u16 eth_type;
30988c2ecf20Sopenharmony_ci	bool rc = false;
30998c2ecf20Sopenharmony_ci
31008c2ecf20Sopenharmony_ci	tmp_buf = (u8 *)rq_hdr_buf;
31018c2ecf20Sopenharmony_ci	/*
31028c2ecf20Sopenharmony_ci	 * If dest mac is not same as I/F mac, this could be a
31038c2ecf20Sopenharmony_ci	 * loopback address or multicast address, check whether
31048c2ecf20Sopenharmony_ci	 * it is a loopback packet
31058c2ecf20Sopenharmony_ci	 */
31068c2ecf20Sopenharmony_ci	if (!ether_addr_equal(tmp_buf, rdev->netdev->dev_addr)) {
31078c2ecf20Sopenharmony_ci		tmp_buf += 4;
31088c2ecf20Sopenharmony_ci		/* Check the  ether type */
31098c2ecf20Sopenharmony_ci		eth_hdr = (struct ethhdr *)tmp_buf;
31108c2ecf20Sopenharmony_ci		eth_type = ntohs(eth_hdr->h_proto);
31118c2ecf20Sopenharmony_ci		switch (eth_type) {
31128c2ecf20Sopenharmony_ci		case ETH_P_IBOE:
31138c2ecf20Sopenharmony_ci			rc = true;
31148c2ecf20Sopenharmony_ci			break;
31158c2ecf20Sopenharmony_ci		case ETH_P_IP:
31168c2ecf20Sopenharmony_ci		case ETH_P_IPV6: {
31178c2ecf20Sopenharmony_ci			u32 len;
31188c2ecf20Sopenharmony_ci			struct udphdr *udp_hdr;
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci			len = (eth_type == ETH_P_IP ? sizeof(struct iphdr) :
31218c2ecf20Sopenharmony_ci						      sizeof(struct ipv6hdr));
31228c2ecf20Sopenharmony_ci			tmp_buf += sizeof(struct ethhdr) + len;
31238c2ecf20Sopenharmony_ci			udp_hdr = (struct udphdr *)tmp_buf;
31248c2ecf20Sopenharmony_ci			if (ntohs(udp_hdr->dest) ==
31258c2ecf20Sopenharmony_ci				    ROCE_V2_UDP_DPORT)
31268c2ecf20Sopenharmony_ci				rc = true;
31278c2ecf20Sopenharmony_ci			break;
31288c2ecf20Sopenharmony_ci			}
31298c2ecf20Sopenharmony_ci		default:
31308c2ecf20Sopenharmony_ci			break;
31318c2ecf20Sopenharmony_ci		}
31328c2ecf20Sopenharmony_ci	}
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci	return rc;
31358c2ecf20Sopenharmony_ci}
31368c2ecf20Sopenharmony_ci
31378c2ecf20Sopenharmony_cistatic int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp,
31388c2ecf20Sopenharmony_ci					 struct bnxt_qplib_cqe *cqe)
31398c2ecf20Sopenharmony_ci{
31408c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = gsi_qp->rdev;
31418c2ecf20Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
31428c2ecf20Sopenharmony_ci	struct bnxt_re_qp *gsi_sqp = rdev->gsi_ctx.gsi_sqp;
31438c2ecf20Sopenharmony_ci	struct bnxt_re_ah *gsi_sah;
31448c2ecf20Sopenharmony_ci	struct ib_send_wr *swr;
31458c2ecf20Sopenharmony_ci	struct ib_ud_wr udwr;
31468c2ecf20Sopenharmony_ci	struct ib_recv_wr rwr;
31478c2ecf20Sopenharmony_ci	int pkt_type = 0;
31488c2ecf20Sopenharmony_ci	u32 tbl_idx;
31498c2ecf20Sopenharmony_ci	void *rq_hdr_buf;
31508c2ecf20Sopenharmony_ci	dma_addr_t rq_hdr_buf_map;
31518c2ecf20Sopenharmony_ci	dma_addr_t shrq_hdr_buf_map;
31528c2ecf20Sopenharmony_ci	u32 offset = 0;
31538c2ecf20Sopenharmony_ci	u32 skip_bytes = 0;
31548c2ecf20Sopenharmony_ci	struct ib_sge s_sge[2];
31558c2ecf20Sopenharmony_ci	struct ib_sge r_sge[2];
31568c2ecf20Sopenharmony_ci	int rc;
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci	memset(&udwr, 0, sizeof(udwr));
31598c2ecf20Sopenharmony_ci	memset(&rwr, 0, sizeof(rwr));
31608c2ecf20Sopenharmony_ci	memset(&s_sge, 0, sizeof(s_sge));
31618c2ecf20Sopenharmony_ci	memset(&r_sge, 0, sizeof(r_sge));
31628c2ecf20Sopenharmony_ci
31638c2ecf20Sopenharmony_ci	swr = &udwr.wr;
31648c2ecf20Sopenharmony_ci	tbl_idx = cqe->wr_id;
31658c2ecf20Sopenharmony_ci
31668c2ecf20Sopenharmony_ci	rq_hdr_buf = gsi_qp->qplib_qp.rq_hdr_buf +
31678c2ecf20Sopenharmony_ci			(tbl_idx * gsi_qp->qplib_qp.rq_hdr_buf_size);
31688c2ecf20Sopenharmony_ci	rq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
31698c2ecf20Sopenharmony_ci							  tbl_idx);
31708c2ecf20Sopenharmony_ci
31718c2ecf20Sopenharmony_ci	/* Shadow QP header buffer */
31728c2ecf20Sopenharmony_ci	shrq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
31738c2ecf20Sopenharmony_ci							    tbl_idx);
31748c2ecf20Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	/* Store this cqe */
31778c2ecf20Sopenharmony_ci	memcpy(&sqp_entry->cqe, cqe, sizeof(struct bnxt_qplib_cqe));
31788c2ecf20Sopenharmony_ci	sqp_entry->qp1_qp = gsi_qp;
31798c2ecf20Sopenharmony_ci
31808c2ecf20Sopenharmony_ci	/* Find packet type from the cqe */
31818c2ecf20Sopenharmony_ci
31828c2ecf20Sopenharmony_ci	pkt_type = bnxt_re_check_packet_type(cqe->raweth_qp1_flags,
31838c2ecf20Sopenharmony_ci					     cqe->raweth_qp1_flags2);
31848c2ecf20Sopenharmony_ci	if (pkt_type < 0) {
31858c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Invalid packet\n");
31868c2ecf20Sopenharmony_ci		return -EINVAL;
31878c2ecf20Sopenharmony_ci	}
31888c2ecf20Sopenharmony_ci
31898c2ecf20Sopenharmony_ci	/* Adjust the offset for the user buffer and post in the rq */
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	if (pkt_type == BNXT_RE_ROCEV2_IPV4_PACKET)
31928c2ecf20Sopenharmony_ci		offset = 20;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	/*
31958c2ecf20Sopenharmony_ci	 * QP1 loopback packet has 4 bytes of internal header before
31968c2ecf20Sopenharmony_ci	 * ether header. Skip these four bytes.
31978c2ecf20Sopenharmony_ci	 */
31988c2ecf20Sopenharmony_ci	if (bnxt_re_is_loopback_packet(rdev, rq_hdr_buf))
31998c2ecf20Sopenharmony_ci		skip_bytes = 4;
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	/* First send SGE . Skip the ether header*/
32028c2ecf20Sopenharmony_ci	s_sge[0].addr = rq_hdr_buf_map + BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE
32038c2ecf20Sopenharmony_ci			+ skip_bytes;
32048c2ecf20Sopenharmony_ci	s_sge[0].lkey = 0xFFFFFFFF;
32058c2ecf20Sopenharmony_ci	s_sge[0].length = offset ? BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV4 :
32068c2ecf20Sopenharmony_ci				BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6;
32078c2ecf20Sopenharmony_ci
32088c2ecf20Sopenharmony_ci	/* Second Send SGE */
32098c2ecf20Sopenharmony_ci	s_sge[1].addr = s_sge[0].addr + s_sge[0].length +
32108c2ecf20Sopenharmony_ci			BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE;
32118c2ecf20Sopenharmony_ci	if (pkt_type != BNXT_RE_ROCE_V1_PACKET)
32128c2ecf20Sopenharmony_ci		s_sge[1].addr += 8;
32138c2ecf20Sopenharmony_ci	s_sge[1].lkey = 0xFFFFFFFF;
32148c2ecf20Sopenharmony_ci	s_sge[1].length = 256;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	/* First recv SGE */
32178c2ecf20Sopenharmony_ci
32188c2ecf20Sopenharmony_ci	r_sge[0].addr = shrq_hdr_buf_map;
32198c2ecf20Sopenharmony_ci	r_sge[0].lkey = 0xFFFFFFFF;
32208c2ecf20Sopenharmony_ci	r_sge[0].length = 40;
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	r_sge[1].addr = sqp_entry->sge.addr + offset;
32238c2ecf20Sopenharmony_ci	r_sge[1].lkey = sqp_entry->sge.lkey;
32248c2ecf20Sopenharmony_ci	r_sge[1].length = BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6 + 256 - offset;
32258c2ecf20Sopenharmony_ci
32268c2ecf20Sopenharmony_ci	/* Create receive work request */
32278c2ecf20Sopenharmony_ci	rwr.num_sge = 2;
32288c2ecf20Sopenharmony_ci	rwr.sg_list = r_sge;
32298c2ecf20Sopenharmony_ci	rwr.wr_id = tbl_idx;
32308c2ecf20Sopenharmony_ci	rwr.next = NULL;
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci	rc = bnxt_re_post_recv_shadow_qp(rdev, gsi_sqp, &rwr);
32338c2ecf20Sopenharmony_ci	if (rc) {
32348c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
32358c2ecf20Sopenharmony_ci			  "Failed to post Rx buffers to shadow QP");
32368c2ecf20Sopenharmony_ci		return -ENOMEM;
32378c2ecf20Sopenharmony_ci	}
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	swr->num_sge = 2;
32408c2ecf20Sopenharmony_ci	swr->sg_list = s_sge;
32418c2ecf20Sopenharmony_ci	swr->wr_id = tbl_idx;
32428c2ecf20Sopenharmony_ci	swr->opcode = IB_WR_SEND;
32438c2ecf20Sopenharmony_ci	swr->next = NULL;
32448c2ecf20Sopenharmony_ci	gsi_sah = rdev->gsi_ctx.gsi_sah;
32458c2ecf20Sopenharmony_ci	udwr.ah = &gsi_sah->ib_ah;
32468c2ecf20Sopenharmony_ci	udwr.remote_qpn = gsi_sqp->qplib_qp.id;
32478c2ecf20Sopenharmony_ci	udwr.remote_qkey = gsi_sqp->qplib_qp.qkey;
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	/* post data received  in the send queue */
32508c2ecf20Sopenharmony_ci	return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
32518c2ecf20Sopenharmony_ci}
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_cistatic void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
32548c2ecf20Sopenharmony_ci					  struct bnxt_qplib_cqe *cqe)
32558c2ecf20Sopenharmony_ci{
32568c2ecf20Sopenharmony_ci	wc->opcode = IB_WC_RECV;
32578c2ecf20Sopenharmony_ci	wc->status = __rawqp1_to_ib_wc_status(cqe->status);
32588c2ecf20Sopenharmony_ci	wc->wc_flags |= IB_WC_GRH;
32598c2ecf20Sopenharmony_ci}
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_cistatic bool bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev,
32628c2ecf20Sopenharmony_ci					u16 vlan_id)
32638c2ecf20Sopenharmony_ci{
32648c2ecf20Sopenharmony_ci	/*
32658c2ecf20Sopenharmony_ci	 * Check if the vlan is configured in the host.  If not configured, it
32668c2ecf20Sopenharmony_ci	 * can be a transparent VLAN. So dont report the vlan id.
32678c2ecf20Sopenharmony_ci	 */
32688c2ecf20Sopenharmony_ci	if (!__vlan_find_dev_deep_rcu(rdev->netdev,
32698c2ecf20Sopenharmony_ci				      htons(ETH_P_8021Q), vlan_id))
32708c2ecf20Sopenharmony_ci		return false;
32718c2ecf20Sopenharmony_ci	return true;
32728c2ecf20Sopenharmony_ci}
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_cistatic bool bnxt_re_is_vlan_pkt(struct bnxt_qplib_cqe *orig_cqe,
32758c2ecf20Sopenharmony_ci				u16 *vid, u8 *sl)
32768c2ecf20Sopenharmony_ci{
32778c2ecf20Sopenharmony_ci	bool ret = false;
32788c2ecf20Sopenharmony_ci	u32 metadata;
32798c2ecf20Sopenharmony_ci	u16 tpid;
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_ci	metadata = orig_cqe->raweth_qp1_metadata;
32828c2ecf20Sopenharmony_ci	if (orig_cqe->raweth_qp1_flags2 &
32838c2ecf20Sopenharmony_ci		CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_VLAN) {
32848c2ecf20Sopenharmony_ci		tpid = ((metadata &
32858c2ecf20Sopenharmony_ci			 CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_MASK) >>
32868c2ecf20Sopenharmony_ci			 CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_SFT);
32878c2ecf20Sopenharmony_ci		if (tpid == ETH_P_8021Q) {
32888c2ecf20Sopenharmony_ci			*vid = metadata &
32898c2ecf20Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_VID_MASK;
32908c2ecf20Sopenharmony_ci			*sl = (metadata &
32918c2ecf20Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_MASK) >>
32928c2ecf20Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_SFT;
32938c2ecf20Sopenharmony_ci			ret = true;
32948c2ecf20Sopenharmony_ci		}
32958c2ecf20Sopenharmony_ci	}
32968c2ecf20Sopenharmony_ci
32978c2ecf20Sopenharmony_ci	return ret;
32988c2ecf20Sopenharmony_ci}
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_cistatic void bnxt_re_process_res_rc_wc(struct ib_wc *wc,
33018c2ecf20Sopenharmony_ci				      struct bnxt_qplib_cqe *cqe)
33028c2ecf20Sopenharmony_ci{
33038c2ecf20Sopenharmony_ci	wc->opcode = IB_WC_RECV;
33048c2ecf20Sopenharmony_ci	wc->status = __rc_to_ib_wc_status(cqe->status);
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	if (cqe->flags & CQ_RES_RC_FLAGS_IMM)
33078c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
33088c2ecf20Sopenharmony_ci	if (cqe->flags & CQ_RES_RC_FLAGS_INV)
33098c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_INVALIDATE;
33108c2ecf20Sopenharmony_ci	if ((cqe->flags & (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM)) ==
33118c2ecf20Sopenharmony_ci	    (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM))
33128c2ecf20Sopenharmony_ci		wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
33138c2ecf20Sopenharmony_ci}
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_cistatic void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
33168c2ecf20Sopenharmony_ci					     struct ib_wc *wc,
33178c2ecf20Sopenharmony_ci					     struct bnxt_qplib_cqe *cqe)
33188c2ecf20Sopenharmony_ci{
33198c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = gsi_sqp->rdev;
33208c2ecf20Sopenharmony_ci	struct bnxt_re_qp *gsi_qp = NULL;
33218c2ecf20Sopenharmony_ci	struct bnxt_qplib_cqe *orig_cqe = NULL;
33228c2ecf20Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
33238c2ecf20Sopenharmony_ci	int nw_type;
33248c2ecf20Sopenharmony_ci	u32 tbl_idx;
33258c2ecf20Sopenharmony_ci	u16 vlan_id;
33268c2ecf20Sopenharmony_ci	u8 sl;
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci	tbl_idx = cqe->wr_id;
33298c2ecf20Sopenharmony_ci
33308c2ecf20Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
33318c2ecf20Sopenharmony_ci	gsi_qp = sqp_entry->qp1_qp;
33328c2ecf20Sopenharmony_ci	orig_cqe = &sqp_entry->cqe;
33338c2ecf20Sopenharmony_ci
33348c2ecf20Sopenharmony_ci	wc->wr_id = sqp_entry->wrid;
33358c2ecf20Sopenharmony_ci	wc->byte_len = orig_cqe->length;
33368c2ecf20Sopenharmony_ci	wc->qp = &gsi_qp->ib_qp;
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	wc->ex.imm_data = orig_cqe->immdata;
33398c2ecf20Sopenharmony_ci	wc->src_qp = orig_cqe->src_qp;
33408c2ecf20Sopenharmony_ci	memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
33418c2ecf20Sopenharmony_ci	if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
33428c2ecf20Sopenharmony_ci		if (bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
33438c2ecf20Sopenharmony_ci			wc->vlan_id = vlan_id;
33448c2ecf20Sopenharmony_ci			wc->sl = sl;
33458c2ecf20Sopenharmony_ci			wc->wc_flags |= IB_WC_WITH_VLAN;
33468c2ecf20Sopenharmony_ci		}
33478c2ecf20Sopenharmony_ci	}
33488c2ecf20Sopenharmony_ci	wc->port_num = 1;
33498c2ecf20Sopenharmony_ci	wc->vendor_err = orig_cqe->status;
33508c2ecf20Sopenharmony_ci
33518c2ecf20Sopenharmony_ci	wc->opcode = IB_WC_RECV;
33528c2ecf20Sopenharmony_ci	wc->status = __rawqp1_to_ib_wc_status(orig_cqe->status);
33538c2ecf20Sopenharmony_ci	wc->wc_flags |= IB_WC_GRH;
33548c2ecf20Sopenharmony_ci
33558c2ecf20Sopenharmony_ci	nw_type = bnxt_re_check_packet_type(orig_cqe->raweth_qp1_flags,
33568c2ecf20Sopenharmony_ci					    orig_cqe->raweth_qp1_flags2);
33578c2ecf20Sopenharmony_ci	if (nw_type >= 0) {
33588c2ecf20Sopenharmony_ci		wc->network_hdr_type = bnxt_re_to_ib_nw_type(nw_type);
33598c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_NETWORK_HDR_TYPE;
33608c2ecf20Sopenharmony_ci	}
33618c2ecf20Sopenharmony_ci}
33628c2ecf20Sopenharmony_ci
33638c2ecf20Sopenharmony_cistatic void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp,
33648c2ecf20Sopenharmony_ci				      struct ib_wc *wc,
33658c2ecf20Sopenharmony_ci				      struct bnxt_qplib_cqe *cqe)
33668c2ecf20Sopenharmony_ci{
33678c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev;
33688c2ecf20Sopenharmony_ci	u16 vlan_id = 0;
33698c2ecf20Sopenharmony_ci	u8 nw_type;
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	rdev = qp->rdev;
33728c2ecf20Sopenharmony_ci	wc->opcode = IB_WC_RECV;
33738c2ecf20Sopenharmony_ci	wc->status = __rc_to_ib_wc_status(cqe->status);
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	if (cqe->flags & CQ_RES_UD_FLAGS_IMM)
33768c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
33778c2ecf20Sopenharmony_ci	/* report only on GSI QP for Thor */
33788c2ecf20Sopenharmony_ci	if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_GSI) {
33798c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_GRH;
33808c2ecf20Sopenharmony_ci		memcpy(wc->smac, cqe->smac, ETH_ALEN);
33818c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_SMAC;
33828c2ecf20Sopenharmony_ci		if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) {
33838c2ecf20Sopenharmony_ci			vlan_id = (cqe->cfa_meta & 0xFFF);
33848c2ecf20Sopenharmony_ci		}
33858c2ecf20Sopenharmony_ci		/* Mark only if vlan_id is non zero */
33868c2ecf20Sopenharmony_ci		if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
33878c2ecf20Sopenharmony_ci			wc->vlan_id = vlan_id;
33888c2ecf20Sopenharmony_ci			wc->wc_flags |= IB_WC_WITH_VLAN;
33898c2ecf20Sopenharmony_ci		}
33908c2ecf20Sopenharmony_ci		nw_type = (cqe->flags & CQ_RES_UD_FLAGS_ROCE_IP_VER_MASK) >>
33918c2ecf20Sopenharmony_ci			   CQ_RES_UD_FLAGS_ROCE_IP_VER_SFT;
33928c2ecf20Sopenharmony_ci		wc->network_hdr_type = bnxt_re_to_ib_nw_type(nw_type);
33938c2ecf20Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_NETWORK_HDR_TYPE;
33948c2ecf20Sopenharmony_ci	}
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci}
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_cistatic int send_phantom_wqe(struct bnxt_re_qp *qp)
33998c2ecf20Sopenharmony_ci{
34008c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp;
34018c2ecf20Sopenharmony_ci	unsigned long flags;
34028c2ecf20Sopenharmony_ci	int rc = 0;
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
34058c2ecf20Sopenharmony_ci
34068c2ecf20Sopenharmony_ci	rc = bnxt_re_bind_fence_mw(lib_qp);
34078c2ecf20Sopenharmony_ci	if (!rc) {
34088c2ecf20Sopenharmony_ci		lib_qp->sq.phantom_wqe_cnt++;
34098c2ecf20Sopenharmony_ci		ibdev_dbg(&qp->rdev->ibdev,
34108c2ecf20Sopenharmony_ci			  "qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n",
34118c2ecf20Sopenharmony_ci			  lib_qp->id, lib_qp->sq.hwq.prod,
34128c2ecf20Sopenharmony_ci			  HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq),
34138c2ecf20Sopenharmony_ci			  lib_qp->sq.phantom_wqe_cnt);
34148c2ecf20Sopenharmony_ci	}
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
34178c2ecf20Sopenharmony_ci	return rc;
34188c2ecf20Sopenharmony_ci}
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_ciint bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
34218c2ecf20Sopenharmony_ci{
34228c2ecf20Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
34238c2ecf20Sopenharmony_ci	struct bnxt_re_qp *qp, *sh_qp;
34248c2ecf20Sopenharmony_ci	struct bnxt_qplib_cqe *cqe;
34258c2ecf20Sopenharmony_ci	int i, ncqe, budget;
34268c2ecf20Sopenharmony_ci	struct bnxt_qplib_q *sq;
34278c2ecf20Sopenharmony_ci	struct bnxt_qplib_qp *lib_qp;
34288c2ecf20Sopenharmony_ci	u32 tbl_idx;
34298c2ecf20Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
34308c2ecf20Sopenharmony_ci	unsigned long flags;
34318c2ecf20Sopenharmony_ci
34328c2ecf20Sopenharmony_ci	spin_lock_irqsave(&cq->cq_lock, flags);
34338c2ecf20Sopenharmony_ci	budget = min_t(u32, num_entries, cq->max_cql);
34348c2ecf20Sopenharmony_ci	num_entries = budget;
34358c2ecf20Sopenharmony_ci	if (!cq->cql) {
34368c2ecf20Sopenharmony_ci		ibdev_err(&cq->rdev->ibdev, "POLL CQ : no CQL to use");
34378c2ecf20Sopenharmony_ci		goto exit;
34388c2ecf20Sopenharmony_ci	}
34398c2ecf20Sopenharmony_ci	cqe = &cq->cql[0];
34408c2ecf20Sopenharmony_ci	while (budget) {
34418c2ecf20Sopenharmony_ci		lib_qp = NULL;
34428c2ecf20Sopenharmony_ci		ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp);
34438c2ecf20Sopenharmony_ci		if (lib_qp) {
34448c2ecf20Sopenharmony_ci			sq = &lib_qp->sq;
34458c2ecf20Sopenharmony_ci			if (sq->send_phantom) {
34468c2ecf20Sopenharmony_ci				qp = container_of(lib_qp,
34478c2ecf20Sopenharmony_ci						  struct bnxt_re_qp, qplib_qp);
34488c2ecf20Sopenharmony_ci				if (send_phantom_wqe(qp) == -ENOMEM)
34498c2ecf20Sopenharmony_ci					ibdev_err(&cq->rdev->ibdev,
34508c2ecf20Sopenharmony_ci						  "Phantom failed! Scheduled to send again\n");
34518c2ecf20Sopenharmony_ci				else
34528c2ecf20Sopenharmony_ci					sq->send_phantom = false;
34538c2ecf20Sopenharmony_ci			}
34548c2ecf20Sopenharmony_ci		}
34558c2ecf20Sopenharmony_ci		if (ncqe < budget)
34568c2ecf20Sopenharmony_ci			ncqe += bnxt_qplib_process_flush_list(&cq->qplib_cq,
34578c2ecf20Sopenharmony_ci							      cqe + ncqe,
34588c2ecf20Sopenharmony_ci							      budget - ncqe);
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_ci		if (!ncqe)
34618c2ecf20Sopenharmony_ci			break;
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_ci		for (i = 0; i < ncqe; i++, cqe++) {
34648c2ecf20Sopenharmony_ci			/* Transcribe each qplib_wqe back to ib_wc */
34658c2ecf20Sopenharmony_ci			memset(wc, 0, sizeof(*wc));
34668c2ecf20Sopenharmony_ci
34678c2ecf20Sopenharmony_ci			wc->wr_id = cqe->wr_id;
34688c2ecf20Sopenharmony_ci			wc->byte_len = cqe->length;
34698c2ecf20Sopenharmony_ci			qp = container_of
34708c2ecf20Sopenharmony_ci				((struct bnxt_qplib_qp *)
34718c2ecf20Sopenharmony_ci				 (unsigned long)(cqe->qp_handle),
34728c2ecf20Sopenharmony_ci				 struct bnxt_re_qp, qplib_qp);
34738c2ecf20Sopenharmony_ci			if (!qp) {
34748c2ecf20Sopenharmony_ci				ibdev_err(&cq->rdev->ibdev, "POLL CQ : bad QP handle");
34758c2ecf20Sopenharmony_ci				continue;
34768c2ecf20Sopenharmony_ci			}
34778c2ecf20Sopenharmony_ci			wc->qp = &qp->ib_qp;
34788c2ecf20Sopenharmony_ci			wc->ex.imm_data = cqe->immdata;
34798c2ecf20Sopenharmony_ci			wc->src_qp = cqe->src_qp;
34808c2ecf20Sopenharmony_ci			memcpy(wc->smac, cqe->smac, ETH_ALEN);
34818c2ecf20Sopenharmony_ci			wc->port_num = 1;
34828c2ecf20Sopenharmony_ci			wc->vendor_err = cqe->status;
34838c2ecf20Sopenharmony_ci
34848c2ecf20Sopenharmony_ci			switch (cqe->opcode) {
34858c2ecf20Sopenharmony_ci			case CQ_BASE_CQE_TYPE_REQ:
34868c2ecf20Sopenharmony_ci				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
34878c2ecf20Sopenharmony_ci				if (sh_qp &&
34888c2ecf20Sopenharmony_ci				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
34898c2ecf20Sopenharmony_ci					/* Handle this completion with
34908c2ecf20Sopenharmony_ci					 * the stored completion
34918c2ecf20Sopenharmony_ci					 */
34928c2ecf20Sopenharmony_ci					memset(wc, 0, sizeof(*wc));
34938c2ecf20Sopenharmony_ci					continue;
34948c2ecf20Sopenharmony_ci				}
34958c2ecf20Sopenharmony_ci				bnxt_re_process_req_wc(wc, cqe);
34968c2ecf20Sopenharmony_ci				break;
34978c2ecf20Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_RAWETH_QP1:
34988c2ecf20Sopenharmony_ci				if (!cqe->status) {
34998c2ecf20Sopenharmony_ci					int rc = 0;
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci					rc = bnxt_re_process_raw_qp_pkt_rx
35028c2ecf20Sopenharmony_ci								(qp, cqe);
35038c2ecf20Sopenharmony_ci					if (!rc) {
35048c2ecf20Sopenharmony_ci						memset(wc, 0, sizeof(*wc));
35058c2ecf20Sopenharmony_ci						continue;
35068c2ecf20Sopenharmony_ci					}
35078c2ecf20Sopenharmony_ci					cqe->status = -1;
35088c2ecf20Sopenharmony_ci				}
35098c2ecf20Sopenharmony_ci				/* Errors need not be looped back.
35108c2ecf20Sopenharmony_ci				 * But change the wr_id to the one
35118c2ecf20Sopenharmony_ci				 * stored in the table
35128c2ecf20Sopenharmony_ci				 */
35138c2ecf20Sopenharmony_ci				tbl_idx = cqe->wr_id;
35148c2ecf20Sopenharmony_ci				sqp_entry = &cq->rdev->gsi_ctx.sqp_tbl[tbl_idx];
35158c2ecf20Sopenharmony_ci				wc->wr_id = sqp_entry->wrid;
35168c2ecf20Sopenharmony_ci				bnxt_re_process_res_rawqp1_wc(wc, cqe);
35178c2ecf20Sopenharmony_ci				break;
35188c2ecf20Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_RC:
35198c2ecf20Sopenharmony_ci				bnxt_re_process_res_rc_wc(wc, cqe);
35208c2ecf20Sopenharmony_ci				break;
35218c2ecf20Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_UD:
35228c2ecf20Sopenharmony_ci				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
35238c2ecf20Sopenharmony_ci				if (sh_qp &&
35248c2ecf20Sopenharmony_ci				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
35258c2ecf20Sopenharmony_ci					/* Handle this completion with
35268c2ecf20Sopenharmony_ci					 * the stored completion
35278c2ecf20Sopenharmony_ci					 */
35288c2ecf20Sopenharmony_ci					if (cqe->status) {
35298c2ecf20Sopenharmony_ci						continue;
35308c2ecf20Sopenharmony_ci					} else {
35318c2ecf20Sopenharmony_ci						bnxt_re_process_res_shadow_qp_wc
35328c2ecf20Sopenharmony_ci								(qp, wc, cqe);
35338c2ecf20Sopenharmony_ci						break;
35348c2ecf20Sopenharmony_ci					}
35358c2ecf20Sopenharmony_ci				}
35368c2ecf20Sopenharmony_ci				bnxt_re_process_res_ud_wc(qp, wc, cqe);
35378c2ecf20Sopenharmony_ci				break;
35388c2ecf20Sopenharmony_ci			default:
35398c2ecf20Sopenharmony_ci				ibdev_err(&cq->rdev->ibdev,
35408c2ecf20Sopenharmony_ci					  "POLL CQ : type 0x%x not handled",
35418c2ecf20Sopenharmony_ci					  cqe->opcode);
35428c2ecf20Sopenharmony_ci				continue;
35438c2ecf20Sopenharmony_ci			}
35448c2ecf20Sopenharmony_ci			wc++;
35458c2ecf20Sopenharmony_ci			budget--;
35468c2ecf20Sopenharmony_ci		}
35478c2ecf20Sopenharmony_ci	}
35488c2ecf20Sopenharmony_ciexit:
35498c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&cq->cq_lock, flags);
35508c2ecf20Sopenharmony_ci	return num_entries - budget;
35518c2ecf20Sopenharmony_ci}
35528c2ecf20Sopenharmony_ci
35538c2ecf20Sopenharmony_ciint bnxt_re_req_notify_cq(struct ib_cq *ib_cq,
35548c2ecf20Sopenharmony_ci			  enum ib_cq_notify_flags ib_cqn_flags)
35558c2ecf20Sopenharmony_ci{
35568c2ecf20Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
35578c2ecf20Sopenharmony_ci	int type = 0, rc = 0;
35588c2ecf20Sopenharmony_ci	unsigned long flags;
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci	spin_lock_irqsave(&cq->cq_lock, flags);
35618c2ecf20Sopenharmony_ci	/* Trigger on the very next completion */
35628c2ecf20Sopenharmony_ci	if (ib_cqn_flags & IB_CQ_NEXT_COMP)
35638c2ecf20Sopenharmony_ci		type = DBC_DBC_TYPE_CQ_ARMALL;
35648c2ecf20Sopenharmony_ci	/* Trigger on the next solicited completion */
35658c2ecf20Sopenharmony_ci	else if (ib_cqn_flags & IB_CQ_SOLICITED)
35668c2ecf20Sopenharmony_ci		type = DBC_DBC_TYPE_CQ_ARMSE;
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_ci	/* Poll to see if there are missed events */
35698c2ecf20Sopenharmony_ci	if ((ib_cqn_flags & IB_CQ_REPORT_MISSED_EVENTS) &&
35708c2ecf20Sopenharmony_ci	    !(bnxt_qplib_is_cq_empty(&cq->qplib_cq))) {
35718c2ecf20Sopenharmony_ci		rc = 1;
35728c2ecf20Sopenharmony_ci		goto exit;
35738c2ecf20Sopenharmony_ci	}
35748c2ecf20Sopenharmony_ci	bnxt_qplib_req_notify_cq(&cq->qplib_cq, type);
35758c2ecf20Sopenharmony_ci
35768c2ecf20Sopenharmony_ciexit:
35778c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&cq->cq_lock, flags);
35788c2ecf20Sopenharmony_ci	return rc;
35798c2ecf20Sopenharmony_ci}
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci/* Memory Regions */
35828c2ecf20Sopenharmony_cistruct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags)
35838c2ecf20Sopenharmony_ci{
35848c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
35858c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
35868c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr;
35878c2ecf20Sopenharmony_ci	int rc;
35888c2ecf20Sopenharmony_ci
35898c2ecf20Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
35908c2ecf20Sopenharmony_ci	if (!mr)
35918c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
35928c2ecf20Sopenharmony_ci
35938c2ecf20Sopenharmony_ci	mr->rdev = rdev;
35948c2ecf20Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
35958c2ecf20Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
35968c2ecf20Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
35978c2ecf20Sopenharmony_ci
35988c2ecf20Sopenharmony_ci	/* Allocate and register 0 as the address */
35998c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
36008c2ecf20Sopenharmony_ci	if (rc)
36018c2ecf20Sopenharmony_ci		goto fail;
36028c2ecf20Sopenharmony_ci
36038c2ecf20Sopenharmony_ci	mr->qplib_mr.hwq.level = PBL_LVL_MAX;
36048c2ecf20Sopenharmony_ci	mr->qplib_mr.total_size = -1; /* Infinte length */
36058c2ecf20Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, NULL, 0,
36068c2ecf20Sopenharmony_ci			       PAGE_SIZE);
36078c2ecf20Sopenharmony_ci	if (rc)
36088c2ecf20Sopenharmony_ci		goto fail_mr;
36098c2ecf20Sopenharmony_ci
36108c2ecf20Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
36118c2ecf20Sopenharmony_ci	if (mr_access_flags & (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ |
36128c2ecf20Sopenharmony_ci			       IB_ACCESS_REMOTE_ATOMIC))
36138c2ecf20Sopenharmony_ci		mr->ib_mr.rkey = mr->ib_mr.lkey;
36148c2ecf20Sopenharmony_ci	atomic_inc(&rdev->mr_count);
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	return &mr->ib_mr;
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_cifail_mr:
36198c2ecf20Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
36208c2ecf20Sopenharmony_cifail:
36218c2ecf20Sopenharmony_ci	kfree(mr);
36228c2ecf20Sopenharmony_ci	return ERR_PTR(rc);
36238c2ecf20Sopenharmony_ci}
36248c2ecf20Sopenharmony_ci
36258c2ecf20Sopenharmony_ciint bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
36268c2ecf20Sopenharmony_ci{
36278c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
36288c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = mr->rdev;
36298c2ecf20Sopenharmony_ci	int rc;
36308c2ecf20Sopenharmony_ci
36318c2ecf20Sopenharmony_ci	rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
36328c2ecf20Sopenharmony_ci	if (rc) {
36338c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Dereg MR failed: %#x\n", rc);
36348c2ecf20Sopenharmony_ci		return rc;
36358c2ecf20Sopenharmony_ci	}
36368c2ecf20Sopenharmony_ci
36378c2ecf20Sopenharmony_ci	if (mr->pages) {
36388c2ecf20Sopenharmony_ci		rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
36398c2ecf20Sopenharmony_ci							&mr->qplib_frpl);
36408c2ecf20Sopenharmony_ci		kfree(mr->pages);
36418c2ecf20Sopenharmony_ci		mr->npages = 0;
36428c2ecf20Sopenharmony_ci		mr->pages = NULL;
36438c2ecf20Sopenharmony_ci	}
36448c2ecf20Sopenharmony_ci	ib_umem_release(mr->ib_umem);
36458c2ecf20Sopenharmony_ci
36468c2ecf20Sopenharmony_ci	kfree(mr);
36478c2ecf20Sopenharmony_ci	atomic_dec(&rdev->mr_count);
36488c2ecf20Sopenharmony_ci	return rc;
36498c2ecf20Sopenharmony_ci}
36508c2ecf20Sopenharmony_ci
36518c2ecf20Sopenharmony_cistatic int bnxt_re_set_page(struct ib_mr *ib_mr, u64 addr)
36528c2ecf20Sopenharmony_ci{
36538c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_ci	if (unlikely(mr->npages == mr->qplib_frpl.max_pg_ptrs))
36568c2ecf20Sopenharmony_ci		return -ENOMEM;
36578c2ecf20Sopenharmony_ci
36588c2ecf20Sopenharmony_ci	mr->pages[mr->npages++] = addr;
36598c2ecf20Sopenharmony_ci	return 0;
36608c2ecf20Sopenharmony_ci}
36618c2ecf20Sopenharmony_ci
36628c2ecf20Sopenharmony_ciint bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
36638c2ecf20Sopenharmony_ci		      unsigned int *sg_offset)
36648c2ecf20Sopenharmony_ci{
36658c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	mr->npages = 0;
36688c2ecf20Sopenharmony_ci	return ib_sg_to_pages(ib_mr, sg, sg_nents, sg_offset, bnxt_re_set_page);
36698c2ecf20Sopenharmony_ci}
36708c2ecf20Sopenharmony_ci
36718c2ecf20Sopenharmony_cistruct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
36728c2ecf20Sopenharmony_ci			       u32 max_num_sg)
36738c2ecf20Sopenharmony_ci{
36748c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
36758c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
36768c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr = NULL;
36778c2ecf20Sopenharmony_ci	int rc;
36788c2ecf20Sopenharmony_ci
36798c2ecf20Sopenharmony_ci	if (type != IB_MR_TYPE_MEM_REG) {
36808c2ecf20Sopenharmony_ci		ibdev_dbg(&rdev->ibdev, "MR type 0x%x not supported", type);
36818c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
36828c2ecf20Sopenharmony_ci	}
36838c2ecf20Sopenharmony_ci	if (max_num_sg > MAX_PBL_LVL_1_PGS)
36848c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
36858c2ecf20Sopenharmony_ci
36868c2ecf20Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
36878c2ecf20Sopenharmony_ci	if (!mr)
36888c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci	mr->rdev = rdev;
36918c2ecf20Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
36928c2ecf20Sopenharmony_ci	mr->qplib_mr.flags = BNXT_QPLIB_FR_PMR;
36938c2ecf20Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
36948c2ecf20Sopenharmony_ci
36958c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
36968c2ecf20Sopenharmony_ci	if (rc)
36978c2ecf20Sopenharmony_ci		goto bail;
36988c2ecf20Sopenharmony_ci
36998c2ecf20Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
37008c2ecf20Sopenharmony_ci	mr->ib_mr.rkey = mr->ib_mr.lkey;
37018c2ecf20Sopenharmony_ci
37028c2ecf20Sopenharmony_ci	mr->pages = kcalloc(max_num_sg, sizeof(u64), GFP_KERNEL);
37038c2ecf20Sopenharmony_ci	if (!mr->pages) {
37048c2ecf20Sopenharmony_ci		rc = -ENOMEM;
37058c2ecf20Sopenharmony_ci		goto fail;
37068c2ecf20Sopenharmony_ci	}
37078c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_fast_reg_page_list(&rdev->qplib_res,
37088c2ecf20Sopenharmony_ci						 &mr->qplib_frpl, max_num_sg);
37098c2ecf20Sopenharmony_ci	if (rc) {
37108c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev,
37118c2ecf20Sopenharmony_ci			  "Failed to allocate HW FR page list");
37128c2ecf20Sopenharmony_ci		goto fail_mr;
37138c2ecf20Sopenharmony_ci	}
37148c2ecf20Sopenharmony_ci
37158c2ecf20Sopenharmony_ci	atomic_inc(&rdev->mr_count);
37168c2ecf20Sopenharmony_ci	return &mr->ib_mr;
37178c2ecf20Sopenharmony_ci
37188c2ecf20Sopenharmony_cifail_mr:
37198c2ecf20Sopenharmony_ci	kfree(mr->pages);
37208c2ecf20Sopenharmony_cifail:
37218c2ecf20Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
37228c2ecf20Sopenharmony_cibail:
37238c2ecf20Sopenharmony_ci	kfree(mr);
37248c2ecf20Sopenharmony_ci	return ERR_PTR(rc);
37258c2ecf20Sopenharmony_ci}
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_cistruct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
37288c2ecf20Sopenharmony_ci			       struct ib_udata *udata)
37298c2ecf20Sopenharmony_ci{
37308c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
37318c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
37328c2ecf20Sopenharmony_ci	struct bnxt_re_mw *mw;
37338c2ecf20Sopenharmony_ci	int rc;
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci	mw = kzalloc(sizeof(*mw), GFP_KERNEL);
37368c2ecf20Sopenharmony_ci	if (!mw)
37378c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
37388c2ecf20Sopenharmony_ci	mw->rdev = rdev;
37398c2ecf20Sopenharmony_ci	mw->qplib_mw.pd = &pd->qplib_pd;
37408c2ecf20Sopenharmony_ci
37418c2ecf20Sopenharmony_ci	mw->qplib_mw.type = (type == IB_MW_TYPE_1 ?
37428c2ecf20Sopenharmony_ci			       CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 :
37438c2ecf20Sopenharmony_ci			       CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B);
37448c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw);
37458c2ecf20Sopenharmony_ci	if (rc) {
37468c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Allocate MW failed!");
37478c2ecf20Sopenharmony_ci		goto fail;
37488c2ecf20Sopenharmony_ci	}
37498c2ecf20Sopenharmony_ci	mw->ib_mw.rkey = mw->qplib_mw.rkey;
37508c2ecf20Sopenharmony_ci
37518c2ecf20Sopenharmony_ci	atomic_inc(&rdev->mw_count);
37528c2ecf20Sopenharmony_ci	return &mw->ib_mw;
37538c2ecf20Sopenharmony_ci
37548c2ecf20Sopenharmony_cifail:
37558c2ecf20Sopenharmony_ci	kfree(mw);
37568c2ecf20Sopenharmony_ci	return ERR_PTR(rc);
37578c2ecf20Sopenharmony_ci}
37588c2ecf20Sopenharmony_ci
37598c2ecf20Sopenharmony_ciint bnxt_re_dealloc_mw(struct ib_mw *ib_mw)
37608c2ecf20Sopenharmony_ci{
37618c2ecf20Sopenharmony_ci	struct bnxt_re_mw *mw = container_of(ib_mw, struct bnxt_re_mw, ib_mw);
37628c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = mw->rdev;
37638c2ecf20Sopenharmony_ci	int rc;
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci	rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw);
37668c2ecf20Sopenharmony_ci	if (rc) {
37678c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Free MW failed: %#x\n", rc);
37688c2ecf20Sopenharmony_ci		return rc;
37698c2ecf20Sopenharmony_ci	}
37708c2ecf20Sopenharmony_ci
37718c2ecf20Sopenharmony_ci	kfree(mw);
37728c2ecf20Sopenharmony_ci	atomic_dec(&rdev->mw_count);
37738c2ecf20Sopenharmony_ci	return rc;
37748c2ecf20Sopenharmony_ci}
37758c2ecf20Sopenharmony_ci
37768c2ecf20Sopenharmony_ci/* uverbs */
37778c2ecf20Sopenharmony_cistruct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
37788c2ecf20Sopenharmony_ci				  u64 virt_addr, int mr_access_flags,
37798c2ecf20Sopenharmony_ci				  struct ib_udata *udata)
37808c2ecf20Sopenharmony_ci{
37818c2ecf20Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
37828c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
37838c2ecf20Sopenharmony_ci	struct bnxt_re_mr *mr;
37848c2ecf20Sopenharmony_ci	struct ib_umem *umem;
37858c2ecf20Sopenharmony_ci	unsigned long page_size;
37868c2ecf20Sopenharmony_ci	int umem_pgs, rc;
37878c2ecf20Sopenharmony_ci
37888c2ecf20Sopenharmony_ci	if (length > BNXT_RE_MAX_MR_SIZE) {
37898c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "MR Size: %lld > Max supported:%lld\n",
37908c2ecf20Sopenharmony_ci			  length, BNXT_RE_MAX_MR_SIZE);
37918c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
37928c2ecf20Sopenharmony_ci	}
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
37958c2ecf20Sopenharmony_ci	if (!mr)
37968c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_ci	mr->rdev = rdev;
37998c2ecf20Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
38008c2ecf20Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
38018c2ecf20Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR;
38028c2ecf20Sopenharmony_ci
38038c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
38048c2ecf20Sopenharmony_ci	if (rc) {
38058c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate MR");
38068c2ecf20Sopenharmony_ci		goto free_mr;
38078c2ecf20Sopenharmony_ci	}
38088c2ecf20Sopenharmony_ci	/* The fixed portion of the rkey is the same as the lkey */
38098c2ecf20Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.rkey;
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, start, length, mr_access_flags);
38128c2ecf20Sopenharmony_ci	if (IS_ERR(umem)) {
38138c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to get umem");
38148c2ecf20Sopenharmony_ci		rc = -EFAULT;
38158c2ecf20Sopenharmony_ci		goto free_mrw;
38168c2ecf20Sopenharmony_ci	}
38178c2ecf20Sopenharmony_ci	mr->ib_umem = umem;
38188c2ecf20Sopenharmony_ci
38198c2ecf20Sopenharmony_ci	mr->qplib_mr.va = virt_addr;
38208c2ecf20Sopenharmony_ci	page_size = ib_umem_find_best_pgsz(
38218c2ecf20Sopenharmony_ci		umem, BNXT_RE_PAGE_SIZE_4K | BNXT_RE_PAGE_SIZE_2M, virt_addr);
38228c2ecf20Sopenharmony_ci	if (!page_size) {
38238c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "umem page size unsupported!");
38248c2ecf20Sopenharmony_ci		rc = -EFAULT;
38258c2ecf20Sopenharmony_ci		goto free_umem;
38268c2ecf20Sopenharmony_ci	}
38278c2ecf20Sopenharmony_ci	mr->qplib_mr.total_size = length;
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	if (page_size == BNXT_RE_PAGE_SIZE_4K &&
38308c2ecf20Sopenharmony_ci	    length > BNXT_RE_MAX_MR_SIZE_LOW) {
38318c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Requested MR Sz:%llu Max sup:%llu",
38328c2ecf20Sopenharmony_ci			  length, (u64)BNXT_RE_MAX_MR_SIZE_LOW);
38338c2ecf20Sopenharmony_ci		rc = -EINVAL;
38348c2ecf20Sopenharmony_ci		goto free_umem;
38358c2ecf20Sopenharmony_ci	}
38368c2ecf20Sopenharmony_ci
38378c2ecf20Sopenharmony_ci	umem_pgs = ib_umem_num_dma_blocks(umem, page_size);
38388c2ecf20Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, umem,
38398c2ecf20Sopenharmony_ci			       umem_pgs, page_size);
38408c2ecf20Sopenharmony_ci	if (rc) {
38418c2ecf20Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to register user MR");
38428c2ecf20Sopenharmony_ci		goto free_umem;
38438c2ecf20Sopenharmony_ci	}
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
38468c2ecf20Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.lkey;
38478c2ecf20Sopenharmony_ci	atomic_inc(&rdev->mr_count);
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci	return &mr->ib_mr;
38508c2ecf20Sopenharmony_cifree_umem:
38518c2ecf20Sopenharmony_ci	ib_umem_release(umem);
38528c2ecf20Sopenharmony_cifree_mrw:
38538c2ecf20Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
38548c2ecf20Sopenharmony_cifree_mr:
38558c2ecf20Sopenharmony_ci	kfree(mr);
38568c2ecf20Sopenharmony_ci	return ERR_PTR(rc);
38578c2ecf20Sopenharmony_ci}
38588c2ecf20Sopenharmony_ci
38598c2ecf20Sopenharmony_ciint bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
38608c2ecf20Sopenharmony_ci{
38618c2ecf20Sopenharmony_ci	struct ib_device *ibdev = ctx->device;
38628c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *uctx =
38638c2ecf20Sopenharmony_ci		container_of(ctx, struct bnxt_re_ucontext, ib_uctx);
38648c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
38658c2ecf20Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
38668c2ecf20Sopenharmony_ci	struct bnxt_re_uctx_resp resp;
38678c2ecf20Sopenharmony_ci	u32 chip_met_rev_num = 0;
38688c2ecf20Sopenharmony_ci	int rc;
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ci	ibdev_dbg(ibdev, "ABI version requested %u", ibdev->ops.uverbs_abi_ver);
38718c2ecf20Sopenharmony_ci
38728c2ecf20Sopenharmony_ci	if (ibdev->ops.uverbs_abi_ver != BNXT_RE_ABI_VERSION) {
38738c2ecf20Sopenharmony_ci		ibdev_dbg(ibdev, " is different from the device %d ",
38748c2ecf20Sopenharmony_ci			  BNXT_RE_ABI_VERSION);
38758c2ecf20Sopenharmony_ci		return -EPERM;
38768c2ecf20Sopenharmony_ci	}
38778c2ecf20Sopenharmony_ci
38788c2ecf20Sopenharmony_ci	uctx->rdev = rdev;
38798c2ecf20Sopenharmony_ci
38808c2ecf20Sopenharmony_ci	uctx->shpg = (void *)__get_free_page(GFP_KERNEL);
38818c2ecf20Sopenharmony_ci	if (!uctx->shpg) {
38828c2ecf20Sopenharmony_ci		rc = -ENOMEM;
38838c2ecf20Sopenharmony_ci		goto fail;
38848c2ecf20Sopenharmony_ci	}
38858c2ecf20Sopenharmony_ci	spin_lock_init(&uctx->sh_lock);
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	resp.comp_mask = BNXT_RE_UCNTX_CMASK_HAVE_CCTX;
38888c2ecf20Sopenharmony_ci	chip_met_rev_num = rdev->chip_ctx->chip_num;
38898c2ecf20Sopenharmony_ci	chip_met_rev_num |= ((u32)rdev->chip_ctx->chip_rev & 0xFF) <<
38908c2ecf20Sopenharmony_ci			     BNXT_RE_CHIP_ID0_CHIP_REV_SFT;
38918c2ecf20Sopenharmony_ci	chip_met_rev_num |= ((u32)rdev->chip_ctx->chip_metal & 0xFF) <<
38928c2ecf20Sopenharmony_ci			     BNXT_RE_CHIP_ID0_CHIP_MET_SFT;
38938c2ecf20Sopenharmony_ci	resp.chip_id0 = chip_met_rev_num;
38948c2ecf20Sopenharmony_ci	/* Future extension of chip info */
38958c2ecf20Sopenharmony_ci	resp.chip_id1 = 0;
38968c2ecf20Sopenharmony_ci	/*Temp, Use xa_alloc instead */
38978c2ecf20Sopenharmony_ci	resp.dev_id = rdev->en_dev->pdev->devfn;
38988c2ecf20Sopenharmony_ci	resp.max_qp = rdev->qplib_ctx.qpc_count;
38998c2ecf20Sopenharmony_ci	resp.pg_size = PAGE_SIZE;
39008c2ecf20Sopenharmony_ci	resp.cqe_sz = sizeof(struct cq_base);
39018c2ecf20Sopenharmony_ci	resp.max_cqd = dev_attr->max_cq_wqes;
39028c2ecf20Sopenharmony_ci	resp.rsvd    = 0;
39038c2ecf20Sopenharmony_ci
39048c2ecf20Sopenharmony_ci	rc = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp)));
39058c2ecf20Sopenharmony_ci	if (rc) {
39068c2ecf20Sopenharmony_ci		ibdev_err(ibdev, "Failed to copy user context");
39078c2ecf20Sopenharmony_ci		rc = -EFAULT;
39088c2ecf20Sopenharmony_ci		goto cfail;
39098c2ecf20Sopenharmony_ci	}
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci	return 0;
39128c2ecf20Sopenharmony_cicfail:
39138c2ecf20Sopenharmony_ci	free_page((unsigned long)uctx->shpg);
39148c2ecf20Sopenharmony_ci	uctx->shpg = NULL;
39158c2ecf20Sopenharmony_cifail:
39168c2ecf20Sopenharmony_ci	return rc;
39178c2ecf20Sopenharmony_ci}
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_civoid bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
39208c2ecf20Sopenharmony_ci{
39218c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *uctx = container_of(ib_uctx,
39228c2ecf20Sopenharmony_ci						   struct bnxt_re_ucontext,
39238c2ecf20Sopenharmony_ci						   ib_uctx);
39248c2ecf20Sopenharmony_ci
39258c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = uctx->rdev;
39268c2ecf20Sopenharmony_ci
39278c2ecf20Sopenharmony_ci	if (uctx->shpg)
39288c2ecf20Sopenharmony_ci		free_page((unsigned long)uctx->shpg);
39298c2ecf20Sopenharmony_ci
39308c2ecf20Sopenharmony_ci	if (uctx->dpi.dbr) {
39318c2ecf20Sopenharmony_ci		/* Free DPI only if this is the first PD allocated by the
39328c2ecf20Sopenharmony_ci		 * application and mark the context dpi as NULL
39338c2ecf20Sopenharmony_ci		 */
39348c2ecf20Sopenharmony_ci		bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
39358c2ecf20Sopenharmony_ci				       &rdev->qplib_res.dpi_tbl, &uctx->dpi);
39368c2ecf20Sopenharmony_ci		uctx->dpi.dbr = NULL;
39378c2ecf20Sopenharmony_ci	}
39388c2ecf20Sopenharmony_ci}
39398c2ecf20Sopenharmony_ci
39408c2ecf20Sopenharmony_ci/* Helper function to mmap the virtual memory from user app */
39418c2ecf20Sopenharmony_ciint bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)
39428c2ecf20Sopenharmony_ci{
39438c2ecf20Sopenharmony_ci	struct bnxt_re_ucontext *uctx = container_of(ib_uctx,
39448c2ecf20Sopenharmony_ci						   struct bnxt_re_ucontext,
39458c2ecf20Sopenharmony_ci						   ib_uctx);
39468c2ecf20Sopenharmony_ci	struct bnxt_re_dev *rdev = uctx->rdev;
39478c2ecf20Sopenharmony_ci	u64 pfn;
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci	if (vma->vm_end - vma->vm_start != PAGE_SIZE)
39508c2ecf20Sopenharmony_ci		return -EINVAL;
39518c2ecf20Sopenharmony_ci
39528c2ecf20Sopenharmony_ci	if (vma->vm_pgoff) {
39538c2ecf20Sopenharmony_ci		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
39548c2ecf20Sopenharmony_ci		if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
39558c2ecf20Sopenharmony_ci				       PAGE_SIZE, vma->vm_page_prot)) {
39568c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to map DPI");
39578c2ecf20Sopenharmony_ci			return -EAGAIN;
39588c2ecf20Sopenharmony_ci		}
39598c2ecf20Sopenharmony_ci	} else {
39608c2ecf20Sopenharmony_ci		pfn = virt_to_phys(uctx->shpg) >> PAGE_SHIFT;
39618c2ecf20Sopenharmony_ci		if (remap_pfn_range(vma, vma->vm_start,
39628c2ecf20Sopenharmony_ci				    pfn, PAGE_SIZE, vma->vm_page_prot)) {
39638c2ecf20Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to map shared page");
39648c2ecf20Sopenharmony_ci			return -EAGAIN;
39658c2ecf20Sopenharmony_ci		}
39668c2ecf20Sopenharmony_ci	}
39678c2ecf20Sopenharmony_ci
39688c2ecf20Sopenharmony_ci	return 0;
39698c2ecf20Sopenharmony_ci}
3970