162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
562306a36Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This software is available to you under a choice of one of two
862306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
962306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
1062306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
1162306a36Sopenharmony_ci * BSD license below:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1462306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1562306a36Sopenharmony_ci * are met:
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1862306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
1962306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
2062306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
2162306a36Sopenharmony_ci *    the documentation and/or other materials provided with the
2262306a36Sopenharmony_ci *    distribution.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
2562306a36Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2662306a36Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2762306a36Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
2862306a36Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2962306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3062306a36Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3162306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3262306a36Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
3362306a36Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
3462306a36Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * Description: IB Verbs interpreter
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include <linux/interrupt.h>
4062306a36Sopenharmony_ci#include <linux/types.h>
4162306a36Sopenharmony_ci#include <linux/pci.h>
4262306a36Sopenharmony_ci#include <linux/netdevice.h>
4362306a36Sopenharmony_ci#include <linux/if_ether.h>
4462306a36Sopenharmony_ci#include <net/addrconf.h>
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#include <rdma/ib_verbs.h>
4762306a36Sopenharmony_ci#include <rdma/ib_user_verbs.h>
4862306a36Sopenharmony_ci#include <rdma/ib_umem.h>
4962306a36Sopenharmony_ci#include <rdma/ib_addr.h>
5062306a36Sopenharmony_ci#include <rdma/ib_mad.h>
5162306a36Sopenharmony_ci#include <rdma/ib_cache.h>
5262306a36Sopenharmony_ci#include <rdma/uverbs_ioctl.h>
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#include "bnxt_ulp.h"
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#include "roce_hsi.h"
5762306a36Sopenharmony_ci#include "qplib_res.h"
5862306a36Sopenharmony_ci#include "qplib_sp.h"
5962306a36Sopenharmony_ci#include "qplib_fp.h"
6062306a36Sopenharmony_ci#include "qplib_rcfw.h"
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#include "bnxt_re.h"
6362306a36Sopenharmony_ci#include "ib_verbs.h"
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#include <rdma/uverbs_types.h>
6662306a36Sopenharmony_ci#include <rdma/uverbs_std_types.h>
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#include <rdma/ib_user_ioctl_cmds.h>
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define UVERBS_MODULE_NAME bnxt_re
7162306a36Sopenharmony_ci#include <rdma/uverbs_named_ioctl.h>
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#include <rdma/bnxt_re-abi.h>
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic int __from_ib_access_flags(int iflags)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	int qflags = 0;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (iflags & IB_ACCESS_LOCAL_WRITE)
8062306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
8162306a36Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_READ)
8262306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
8362306a36Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_WRITE)
8462306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
8562306a36Sopenharmony_ci	if (iflags & IB_ACCESS_REMOTE_ATOMIC)
8662306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
8762306a36Sopenharmony_ci	if (iflags & IB_ACCESS_MW_BIND)
8862306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
8962306a36Sopenharmony_ci	if (iflags & IB_ZERO_BASED)
9062306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
9162306a36Sopenharmony_ci	if (iflags & IB_ACCESS_ON_DEMAND)
9262306a36Sopenharmony_ci		qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
9362306a36Sopenharmony_ci	return qflags;
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic enum ib_access_flags __to_ib_access_flags(int qflags)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	enum ib_access_flags iflags = 0;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
10162306a36Sopenharmony_ci		iflags |= IB_ACCESS_LOCAL_WRITE;
10262306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
10362306a36Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_WRITE;
10462306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
10562306a36Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_READ;
10662306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
10762306a36Sopenharmony_ci		iflags |= IB_ACCESS_REMOTE_ATOMIC;
10862306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
10962306a36Sopenharmony_ci		iflags |= IB_ACCESS_MW_BIND;
11062306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
11162306a36Sopenharmony_ci		iflags |= IB_ZERO_BASED;
11262306a36Sopenharmony_ci	if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
11362306a36Sopenharmony_ci		iflags |= IB_ACCESS_ON_DEMAND;
11462306a36Sopenharmony_ci	return iflags;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
11862306a36Sopenharmony_ci			     struct bnxt_qplib_sge *sg_list, int num)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	int i, total = 0;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
12362306a36Sopenharmony_ci		sg_list[i].addr = ib_sg_list[i].addr;
12462306a36Sopenharmony_ci		sg_list[i].lkey = ib_sg_list[i].lkey;
12562306a36Sopenharmony_ci		sg_list[i].size = ib_sg_list[i].length;
12662306a36Sopenharmony_ci		total += sg_list[i].size;
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci	return total;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/* Device */
13262306a36Sopenharmony_ciint bnxt_re_query_device(struct ib_device *ibdev,
13362306a36Sopenharmony_ci			 struct ib_device_attr *ib_attr,
13462306a36Sopenharmony_ci			 struct ib_udata *udata)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
13762306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	memset(ib_attr, 0, sizeof(*ib_attr));
14062306a36Sopenharmony_ci	memcpy(&ib_attr->fw_ver, dev_attr->fw_ver,
14162306a36Sopenharmony_ci	       min(sizeof(dev_attr->fw_ver),
14262306a36Sopenharmony_ci		   sizeof(ib_attr->fw_ver)));
14362306a36Sopenharmony_ci	addrconf_addr_eui48((u8 *)&ib_attr->sys_image_guid,
14462306a36Sopenharmony_ci			    rdev->netdev->dev_addr);
14562306a36Sopenharmony_ci	ib_attr->max_mr_size = BNXT_RE_MAX_MR_SIZE;
14662306a36Sopenharmony_ci	ib_attr->page_size_cap = BNXT_RE_PAGE_SIZE_SUPPORTED;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
14962306a36Sopenharmony_ci	ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
15062306a36Sopenharmony_ci	ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
15162306a36Sopenharmony_ci	ib_attr->max_qp = dev_attr->max_qp;
15262306a36Sopenharmony_ci	ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
15362306a36Sopenharmony_ci	ib_attr->device_cap_flags =
15462306a36Sopenharmony_ci				    IB_DEVICE_CURR_QP_STATE_MOD
15562306a36Sopenharmony_ci				    | IB_DEVICE_RC_RNR_NAK_GEN
15662306a36Sopenharmony_ci				    | IB_DEVICE_SHUTDOWN_PORT
15762306a36Sopenharmony_ci				    | IB_DEVICE_SYS_IMAGE_GUID
15862306a36Sopenharmony_ci				    | IB_DEVICE_RESIZE_MAX_WR
15962306a36Sopenharmony_ci				    | IB_DEVICE_PORT_ACTIVE_EVENT
16062306a36Sopenharmony_ci				    | IB_DEVICE_N_NOTIFY_CQ
16162306a36Sopenharmony_ci				    | IB_DEVICE_MEM_WINDOW
16262306a36Sopenharmony_ci				    | IB_DEVICE_MEM_WINDOW_TYPE_2B
16362306a36Sopenharmony_ci				    | IB_DEVICE_MEM_MGT_EXTENSIONS;
16462306a36Sopenharmony_ci	ib_attr->kernel_cap_flags = IBK_LOCAL_DMA_LKEY;
16562306a36Sopenharmony_ci	ib_attr->max_send_sge = dev_attr->max_qp_sges;
16662306a36Sopenharmony_ci	ib_attr->max_recv_sge = dev_attr->max_qp_sges;
16762306a36Sopenharmony_ci	ib_attr->max_sge_rd = dev_attr->max_qp_sges;
16862306a36Sopenharmony_ci	ib_attr->max_cq = dev_attr->max_cq;
16962306a36Sopenharmony_ci	ib_attr->max_cqe = dev_attr->max_cq_wqes;
17062306a36Sopenharmony_ci	ib_attr->max_mr = dev_attr->max_mr;
17162306a36Sopenharmony_ci	ib_attr->max_pd = dev_attr->max_pd;
17262306a36Sopenharmony_ci	ib_attr->max_qp_rd_atom = dev_attr->max_qp_rd_atom;
17362306a36Sopenharmony_ci	ib_attr->max_qp_init_rd_atom = dev_attr->max_qp_init_rd_atom;
17462306a36Sopenharmony_ci	ib_attr->atomic_cap = IB_ATOMIC_NONE;
17562306a36Sopenharmony_ci	ib_attr->masked_atomic_cap = IB_ATOMIC_NONE;
17662306a36Sopenharmony_ci	if (dev_attr->is_atomic) {
17762306a36Sopenharmony_ci		ib_attr->atomic_cap = IB_ATOMIC_GLOB;
17862306a36Sopenharmony_ci		ib_attr->masked_atomic_cap = IB_ATOMIC_GLOB;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	ib_attr->max_ee_rd_atom = 0;
18262306a36Sopenharmony_ci	ib_attr->max_res_rd_atom = 0;
18362306a36Sopenharmony_ci	ib_attr->max_ee_init_rd_atom = 0;
18462306a36Sopenharmony_ci	ib_attr->max_ee = 0;
18562306a36Sopenharmony_ci	ib_attr->max_rdd = 0;
18662306a36Sopenharmony_ci	ib_attr->max_mw = dev_attr->max_mw;
18762306a36Sopenharmony_ci	ib_attr->max_raw_ipv6_qp = 0;
18862306a36Sopenharmony_ci	ib_attr->max_raw_ethy_qp = dev_attr->max_raw_ethy_qp;
18962306a36Sopenharmony_ci	ib_attr->max_mcast_grp = 0;
19062306a36Sopenharmony_ci	ib_attr->max_mcast_qp_attach = 0;
19162306a36Sopenharmony_ci	ib_attr->max_total_mcast_qp_attach = 0;
19262306a36Sopenharmony_ci	ib_attr->max_ah = dev_attr->max_ah;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	ib_attr->max_srq = dev_attr->max_srq;
19562306a36Sopenharmony_ci	ib_attr->max_srq_wr = dev_attr->max_srq_wqes;
19662306a36Sopenharmony_ci	ib_attr->max_srq_sge = dev_attr->max_srq_sges;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	ib_attr->max_fast_reg_page_list_len = MAX_PBL_LVL_1_PGS;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	ib_attr->max_pkeys = 1;
20162306a36Sopenharmony_ci	ib_attr->local_ca_ack_delay = BNXT_RE_DEFAULT_ACK_DELAY;
20262306a36Sopenharmony_ci	return 0;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/* Port */
20662306a36Sopenharmony_ciint bnxt_re_query_port(struct ib_device *ibdev, u32 port_num,
20762306a36Sopenharmony_ci		       struct ib_port_attr *port_attr)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
21062306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
21162306a36Sopenharmony_ci	int rc;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	memset(port_attr, 0, sizeof(*port_attr));
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (netif_running(rdev->netdev) && netif_carrier_ok(rdev->netdev)) {
21662306a36Sopenharmony_ci		port_attr->state = IB_PORT_ACTIVE;
21762306a36Sopenharmony_ci		port_attr->phys_state = IB_PORT_PHYS_STATE_LINK_UP;
21862306a36Sopenharmony_ci	} else {
21962306a36Sopenharmony_ci		port_attr->state = IB_PORT_DOWN;
22062306a36Sopenharmony_ci		port_attr->phys_state = IB_PORT_PHYS_STATE_DISABLED;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci	port_attr->max_mtu = IB_MTU_4096;
22362306a36Sopenharmony_ci	port_attr->active_mtu = iboe_get_mtu(rdev->netdev->mtu);
22462306a36Sopenharmony_ci	port_attr->gid_tbl_len = dev_attr->max_sgid;
22562306a36Sopenharmony_ci	port_attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP |
22662306a36Sopenharmony_ci				    IB_PORT_DEVICE_MGMT_SUP |
22762306a36Sopenharmony_ci				    IB_PORT_VENDOR_CLASS_SUP;
22862306a36Sopenharmony_ci	port_attr->ip_gids = true;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	port_attr->max_msg_sz = (u32)BNXT_RE_MAX_MR_SIZE_LOW;
23162306a36Sopenharmony_ci	port_attr->bad_pkey_cntr = 0;
23262306a36Sopenharmony_ci	port_attr->qkey_viol_cntr = 0;
23362306a36Sopenharmony_ci	port_attr->pkey_tbl_len = dev_attr->max_pkey;
23462306a36Sopenharmony_ci	port_attr->lid = 0;
23562306a36Sopenharmony_ci	port_attr->sm_lid = 0;
23662306a36Sopenharmony_ci	port_attr->lmc = 0;
23762306a36Sopenharmony_ci	port_attr->max_vl_num = 4;
23862306a36Sopenharmony_ci	port_attr->sm_sl = 0;
23962306a36Sopenharmony_ci	port_attr->subnet_timeout = 0;
24062306a36Sopenharmony_ci	port_attr->init_type_reply = 0;
24162306a36Sopenharmony_ci	rc = ib_get_eth_speed(&rdev->ibdev, port_num, &port_attr->active_speed,
24262306a36Sopenharmony_ci			      &port_attr->active_width);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return rc;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ciint bnxt_re_get_port_immutable(struct ib_device *ibdev, u32 port_num,
24862306a36Sopenharmony_ci			       struct ib_port_immutable *immutable)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	struct ib_port_attr port_attr;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	if (bnxt_re_query_port(ibdev, port_num, &port_attr))
25362306a36Sopenharmony_ci		return -EINVAL;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	immutable->pkey_tbl_len = port_attr.pkey_tbl_len;
25662306a36Sopenharmony_ci	immutable->gid_tbl_len = port_attr.gid_tbl_len;
25762306a36Sopenharmony_ci	immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
25862306a36Sopenharmony_ci	immutable->core_cap_flags |= RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP;
25962306a36Sopenharmony_ci	immutable->max_mad_size = IB_MGMT_MAD_SIZE;
26062306a36Sopenharmony_ci	return 0;
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_civoid bnxt_re_query_fw_str(struct ib_device *ibdev, char *str)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%d.%d",
26862306a36Sopenharmony_ci		 rdev->dev_attr.fw_ver[0], rdev->dev_attr.fw_ver[1],
26962306a36Sopenharmony_ci		 rdev->dev_attr.fw_ver[2], rdev->dev_attr.fw_ver[3]);
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ciint bnxt_re_query_pkey(struct ib_device *ibdev, u32 port_num,
27362306a36Sopenharmony_ci		       u16 index, u16 *pkey)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	if (index > 0)
27662306a36Sopenharmony_ci		return -EINVAL;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	*pkey = IB_DEFAULT_PKEY_FULL;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	return 0;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ciint bnxt_re_query_gid(struct ib_device *ibdev, u32 port_num,
28462306a36Sopenharmony_ci		      int index, union ib_gid *gid)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
28762306a36Sopenharmony_ci	int rc;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* Ignore port_num */
29062306a36Sopenharmony_ci	memset(gid, 0, sizeof(*gid));
29162306a36Sopenharmony_ci	rc = bnxt_qplib_get_sgid(&rdev->qplib_res,
29262306a36Sopenharmony_ci				 &rdev->qplib_res.sgid_tbl, index,
29362306a36Sopenharmony_ci				 (struct bnxt_qplib_gid *)gid);
29462306a36Sopenharmony_ci	return rc;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ciint bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	int rc = 0;
30062306a36Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
30162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
30262306a36Sopenharmony_ci	struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
30362306a36Sopenharmony_ci	struct bnxt_qplib_gid *gid_to_del;
30462306a36Sopenharmony_ci	u16 vlan_id = 0xFFFF;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* Delete the entry from the hardware */
30762306a36Sopenharmony_ci	ctx = *context;
30862306a36Sopenharmony_ci	if (!ctx)
30962306a36Sopenharmony_ci		return -EINVAL;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	if (sgid_tbl && sgid_tbl->active) {
31262306a36Sopenharmony_ci		if (ctx->idx >= sgid_tbl->max)
31362306a36Sopenharmony_ci			return -EINVAL;
31462306a36Sopenharmony_ci		gid_to_del = &sgid_tbl->tbl[ctx->idx].gid;
31562306a36Sopenharmony_ci		vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id;
31662306a36Sopenharmony_ci		/* DEL_GID is called in WQ context(netdevice_event_work_handler)
31762306a36Sopenharmony_ci		 * or via the ib_unregister_device path. In the former case QP1
31862306a36Sopenharmony_ci		 * may not be destroyed yet, in which case just return as FW
31962306a36Sopenharmony_ci		 * needs that entry to be present and will fail it's deletion.
32062306a36Sopenharmony_ci		 * We could get invoked again after QP1 is destroyed OR get an
32162306a36Sopenharmony_ci		 * ADD_GID call with a different GID value for the same index
32262306a36Sopenharmony_ci		 * where we issue MODIFY_GID cmd to update the GID entry -- TBD
32362306a36Sopenharmony_ci		 */
32462306a36Sopenharmony_ci		if (ctx->idx == 0 &&
32562306a36Sopenharmony_ci		    rdma_link_local_addr((struct in6_addr *)gid_to_del) &&
32662306a36Sopenharmony_ci		    ctx->refcnt == 1 && rdev->gsi_ctx.gsi_sqp) {
32762306a36Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
32862306a36Sopenharmony_ci				  "Trying to delete GID0 while QP1 is alive\n");
32962306a36Sopenharmony_ci			return -EFAULT;
33062306a36Sopenharmony_ci		}
33162306a36Sopenharmony_ci		ctx->refcnt--;
33262306a36Sopenharmony_ci		if (!ctx->refcnt) {
33362306a36Sopenharmony_ci			rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
33462306a36Sopenharmony_ci						 vlan_id,  true);
33562306a36Sopenharmony_ci			if (rc) {
33662306a36Sopenharmony_ci				ibdev_err(&rdev->ibdev,
33762306a36Sopenharmony_ci					  "Failed to remove GID: %#x", rc);
33862306a36Sopenharmony_ci			} else {
33962306a36Sopenharmony_ci				ctx_tbl = sgid_tbl->ctx;
34062306a36Sopenharmony_ci				ctx_tbl[ctx->idx] = NULL;
34162306a36Sopenharmony_ci				kfree(ctx);
34262306a36Sopenharmony_ci			}
34362306a36Sopenharmony_ci		}
34462306a36Sopenharmony_ci	} else {
34562306a36Sopenharmony_ci		return -EINVAL;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	return rc;
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ciint bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	int rc;
35362306a36Sopenharmony_ci	u32 tbl_idx = 0;
35462306a36Sopenharmony_ci	u16 vlan_id = 0xFFFF;
35562306a36Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
35662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
35762306a36Sopenharmony_ci	struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL);
36062306a36Sopenharmony_ci	if (rc)
36162306a36Sopenharmony_ci		return rc;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid,
36462306a36Sopenharmony_ci				 rdev->qplib_res.netdev->dev_addr,
36562306a36Sopenharmony_ci				 vlan_id, true, &tbl_idx);
36662306a36Sopenharmony_ci	if (rc == -EALREADY) {
36762306a36Sopenharmony_ci		ctx_tbl = sgid_tbl->ctx;
36862306a36Sopenharmony_ci		ctx_tbl[tbl_idx]->refcnt++;
36962306a36Sopenharmony_ci		*context = ctx_tbl[tbl_idx];
37062306a36Sopenharmony_ci		return 0;
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	if (rc < 0) {
37462306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to add GID: %#x", rc);
37562306a36Sopenharmony_ci		return rc;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
37962306a36Sopenharmony_ci	if (!ctx)
38062306a36Sopenharmony_ci		return -ENOMEM;
38162306a36Sopenharmony_ci	ctx_tbl = sgid_tbl->ctx;
38262306a36Sopenharmony_ci	ctx->idx = tbl_idx;
38362306a36Sopenharmony_ci	ctx->refcnt = 1;
38462306a36Sopenharmony_ci	ctx_tbl[tbl_idx] = ctx;
38562306a36Sopenharmony_ci	*context = ctx;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	return rc;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cienum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
39162306a36Sopenharmony_ci					    u32 port_num)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	return IB_LINK_LAYER_ETHERNET;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci#define	BNXT_RE_FENCE_PBL_SIZE	DIV_ROUND_UP(BNXT_RE_FENCE_BYTES, PAGE_SIZE)
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic void bnxt_re_create_fence_wqe(struct bnxt_re_pd *pd)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
40162306a36Sopenharmony_ci	struct ib_mr *ib_mr = &fence->mr->ib_mr;
40262306a36Sopenharmony_ci	struct bnxt_qplib_swqe *wqe = &fence->bind_wqe;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	memset(wqe, 0, sizeof(*wqe));
40562306a36Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW;
40662306a36Sopenharmony_ci	wqe->wr_id = BNXT_QPLIB_FENCE_WRID;
40762306a36Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
40862306a36Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
40962306a36Sopenharmony_ci	wqe->bind.zero_based = false;
41062306a36Sopenharmony_ci	wqe->bind.parent_l_key = ib_mr->lkey;
41162306a36Sopenharmony_ci	wqe->bind.va = (u64)(unsigned long)fence->va;
41262306a36Sopenharmony_ci	wqe->bind.length = fence->size;
41362306a36Sopenharmony_ci	wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ);
41462306a36Sopenharmony_ci	wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	/* Save the initial rkey in fence structure for now;
41762306a36Sopenharmony_ci	 * wqe->bind.r_key will be set at (re)bind time.
41862306a36Sopenharmony_ci	 */
41962306a36Sopenharmony_ci	fence->bind_rkey = ib_inc_rkey(fence->mw->rkey);
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic int bnxt_re_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp,
42562306a36Sopenharmony_ci					     qplib_qp);
42662306a36Sopenharmony_ci	struct ib_pd *ib_pd = qp->ib_qp.pd;
42762306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
42862306a36Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
42962306a36Sopenharmony_ci	struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe;
43062306a36Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
43162306a36Sopenharmony_ci	int rc;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	memcpy(&wqe, fence_wqe, sizeof(wqe));
43462306a36Sopenharmony_ci	wqe.bind.r_key = fence->bind_rkey;
43562306a36Sopenharmony_ci	fence->bind_rkey = ib_inc_rkey(fence->bind_rkey);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	ibdev_dbg(&qp->rdev->ibdev,
43862306a36Sopenharmony_ci		  "Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n",
43962306a36Sopenharmony_ci		wqe.bind.r_key, qp->qplib_qp.id, pd);
44062306a36Sopenharmony_ci	rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
44162306a36Sopenharmony_ci	if (rc) {
44262306a36Sopenharmony_ci		ibdev_err(&qp->rdev->ibdev, "Failed to bind fence-WQE\n");
44362306a36Sopenharmony_ci		return rc;
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	return rc;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic void bnxt_re_destroy_fence_mr(struct bnxt_re_pd *pd)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
45362306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
45462306a36Sopenharmony_ci	struct device *dev = &rdev->en_dev->pdev->dev;
45562306a36Sopenharmony_ci	struct bnxt_re_mr *mr = fence->mr;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	if (fence->mw) {
45862306a36Sopenharmony_ci		bnxt_re_dealloc_mw(fence->mw);
45962306a36Sopenharmony_ci		fence->mw = NULL;
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci	if (mr) {
46262306a36Sopenharmony_ci		if (mr->ib_mr.rkey)
46362306a36Sopenharmony_ci			bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr,
46462306a36Sopenharmony_ci					     true);
46562306a36Sopenharmony_ci		if (mr->ib_mr.lkey)
46662306a36Sopenharmony_ci			bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
46762306a36Sopenharmony_ci		kfree(mr);
46862306a36Sopenharmony_ci		fence->mr = NULL;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci	if (fence->dma_addr) {
47162306a36Sopenharmony_ci		dma_unmap_single(dev, fence->dma_addr, BNXT_RE_FENCE_BYTES,
47262306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
47362306a36Sopenharmony_ci		fence->dma_addr = 0;
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND;
48062306a36Sopenharmony_ci	struct bnxt_re_fence_data *fence = &pd->fence;
48162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
48262306a36Sopenharmony_ci	struct device *dev = &rdev->en_dev->pdev->dev;
48362306a36Sopenharmony_ci	struct bnxt_re_mr *mr = NULL;
48462306a36Sopenharmony_ci	dma_addr_t dma_addr = 0;
48562306a36Sopenharmony_ci	struct ib_mw *mw;
48662306a36Sopenharmony_ci	int rc;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	dma_addr = dma_map_single(dev, fence->va, BNXT_RE_FENCE_BYTES,
48962306a36Sopenharmony_ci				  DMA_BIDIRECTIONAL);
49062306a36Sopenharmony_ci	rc = dma_mapping_error(dev, dma_addr);
49162306a36Sopenharmony_ci	if (rc) {
49262306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to dma-map fence-MR-mem\n");
49362306a36Sopenharmony_ci		rc = -EIO;
49462306a36Sopenharmony_ci		fence->dma_addr = 0;
49562306a36Sopenharmony_ci		goto fail;
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci	fence->dma_addr = dma_addr;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	/* Allocate a MR */
50062306a36Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
50162306a36Sopenharmony_ci	if (!mr) {
50262306a36Sopenharmony_ci		rc = -ENOMEM;
50362306a36Sopenharmony_ci		goto fail;
50462306a36Sopenharmony_ci	}
50562306a36Sopenharmony_ci	fence->mr = mr;
50662306a36Sopenharmony_ci	mr->rdev = rdev;
50762306a36Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
50862306a36Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
50962306a36Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
51062306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
51162306a36Sopenharmony_ci	if (rc) {
51262306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to alloc fence-HW-MR\n");
51362306a36Sopenharmony_ci		goto fail;
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	/* Register MR */
51762306a36Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
51862306a36Sopenharmony_ci	mr->qplib_mr.va = (u64)(unsigned long)fence->va;
51962306a36Sopenharmony_ci	mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
52062306a36Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, NULL,
52162306a36Sopenharmony_ci			       BNXT_RE_FENCE_PBL_SIZE, PAGE_SIZE);
52262306a36Sopenharmony_ci	if (rc) {
52362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to register fence-MR\n");
52462306a36Sopenharmony_ci		goto fail;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.rkey;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	/* Create a fence MW only for kernel consumers */
52962306a36Sopenharmony_ci	mw = bnxt_re_alloc_mw(&pd->ib_pd, IB_MW_TYPE_1, NULL);
53062306a36Sopenharmony_ci	if (IS_ERR(mw)) {
53162306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
53262306a36Sopenharmony_ci			  "Failed to create fence-MW for PD: %p\n", pd);
53362306a36Sopenharmony_ci		rc = PTR_ERR(mw);
53462306a36Sopenharmony_ci		goto fail;
53562306a36Sopenharmony_ci	}
53662306a36Sopenharmony_ci	fence->mw = mw;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	bnxt_re_create_fence_wqe(pd);
53962306a36Sopenharmony_ci	return 0;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cifail:
54262306a36Sopenharmony_ci	bnxt_re_destroy_fence_mr(pd);
54362306a36Sopenharmony_ci	return rc;
54462306a36Sopenharmony_ci}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_cistatic struct bnxt_re_user_mmap_entry*
54762306a36Sopenharmony_cibnxt_re_mmap_entry_insert(struct bnxt_re_ucontext *uctx, u64 mem_offset,
54862306a36Sopenharmony_ci			  enum bnxt_re_mmap_flag mmap_flag, u64 *offset)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *entry;
55162306a36Sopenharmony_ci	int ret;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
55462306a36Sopenharmony_ci	if (!entry)
55562306a36Sopenharmony_ci		return NULL;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	entry->mem_offset = mem_offset;
55862306a36Sopenharmony_ci	entry->mmap_flag = mmap_flag;
55962306a36Sopenharmony_ci	entry->uctx = uctx;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	switch (mmap_flag) {
56262306a36Sopenharmony_ci	case BNXT_RE_MMAP_SH_PAGE:
56362306a36Sopenharmony_ci		ret = rdma_user_mmap_entry_insert_exact(&uctx->ib_uctx,
56462306a36Sopenharmony_ci							&entry->rdma_entry, PAGE_SIZE, 0);
56562306a36Sopenharmony_ci		break;
56662306a36Sopenharmony_ci	case BNXT_RE_MMAP_UC_DB:
56762306a36Sopenharmony_ci	case BNXT_RE_MMAP_WC_DB:
56862306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_BAR:
56962306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_PAGE:
57062306a36Sopenharmony_ci		ret = rdma_user_mmap_entry_insert(&uctx->ib_uctx,
57162306a36Sopenharmony_ci						  &entry->rdma_entry, PAGE_SIZE);
57262306a36Sopenharmony_ci		break;
57362306a36Sopenharmony_ci	default:
57462306a36Sopenharmony_ci		ret = -EINVAL;
57562306a36Sopenharmony_ci		break;
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	if (ret) {
57962306a36Sopenharmony_ci		kfree(entry);
58062306a36Sopenharmony_ci		return NULL;
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci	if (offset)
58362306a36Sopenharmony_ci		*offset = rdma_user_mmap_get_offset(&entry->rdma_entry);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	return entry;
58662306a36Sopenharmony_ci}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci/* Protection Domains */
58962306a36Sopenharmony_ciint bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
59262306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	if (udata) {
59562306a36Sopenharmony_ci		rdma_user_mmap_entry_remove(pd->pd_db_mmap);
59662306a36Sopenharmony_ci		pd->pd_db_mmap = NULL;
59762306a36Sopenharmony_ci	}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	bnxt_re_destroy_fence_mr(pd);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	if (pd->qplib_pd.id) {
60262306a36Sopenharmony_ci		if (!bnxt_qplib_dealloc_pd(&rdev->qplib_res,
60362306a36Sopenharmony_ci					   &rdev->qplib_res.pd_tbl,
60462306a36Sopenharmony_ci					   &pd->qplib_pd))
60562306a36Sopenharmony_ci			atomic_dec(&rdev->stats.res.pd_count);
60662306a36Sopenharmony_ci	}
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ciint bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	struct ib_device *ibdev = ibpd->device;
61362306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
61462306a36Sopenharmony_ci	struct bnxt_re_ucontext *ucntx = rdma_udata_to_drv_context(
61562306a36Sopenharmony_ci		udata, struct bnxt_re_ucontext, ib_uctx);
61662306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ibpd, struct bnxt_re_pd, ib_pd);
61762306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *entry = NULL;
61862306a36Sopenharmony_ci	u32 active_pds;
61962306a36Sopenharmony_ci	int rc = 0;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	pd->rdev = rdev;
62262306a36Sopenharmony_ci	if (bnxt_qplib_alloc_pd(&rdev->qplib_res, &pd->qplib_pd)) {
62362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate HW PD");
62462306a36Sopenharmony_ci		rc = -ENOMEM;
62562306a36Sopenharmony_ci		goto fail;
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	if (udata) {
62962306a36Sopenharmony_ci		struct bnxt_re_pd_resp resp = {};
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci		if (!ucntx->dpi.dbr) {
63262306a36Sopenharmony_ci			/* Allocate DPI in alloc_pd to avoid failing of
63362306a36Sopenharmony_ci			 * ibv_devinfo and family of application when DPIs
63462306a36Sopenharmony_ci			 * are depleted.
63562306a36Sopenharmony_ci			 */
63662306a36Sopenharmony_ci			if (bnxt_qplib_alloc_dpi(&rdev->qplib_res,
63762306a36Sopenharmony_ci						 &ucntx->dpi, ucntx, BNXT_QPLIB_DPI_TYPE_UC)) {
63862306a36Sopenharmony_ci				rc = -ENOMEM;
63962306a36Sopenharmony_ci				goto dbfail;
64062306a36Sopenharmony_ci			}
64162306a36Sopenharmony_ci		}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		resp.pdid = pd->qplib_pd.id;
64462306a36Sopenharmony_ci		/* Still allow mapping this DBR to the new user PD. */
64562306a36Sopenharmony_ci		resp.dpi = ucntx->dpi.dpi;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci		entry = bnxt_re_mmap_entry_insert(ucntx, (u64)ucntx->dpi.umdbr,
64862306a36Sopenharmony_ci						  BNXT_RE_MMAP_UC_DB, &resp.dbr);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci		if (!entry) {
65162306a36Sopenharmony_ci			rc = -ENOMEM;
65262306a36Sopenharmony_ci			goto dbfail;
65362306a36Sopenharmony_ci		}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci		pd->pd_db_mmap = &entry->rdma_entry;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, min(sizeof(resp), udata->outlen));
65862306a36Sopenharmony_ci		if (rc) {
65962306a36Sopenharmony_ci			rdma_user_mmap_entry_remove(pd->pd_db_mmap);
66062306a36Sopenharmony_ci			rc = -EFAULT;
66162306a36Sopenharmony_ci			goto dbfail;
66262306a36Sopenharmony_ci		}
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	if (!udata)
66662306a36Sopenharmony_ci		if (bnxt_re_create_fence_mr(pd))
66762306a36Sopenharmony_ci			ibdev_warn(&rdev->ibdev,
66862306a36Sopenharmony_ci				   "Failed to create Fence-MR\n");
66962306a36Sopenharmony_ci	active_pds = atomic_inc_return(&rdev->stats.res.pd_count);
67062306a36Sopenharmony_ci	if (active_pds > rdev->stats.res.pd_watermark)
67162306a36Sopenharmony_ci		rdev->stats.res.pd_watermark = active_pds;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	return 0;
67462306a36Sopenharmony_cidbfail:
67562306a36Sopenharmony_ci	bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
67662306a36Sopenharmony_ci			      &pd->qplib_pd);
67762306a36Sopenharmony_cifail:
67862306a36Sopenharmony_ci	return rc;
67962306a36Sopenharmony_ci}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci/* Address Handles */
68262306a36Sopenharmony_ciint bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
68562306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = ah->rdev;
68662306a36Sopenharmony_ci	bool block = true;
68762306a36Sopenharmony_ci	int rc;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	block = !(flags & RDMA_DESTROY_AH_SLEEPABLE);
69062306a36Sopenharmony_ci	rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah, block);
69162306a36Sopenharmony_ci	if (BNXT_RE_CHECK_RC(rc)) {
69262306a36Sopenharmony_ci		if (rc == -ETIMEDOUT)
69362306a36Sopenharmony_ci			rc = 0;
69462306a36Sopenharmony_ci		else
69562306a36Sopenharmony_ci			goto fail;
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.ah_count);
69862306a36Sopenharmony_cifail:
69962306a36Sopenharmony_ci	return rc;
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	u8 nw_type;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	switch (ntype) {
70762306a36Sopenharmony_ci	case RDMA_NETWORK_IPV4:
70862306a36Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V2IPV4;
70962306a36Sopenharmony_ci		break;
71062306a36Sopenharmony_ci	case RDMA_NETWORK_IPV6:
71162306a36Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V2IPV6;
71262306a36Sopenharmony_ci		break;
71362306a36Sopenharmony_ci	default:
71462306a36Sopenharmony_ci		nw_type = CMDQ_CREATE_AH_TYPE_V1;
71562306a36Sopenharmony_ci		break;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci	return nw_type;
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ciint bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_ah_init_attr *init_attr,
72162306a36Sopenharmony_ci		      struct ib_udata *udata)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	struct ib_pd *ib_pd = ib_ah->pd;
72462306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
72562306a36Sopenharmony_ci	struct rdma_ah_attr *ah_attr = init_attr->ah_attr;
72662306a36Sopenharmony_ci	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
72762306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
72862306a36Sopenharmony_ci	const struct ib_gid_attr *sgid_attr;
72962306a36Sopenharmony_ci	struct bnxt_re_gid_ctx *ctx;
73062306a36Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
73162306a36Sopenharmony_ci	u32 active_ahs;
73262306a36Sopenharmony_ci	u8 nw_type;
73362306a36Sopenharmony_ci	int rc;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) {
73662306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to alloc AH: GRH not set");
73762306a36Sopenharmony_ci		return -EINVAL;
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	ah->rdev = rdev;
74162306a36Sopenharmony_ci	ah->qplib_ah.pd = &pd->qplib_pd;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	/* Supply the configuration for the HW */
74462306a36Sopenharmony_ci	memcpy(ah->qplib_ah.dgid.data, grh->dgid.raw,
74562306a36Sopenharmony_ci	       sizeof(union ib_gid));
74662306a36Sopenharmony_ci	sgid_attr = grh->sgid_attr;
74762306a36Sopenharmony_ci	/* Get the HW context of the GID. The reference
74862306a36Sopenharmony_ci	 * of GID table entry is already taken by the caller.
74962306a36Sopenharmony_ci	 */
75062306a36Sopenharmony_ci	ctx = rdma_read_gid_hw_context(sgid_attr);
75162306a36Sopenharmony_ci	ah->qplib_ah.sgid_index = ctx->idx;
75262306a36Sopenharmony_ci	ah->qplib_ah.host_sgid_index = grh->sgid_index;
75362306a36Sopenharmony_ci	ah->qplib_ah.traffic_class = grh->traffic_class;
75462306a36Sopenharmony_ci	ah->qplib_ah.flow_label = grh->flow_label;
75562306a36Sopenharmony_ci	ah->qplib_ah.hop_limit = grh->hop_limit;
75662306a36Sopenharmony_ci	ah->qplib_ah.sl = rdma_ah_get_sl(ah_attr);
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	/* Get network header type for this GID */
75962306a36Sopenharmony_ci	nw_type = rdma_gid_attr_network_type(sgid_attr);
76062306a36Sopenharmony_ci	ah->qplib_ah.nw_type = bnxt_re_stack_to_dev_nw_type(nw_type);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	memcpy(ah->qplib_ah.dmac, ah_attr->roce.dmac, ETH_ALEN);
76362306a36Sopenharmony_ci	rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah,
76462306a36Sopenharmony_ci				  !(init_attr->flags &
76562306a36Sopenharmony_ci				    RDMA_CREATE_AH_SLEEPABLE));
76662306a36Sopenharmony_ci	if (rc) {
76762306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate HW AH");
76862306a36Sopenharmony_ci		return rc;
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* Write AVID to shared page. */
77262306a36Sopenharmony_ci	if (udata) {
77362306a36Sopenharmony_ci		struct bnxt_re_ucontext *uctx = rdma_udata_to_drv_context(
77462306a36Sopenharmony_ci			udata, struct bnxt_re_ucontext, ib_uctx);
77562306a36Sopenharmony_ci		unsigned long flag;
77662306a36Sopenharmony_ci		u32 *wrptr;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci		spin_lock_irqsave(&uctx->sh_lock, flag);
77962306a36Sopenharmony_ci		wrptr = (u32 *)(uctx->shpg + BNXT_RE_AVID_OFFT);
78062306a36Sopenharmony_ci		*wrptr = ah->qplib_ah.id;
78162306a36Sopenharmony_ci		wmb(); /* make sure cache is updated. */
78262306a36Sopenharmony_ci		spin_unlock_irqrestore(&uctx->sh_lock, flag);
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci	active_ahs = atomic_inc_return(&rdev->stats.res.ah_count);
78562306a36Sopenharmony_ci	if (active_ahs > rdev->stats.res.ah_watermark)
78662306a36Sopenharmony_ci		rdev->stats.res.ah_watermark = active_ahs;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	return 0;
78962306a36Sopenharmony_ci}
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ciint bnxt_re_query_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	ah_attr->type = ib_ah->type;
79662306a36Sopenharmony_ci	rdma_ah_set_sl(ah_attr, ah->qplib_ah.sl);
79762306a36Sopenharmony_ci	memcpy(ah_attr->roce.dmac, ah->qplib_ah.dmac, ETH_ALEN);
79862306a36Sopenharmony_ci	rdma_ah_set_grh(ah_attr, NULL, 0,
79962306a36Sopenharmony_ci			ah->qplib_ah.host_sgid_index,
80062306a36Sopenharmony_ci			0, ah->qplib_ah.traffic_class);
80162306a36Sopenharmony_ci	rdma_ah_set_dgid_raw(ah_attr, ah->qplib_ah.dgid.data);
80262306a36Sopenharmony_ci	rdma_ah_set_port_num(ah_attr, 1);
80362306a36Sopenharmony_ci	rdma_ah_set_static_rate(ah_attr, 0);
80462306a36Sopenharmony_ci	return 0;
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ciunsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp)
80862306a36Sopenharmony_ci	__acquires(&qp->scq->cq_lock) __acquires(&qp->rcq->cq_lock)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	unsigned long flags;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	spin_lock_irqsave(&qp->scq->cq_lock, flags);
81362306a36Sopenharmony_ci	if (qp->rcq != qp->scq)
81462306a36Sopenharmony_ci		spin_lock(&qp->rcq->cq_lock);
81562306a36Sopenharmony_ci	else
81662306a36Sopenharmony_ci		__acquire(&qp->rcq->cq_lock);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	return flags;
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_civoid bnxt_re_unlock_cqs(struct bnxt_re_qp *qp,
82262306a36Sopenharmony_ci			unsigned long flags)
82362306a36Sopenharmony_ci	__releases(&qp->scq->cq_lock) __releases(&qp->rcq->cq_lock)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	if (qp->rcq != qp->scq)
82662306a36Sopenharmony_ci		spin_unlock(&qp->rcq->cq_lock);
82762306a36Sopenharmony_ci	else
82862306a36Sopenharmony_ci		__release(&qp->rcq->cq_lock);
82962306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->scq->cq_lock, flags);
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	struct bnxt_re_qp *gsi_sqp;
83562306a36Sopenharmony_ci	struct bnxt_re_ah *gsi_sah;
83662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
83762306a36Sopenharmony_ci	int rc;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	rdev = qp->rdev;
84062306a36Sopenharmony_ci	gsi_sqp = rdev->gsi_ctx.gsi_sqp;
84162306a36Sopenharmony_ci	gsi_sah = rdev->gsi_ctx.gsi_sah;
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	ibdev_dbg(&rdev->ibdev, "Destroy the shadow AH\n");
84462306a36Sopenharmony_ci	bnxt_qplib_destroy_ah(&rdev->qplib_res,
84562306a36Sopenharmony_ci			      &gsi_sah->qplib_ah,
84662306a36Sopenharmony_ci			      true);
84762306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.ah_count);
84862306a36Sopenharmony_ci	bnxt_qplib_clean_qp(&qp->qplib_qp);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	ibdev_dbg(&rdev->ibdev, "Destroy the shadow QP\n");
85162306a36Sopenharmony_ci	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &gsi_sqp->qplib_qp);
85262306a36Sopenharmony_ci	if (rc) {
85362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Destroy Shadow QP failed");
85462306a36Sopenharmony_ci		goto fail;
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci	bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	/* remove from active qp list */
85962306a36Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
86062306a36Sopenharmony_ci	list_del(&gsi_sqp->list);
86162306a36Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
86262306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.qp_count);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	kfree(rdev->gsi_ctx.sqp_tbl);
86562306a36Sopenharmony_ci	kfree(gsi_sah);
86662306a36Sopenharmony_ci	kfree(gsi_sqp);
86762306a36Sopenharmony_ci	rdev->gsi_ctx.gsi_sqp = NULL;
86862306a36Sopenharmony_ci	rdev->gsi_ctx.gsi_sah = NULL;
86962306a36Sopenharmony_ci	rdev->gsi_ctx.sqp_tbl = NULL;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	return 0;
87262306a36Sopenharmony_cifail:
87362306a36Sopenharmony_ci	return rc;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci/* Queue Pairs */
87762306a36Sopenharmony_ciint bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
87862306a36Sopenharmony_ci{
87962306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
88062306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp;
88162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
88262306a36Sopenharmony_ci	struct bnxt_qplib_nq *scq_nq = NULL;
88362306a36Sopenharmony_ci	struct bnxt_qplib_nq *rcq_nq = NULL;
88462306a36Sopenharmony_ci	unsigned int flags;
88562306a36Sopenharmony_ci	int rc;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
89062306a36Sopenharmony_ci	if (rc) {
89162306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to destroy HW QP");
89262306a36Sopenharmony_ci		return rc;
89362306a36Sopenharmony_ci	}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	if (rdma_is_kernel_res(&qp->ib_qp.res)) {
89662306a36Sopenharmony_ci		flags = bnxt_re_lock_cqs(qp);
89762306a36Sopenharmony_ci		bnxt_qplib_clean_qp(&qp->qplib_qp);
89862306a36Sopenharmony_ci		bnxt_re_unlock_cqs(qp, flags);
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
90462306a36Sopenharmony_ci		rc = bnxt_re_destroy_gsi_sqp(qp);
90562306a36Sopenharmony_ci		if (rc)
90662306a36Sopenharmony_ci			return rc;
90762306a36Sopenharmony_ci	}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
91062306a36Sopenharmony_ci	list_del(&qp->list);
91162306a36Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
91262306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.qp_count);
91362306a36Sopenharmony_ci	if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_RC)
91462306a36Sopenharmony_ci		atomic_dec(&rdev->stats.res.rc_qp_count);
91562306a36Sopenharmony_ci	else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD)
91662306a36Sopenharmony_ci		atomic_dec(&rdev->stats.res.ud_qp_count);
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	ib_umem_release(qp->rumem);
91962306a36Sopenharmony_ci	ib_umem_release(qp->sumem);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	/* Flush all the entries of notification queue associated with
92262306a36Sopenharmony_ci	 * given qp.
92362306a36Sopenharmony_ci	 */
92462306a36Sopenharmony_ci	scq_nq = qplib_qp->scq->nq;
92562306a36Sopenharmony_ci	rcq_nq = qplib_qp->rcq->nq;
92662306a36Sopenharmony_ci	bnxt_re_synchronize_nq(scq_nq);
92762306a36Sopenharmony_ci	if (scq_nq != rcq_nq)
92862306a36Sopenharmony_ci		bnxt_re_synchronize_nq(rcq_nq);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	return 0;
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic u8 __from_ib_qp_type(enum ib_qp_type type)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	switch (type) {
93662306a36Sopenharmony_ci	case IB_QPT_GSI:
93762306a36Sopenharmony_ci		return CMDQ_CREATE_QP1_TYPE_GSI;
93862306a36Sopenharmony_ci	case IB_QPT_RC:
93962306a36Sopenharmony_ci		return CMDQ_CREATE_QP_TYPE_RC;
94062306a36Sopenharmony_ci	case IB_QPT_UD:
94162306a36Sopenharmony_ci		return CMDQ_CREATE_QP_TYPE_UD;
94262306a36Sopenharmony_ci	default:
94362306a36Sopenharmony_ci		return IB_QPT_MAX;
94462306a36Sopenharmony_ci	}
94562306a36Sopenharmony_ci}
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_cistatic u16 bnxt_re_setup_rwqe_size(struct bnxt_qplib_qp *qplqp,
94862306a36Sopenharmony_ci				   int rsge, int max)
94962306a36Sopenharmony_ci{
95062306a36Sopenharmony_ci	if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
95162306a36Sopenharmony_ci		rsge = max;
95262306a36Sopenharmony_ci	return bnxt_re_get_rwqe_size(rsge);
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic u16 bnxt_re_get_wqe_size(int ilsize, int nsge)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	u16 wqe_size, calc_ils;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	wqe_size = bnxt_re_get_swqe_size(nsge);
96062306a36Sopenharmony_ci	if (ilsize) {
96162306a36Sopenharmony_ci		calc_ils = sizeof(struct sq_send_hdr) + ilsize;
96262306a36Sopenharmony_ci		wqe_size = max_t(u16, calc_ils, wqe_size);
96362306a36Sopenharmony_ci		wqe_size = ALIGN(wqe_size, sizeof(struct sq_send_hdr));
96462306a36Sopenharmony_ci	}
96562306a36Sopenharmony_ci	return wqe_size;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp,
96962306a36Sopenharmony_ci				   struct ib_qp_init_attr *init_attr)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
97262306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
97362306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
97462306a36Sopenharmony_ci	struct bnxt_qplib_q *sq;
97562306a36Sopenharmony_ci	int align, ilsize;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	rdev = qp->rdev;
97862306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
97962306a36Sopenharmony_ci	sq = &qplqp->sq;
98062306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	align = sizeof(struct sq_send_hdr);
98362306a36Sopenharmony_ci	ilsize = ALIGN(init_attr->cap.max_inline_data, align);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
98662306a36Sopenharmony_ci	if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
98762306a36Sopenharmony_ci		return -EINVAL;
98862306a36Sopenharmony_ci	/* For gen p4 and gen p5 backward compatibility mode
98962306a36Sopenharmony_ci	 * wqe size is fixed to 128 bytes
99062306a36Sopenharmony_ci	 */
99162306a36Sopenharmony_ci	if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) &&
99262306a36Sopenharmony_ci			qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
99362306a36Sopenharmony_ci		sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges);
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	if (init_attr->cap.max_inline_data) {
99662306a36Sopenharmony_ci		qplqp->max_inline_data = sq->wqe_size -
99762306a36Sopenharmony_ci			sizeof(struct sq_send_hdr);
99862306a36Sopenharmony_ci		init_attr->cap.max_inline_data = qplqp->max_inline_data;
99962306a36Sopenharmony_ci		if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
100062306a36Sopenharmony_ci			sq->max_sge = qplqp->max_inline_data /
100162306a36Sopenharmony_ci				sizeof(struct sq_sge);
100262306a36Sopenharmony_ci	}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	return 0;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_cistatic int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
100862306a36Sopenharmony_ci				struct bnxt_re_qp *qp, struct ib_udata *udata)
100962306a36Sopenharmony_ci{
101062306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplib_qp;
101162306a36Sopenharmony_ci	struct bnxt_re_ucontext *cntx;
101262306a36Sopenharmony_ci	struct bnxt_re_qp_req ureq;
101362306a36Sopenharmony_ci	int bytes = 0, psn_sz;
101462306a36Sopenharmony_ci	struct ib_umem *umem;
101562306a36Sopenharmony_ci	int psn_nume;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	qplib_qp = &qp->qplib_qp;
101862306a36Sopenharmony_ci	cntx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext,
101962306a36Sopenharmony_ci					 ib_uctx);
102062306a36Sopenharmony_ci	if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
102162306a36Sopenharmony_ci		return -EFAULT;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	bytes = (qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size);
102462306a36Sopenharmony_ci	/* Consider mapping PSN search memory only for RC QPs. */
102562306a36Sopenharmony_ci	if (qplib_qp->type == CMDQ_CREATE_QP_TYPE_RC) {
102662306a36Sopenharmony_ci		psn_sz = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ?
102762306a36Sopenharmony_ci						   sizeof(struct sq_psn_search_ext) :
102862306a36Sopenharmony_ci						   sizeof(struct sq_psn_search);
102962306a36Sopenharmony_ci		psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
103062306a36Sopenharmony_ci			    qplib_qp->sq.max_wqe :
103162306a36Sopenharmony_ci			    ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) /
103262306a36Sopenharmony_ci			      sizeof(struct bnxt_qplib_sge));
103362306a36Sopenharmony_ci		bytes += (psn_nume * psn_sz);
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	bytes = PAGE_ALIGN(bytes);
103762306a36Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes,
103862306a36Sopenharmony_ci			   IB_ACCESS_LOCAL_WRITE);
103962306a36Sopenharmony_ci	if (IS_ERR(umem))
104062306a36Sopenharmony_ci		return PTR_ERR(umem);
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	qp->sumem = umem;
104362306a36Sopenharmony_ci	qplib_qp->sq.sg_info.umem = umem;
104462306a36Sopenharmony_ci	qplib_qp->sq.sg_info.pgsize = PAGE_SIZE;
104562306a36Sopenharmony_ci	qplib_qp->sq.sg_info.pgshft = PAGE_SHIFT;
104662306a36Sopenharmony_ci	qplib_qp->qp_handle = ureq.qp_handle;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	if (!qp->qplib_qp.srq) {
104962306a36Sopenharmony_ci		bytes = (qplib_qp->rq.max_wqe * qplib_qp->rq.wqe_size);
105062306a36Sopenharmony_ci		bytes = PAGE_ALIGN(bytes);
105162306a36Sopenharmony_ci		umem = ib_umem_get(&rdev->ibdev, ureq.qprva, bytes,
105262306a36Sopenharmony_ci				   IB_ACCESS_LOCAL_WRITE);
105362306a36Sopenharmony_ci		if (IS_ERR(umem))
105462306a36Sopenharmony_ci			goto rqfail;
105562306a36Sopenharmony_ci		qp->rumem = umem;
105662306a36Sopenharmony_ci		qplib_qp->rq.sg_info.umem = umem;
105762306a36Sopenharmony_ci		qplib_qp->rq.sg_info.pgsize = PAGE_SIZE;
105862306a36Sopenharmony_ci		qplib_qp->rq.sg_info.pgshft = PAGE_SHIFT;
105962306a36Sopenharmony_ci	}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	qplib_qp->dpi = &cntx->dpi;
106262306a36Sopenharmony_ci	return 0;
106362306a36Sopenharmony_cirqfail:
106462306a36Sopenharmony_ci	ib_umem_release(qp->sumem);
106562306a36Sopenharmony_ci	qp->sumem = NULL;
106662306a36Sopenharmony_ci	memset(&qplib_qp->sq.sg_info, 0, sizeof(qplib_qp->sq.sg_info));
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	return PTR_ERR(umem);
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_cistatic struct bnxt_re_ah *bnxt_re_create_shadow_qp_ah
107262306a36Sopenharmony_ci				(struct bnxt_re_pd *pd,
107362306a36Sopenharmony_ci				 struct bnxt_qplib_res *qp1_res,
107462306a36Sopenharmony_ci				 struct bnxt_qplib_qp *qp1_qp)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
107762306a36Sopenharmony_ci	struct bnxt_re_ah *ah;
107862306a36Sopenharmony_ci	union ib_gid sgid;
107962306a36Sopenharmony_ci	int rc;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	ah = kzalloc(sizeof(*ah), GFP_KERNEL);
108262306a36Sopenharmony_ci	if (!ah)
108362306a36Sopenharmony_ci		return NULL;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	ah->rdev = rdev;
108662306a36Sopenharmony_ci	ah->qplib_ah.pd = &pd->qplib_pd;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	rc = bnxt_re_query_gid(&rdev->ibdev, 1, 0, &sgid);
108962306a36Sopenharmony_ci	if (rc)
109062306a36Sopenharmony_ci		goto fail;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	/* supply the dgid data same as sgid */
109362306a36Sopenharmony_ci	memcpy(ah->qplib_ah.dgid.data, &sgid.raw,
109462306a36Sopenharmony_ci	       sizeof(union ib_gid));
109562306a36Sopenharmony_ci	ah->qplib_ah.sgid_index = 0;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	ah->qplib_ah.traffic_class = 0;
109862306a36Sopenharmony_ci	ah->qplib_ah.flow_label = 0;
109962306a36Sopenharmony_ci	ah->qplib_ah.hop_limit = 1;
110062306a36Sopenharmony_ci	ah->qplib_ah.sl = 0;
110162306a36Sopenharmony_ci	/* Have DMAC same as SMAC */
110262306a36Sopenharmony_ci	ether_addr_copy(ah->qplib_ah.dmac, rdev->netdev->dev_addr);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah, false);
110562306a36Sopenharmony_ci	if (rc) {
110662306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
110762306a36Sopenharmony_ci			  "Failed to allocate HW AH for Shadow QP");
110862306a36Sopenharmony_ci		goto fail;
110962306a36Sopenharmony_ci	}
111062306a36Sopenharmony_ci	atomic_inc(&rdev->stats.res.ah_count);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	return ah;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_cifail:
111562306a36Sopenharmony_ci	kfree(ah);
111662306a36Sopenharmony_ci	return NULL;
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic struct bnxt_re_qp *bnxt_re_create_shadow_qp
112062306a36Sopenharmony_ci				(struct bnxt_re_pd *pd,
112162306a36Sopenharmony_ci				 struct bnxt_qplib_res *qp1_res,
112262306a36Sopenharmony_ci				 struct bnxt_qplib_qp *qp1_qp)
112362306a36Sopenharmony_ci{
112462306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
112562306a36Sopenharmony_ci	struct bnxt_re_qp *qp;
112662306a36Sopenharmony_ci	int rc;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
112962306a36Sopenharmony_ci	if (!qp)
113062306a36Sopenharmony_ci		return NULL;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	qp->rdev = rdev;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	/* Initialize the shadow QP structure from the QP1 values */
113562306a36Sopenharmony_ci	ether_addr_copy(qp->qplib_qp.smac, rdev->netdev->dev_addr);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	qp->qplib_qp.pd = &pd->qplib_pd;
113862306a36Sopenharmony_ci	qp->qplib_qp.qp_handle = (u64)(unsigned long)(&qp->qplib_qp);
113962306a36Sopenharmony_ci	qp->qplib_qp.type = IB_QPT_UD;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	qp->qplib_qp.max_inline_data = 0;
114262306a36Sopenharmony_ci	qp->qplib_qp.sig_type = true;
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	/* Shadow QP SQ depth should be same as QP1 RQ depth */
114562306a36Sopenharmony_ci	qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6);
114662306a36Sopenharmony_ci	qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
114762306a36Sopenharmony_ci	qp->qplib_qp.sq.max_sge = 2;
114862306a36Sopenharmony_ci	/* Q full delta can be 1 since it is internal QP */
114962306a36Sopenharmony_ci	qp->qplib_qp.sq.q_full_delta = 1;
115062306a36Sopenharmony_ci	qp->qplib_qp.sq.sg_info.pgsize = PAGE_SIZE;
115162306a36Sopenharmony_ci	qp->qplib_qp.sq.sg_info.pgshft = PAGE_SHIFT;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	qp->qplib_qp.scq = qp1_qp->scq;
115462306a36Sopenharmony_ci	qp->qplib_qp.rcq = qp1_qp->rcq;
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6);
115762306a36Sopenharmony_ci	qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
115862306a36Sopenharmony_ci	qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
115962306a36Sopenharmony_ci	/* Q full delta can be 1 since it is internal QP */
116062306a36Sopenharmony_ci	qp->qplib_qp.rq.q_full_delta = 1;
116162306a36Sopenharmony_ci	qp->qplib_qp.rq.sg_info.pgsize = PAGE_SIZE;
116262306a36Sopenharmony_ci	qp->qplib_qp.rq.sg_info.pgshft = PAGE_SHIFT;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	qp->qplib_qp.mtu = qp1_qp->mtu;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	qp->qplib_qp.sq_hdr_buf_size = 0;
116762306a36Sopenharmony_ci	qp->qplib_qp.rq_hdr_buf_size = BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6;
116862306a36Sopenharmony_ci	qp->qplib_qp.dpi = &rdev->dpi_privileged;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	rc = bnxt_qplib_create_qp(qp1_res, &qp->qplib_qp);
117162306a36Sopenharmony_ci	if (rc)
117262306a36Sopenharmony_ci		goto fail;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	spin_lock_init(&qp->sq_lock);
117562306a36Sopenharmony_ci	INIT_LIST_HEAD(&qp->list);
117662306a36Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
117762306a36Sopenharmony_ci	list_add_tail(&qp->list, &rdev->qp_list);
117862306a36Sopenharmony_ci	atomic_inc(&rdev->stats.res.qp_count);
117962306a36Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
118062306a36Sopenharmony_ci	return qp;
118162306a36Sopenharmony_cifail:
118262306a36Sopenharmony_ci	kfree(qp);
118362306a36Sopenharmony_ci	return NULL;
118462306a36Sopenharmony_ci}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_cistatic int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
118762306a36Sopenharmony_ci				struct ib_qp_init_attr *init_attr)
118862306a36Sopenharmony_ci{
118962306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
119062306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
119162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
119262306a36Sopenharmony_ci	struct bnxt_qplib_q *rq;
119362306a36Sopenharmony_ci	int entries;
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	rdev = qp->rdev;
119662306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
119762306a36Sopenharmony_ci	rq = &qplqp->rq;
119862306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	if (init_attr->srq) {
120162306a36Sopenharmony_ci		struct bnxt_re_srq *srq;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci		srq = container_of(init_attr->srq, struct bnxt_re_srq, ib_srq);
120462306a36Sopenharmony_ci		qplqp->srq = &srq->qplib_srq;
120562306a36Sopenharmony_ci		rq->max_wqe = 0;
120662306a36Sopenharmony_ci	} else {
120762306a36Sopenharmony_ci		rq->max_sge = init_attr->cap.max_recv_sge;
120862306a36Sopenharmony_ci		if (rq->max_sge > dev_attr->max_qp_sges)
120962306a36Sopenharmony_ci			rq->max_sge = dev_attr->max_qp_sges;
121062306a36Sopenharmony_ci		init_attr->cap.max_recv_sge = rq->max_sge;
121162306a36Sopenharmony_ci		rq->wqe_size = bnxt_re_setup_rwqe_size(qplqp, rq->max_sge,
121262306a36Sopenharmony_ci						       dev_attr->max_qp_sges);
121362306a36Sopenharmony_ci		/* Allocate 1 more than what's provided so posting max doesn't
121462306a36Sopenharmony_ci		 * mean empty.
121562306a36Sopenharmony_ci		 */
121662306a36Sopenharmony_ci		entries = roundup_pow_of_two(init_attr->cap.max_recv_wr + 1);
121762306a36Sopenharmony_ci		rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1);
121862306a36Sopenharmony_ci		rq->q_full_delta = 0;
121962306a36Sopenharmony_ci		rq->sg_info.pgsize = PAGE_SIZE;
122062306a36Sopenharmony_ci		rq->sg_info.pgshft = PAGE_SHIFT;
122162306a36Sopenharmony_ci	}
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	return 0;
122462306a36Sopenharmony_ci}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_cistatic void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp)
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
122962306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
123062306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	rdev = qp->rdev;
123362306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
123462306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
123762306a36Sopenharmony_ci		qplqp->rq.max_sge = dev_attr->max_qp_sges;
123862306a36Sopenharmony_ci		if (qplqp->rq.max_sge > dev_attr->max_qp_sges)
123962306a36Sopenharmony_ci			qplqp->rq.max_sge = dev_attr->max_qp_sges;
124062306a36Sopenharmony_ci		qplqp->rq.max_sge = 6;
124162306a36Sopenharmony_ci	}
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cistatic int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
124562306a36Sopenharmony_ci				struct ib_qp_init_attr *init_attr,
124662306a36Sopenharmony_ci				struct ib_udata *udata)
124762306a36Sopenharmony_ci{
124862306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
124962306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
125062306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
125162306a36Sopenharmony_ci	struct bnxt_qplib_q *sq;
125262306a36Sopenharmony_ci	int entries;
125362306a36Sopenharmony_ci	int diff;
125462306a36Sopenharmony_ci	int rc;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	rdev = qp->rdev;
125762306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
125862306a36Sopenharmony_ci	sq = &qplqp->sq;
125962306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	sq->max_sge = init_attr->cap.max_send_sge;
126262306a36Sopenharmony_ci	if (sq->max_sge > dev_attr->max_qp_sges) {
126362306a36Sopenharmony_ci		sq->max_sge = dev_attr->max_qp_sges;
126462306a36Sopenharmony_ci		init_attr->cap.max_send_sge = sq->max_sge;
126562306a36Sopenharmony_ci	}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	rc = bnxt_re_setup_swqe_size(qp, init_attr);
126862306a36Sopenharmony_ci	if (rc)
126962306a36Sopenharmony_ci		return rc;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	entries = init_attr->cap.max_send_wr;
127262306a36Sopenharmony_ci	/* Allocate 128 + 1 more than what's provided */
127362306a36Sopenharmony_ci	diff = (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ?
127462306a36Sopenharmony_ci		0 : BNXT_QPLIB_RESERVED_QP_WRS;
127562306a36Sopenharmony_ci	entries = roundup_pow_of_two(entries + diff + 1);
127662306a36Sopenharmony_ci	sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1);
127762306a36Sopenharmony_ci	sq->q_full_delta = diff + 1;
127862306a36Sopenharmony_ci	/*
127962306a36Sopenharmony_ci	 * Reserving one slot for Phantom WQE. Application can
128062306a36Sopenharmony_ci	 * post one extra entry in this case. But allowing this to avoid
128162306a36Sopenharmony_ci	 * unexpected Queue full condition
128262306a36Sopenharmony_ci	 */
128362306a36Sopenharmony_ci	qplqp->sq.q_full_delta -= 1;
128462306a36Sopenharmony_ci	qplqp->sq.sg_info.pgsize = PAGE_SIZE;
128562306a36Sopenharmony_ci	qplqp->sq.sg_info.pgshft = PAGE_SHIFT;
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	return 0;
128862306a36Sopenharmony_ci}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_cistatic void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp,
129162306a36Sopenharmony_ci				       struct ib_qp_init_attr *init_attr)
129262306a36Sopenharmony_ci{
129362306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
129462306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
129562306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
129662306a36Sopenharmony_ci	int entries;
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	rdev = qp->rdev;
129962306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
130062306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
130362306a36Sopenharmony_ci		entries = roundup_pow_of_two(init_attr->cap.max_send_wr + 1);
130462306a36Sopenharmony_ci		qplqp->sq.max_wqe = min_t(u32, entries,
130562306a36Sopenharmony_ci					  dev_attr->max_qp_wqes + 1);
130662306a36Sopenharmony_ci		qplqp->sq.q_full_delta = qplqp->sq.max_wqe -
130762306a36Sopenharmony_ci			init_attr->cap.max_send_wr;
130862306a36Sopenharmony_ci		qplqp->sq.max_sge++; /* Need one extra sge to put UD header */
130962306a36Sopenharmony_ci		if (qplqp->sq.max_sge > dev_attr->max_qp_sges)
131062306a36Sopenharmony_ci			qplqp->sq.max_sge = dev_attr->max_qp_sges;
131162306a36Sopenharmony_ci	}
131262306a36Sopenharmony_ci}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_cistatic int bnxt_re_init_qp_type(struct bnxt_re_dev *rdev,
131562306a36Sopenharmony_ci				struct ib_qp_init_attr *init_attr)
131662306a36Sopenharmony_ci{
131762306a36Sopenharmony_ci	struct bnxt_qplib_chip_ctx *chip_ctx;
131862306a36Sopenharmony_ci	int qptype;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	chip_ctx = rdev->chip_ctx;
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	qptype = __from_ib_qp_type(init_attr->qp_type);
132362306a36Sopenharmony_ci	if (qptype == IB_QPT_MAX) {
132462306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "QP type 0x%x not supported", qptype);
132562306a36Sopenharmony_ci		qptype = -EOPNOTSUPP;
132662306a36Sopenharmony_ci		goto out;
132762306a36Sopenharmony_ci	}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	if (bnxt_qplib_is_chip_gen_p5(chip_ctx) &&
133062306a36Sopenharmony_ci	    init_attr->qp_type == IB_QPT_GSI)
133162306a36Sopenharmony_ci		qptype = CMDQ_CREATE_QP_TYPE_GSI;
133262306a36Sopenharmony_ciout:
133362306a36Sopenharmony_ci	return qptype;
133462306a36Sopenharmony_ci}
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_cistatic int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
133762306a36Sopenharmony_ci				struct ib_qp_init_attr *init_attr,
133862306a36Sopenharmony_ci				struct ib_udata *udata)
133962306a36Sopenharmony_ci{
134062306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
134162306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
134262306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
134362306a36Sopenharmony_ci	struct bnxt_re_cq *cq;
134462306a36Sopenharmony_ci	int rc = 0, qptype;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	rdev = qp->rdev;
134762306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
134862306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	/* Setup misc params */
135162306a36Sopenharmony_ci	ether_addr_copy(qplqp->smac, rdev->netdev->dev_addr);
135262306a36Sopenharmony_ci	qplqp->pd = &pd->qplib_pd;
135362306a36Sopenharmony_ci	qplqp->qp_handle = (u64)qplqp;
135462306a36Sopenharmony_ci	qplqp->max_inline_data = init_attr->cap.max_inline_data;
135562306a36Sopenharmony_ci	qplqp->sig_type = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
135662306a36Sopenharmony_ci	qptype = bnxt_re_init_qp_type(rdev, init_attr);
135762306a36Sopenharmony_ci	if (qptype < 0) {
135862306a36Sopenharmony_ci		rc = qptype;
135962306a36Sopenharmony_ci		goto out;
136062306a36Sopenharmony_ci	}
136162306a36Sopenharmony_ci	qplqp->type = (u8)qptype;
136262306a36Sopenharmony_ci	qplqp->wqe_mode = rdev->chip_ctx->modes.wqe_mode;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_RC) {
136562306a36Sopenharmony_ci		qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom;
136662306a36Sopenharmony_ci		qplqp->max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
136762306a36Sopenharmony_ci	}
136862306a36Sopenharmony_ci	qplqp->mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
136962306a36Sopenharmony_ci	qplqp->dpi = &rdev->dpi_privileged; /* Doorbell page */
137062306a36Sopenharmony_ci	if (init_attr->create_flags) {
137162306a36Sopenharmony_ci		ibdev_dbg(&rdev->ibdev,
137262306a36Sopenharmony_ci			  "QP create flags 0x%x not supported",
137362306a36Sopenharmony_ci			  init_attr->create_flags);
137462306a36Sopenharmony_ci		return -EOPNOTSUPP;
137562306a36Sopenharmony_ci	}
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	/* Setup CQs */
137862306a36Sopenharmony_ci	if (init_attr->send_cq) {
137962306a36Sopenharmony_ci		cq = container_of(init_attr->send_cq, struct bnxt_re_cq, ib_cq);
138062306a36Sopenharmony_ci		qplqp->scq = &cq->qplib_cq;
138162306a36Sopenharmony_ci		qp->scq = cq;
138262306a36Sopenharmony_ci	}
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	if (init_attr->recv_cq) {
138562306a36Sopenharmony_ci		cq = container_of(init_attr->recv_cq, struct bnxt_re_cq, ib_cq);
138662306a36Sopenharmony_ci		qplqp->rcq = &cq->qplib_cq;
138762306a36Sopenharmony_ci		qp->rcq = cq;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	/* Setup RQ/SRQ */
139162306a36Sopenharmony_ci	rc = bnxt_re_init_rq_attr(qp, init_attr);
139262306a36Sopenharmony_ci	if (rc)
139362306a36Sopenharmony_ci		goto out;
139462306a36Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_GSI)
139562306a36Sopenharmony_ci		bnxt_re_adjust_gsi_rq_attr(qp);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	/* Setup SQ */
139862306a36Sopenharmony_ci	rc = bnxt_re_init_sq_attr(qp, init_attr, udata);
139962306a36Sopenharmony_ci	if (rc)
140062306a36Sopenharmony_ci		goto out;
140162306a36Sopenharmony_ci	if (init_attr->qp_type == IB_QPT_GSI)
140262306a36Sopenharmony_ci		bnxt_re_adjust_gsi_sq_attr(qp, init_attr);
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	if (udata) /* This will update DPI and qp_handle */
140562306a36Sopenharmony_ci		rc = bnxt_re_init_user_qp(rdev, pd, qp, udata);
140662306a36Sopenharmony_ciout:
140762306a36Sopenharmony_ci	return rc;
140862306a36Sopenharmony_ci}
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_cistatic int bnxt_re_create_shadow_gsi(struct bnxt_re_qp *qp,
141162306a36Sopenharmony_ci				     struct bnxt_re_pd *pd)
141262306a36Sopenharmony_ci{
141362306a36Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_tbl;
141462306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
141562306a36Sopenharmony_ci	struct bnxt_re_qp *sqp;
141662306a36Sopenharmony_ci	struct bnxt_re_ah *sah;
141762306a36Sopenharmony_ci	int rc = 0;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	rdev = qp->rdev;
142062306a36Sopenharmony_ci	/* Create a shadow QP to handle the QP1 traffic */
142162306a36Sopenharmony_ci	sqp_tbl = kcalloc(BNXT_RE_MAX_GSI_SQP_ENTRIES, sizeof(*sqp_tbl),
142262306a36Sopenharmony_ci			  GFP_KERNEL);
142362306a36Sopenharmony_ci	if (!sqp_tbl)
142462306a36Sopenharmony_ci		return -ENOMEM;
142562306a36Sopenharmony_ci	rdev->gsi_ctx.sqp_tbl = sqp_tbl;
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	sqp = bnxt_re_create_shadow_qp(pd, &rdev->qplib_res, &qp->qplib_qp);
142862306a36Sopenharmony_ci	if (!sqp) {
142962306a36Sopenharmony_ci		rc = -ENODEV;
143062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create Shadow QP for QP1");
143162306a36Sopenharmony_ci		goto out;
143262306a36Sopenharmony_ci	}
143362306a36Sopenharmony_ci	rdev->gsi_ctx.gsi_sqp = sqp;
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	sqp->rcq = qp->rcq;
143662306a36Sopenharmony_ci	sqp->scq = qp->scq;
143762306a36Sopenharmony_ci	sah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res,
143862306a36Sopenharmony_ci					  &qp->qplib_qp);
143962306a36Sopenharmony_ci	if (!sah) {
144062306a36Sopenharmony_ci		bnxt_qplib_destroy_qp(&rdev->qplib_res,
144162306a36Sopenharmony_ci				      &sqp->qplib_qp);
144262306a36Sopenharmony_ci		rc = -ENODEV;
144362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
144462306a36Sopenharmony_ci			  "Failed to create AH entry for ShadowQP");
144562306a36Sopenharmony_ci		goto out;
144662306a36Sopenharmony_ci	}
144762306a36Sopenharmony_ci	rdev->gsi_ctx.gsi_sah = sah;
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return 0;
145062306a36Sopenharmony_ciout:
145162306a36Sopenharmony_ci	kfree(sqp_tbl);
145262306a36Sopenharmony_ci	return rc;
145362306a36Sopenharmony_ci}
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_cistatic int bnxt_re_create_gsi_qp(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
145662306a36Sopenharmony_ci				 struct ib_qp_init_attr *init_attr)
145762306a36Sopenharmony_ci{
145862306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
145962306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplqp;
146062306a36Sopenharmony_ci	int rc;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	rdev = qp->rdev;
146362306a36Sopenharmony_ci	qplqp = &qp->qplib_qp;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	qplqp->rq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
146662306a36Sopenharmony_ci	qplqp->sq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2;
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	rc = bnxt_qplib_create_qp1(&rdev->qplib_res, qplqp);
146962306a36Sopenharmony_ci	if (rc) {
147062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "create HW QP1 failed!");
147162306a36Sopenharmony_ci		goto out;
147262306a36Sopenharmony_ci	}
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	rc = bnxt_re_create_shadow_gsi(qp, pd);
147562306a36Sopenharmony_ciout:
147662306a36Sopenharmony_ci	return rc;
147762306a36Sopenharmony_ci}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_cistatic bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
148062306a36Sopenharmony_ci				   struct ib_qp_init_attr *init_attr,
148162306a36Sopenharmony_ci				   struct bnxt_qplib_dev_attr *dev_attr)
148262306a36Sopenharmony_ci{
148362306a36Sopenharmony_ci	bool rc = true;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	if (init_attr->cap.max_send_wr > dev_attr->max_qp_wqes ||
148662306a36Sopenharmony_ci	    init_attr->cap.max_recv_wr > dev_attr->max_qp_wqes ||
148762306a36Sopenharmony_ci	    init_attr->cap.max_send_sge > dev_attr->max_qp_sges ||
148862306a36Sopenharmony_ci	    init_attr->cap.max_recv_sge > dev_attr->max_qp_sges ||
148962306a36Sopenharmony_ci	    init_attr->cap.max_inline_data > dev_attr->max_inline_data) {
149062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
149162306a36Sopenharmony_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",
149262306a36Sopenharmony_ci			  init_attr->cap.max_send_wr, dev_attr->max_qp_wqes,
149362306a36Sopenharmony_ci			  init_attr->cap.max_recv_wr, dev_attr->max_qp_wqes,
149462306a36Sopenharmony_ci			  init_attr->cap.max_send_sge, dev_attr->max_qp_sges,
149562306a36Sopenharmony_ci			  init_attr->cap.max_recv_sge, dev_attr->max_qp_sges,
149662306a36Sopenharmony_ci			  init_attr->cap.max_inline_data,
149762306a36Sopenharmony_ci			  dev_attr->max_inline_data);
149862306a36Sopenharmony_ci		rc = false;
149962306a36Sopenharmony_ci	}
150062306a36Sopenharmony_ci	return rc;
150162306a36Sopenharmony_ci}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ciint bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
150462306a36Sopenharmony_ci		      struct ib_udata *udata)
150562306a36Sopenharmony_ci{
150662306a36Sopenharmony_ci	struct ib_pd *ib_pd = ib_qp->pd;
150762306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
150862306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
150962306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
151062306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
151162306a36Sopenharmony_ci	u32 active_qps;
151262306a36Sopenharmony_ci	int rc;
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci	rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
151562306a36Sopenharmony_ci	if (!rc) {
151662306a36Sopenharmony_ci		rc = -EINVAL;
151762306a36Sopenharmony_ci		goto fail;
151862306a36Sopenharmony_ci	}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	qp->rdev = rdev;
152162306a36Sopenharmony_ci	rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
152262306a36Sopenharmony_ci	if (rc)
152362306a36Sopenharmony_ci		goto fail;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	if (qp_init_attr->qp_type == IB_QPT_GSI &&
152662306a36Sopenharmony_ci	    !(bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx))) {
152762306a36Sopenharmony_ci		rc = bnxt_re_create_gsi_qp(qp, pd, qp_init_attr);
152862306a36Sopenharmony_ci		if (rc == -ENODEV)
152962306a36Sopenharmony_ci			goto qp_destroy;
153062306a36Sopenharmony_ci		if (rc)
153162306a36Sopenharmony_ci			goto fail;
153262306a36Sopenharmony_ci	} else {
153362306a36Sopenharmony_ci		rc = bnxt_qplib_create_qp(&rdev->qplib_res, &qp->qplib_qp);
153462306a36Sopenharmony_ci		if (rc) {
153562306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to create HW QP");
153662306a36Sopenharmony_ci			goto free_umem;
153762306a36Sopenharmony_ci		}
153862306a36Sopenharmony_ci		if (udata) {
153962306a36Sopenharmony_ci			struct bnxt_re_qp_resp resp;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci			resp.qpid = qp->qplib_qp.id;
154262306a36Sopenharmony_ci			resp.rsvd = 0;
154362306a36Sopenharmony_ci			rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
154462306a36Sopenharmony_ci			if (rc) {
154562306a36Sopenharmony_ci				ibdev_err(&rdev->ibdev, "Failed to copy QP udata");
154662306a36Sopenharmony_ci				goto qp_destroy;
154762306a36Sopenharmony_ci			}
154862306a36Sopenharmony_ci		}
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	qp->ib_qp.qp_num = qp->qplib_qp.id;
155262306a36Sopenharmony_ci	if (qp_init_attr->qp_type == IB_QPT_GSI)
155362306a36Sopenharmony_ci		rdev->gsi_ctx.gsi_qp = qp;
155462306a36Sopenharmony_ci	spin_lock_init(&qp->sq_lock);
155562306a36Sopenharmony_ci	spin_lock_init(&qp->rq_lock);
155662306a36Sopenharmony_ci	INIT_LIST_HEAD(&qp->list);
155762306a36Sopenharmony_ci	mutex_lock(&rdev->qp_lock);
155862306a36Sopenharmony_ci	list_add_tail(&qp->list, &rdev->qp_list);
155962306a36Sopenharmony_ci	mutex_unlock(&rdev->qp_lock);
156062306a36Sopenharmony_ci	active_qps = atomic_inc_return(&rdev->stats.res.qp_count);
156162306a36Sopenharmony_ci	if (active_qps > rdev->stats.res.qp_watermark)
156262306a36Sopenharmony_ci		rdev->stats.res.qp_watermark = active_qps;
156362306a36Sopenharmony_ci	if (qp_init_attr->qp_type == IB_QPT_RC) {
156462306a36Sopenharmony_ci		active_qps = atomic_inc_return(&rdev->stats.res.rc_qp_count);
156562306a36Sopenharmony_ci		if (active_qps > rdev->stats.res.rc_qp_watermark)
156662306a36Sopenharmony_ci			rdev->stats.res.rc_qp_watermark = active_qps;
156762306a36Sopenharmony_ci	} else if (qp_init_attr->qp_type == IB_QPT_UD) {
156862306a36Sopenharmony_ci		active_qps = atomic_inc_return(&rdev->stats.res.ud_qp_count);
156962306a36Sopenharmony_ci		if (active_qps > rdev->stats.res.ud_qp_watermark)
157062306a36Sopenharmony_ci			rdev->stats.res.ud_qp_watermark = active_qps;
157162306a36Sopenharmony_ci	}
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	return 0;
157462306a36Sopenharmony_ciqp_destroy:
157562306a36Sopenharmony_ci	bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
157662306a36Sopenharmony_cifree_umem:
157762306a36Sopenharmony_ci	ib_umem_release(qp->rumem);
157862306a36Sopenharmony_ci	ib_umem_release(qp->sumem);
157962306a36Sopenharmony_cifail:
158062306a36Sopenharmony_ci	return rc;
158162306a36Sopenharmony_ci}
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_cistatic u8 __from_ib_qp_state(enum ib_qp_state state)
158462306a36Sopenharmony_ci{
158562306a36Sopenharmony_ci	switch (state) {
158662306a36Sopenharmony_ci	case IB_QPS_RESET:
158762306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RESET;
158862306a36Sopenharmony_ci	case IB_QPS_INIT:
158962306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_INIT;
159062306a36Sopenharmony_ci	case IB_QPS_RTR:
159162306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RTR;
159262306a36Sopenharmony_ci	case IB_QPS_RTS:
159362306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_RTS;
159462306a36Sopenharmony_ci	case IB_QPS_SQD:
159562306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_SQD;
159662306a36Sopenharmony_ci	case IB_QPS_SQE:
159762306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_SQE;
159862306a36Sopenharmony_ci	case IB_QPS_ERR:
159962306a36Sopenharmony_ci	default:
160062306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_NEW_STATE_ERR;
160162306a36Sopenharmony_ci	}
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cistatic enum ib_qp_state __to_ib_qp_state(u8 state)
160562306a36Sopenharmony_ci{
160662306a36Sopenharmony_ci	switch (state) {
160762306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RESET:
160862306a36Sopenharmony_ci		return IB_QPS_RESET;
160962306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_INIT:
161062306a36Sopenharmony_ci		return IB_QPS_INIT;
161162306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RTR:
161262306a36Sopenharmony_ci		return IB_QPS_RTR;
161362306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_RTS:
161462306a36Sopenharmony_ci		return IB_QPS_RTS;
161562306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_SQD:
161662306a36Sopenharmony_ci		return IB_QPS_SQD;
161762306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_SQE:
161862306a36Sopenharmony_ci		return IB_QPS_SQE;
161962306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_NEW_STATE_ERR:
162062306a36Sopenharmony_ci	default:
162162306a36Sopenharmony_ci		return IB_QPS_ERR;
162262306a36Sopenharmony_ci	}
162362306a36Sopenharmony_ci}
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_cistatic u32 __from_ib_mtu(enum ib_mtu mtu)
162662306a36Sopenharmony_ci{
162762306a36Sopenharmony_ci	switch (mtu) {
162862306a36Sopenharmony_ci	case IB_MTU_256:
162962306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_256;
163062306a36Sopenharmony_ci	case IB_MTU_512:
163162306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_512;
163262306a36Sopenharmony_ci	case IB_MTU_1024:
163362306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_1024;
163462306a36Sopenharmony_ci	case IB_MTU_2048:
163562306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
163662306a36Sopenharmony_ci	case IB_MTU_4096:
163762306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_4096;
163862306a36Sopenharmony_ci	default:
163962306a36Sopenharmony_ci		return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci}
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_cistatic enum ib_mtu __to_ib_mtu(u32 mtu)
164462306a36Sopenharmony_ci{
164562306a36Sopenharmony_ci	switch (mtu & CREQ_QUERY_QP_RESP_SB_PATH_MTU_MASK) {
164662306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_256:
164762306a36Sopenharmony_ci		return IB_MTU_256;
164862306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_512:
164962306a36Sopenharmony_ci		return IB_MTU_512;
165062306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_1024:
165162306a36Sopenharmony_ci		return IB_MTU_1024;
165262306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_2048:
165362306a36Sopenharmony_ci		return IB_MTU_2048;
165462306a36Sopenharmony_ci	case CMDQ_MODIFY_QP_PATH_MTU_MTU_4096:
165562306a36Sopenharmony_ci		return IB_MTU_4096;
165662306a36Sopenharmony_ci	default:
165762306a36Sopenharmony_ci		return IB_MTU_2048;
165862306a36Sopenharmony_ci	}
165962306a36Sopenharmony_ci}
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci/* Shared Receive Queues */
166262306a36Sopenharmony_ciint bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata)
166362306a36Sopenharmony_ci{
166462306a36Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
166562306a36Sopenharmony_ci					       ib_srq);
166662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
166762306a36Sopenharmony_ci	struct bnxt_qplib_srq *qplib_srq = &srq->qplib_srq;
166862306a36Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	if (qplib_srq->cq)
167162306a36Sopenharmony_ci		nq = qplib_srq->cq->nq;
167262306a36Sopenharmony_ci	bnxt_qplib_destroy_srq(&rdev->qplib_res, qplib_srq);
167362306a36Sopenharmony_ci	ib_umem_release(srq->umem);
167462306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.srq_count);
167562306a36Sopenharmony_ci	if (nq)
167662306a36Sopenharmony_ci		nq->budget--;
167762306a36Sopenharmony_ci	return 0;
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_cistatic int bnxt_re_init_user_srq(struct bnxt_re_dev *rdev,
168162306a36Sopenharmony_ci				 struct bnxt_re_pd *pd,
168262306a36Sopenharmony_ci				 struct bnxt_re_srq *srq,
168362306a36Sopenharmony_ci				 struct ib_udata *udata)
168462306a36Sopenharmony_ci{
168562306a36Sopenharmony_ci	struct bnxt_re_srq_req ureq;
168662306a36Sopenharmony_ci	struct bnxt_qplib_srq *qplib_srq = &srq->qplib_srq;
168762306a36Sopenharmony_ci	struct ib_umem *umem;
168862306a36Sopenharmony_ci	int bytes = 0;
168962306a36Sopenharmony_ci	struct bnxt_re_ucontext *cntx = rdma_udata_to_drv_context(
169062306a36Sopenharmony_ci		udata, struct bnxt_re_ucontext, ib_uctx);
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci	if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
169362306a36Sopenharmony_ci		return -EFAULT;
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	bytes = (qplib_srq->max_wqe * qplib_srq->wqe_size);
169662306a36Sopenharmony_ci	bytes = PAGE_ALIGN(bytes);
169762306a36Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, ureq.srqva, bytes,
169862306a36Sopenharmony_ci			   IB_ACCESS_LOCAL_WRITE);
169962306a36Sopenharmony_ci	if (IS_ERR(umem))
170062306a36Sopenharmony_ci		return PTR_ERR(umem);
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	srq->umem = umem;
170362306a36Sopenharmony_ci	qplib_srq->sg_info.umem = umem;
170462306a36Sopenharmony_ci	qplib_srq->sg_info.pgsize = PAGE_SIZE;
170562306a36Sopenharmony_ci	qplib_srq->sg_info.pgshft = PAGE_SHIFT;
170662306a36Sopenharmony_ci	qplib_srq->srq_handle = ureq.srq_handle;
170762306a36Sopenharmony_ci	qplib_srq->dpi = &cntx->dpi;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	return 0;
171062306a36Sopenharmony_ci}
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ciint bnxt_re_create_srq(struct ib_srq *ib_srq,
171362306a36Sopenharmony_ci		       struct ib_srq_init_attr *srq_init_attr,
171462306a36Sopenharmony_ci		       struct ib_udata *udata)
171562306a36Sopenharmony_ci{
171662306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
171762306a36Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
171862306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
171962306a36Sopenharmony_ci	struct bnxt_re_srq *srq;
172062306a36Sopenharmony_ci	struct bnxt_re_pd *pd;
172162306a36Sopenharmony_ci	struct ib_pd *ib_pd;
172262306a36Sopenharmony_ci	u32 active_srqs;
172362306a36Sopenharmony_ci	int rc, entries;
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	ib_pd = ib_srq->pd;
172662306a36Sopenharmony_ci	pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
172762306a36Sopenharmony_ci	rdev = pd->rdev;
172862306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
172962306a36Sopenharmony_ci	srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	if (srq_init_attr->attr.max_wr >= dev_attr->max_srq_wqes) {
173262306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Create CQ failed - max exceeded");
173362306a36Sopenharmony_ci		rc = -EINVAL;
173462306a36Sopenharmony_ci		goto exit;
173562306a36Sopenharmony_ci	}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
173862306a36Sopenharmony_ci		rc = -EOPNOTSUPP;
173962306a36Sopenharmony_ci		goto exit;
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	srq->rdev = rdev;
174362306a36Sopenharmony_ci	srq->qplib_srq.pd = &pd->qplib_pd;
174462306a36Sopenharmony_ci	srq->qplib_srq.dpi = &rdev->dpi_privileged;
174562306a36Sopenharmony_ci	/* Allocate 1 more than what's provided so posting max doesn't
174662306a36Sopenharmony_ci	 * mean empty
174762306a36Sopenharmony_ci	 */
174862306a36Sopenharmony_ci	entries = roundup_pow_of_two(srq_init_attr->attr.max_wr + 1);
174962306a36Sopenharmony_ci	if (entries > dev_attr->max_srq_wqes + 1)
175062306a36Sopenharmony_ci		entries = dev_attr->max_srq_wqes + 1;
175162306a36Sopenharmony_ci	srq->qplib_srq.max_wqe = entries;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	srq->qplib_srq.max_sge = srq_init_attr->attr.max_sge;
175462306a36Sopenharmony_ci	 /* 128 byte wqe size for SRQ . So use max sges */
175562306a36Sopenharmony_ci	srq->qplib_srq.wqe_size = bnxt_re_get_rwqe_size(dev_attr->max_srq_sges);
175662306a36Sopenharmony_ci	srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit;
175762306a36Sopenharmony_ci	srq->srq_limit = srq_init_attr->attr.srq_limit;
175862306a36Sopenharmony_ci	srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0].ring_id;
175962306a36Sopenharmony_ci	nq = &rdev->nq[0];
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	if (udata) {
176262306a36Sopenharmony_ci		rc = bnxt_re_init_user_srq(rdev, pd, srq, udata);
176362306a36Sopenharmony_ci		if (rc)
176462306a36Sopenharmony_ci			goto fail;
176562306a36Sopenharmony_ci	}
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	rc = bnxt_qplib_create_srq(&rdev->qplib_res, &srq->qplib_srq);
176862306a36Sopenharmony_ci	if (rc) {
176962306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Create HW SRQ failed!");
177062306a36Sopenharmony_ci		goto fail;
177162306a36Sopenharmony_ci	}
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	if (udata) {
177462306a36Sopenharmony_ci		struct bnxt_re_srq_resp resp;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci		resp.srqid = srq->qplib_srq.id;
177762306a36Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
177862306a36Sopenharmony_ci		if (rc) {
177962306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev, "SRQ copy to udata failed!");
178062306a36Sopenharmony_ci			bnxt_qplib_destroy_srq(&rdev->qplib_res,
178162306a36Sopenharmony_ci					       &srq->qplib_srq);
178262306a36Sopenharmony_ci			goto fail;
178362306a36Sopenharmony_ci		}
178462306a36Sopenharmony_ci	}
178562306a36Sopenharmony_ci	if (nq)
178662306a36Sopenharmony_ci		nq->budget++;
178762306a36Sopenharmony_ci	active_srqs = atomic_inc_return(&rdev->stats.res.srq_count);
178862306a36Sopenharmony_ci	if (active_srqs > rdev->stats.res.srq_watermark)
178962306a36Sopenharmony_ci		rdev->stats.res.srq_watermark = active_srqs;
179062306a36Sopenharmony_ci	spin_lock_init(&srq->lock);
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	return 0;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_cifail:
179562306a36Sopenharmony_ci	ib_umem_release(srq->umem);
179662306a36Sopenharmony_ciexit:
179762306a36Sopenharmony_ci	return rc;
179862306a36Sopenharmony_ci}
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ciint bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
180162306a36Sopenharmony_ci		       enum ib_srq_attr_mask srq_attr_mask,
180262306a36Sopenharmony_ci		       struct ib_udata *udata)
180362306a36Sopenharmony_ci{
180462306a36Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
180562306a36Sopenharmony_ci					       ib_srq);
180662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
180762306a36Sopenharmony_ci	int rc;
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	switch (srq_attr_mask) {
181062306a36Sopenharmony_ci	case IB_SRQ_MAX_WR:
181162306a36Sopenharmony_ci		/* SRQ resize is not supported */
181262306a36Sopenharmony_ci		return -EINVAL;
181362306a36Sopenharmony_ci	case IB_SRQ_LIMIT:
181462306a36Sopenharmony_ci		/* Change the SRQ threshold */
181562306a36Sopenharmony_ci		if (srq_attr->srq_limit > srq->qplib_srq.max_wqe)
181662306a36Sopenharmony_ci			return -EINVAL;
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci		srq->qplib_srq.threshold = srq_attr->srq_limit;
181962306a36Sopenharmony_ci		rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq);
182062306a36Sopenharmony_ci		if (rc) {
182162306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Modify HW SRQ failed!");
182262306a36Sopenharmony_ci			return rc;
182362306a36Sopenharmony_ci		}
182462306a36Sopenharmony_ci		/* On success, update the shadow */
182562306a36Sopenharmony_ci		srq->srq_limit = srq_attr->srq_limit;
182662306a36Sopenharmony_ci		/* No need to Build and send response back to udata */
182762306a36Sopenharmony_ci		return 0;
182862306a36Sopenharmony_ci	default:
182962306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
183062306a36Sopenharmony_ci			  "Unsupported srq_attr_mask 0x%x", srq_attr_mask);
183162306a36Sopenharmony_ci		return -EINVAL;
183262306a36Sopenharmony_ci	}
183362306a36Sopenharmony_ci}
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ciint bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr)
183662306a36Sopenharmony_ci{
183762306a36Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
183862306a36Sopenharmony_ci					       ib_srq);
183962306a36Sopenharmony_ci	struct bnxt_re_srq tsrq;
184062306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = srq->rdev;
184162306a36Sopenharmony_ci	int rc;
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	/* Get live SRQ attr */
184462306a36Sopenharmony_ci	tsrq.qplib_srq.id = srq->qplib_srq.id;
184562306a36Sopenharmony_ci	rc = bnxt_qplib_query_srq(&rdev->qplib_res, &tsrq.qplib_srq);
184662306a36Sopenharmony_ci	if (rc) {
184762306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Query HW SRQ failed!");
184862306a36Sopenharmony_ci		return rc;
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci	srq_attr->max_wr = srq->qplib_srq.max_wqe;
185162306a36Sopenharmony_ci	srq_attr->max_sge = srq->qplib_srq.max_sge;
185262306a36Sopenharmony_ci	srq_attr->srq_limit = tsrq.qplib_srq.threshold;
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	return 0;
185562306a36Sopenharmony_ci}
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ciint bnxt_re_post_srq_recv(struct ib_srq *ib_srq, const struct ib_recv_wr *wr,
185862306a36Sopenharmony_ci			  const struct ib_recv_wr **bad_wr)
185962306a36Sopenharmony_ci{
186062306a36Sopenharmony_ci	struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq,
186162306a36Sopenharmony_ci					       ib_srq);
186262306a36Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
186362306a36Sopenharmony_ci	unsigned long flags;
186462306a36Sopenharmony_ci	int rc = 0;
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	spin_lock_irqsave(&srq->lock, flags);
186762306a36Sopenharmony_ci	while (wr) {
186862306a36Sopenharmony_ci		/* Transcribe each ib_recv_wr to qplib_swqe */
186962306a36Sopenharmony_ci		wqe.num_sge = wr->num_sge;
187062306a36Sopenharmony_ci		bnxt_re_build_sgl(wr->sg_list, wqe.sg_list, wr->num_sge);
187162306a36Sopenharmony_ci		wqe.wr_id = wr->wr_id;
187262306a36Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci		rc = bnxt_qplib_post_srq_recv(&srq->qplib_srq, &wqe);
187562306a36Sopenharmony_ci		if (rc) {
187662306a36Sopenharmony_ci			*bad_wr = wr;
187762306a36Sopenharmony_ci			break;
187862306a36Sopenharmony_ci		}
187962306a36Sopenharmony_ci		wr = wr->next;
188062306a36Sopenharmony_ci	}
188162306a36Sopenharmony_ci	spin_unlock_irqrestore(&srq->lock, flags);
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	return rc;
188462306a36Sopenharmony_ci}
188562306a36Sopenharmony_cistatic int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev,
188662306a36Sopenharmony_ci				    struct bnxt_re_qp *qp1_qp,
188762306a36Sopenharmony_ci				    int qp_attr_mask)
188862306a36Sopenharmony_ci{
188962306a36Sopenharmony_ci	struct bnxt_re_qp *qp = rdev->gsi_ctx.gsi_sqp;
189062306a36Sopenharmony_ci	int rc;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_STATE) {
189362306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE;
189462306a36Sopenharmony_ci		qp->qplib_qp.state = qp1_qp->qplib_qp.state;
189562306a36Sopenharmony_ci	}
189662306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_PKEY_INDEX) {
189762306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
189862306a36Sopenharmony_ci		qp->qplib_qp.pkey_index = qp1_qp->qplib_qp.pkey_index;
189962306a36Sopenharmony_ci	}
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_QKEY) {
190262306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
190362306a36Sopenharmony_ci		/* Using a Random  QKEY */
190462306a36Sopenharmony_ci		qp->qplib_qp.qkey = 0x81818181;
190562306a36Sopenharmony_ci	}
190662306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_SQ_PSN) {
190762306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN;
190862306a36Sopenharmony_ci		qp->qplib_qp.sq.psn = qp1_qp->qplib_qp.sq.psn;
190962306a36Sopenharmony_ci	}
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp);
191262306a36Sopenharmony_ci	if (rc)
191362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to modify Shadow QP for QP1");
191462306a36Sopenharmony_ci	return rc;
191562306a36Sopenharmony_ci}
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ciint bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
191862306a36Sopenharmony_ci		      int qp_attr_mask, struct ib_udata *udata)
191962306a36Sopenharmony_ci{
192062306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
192162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
192262306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
192362306a36Sopenharmony_ci	enum ib_qp_state curr_qp_state, new_qp_state;
192462306a36Sopenharmony_ci	int rc, entries;
192562306a36Sopenharmony_ci	unsigned int flags;
192662306a36Sopenharmony_ci	u8 nw_type;
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	if (qp_attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
192962306a36Sopenharmony_ci		return -EOPNOTSUPP;
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	qp->qplib_qp.modify_flags = 0;
193262306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_STATE) {
193362306a36Sopenharmony_ci		curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state);
193462306a36Sopenharmony_ci		new_qp_state = qp_attr->qp_state;
193562306a36Sopenharmony_ci		if (!ib_modify_qp_is_ok(curr_qp_state, new_qp_state,
193662306a36Sopenharmony_ci					ib_qp->qp_type, qp_attr_mask)) {
193762306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
193862306a36Sopenharmony_ci				  "Invalid attribute mask: %#x specified ",
193962306a36Sopenharmony_ci				  qp_attr_mask);
194062306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
194162306a36Sopenharmony_ci				  "for qpn: %#x type: %#x",
194262306a36Sopenharmony_ci				  ib_qp->qp_num, ib_qp->qp_type);
194362306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
194462306a36Sopenharmony_ci				  "curr_qp_state=0x%x, new_qp_state=0x%x\n",
194562306a36Sopenharmony_ci				  curr_qp_state, new_qp_state);
194662306a36Sopenharmony_ci			return -EINVAL;
194762306a36Sopenharmony_ci		}
194862306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE;
194962306a36Sopenharmony_ci		qp->qplib_qp.state = __from_ib_qp_state(qp_attr->qp_state);
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci		if (!qp->sumem &&
195262306a36Sopenharmony_ci		    qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR) {
195362306a36Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
195462306a36Sopenharmony_ci				  "Move QP = %p to flush list\n", qp);
195562306a36Sopenharmony_ci			flags = bnxt_re_lock_cqs(qp);
195662306a36Sopenharmony_ci			bnxt_qplib_add_flush_qp(&qp->qplib_qp);
195762306a36Sopenharmony_ci			bnxt_re_unlock_cqs(qp, flags);
195862306a36Sopenharmony_ci		}
195962306a36Sopenharmony_ci		if (!qp->sumem &&
196062306a36Sopenharmony_ci		    qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_RESET) {
196162306a36Sopenharmony_ci			ibdev_dbg(&rdev->ibdev,
196262306a36Sopenharmony_ci				  "Move QP = %p out of flush list\n", qp);
196362306a36Sopenharmony_ci			flags = bnxt_re_lock_cqs(qp);
196462306a36Sopenharmony_ci			bnxt_qplib_clean_qp(&qp->qplib_qp);
196562306a36Sopenharmony_ci			bnxt_re_unlock_cqs(qp, flags);
196662306a36Sopenharmony_ci		}
196762306a36Sopenharmony_ci	}
196862306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) {
196962306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
197062306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_EN_SQD_ASYNC_NOTIFY;
197162306a36Sopenharmony_ci		qp->qplib_qp.en_sqd_async_notify = true;
197262306a36Sopenharmony_ci	}
197362306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_ACCESS_FLAGS) {
197462306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS;
197562306a36Sopenharmony_ci		qp->qplib_qp.access =
197662306a36Sopenharmony_ci			__from_ib_access_flags(qp_attr->qp_access_flags);
197762306a36Sopenharmony_ci		/* LOCAL_WRITE access must be set to allow RC receive */
197862306a36Sopenharmony_ci		qp->qplib_qp.access |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
197962306a36Sopenharmony_ci		/* Temp: Set all params on QP as of now */
198062306a36Sopenharmony_ci		qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE;
198162306a36Sopenharmony_ci		qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_READ;
198262306a36Sopenharmony_ci	}
198362306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_PKEY_INDEX) {
198462306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
198562306a36Sopenharmony_ci		qp->qplib_qp.pkey_index = qp_attr->pkey_index;
198662306a36Sopenharmony_ci	}
198762306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_QKEY) {
198862306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
198962306a36Sopenharmony_ci		qp->qplib_qp.qkey = qp_attr->qkey;
199062306a36Sopenharmony_ci	}
199162306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_AV) {
199262306a36Sopenharmony_ci		const struct ib_global_route *grh =
199362306a36Sopenharmony_ci			rdma_ah_read_grh(&qp_attr->ah_attr);
199462306a36Sopenharmony_ci		const struct ib_gid_attr *sgid_attr;
199562306a36Sopenharmony_ci		struct bnxt_re_gid_ctx *ctx;
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_DGID |
199862306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_FLOW_LABEL |
199962306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX |
200062306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_HOP_LIMIT |
200162306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_TRAFFIC_CLASS |
200262306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_DEST_MAC |
200362306a36Sopenharmony_ci				     CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID;
200462306a36Sopenharmony_ci		memcpy(qp->qplib_qp.ah.dgid.data, grh->dgid.raw,
200562306a36Sopenharmony_ci		       sizeof(qp->qplib_qp.ah.dgid.data));
200662306a36Sopenharmony_ci		qp->qplib_qp.ah.flow_label = grh->flow_label;
200762306a36Sopenharmony_ci		sgid_attr = grh->sgid_attr;
200862306a36Sopenharmony_ci		/* Get the HW context of the GID. The reference
200962306a36Sopenharmony_ci		 * of GID table entry is already taken by the caller.
201062306a36Sopenharmony_ci		 */
201162306a36Sopenharmony_ci		ctx = rdma_read_gid_hw_context(sgid_attr);
201262306a36Sopenharmony_ci		qp->qplib_qp.ah.sgid_index = ctx->idx;
201362306a36Sopenharmony_ci		qp->qplib_qp.ah.host_sgid_index = grh->sgid_index;
201462306a36Sopenharmony_ci		qp->qplib_qp.ah.hop_limit = grh->hop_limit;
201562306a36Sopenharmony_ci		qp->qplib_qp.ah.traffic_class = grh->traffic_class;
201662306a36Sopenharmony_ci		qp->qplib_qp.ah.sl = rdma_ah_get_sl(&qp_attr->ah_attr);
201762306a36Sopenharmony_ci		ether_addr_copy(qp->qplib_qp.ah.dmac,
201862306a36Sopenharmony_ci				qp_attr->ah_attr.roce.dmac);
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci		rc = rdma_read_gid_l2_fields(sgid_attr, NULL,
202162306a36Sopenharmony_ci					     &qp->qplib_qp.smac[0]);
202262306a36Sopenharmony_ci		if (rc)
202362306a36Sopenharmony_ci			return rc;
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci		nw_type = rdma_gid_attr_network_type(sgid_attr);
202662306a36Sopenharmony_ci		switch (nw_type) {
202762306a36Sopenharmony_ci		case RDMA_NETWORK_IPV4:
202862306a36Sopenharmony_ci			qp->qplib_qp.nw_type =
202962306a36Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV4;
203062306a36Sopenharmony_ci			break;
203162306a36Sopenharmony_ci		case RDMA_NETWORK_IPV6:
203262306a36Sopenharmony_ci			qp->qplib_qp.nw_type =
203362306a36Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV6;
203462306a36Sopenharmony_ci			break;
203562306a36Sopenharmony_ci		default:
203662306a36Sopenharmony_ci			qp->qplib_qp.nw_type =
203762306a36Sopenharmony_ci				CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV1;
203862306a36Sopenharmony_ci			break;
203962306a36Sopenharmony_ci		}
204062306a36Sopenharmony_ci	}
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_PATH_MTU) {
204362306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
204462306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
204562306a36Sopenharmony_ci		qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
204662306a36Sopenharmony_ci		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
204762306a36Sopenharmony_ci	} else if (qp_attr->qp_state == IB_QPS_RTR) {
204862306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
204962306a36Sopenharmony_ci			CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
205062306a36Sopenharmony_ci		qp->qplib_qp.path_mtu =
205162306a36Sopenharmony_ci			__from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
205262306a36Sopenharmony_ci		qp->qplib_qp.mtu =
205362306a36Sopenharmony_ci			ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
205462306a36Sopenharmony_ci	}
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_TIMEOUT) {
205762306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_TIMEOUT;
205862306a36Sopenharmony_ci		qp->qplib_qp.timeout = qp_attr->timeout;
205962306a36Sopenharmony_ci	}
206062306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_RETRY_CNT) {
206162306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
206262306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RETRY_CNT;
206362306a36Sopenharmony_ci		qp->qplib_qp.retry_cnt = qp_attr->retry_cnt;
206462306a36Sopenharmony_ci	}
206562306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_RNR_RETRY) {
206662306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
206762306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RNR_RETRY;
206862306a36Sopenharmony_ci		qp->qplib_qp.rnr_retry = qp_attr->rnr_retry;
206962306a36Sopenharmony_ci	}
207062306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_MIN_RNR_TIMER) {
207162306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
207262306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER;
207362306a36Sopenharmony_ci		qp->qplib_qp.min_rnr_timer = qp_attr->min_rnr_timer;
207462306a36Sopenharmony_ci	}
207562306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_RQ_PSN) {
207662306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_RQ_PSN;
207762306a36Sopenharmony_ci		qp->qplib_qp.rq.psn = qp_attr->rq_psn;
207862306a36Sopenharmony_ci	}
207962306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
208062306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
208162306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_RD_ATOMIC;
208262306a36Sopenharmony_ci		/* Cap the max_rd_atomic to device max */
208362306a36Sopenharmony_ci		qp->qplib_qp.max_rd_atomic = min_t(u32, qp_attr->max_rd_atomic,
208462306a36Sopenharmony_ci						   dev_attr->max_qp_rd_atom);
208562306a36Sopenharmony_ci	}
208662306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_SQ_PSN) {
208762306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN;
208862306a36Sopenharmony_ci		qp->qplib_qp.sq.psn = qp_attr->sq_psn;
208962306a36Sopenharmony_ci	}
209062306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
209162306a36Sopenharmony_ci		if (qp_attr->max_dest_rd_atomic >
209262306a36Sopenharmony_ci		    dev_attr->max_qp_init_rd_atom) {
209362306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
209462306a36Sopenharmony_ci				  "max_dest_rd_atomic requested%d is > dev_max%d",
209562306a36Sopenharmony_ci				  qp_attr->max_dest_rd_atomic,
209662306a36Sopenharmony_ci				  dev_attr->max_qp_init_rd_atom);
209762306a36Sopenharmony_ci			return -EINVAL;
209862306a36Sopenharmony_ci		}
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
210162306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_DEST_RD_ATOMIC;
210262306a36Sopenharmony_ci		qp->qplib_qp.max_dest_rd_atomic = qp_attr->max_dest_rd_atomic;
210362306a36Sopenharmony_ci	}
210462306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_CAP) {
210562306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
210662306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SIZE |
210762306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SIZE |
210862306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SGE |
210962306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SGE |
211062306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_MAX_INLINE_DATA;
211162306a36Sopenharmony_ci		if ((qp_attr->cap.max_send_wr >= dev_attr->max_qp_wqes) ||
211262306a36Sopenharmony_ci		    (qp_attr->cap.max_recv_wr >= dev_attr->max_qp_wqes) ||
211362306a36Sopenharmony_ci		    (qp_attr->cap.max_send_sge >= dev_attr->max_qp_sges) ||
211462306a36Sopenharmony_ci		    (qp_attr->cap.max_recv_sge >= dev_attr->max_qp_sges) ||
211562306a36Sopenharmony_ci		    (qp_attr->cap.max_inline_data >=
211662306a36Sopenharmony_ci						dev_attr->max_inline_data)) {
211762306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
211862306a36Sopenharmony_ci				  "Create QP failed - max exceeded");
211962306a36Sopenharmony_ci			return -EINVAL;
212062306a36Sopenharmony_ci		}
212162306a36Sopenharmony_ci		entries = roundup_pow_of_two(qp_attr->cap.max_send_wr);
212262306a36Sopenharmony_ci		qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
212362306a36Sopenharmony_ci						dev_attr->max_qp_wqes + 1);
212462306a36Sopenharmony_ci		qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
212562306a36Sopenharmony_ci						qp_attr->cap.max_send_wr;
212662306a36Sopenharmony_ci		/*
212762306a36Sopenharmony_ci		 * Reserving one slot for Phantom WQE. Some application can
212862306a36Sopenharmony_ci		 * post one extra entry in this case. Allowing this to avoid
212962306a36Sopenharmony_ci		 * unexpected Queue full condition
213062306a36Sopenharmony_ci		 */
213162306a36Sopenharmony_ci		qp->qplib_qp.sq.q_full_delta -= 1;
213262306a36Sopenharmony_ci		qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge;
213362306a36Sopenharmony_ci		if (qp->qplib_qp.rq.max_wqe) {
213462306a36Sopenharmony_ci			entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr);
213562306a36Sopenharmony_ci			qp->qplib_qp.rq.max_wqe =
213662306a36Sopenharmony_ci				min_t(u32, entries, dev_attr->max_qp_wqes + 1);
213762306a36Sopenharmony_ci			qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
213862306a36Sopenharmony_ci						       qp_attr->cap.max_recv_wr;
213962306a36Sopenharmony_ci			qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
214062306a36Sopenharmony_ci		} else {
214162306a36Sopenharmony_ci			/* SRQ was used prior, just ignore the RQ caps */
214262306a36Sopenharmony_ci		}
214362306a36Sopenharmony_ci	}
214462306a36Sopenharmony_ci	if (qp_attr_mask & IB_QP_DEST_QPN) {
214562306a36Sopenharmony_ci		qp->qplib_qp.modify_flags |=
214662306a36Sopenharmony_ci				CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID;
214762306a36Sopenharmony_ci		qp->qplib_qp.dest_qpn = qp_attr->dest_qp_num;
214862306a36Sopenharmony_ci	}
214962306a36Sopenharmony_ci	rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp);
215062306a36Sopenharmony_ci	if (rc) {
215162306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to modify HW QP");
215262306a36Sopenharmony_ci		return rc;
215362306a36Sopenharmony_ci	}
215462306a36Sopenharmony_ci	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp)
215562306a36Sopenharmony_ci		rc = bnxt_re_modify_shadow_qp(rdev, qp, qp_attr_mask);
215662306a36Sopenharmony_ci	return rc;
215762306a36Sopenharmony_ci}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ciint bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
216062306a36Sopenharmony_ci		     int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
216162306a36Sopenharmony_ci{
216262306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
216362306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = qp->rdev;
216462306a36Sopenharmony_ci	struct bnxt_qplib_qp *qplib_qp;
216562306a36Sopenharmony_ci	int rc;
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci	qplib_qp = kzalloc(sizeof(*qplib_qp), GFP_KERNEL);
216862306a36Sopenharmony_ci	if (!qplib_qp)
216962306a36Sopenharmony_ci		return -ENOMEM;
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	qplib_qp->id = qp->qplib_qp.id;
217262306a36Sopenharmony_ci	qplib_qp->ah.host_sgid_index = qp->qplib_qp.ah.host_sgid_index;
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci	rc = bnxt_qplib_query_qp(&rdev->qplib_res, qplib_qp);
217562306a36Sopenharmony_ci	if (rc) {
217662306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to query HW QP");
217762306a36Sopenharmony_ci		goto out;
217862306a36Sopenharmony_ci	}
217962306a36Sopenharmony_ci	qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state);
218062306a36Sopenharmony_ci	qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state);
218162306a36Sopenharmony_ci	qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0;
218262306a36Sopenharmony_ci	qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access);
218362306a36Sopenharmony_ci	qp_attr->pkey_index = qplib_qp->pkey_index;
218462306a36Sopenharmony_ci	qp_attr->qkey = qplib_qp->qkey;
218562306a36Sopenharmony_ci	qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
218662306a36Sopenharmony_ci	rdma_ah_set_grh(&qp_attr->ah_attr, NULL, qplib_qp->ah.flow_label,
218762306a36Sopenharmony_ci			qplib_qp->ah.host_sgid_index,
218862306a36Sopenharmony_ci			qplib_qp->ah.hop_limit,
218962306a36Sopenharmony_ci			qplib_qp->ah.traffic_class);
219062306a36Sopenharmony_ci	rdma_ah_set_dgid_raw(&qp_attr->ah_attr, qplib_qp->ah.dgid.data);
219162306a36Sopenharmony_ci	rdma_ah_set_sl(&qp_attr->ah_attr, qplib_qp->ah.sl);
219262306a36Sopenharmony_ci	ether_addr_copy(qp_attr->ah_attr.roce.dmac, qplib_qp->ah.dmac);
219362306a36Sopenharmony_ci	qp_attr->path_mtu = __to_ib_mtu(qplib_qp->path_mtu);
219462306a36Sopenharmony_ci	qp_attr->timeout = qplib_qp->timeout;
219562306a36Sopenharmony_ci	qp_attr->retry_cnt = qplib_qp->retry_cnt;
219662306a36Sopenharmony_ci	qp_attr->rnr_retry = qplib_qp->rnr_retry;
219762306a36Sopenharmony_ci	qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer;
219862306a36Sopenharmony_ci	qp_attr->rq_psn = qplib_qp->rq.psn;
219962306a36Sopenharmony_ci	qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic;
220062306a36Sopenharmony_ci	qp_attr->sq_psn = qplib_qp->sq.psn;
220162306a36Sopenharmony_ci	qp_attr->max_dest_rd_atomic = qplib_qp->max_dest_rd_atomic;
220262306a36Sopenharmony_ci	qp_init_attr->sq_sig_type = qplib_qp->sig_type ? IB_SIGNAL_ALL_WR :
220362306a36Sopenharmony_ci							 IB_SIGNAL_REQ_WR;
220462306a36Sopenharmony_ci	qp_attr->dest_qp_num = qplib_qp->dest_qpn;
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_ci	qp_attr->cap.max_send_wr = qp->qplib_qp.sq.max_wqe;
220762306a36Sopenharmony_ci	qp_attr->cap.max_send_sge = qp->qplib_qp.sq.max_sge;
220862306a36Sopenharmony_ci	qp_attr->cap.max_recv_wr = qp->qplib_qp.rq.max_wqe;
220962306a36Sopenharmony_ci	qp_attr->cap.max_recv_sge = qp->qplib_qp.rq.max_sge;
221062306a36Sopenharmony_ci	qp_attr->cap.max_inline_data = qp->qplib_qp.max_inline_data;
221162306a36Sopenharmony_ci	qp_init_attr->cap = qp_attr->cap;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ciout:
221462306a36Sopenharmony_ci	kfree(qplib_qp);
221562306a36Sopenharmony_ci	return rc;
221662306a36Sopenharmony_ci}
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_ci/* Routine for sending QP1 packets for RoCE V1 an V2
221962306a36Sopenharmony_ci */
222062306a36Sopenharmony_cistatic int bnxt_re_build_qp1_send_v2(struct bnxt_re_qp *qp,
222162306a36Sopenharmony_ci				     const struct ib_send_wr *wr,
222262306a36Sopenharmony_ci				     struct bnxt_qplib_swqe *wqe,
222362306a36Sopenharmony_ci				     int payload_size)
222462306a36Sopenharmony_ci{
222562306a36Sopenharmony_ci	struct bnxt_re_ah *ah = container_of(ud_wr(wr)->ah, struct bnxt_re_ah,
222662306a36Sopenharmony_ci					     ib_ah);
222762306a36Sopenharmony_ci	struct bnxt_qplib_ah *qplib_ah = &ah->qplib_ah;
222862306a36Sopenharmony_ci	const struct ib_gid_attr *sgid_attr = ah->ib_ah.sgid_attr;
222962306a36Sopenharmony_ci	struct bnxt_qplib_sge sge;
223062306a36Sopenharmony_ci	u8 nw_type;
223162306a36Sopenharmony_ci	u16 ether_type;
223262306a36Sopenharmony_ci	union ib_gid dgid;
223362306a36Sopenharmony_ci	bool is_eth = false;
223462306a36Sopenharmony_ci	bool is_vlan = false;
223562306a36Sopenharmony_ci	bool is_grh = false;
223662306a36Sopenharmony_ci	bool is_udp = false;
223762306a36Sopenharmony_ci	u8 ip_version = 0;
223862306a36Sopenharmony_ci	u16 vlan_id = 0xFFFF;
223962306a36Sopenharmony_ci	void *buf;
224062306a36Sopenharmony_ci	int i, rc;
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci	memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr));
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci	rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
224562306a36Sopenharmony_ci	if (rc)
224662306a36Sopenharmony_ci		return rc;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	/* Get network header type for this GID */
224962306a36Sopenharmony_ci	nw_type = rdma_gid_attr_network_type(sgid_attr);
225062306a36Sopenharmony_ci	switch (nw_type) {
225162306a36Sopenharmony_ci	case RDMA_NETWORK_IPV4:
225262306a36Sopenharmony_ci		nw_type = BNXT_RE_ROCEV2_IPV4_PACKET;
225362306a36Sopenharmony_ci		break;
225462306a36Sopenharmony_ci	case RDMA_NETWORK_IPV6:
225562306a36Sopenharmony_ci		nw_type = BNXT_RE_ROCEV2_IPV6_PACKET;
225662306a36Sopenharmony_ci		break;
225762306a36Sopenharmony_ci	default:
225862306a36Sopenharmony_ci		nw_type = BNXT_RE_ROCE_V1_PACKET;
225962306a36Sopenharmony_ci		break;
226062306a36Sopenharmony_ci	}
226162306a36Sopenharmony_ci	memcpy(&dgid.raw, &qplib_ah->dgid, 16);
226262306a36Sopenharmony_ci	is_udp = sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP;
226362306a36Sopenharmony_ci	if (is_udp) {
226462306a36Sopenharmony_ci		if (ipv6_addr_v4mapped((struct in6_addr *)&sgid_attr->gid)) {
226562306a36Sopenharmony_ci			ip_version = 4;
226662306a36Sopenharmony_ci			ether_type = ETH_P_IP;
226762306a36Sopenharmony_ci		} else {
226862306a36Sopenharmony_ci			ip_version = 6;
226962306a36Sopenharmony_ci			ether_type = ETH_P_IPV6;
227062306a36Sopenharmony_ci		}
227162306a36Sopenharmony_ci		is_grh = false;
227262306a36Sopenharmony_ci	} else {
227362306a36Sopenharmony_ci		ether_type = ETH_P_IBOE;
227462306a36Sopenharmony_ci		is_grh = true;
227562306a36Sopenharmony_ci	}
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	is_eth = true;
227862306a36Sopenharmony_ci	is_vlan = vlan_id && (vlan_id < 0x1000);
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	ib_ud_header_init(payload_size, !is_eth, is_eth, is_vlan, is_grh,
228162306a36Sopenharmony_ci			  ip_version, is_udp, 0, &qp->qp1_hdr);
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_ci	/* ETH */
228462306a36Sopenharmony_ci	ether_addr_copy(qp->qp1_hdr.eth.dmac_h, ah->qplib_ah.dmac);
228562306a36Sopenharmony_ci	ether_addr_copy(qp->qp1_hdr.eth.smac_h, qp->qplib_qp.smac);
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	/* For vlan, check the sgid for vlan existence */
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	if (!is_vlan) {
229062306a36Sopenharmony_ci		qp->qp1_hdr.eth.type = cpu_to_be16(ether_type);
229162306a36Sopenharmony_ci	} else {
229262306a36Sopenharmony_ci		qp->qp1_hdr.vlan.type = cpu_to_be16(ether_type);
229362306a36Sopenharmony_ci		qp->qp1_hdr.vlan.tag = cpu_to_be16(vlan_id);
229462306a36Sopenharmony_ci	}
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_ci	if (is_grh || (ip_version == 6)) {
229762306a36Sopenharmony_ci		memcpy(qp->qp1_hdr.grh.source_gid.raw, sgid_attr->gid.raw,
229862306a36Sopenharmony_ci		       sizeof(sgid_attr->gid));
229962306a36Sopenharmony_ci		memcpy(qp->qp1_hdr.grh.destination_gid.raw, qplib_ah->dgid.data,
230062306a36Sopenharmony_ci		       sizeof(sgid_attr->gid));
230162306a36Sopenharmony_ci		qp->qp1_hdr.grh.hop_limit     = qplib_ah->hop_limit;
230262306a36Sopenharmony_ci	}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	if (ip_version == 4) {
230562306a36Sopenharmony_ci		qp->qp1_hdr.ip4.tos = 0;
230662306a36Sopenharmony_ci		qp->qp1_hdr.ip4.id = 0;
230762306a36Sopenharmony_ci		qp->qp1_hdr.ip4.frag_off = htons(IP_DF);
230862306a36Sopenharmony_ci		qp->qp1_hdr.ip4.ttl = qplib_ah->hop_limit;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci		memcpy(&qp->qp1_hdr.ip4.saddr, sgid_attr->gid.raw + 12, 4);
231162306a36Sopenharmony_ci		memcpy(&qp->qp1_hdr.ip4.daddr, qplib_ah->dgid.data + 12, 4);
231262306a36Sopenharmony_ci		qp->qp1_hdr.ip4.check = ib_ud_ip4_csum(&qp->qp1_hdr);
231362306a36Sopenharmony_ci	}
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci	if (is_udp) {
231662306a36Sopenharmony_ci		qp->qp1_hdr.udp.dport = htons(ROCE_V2_UDP_DPORT);
231762306a36Sopenharmony_ci		qp->qp1_hdr.udp.sport = htons(0x8CD1);
231862306a36Sopenharmony_ci		qp->qp1_hdr.udp.csum = 0;
231962306a36Sopenharmony_ci	}
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	/* BTH */
232262306a36Sopenharmony_ci	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
232362306a36Sopenharmony_ci		qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
232462306a36Sopenharmony_ci		qp->qp1_hdr.immediate_present = 1;
232562306a36Sopenharmony_ci	} else {
232662306a36Sopenharmony_ci		qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
232762306a36Sopenharmony_ci	}
232862306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
232962306a36Sopenharmony_ci		qp->qp1_hdr.bth.solicited_event = 1;
233062306a36Sopenharmony_ci	/* pad_count */
233162306a36Sopenharmony_ci	qp->qp1_hdr.bth.pad_count = (4 - payload_size) & 3;
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	/* P_key for QP1 is for all members */
233462306a36Sopenharmony_ci	qp->qp1_hdr.bth.pkey = cpu_to_be16(0xFFFF);
233562306a36Sopenharmony_ci	qp->qp1_hdr.bth.destination_qpn = IB_QP1;
233662306a36Sopenharmony_ci	qp->qp1_hdr.bth.ack_req = 0;
233762306a36Sopenharmony_ci	qp->send_psn++;
233862306a36Sopenharmony_ci	qp->send_psn &= BTH_PSN_MASK;
233962306a36Sopenharmony_ci	qp->qp1_hdr.bth.psn = cpu_to_be32(qp->send_psn);
234062306a36Sopenharmony_ci	/* DETH */
234162306a36Sopenharmony_ci	/* Use the priviledged Q_Key for QP1 */
234262306a36Sopenharmony_ci	qp->qp1_hdr.deth.qkey = cpu_to_be32(IB_QP1_QKEY);
234362306a36Sopenharmony_ci	qp->qp1_hdr.deth.source_qpn = IB_QP1;
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci	/* Pack the QP1 to the transmit buffer */
234662306a36Sopenharmony_ci	buf = bnxt_qplib_get_qp1_sq_buf(&qp->qplib_qp, &sge);
234762306a36Sopenharmony_ci	if (buf) {
234862306a36Sopenharmony_ci		ib_ud_header_pack(&qp->qp1_hdr, buf);
234962306a36Sopenharmony_ci		for (i = wqe->num_sge; i; i--) {
235062306a36Sopenharmony_ci			wqe->sg_list[i].addr = wqe->sg_list[i - 1].addr;
235162306a36Sopenharmony_ci			wqe->sg_list[i].lkey = wqe->sg_list[i - 1].lkey;
235262306a36Sopenharmony_ci			wqe->sg_list[i].size = wqe->sg_list[i - 1].size;
235362306a36Sopenharmony_ci		}
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_ci		/*
235662306a36Sopenharmony_ci		 * Max Header buf size for IPV6 RoCE V2 is 86,
235762306a36Sopenharmony_ci		 * which is same as the QP1 SQ header buffer.
235862306a36Sopenharmony_ci		 * Header buf size for IPV4 RoCE V2 can be 66.
235962306a36Sopenharmony_ci		 * ETH(14) + VLAN(4)+ IP(20) + UDP (8) + BTH(20).
236062306a36Sopenharmony_ci		 * Subtract 20 bytes from QP1 SQ header buf size
236162306a36Sopenharmony_ci		 */
236262306a36Sopenharmony_ci		if (is_udp && ip_version == 4)
236362306a36Sopenharmony_ci			sge.size -= 20;
236462306a36Sopenharmony_ci		/*
236562306a36Sopenharmony_ci		 * Max Header buf size for RoCE V1 is 78.
236662306a36Sopenharmony_ci		 * ETH(14) + VLAN(4) + GRH(40) + BTH(20).
236762306a36Sopenharmony_ci		 * Subtract 8 bytes from QP1 SQ header buf size
236862306a36Sopenharmony_ci		 */
236962306a36Sopenharmony_ci		if (!is_udp)
237062306a36Sopenharmony_ci			sge.size -= 8;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci		/* Subtract 4 bytes for non vlan packets */
237362306a36Sopenharmony_ci		if (!is_vlan)
237462306a36Sopenharmony_ci			sge.size -= 4;
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_ci		wqe->sg_list[0].addr = sge.addr;
237762306a36Sopenharmony_ci		wqe->sg_list[0].lkey = sge.lkey;
237862306a36Sopenharmony_ci		wqe->sg_list[0].size = sge.size;
237962306a36Sopenharmony_ci		wqe->num_sge++;
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	} else {
238262306a36Sopenharmony_ci		ibdev_err(&qp->rdev->ibdev, "QP1 buffer is empty!");
238362306a36Sopenharmony_ci		rc = -ENOMEM;
238462306a36Sopenharmony_ci	}
238562306a36Sopenharmony_ci	return rc;
238662306a36Sopenharmony_ci}
238762306a36Sopenharmony_ci
238862306a36Sopenharmony_ci/* For the MAD layer, it only provides the recv SGE the size of
238962306a36Sopenharmony_ci * ib_grh + MAD datagram.  No Ethernet headers, Ethertype, BTH, DETH,
239062306a36Sopenharmony_ci * nor RoCE iCRC.  The Cu+ solution must provide buffer for the entire
239162306a36Sopenharmony_ci * receive packet (334 bytes) with no VLAN and then copy the GRH
239262306a36Sopenharmony_ci * and the MAD datagram out to the provided SGE.
239362306a36Sopenharmony_ci */
239462306a36Sopenharmony_cistatic int bnxt_re_build_qp1_shadow_qp_recv(struct bnxt_re_qp *qp,
239562306a36Sopenharmony_ci					    const struct ib_recv_wr *wr,
239662306a36Sopenharmony_ci					    struct bnxt_qplib_swqe *wqe,
239762306a36Sopenharmony_ci					    int payload_size)
239862306a36Sopenharmony_ci{
239962306a36Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry;
240062306a36Sopenharmony_ci	struct bnxt_qplib_sge ref, sge;
240162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
240262306a36Sopenharmony_ci	u32 rq_prod_index;
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	rdev = qp->rdev;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	rq_prod_index = bnxt_qplib_get_rq_prod_index(&qp->qplib_qp);
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci	if (!bnxt_qplib_get_qp1_rq_buf(&qp->qplib_qp, &sge))
240962306a36Sopenharmony_ci		return -ENOMEM;
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	/* Create 1 SGE to receive the entire
241262306a36Sopenharmony_ci	 * ethernet packet
241362306a36Sopenharmony_ci	 */
241462306a36Sopenharmony_ci	/* Save the reference from ULP */
241562306a36Sopenharmony_ci	ref.addr = wqe->sg_list[0].addr;
241662306a36Sopenharmony_ci	ref.lkey = wqe->sg_list[0].lkey;
241762306a36Sopenharmony_ci	ref.size = wqe->sg_list[0].size;
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[rq_prod_index];
242062306a36Sopenharmony_ci
242162306a36Sopenharmony_ci	/* SGE 1 */
242262306a36Sopenharmony_ci	wqe->sg_list[0].addr = sge.addr;
242362306a36Sopenharmony_ci	wqe->sg_list[0].lkey = sge.lkey;
242462306a36Sopenharmony_ci	wqe->sg_list[0].size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
242562306a36Sopenharmony_ci	sge.size -= wqe->sg_list[0].size;
242662306a36Sopenharmony_ci
242762306a36Sopenharmony_ci	sqp_entry->sge.addr = ref.addr;
242862306a36Sopenharmony_ci	sqp_entry->sge.lkey = ref.lkey;
242962306a36Sopenharmony_ci	sqp_entry->sge.size = ref.size;
243062306a36Sopenharmony_ci	/* Store the wrid for reporting completion */
243162306a36Sopenharmony_ci	sqp_entry->wrid = wqe->wr_id;
243262306a36Sopenharmony_ci	/* change the wqe->wrid to table index */
243362306a36Sopenharmony_ci	wqe->wr_id = rq_prod_index;
243462306a36Sopenharmony_ci	return 0;
243562306a36Sopenharmony_ci}
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_cistatic int is_ud_qp(struct bnxt_re_qp *qp)
243862306a36Sopenharmony_ci{
243962306a36Sopenharmony_ci	return (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD ||
244062306a36Sopenharmony_ci		qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_GSI);
244162306a36Sopenharmony_ci}
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_cistatic int bnxt_re_build_send_wqe(struct bnxt_re_qp *qp,
244462306a36Sopenharmony_ci				  const struct ib_send_wr *wr,
244562306a36Sopenharmony_ci				  struct bnxt_qplib_swqe *wqe)
244662306a36Sopenharmony_ci{
244762306a36Sopenharmony_ci	struct bnxt_re_ah *ah = NULL;
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci	if (is_ud_qp(qp)) {
245062306a36Sopenharmony_ci		ah = container_of(ud_wr(wr)->ah, struct bnxt_re_ah, ib_ah);
245162306a36Sopenharmony_ci		wqe->send.q_key = ud_wr(wr)->remote_qkey;
245262306a36Sopenharmony_ci		wqe->send.dst_qp = ud_wr(wr)->remote_qpn;
245362306a36Sopenharmony_ci		wqe->send.avid = ah->qplib_ah.id;
245462306a36Sopenharmony_ci	}
245562306a36Sopenharmony_ci	switch (wr->opcode) {
245662306a36Sopenharmony_ci	case IB_WR_SEND:
245762306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND;
245862306a36Sopenharmony_ci		break;
245962306a36Sopenharmony_ci	case IB_WR_SEND_WITH_IMM:
246062306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM;
246162306a36Sopenharmony_ci		wqe->send.imm_data = wr->ex.imm_data;
246262306a36Sopenharmony_ci		break;
246362306a36Sopenharmony_ci	case IB_WR_SEND_WITH_INV:
246462306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV;
246562306a36Sopenharmony_ci		wqe->send.inv_key = wr->ex.invalidate_rkey;
246662306a36Sopenharmony_ci		break;
246762306a36Sopenharmony_ci	default:
246862306a36Sopenharmony_ci		return -EINVAL;
246962306a36Sopenharmony_ci	}
247062306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
247162306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
247262306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
247362306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
247462306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
247562306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
247662306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
247762306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE;
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci	return 0;
248062306a36Sopenharmony_ci}
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_cistatic int bnxt_re_build_rdma_wqe(const struct ib_send_wr *wr,
248362306a36Sopenharmony_ci				  struct bnxt_qplib_swqe *wqe)
248462306a36Sopenharmony_ci{
248562306a36Sopenharmony_ci	switch (wr->opcode) {
248662306a36Sopenharmony_ci	case IB_WR_RDMA_WRITE:
248762306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE;
248862306a36Sopenharmony_ci		break;
248962306a36Sopenharmony_ci	case IB_WR_RDMA_WRITE_WITH_IMM:
249062306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM;
249162306a36Sopenharmony_ci		wqe->rdma.imm_data = wr->ex.imm_data;
249262306a36Sopenharmony_ci		break;
249362306a36Sopenharmony_ci	case IB_WR_RDMA_READ:
249462306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_READ;
249562306a36Sopenharmony_ci		wqe->rdma.inv_key = wr->ex.invalidate_rkey;
249662306a36Sopenharmony_ci		break;
249762306a36Sopenharmony_ci	default:
249862306a36Sopenharmony_ci		return -EINVAL;
249962306a36Sopenharmony_ci	}
250062306a36Sopenharmony_ci	wqe->rdma.remote_va = rdma_wr(wr)->remote_addr;
250162306a36Sopenharmony_ci	wqe->rdma.r_key = rdma_wr(wr)->rkey;
250262306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
250362306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
250462306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
250562306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
250662306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
250762306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
250862306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
250962306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	return 0;
251262306a36Sopenharmony_ci}
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_cistatic int bnxt_re_build_atomic_wqe(const struct ib_send_wr *wr,
251562306a36Sopenharmony_ci				    struct bnxt_qplib_swqe *wqe)
251662306a36Sopenharmony_ci{
251762306a36Sopenharmony_ci	switch (wr->opcode) {
251862306a36Sopenharmony_ci	case IB_WR_ATOMIC_CMP_AND_SWP:
251962306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP;
252062306a36Sopenharmony_ci		wqe->atomic.cmp_data = atomic_wr(wr)->compare_add;
252162306a36Sopenharmony_ci		wqe->atomic.swap_data = atomic_wr(wr)->swap;
252262306a36Sopenharmony_ci		break;
252362306a36Sopenharmony_ci	case IB_WR_ATOMIC_FETCH_AND_ADD:
252462306a36Sopenharmony_ci		wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD;
252562306a36Sopenharmony_ci		wqe->atomic.cmp_data = atomic_wr(wr)->compare_add;
252662306a36Sopenharmony_ci		break;
252762306a36Sopenharmony_ci	default:
252862306a36Sopenharmony_ci		return -EINVAL;
252962306a36Sopenharmony_ci	}
253062306a36Sopenharmony_ci	wqe->atomic.remote_va = atomic_wr(wr)->remote_addr;
253162306a36Sopenharmony_ci	wqe->atomic.r_key = atomic_wr(wr)->rkey;
253262306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
253362306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
253462306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_FENCE)
253562306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
253662306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
253762306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
253862306a36Sopenharmony_ci	return 0;
253962306a36Sopenharmony_ci}
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_cistatic int bnxt_re_build_inv_wqe(const struct ib_send_wr *wr,
254262306a36Sopenharmony_ci				 struct bnxt_qplib_swqe *wqe)
254362306a36Sopenharmony_ci{
254462306a36Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_LOCAL_INV;
254562306a36Sopenharmony_ci	wqe->local_inv.inv_l_key = wr->ex.invalidate_rkey;
254662306a36Sopenharmony_ci
254762306a36Sopenharmony_ci	/* Need unconditional fence for local invalidate
254862306a36Sopenharmony_ci	 * opcode to work as expected.
254962306a36Sopenharmony_ci	 */
255062306a36Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SIGNALED)
255362306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
255462306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_SOLICITED)
255562306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT;
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	return 0;
255862306a36Sopenharmony_ci}
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_cistatic int bnxt_re_build_reg_wqe(const struct ib_reg_wr *wr,
256162306a36Sopenharmony_ci				 struct bnxt_qplib_swqe *wqe)
256262306a36Sopenharmony_ci{
256362306a36Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(wr->mr, struct bnxt_re_mr, ib_mr);
256462306a36Sopenharmony_ci	struct bnxt_qplib_frpl *qplib_frpl = &mr->qplib_frpl;
256562306a36Sopenharmony_ci	int access = wr->access;
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	wqe->frmr.pbl_ptr = (__le64 *)qplib_frpl->hwq.pbl_ptr[0];
256862306a36Sopenharmony_ci	wqe->frmr.pbl_dma_ptr = qplib_frpl->hwq.pbl_dma_ptr[0];
256962306a36Sopenharmony_ci	wqe->frmr.page_list = mr->pages;
257062306a36Sopenharmony_ci	wqe->frmr.page_list_len = mr->npages;
257162306a36Sopenharmony_ci	wqe->frmr.levels = qplib_frpl->hwq.level;
257262306a36Sopenharmony_ci	wqe->type = BNXT_QPLIB_SWQE_TYPE_REG_MR;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	/* Need unconditional fence for reg_mr
257562306a36Sopenharmony_ci	 * opcode to function as expected.
257662306a36Sopenharmony_ci	 */
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci	if (wr->wr.send_flags & IB_SEND_SIGNALED)
258162306a36Sopenharmony_ci		wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	if (access & IB_ACCESS_LOCAL_WRITE)
258462306a36Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_LOCAL_WRITE;
258562306a36Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_READ)
258662306a36Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_READ;
258762306a36Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_WRITE)
258862306a36Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_WRITE;
258962306a36Sopenharmony_ci	if (access & IB_ACCESS_REMOTE_ATOMIC)
259062306a36Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_ATOMIC;
259162306a36Sopenharmony_ci	if (access & IB_ACCESS_MW_BIND)
259262306a36Sopenharmony_ci		wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_WINDOW_BIND;
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_ci	wqe->frmr.l_key = wr->key;
259562306a36Sopenharmony_ci	wqe->frmr.length = wr->mr->length;
259662306a36Sopenharmony_ci	wqe->frmr.pbl_pg_sz_log = ilog2(PAGE_SIZE >> PAGE_SHIFT_4K);
259762306a36Sopenharmony_ci	wqe->frmr.pg_sz_log = ilog2(wr->mr->page_size >> PAGE_SHIFT_4K);
259862306a36Sopenharmony_ci	wqe->frmr.va = wr->mr->iova;
259962306a36Sopenharmony_ci	return 0;
260062306a36Sopenharmony_ci}
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_cistatic int bnxt_re_copy_inline_data(struct bnxt_re_dev *rdev,
260362306a36Sopenharmony_ci				    const struct ib_send_wr *wr,
260462306a36Sopenharmony_ci				    struct bnxt_qplib_swqe *wqe)
260562306a36Sopenharmony_ci{
260662306a36Sopenharmony_ci	/*  Copy the inline data to the data  field */
260762306a36Sopenharmony_ci	u8 *in_data;
260862306a36Sopenharmony_ci	u32 i, sge_len;
260962306a36Sopenharmony_ci	void *sge_addr;
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci	in_data = wqe->inline_data;
261262306a36Sopenharmony_ci	for (i = 0; i < wr->num_sge; i++) {
261362306a36Sopenharmony_ci		sge_addr = (void *)(unsigned long)
261462306a36Sopenharmony_ci				wr->sg_list[i].addr;
261562306a36Sopenharmony_ci		sge_len = wr->sg_list[i].length;
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci		if ((sge_len + wqe->inline_len) >
261862306a36Sopenharmony_ci		    BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH) {
261962306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
262062306a36Sopenharmony_ci				  "Inline data size requested > supported value");
262162306a36Sopenharmony_ci			return -EINVAL;
262262306a36Sopenharmony_ci		}
262362306a36Sopenharmony_ci		sge_len = wr->sg_list[i].length;
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci		memcpy(in_data, sge_addr, sge_len);
262662306a36Sopenharmony_ci		in_data += wr->sg_list[i].length;
262762306a36Sopenharmony_ci		wqe->inline_len += wr->sg_list[i].length;
262862306a36Sopenharmony_ci	}
262962306a36Sopenharmony_ci	return wqe->inline_len;
263062306a36Sopenharmony_ci}
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_cistatic int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev,
263362306a36Sopenharmony_ci				   const struct ib_send_wr *wr,
263462306a36Sopenharmony_ci				   struct bnxt_qplib_swqe *wqe)
263562306a36Sopenharmony_ci{
263662306a36Sopenharmony_ci	int payload_sz = 0;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	if (wr->send_flags & IB_SEND_INLINE)
263962306a36Sopenharmony_ci		payload_sz = bnxt_re_copy_inline_data(rdev, wr, wqe);
264062306a36Sopenharmony_ci	else
264162306a36Sopenharmony_ci		payload_sz = bnxt_re_build_sgl(wr->sg_list, wqe->sg_list,
264262306a36Sopenharmony_ci					       wqe->num_sge);
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci	return payload_sz;
264562306a36Sopenharmony_ci}
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_cistatic void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp)
264862306a36Sopenharmony_ci{
264962306a36Sopenharmony_ci	if ((qp->ib_qp.qp_type == IB_QPT_UD ||
265062306a36Sopenharmony_ci	     qp->ib_qp.qp_type == IB_QPT_GSI ||
265162306a36Sopenharmony_ci	     qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) &&
265262306a36Sopenharmony_ci	     qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) {
265362306a36Sopenharmony_ci		int qp_attr_mask;
265462306a36Sopenharmony_ci		struct ib_qp_attr qp_attr;
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci		qp_attr_mask = IB_QP_STATE;
265762306a36Sopenharmony_ci		qp_attr.qp_state = IB_QPS_RTS;
265862306a36Sopenharmony_ci		bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL);
265962306a36Sopenharmony_ci		qp->qplib_qp.wqe_cnt = 0;
266062306a36Sopenharmony_ci	}
266162306a36Sopenharmony_ci}
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_cistatic int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
266462306a36Sopenharmony_ci				       struct bnxt_re_qp *qp,
266562306a36Sopenharmony_ci				       const struct ib_send_wr *wr)
266662306a36Sopenharmony_ci{
266762306a36Sopenharmony_ci	int rc = 0, payload_sz = 0;
266862306a36Sopenharmony_ci	unsigned long flags;
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
267162306a36Sopenharmony_ci	while (wr) {
267262306a36Sopenharmony_ci		struct bnxt_qplib_swqe wqe = {};
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci		/* Common */
267562306a36Sopenharmony_ci		wqe.num_sge = wr->num_sge;
267662306a36Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.sq.max_sge) {
267762306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
267862306a36Sopenharmony_ci				  "Limit exceeded for Send SGEs");
267962306a36Sopenharmony_ci			rc = -EINVAL;
268062306a36Sopenharmony_ci			goto bad;
268162306a36Sopenharmony_ci		}
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci		payload_sz = bnxt_re_copy_wr_payload(qp->rdev, wr, &wqe);
268462306a36Sopenharmony_ci		if (payload_sz < 0) {
268562306a36Sopenharmony_ci			rc = -EINVAL;
268662306a36Sopenharmony_ci			goto bad;
268762306a36Sopenharmony_ci		}
268862306a36Sopenharmony_ci		wqe.wr_id = wr->wr_id;
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_SEND;
269162306a36Sopenharmony_ci
269262306a36Sopenharmony_ci		rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
269362306a36Sopenharmony_ci		if (!rc)
269462306a36Sopenharmony_ci			rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
269562306a36Sopenharmony_cibad:
269662306a36Sopenharmony_ci		if (rc) {
269762306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
269862306a36Sopenharmony_ci				  "Post send failed opcode = %#x rc = %d",
269962306a36Sopenharmony_ci				  wr->opcode, rc);
270062306a36Sopenharmony_ci			break;
270162306a36Sopenharmony_ci		}
270262306a36Sopenharmony_ci		wr = wr->next;
270362306a36Sopenharmony_ci	}
270462306a36Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
270562306a36Sopenharmony_ci	bnxt_ud_qp_hw_stall_workaround(qp);
270662306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
270762306a36Sopenharmony_ci	return rc;
270862306a36Sopenharmony_ci}
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ciint bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
271162306a36Sopenharmony_ci		      const struct ib_send_wr **bad_wr)
271262306a36Sopenharmony_ci{
271362306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
271462306a36Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
271562306a36Sopenharmony_ci	int rc = 0, payload_sz = 0;
271662306a36Sopenharmony_ci	unsigned long flags;
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
271962306a36Sopenharmony_ci	while (wr) {
272062306a36Sopenharmony_ci		/* House keeping */
272162306a36Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci		/* Common */
272462306a36Sopenharmony_ci		wqe.num_sge = wr->num_sge;
272562306a36Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.sq.max_sge) {
272662306a36Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
272762306a36Sopenharmony_ci				  "Limit exceeded for Send SGEs");
272862306a36Sopenharmony_ci			rc = -EINVAL;
272962306a36Sopenharmony_ci			goto bad;
273062306a36Sopenharmony_ci		}
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci		payload_sz = bnxt_re_copy_wr_payload(qp->rdev, wr, &wqe);
273362306a36Sopenharmony_ci		if (payload_sz < 0) {
273462306a36Sopenharmony_ci			rc = -EINVAL;
273562306a36Sopenharmony_ci			goto bad;
273662306a36Sopenharmony_ci		}
273762306a36Sopenharmony_ci		wqe.wr_id = wr->wr_id;
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci		switch (wr->opcode) {
274062306a36Sopenharmony_ci		case IB_WR_SEND:
274162306a36Sopenharmony_ci		case IB_WR_SEND_WITH_IMM:
274262306a36Sopenharmony_ci			if (qp->qplib_qp.type == CMDQ_CREATE_QP1_TYPE_GSI) {
274362306a36Sopenharmony_ci				rc = bnxt_re_build_qp1_send_v2(qp, wr, &wqe,
274462306a36Sopenharmony_ci							       payload_sz);
274562306a36Sopenharmony_ci				if (rc)
274662306a36Sopenharmony_ci					goto bad;
274762306a36Sopenharmony_ci				wqe.rawqp1.lflags |=
274862306a36Sopenharmony_ci					SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
274962306a36Sopenharmony_ci			}
275062306a36Sopenharmony_ci			switch (wr->send_flags) {
275162306a36Sopenharmony_ci			case IB_SEND_IP_CSUM:
275262306a36Sopenharmony_ci				wqe.rawqp1.lflags |=
275362306a36Sopenharmony_ci					SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
275462306a36Sopenharmony_ci				break;
275562306a36Sopenharmony_ci			default:
275662306a36Sopenharmony_ci				break;
275762306a36Sopenharmony_ci			}
275862306a36Sopenharmony_ci			fallthrough;
275962306a36Sopenharmony_ci		case IB_WR_SEND_WITH_INV:
276062306a36Sopenharmony_ci			rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
276162306a36Sopenharmony_ci			break;
276262306a36Sopenharmony_ci		case IB_WR_RDMA_WRITE:
276362306a36Sopenharmony_ci		case IB_WR_RDMA_WRITE_WITH_IMM:
276462306a36Sopenharmony_ci		case IB_WR_RDMA_READ:
276562306a36Sopenharmony_ci			rc = bnxt_re_build_rdma_wqe(wr, &wqe);
276662306a36Sopenharmony_ci			break;
276762306a36Sopenharmony_ci		case IB_WR_ATOMIC_CMP_AND_SWP:
276862306a36Sopenharmony_ci		case IB_WR_ATOMIC_FETCH_AND_ADD:
276962306a36Sopenharmony_ci			rc = bnxt_re_build_atomic_wqe(wr, &wqe);
277062306a36Sopenharmony_ci			break;
277162306a36Sopenharmony_ci		case IB_WR_RDMA_READ_WITH_INV:
277262306a36Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
277362306a36Sopenharmony_ci				  "RDMA Read with Invalidate is not supported");
277462306a36Sopenharmony_ci			rc = -EINVAL;
277562306a36Sopenharmony_ci			goto bad;
277662306a36Sopenharmony_ci		case IB_WR_LOCAL_INV:
277762306a36Sopenharmony_ci			rc = bnxt_re_build_inv_wqe(wr, &wqe);
277862306a36Sopenharmony_ci			break;
277962306a36Sopenharmony_ci		case IB_WR_REG_MR:
278062306a36Sopenharmony_ci			rc = bnxt_re_build_reg_wqe(reg_wr(wr), &wqe);
278162306a36Sopenharmony_ci			break;
278262306a36Sopenharmony_ci		default:
278362306a36Sopenharmony_ci			/* Unsupported WRs */
278462306a36Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
278562306a36Sopenharmony_ci				  "WR (%#x) is not supported", wr->opcode);
278662306a36Sopenharmony_ci			rc = -EINVAL;
278762306a36Sopenharmony_ci			goto bad;
278862306a36Sopenharmony_ci		}
278962306a36Sopenharmony_ci		if (!rc)
279062306a36Sopenharmony_ci			rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
279162306a36Sopenharmony_cibad:
279262306a36Sopenharmony_ci		if (rc) {
279362306a36Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
279462306a36Sopenharmony_ci				  "post_send failed op:%#x qps = %#x rc = %d\n",
279562306a36Sopenharmony_ci				  wr->opcode, qp->qplib_qp.state, rc);
279662306a36Sopenharmony_ci			*bad_wr = wr;
279762306a36Sopenharmony_ci			break;
279862306a36Sopenharmony_ci		}
279962306a36Sopenharmony_ci		wr = wr->next;
280062306a36Sopenharmony_ci	}
280162306a36Sopenharmony_ci	bnxt_qplib_post_send_db(&qp->qplib_qp);
280262306a36Sopenharmony_ci	bnxt_ud_qp_hw_stall_workaround(qp);
280362306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	return rc;
280662306a36Sopenharmony_ci}
280762306a36Sopenharmony_ci
280862306a36Sopenharmony_cistatic int bnxt_re_post_recv_shadow_qp(struct bnxt_re_dev *rdev,
280962306a36Sopenharmony_ci				       struct bnxt_re_qp *qp,
281062306a36Sopenharmony_ci				       const struct ib_recv_wr *wr)
281162306a36Sopenharmony_ci{
281262306a36Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
281362306a36Sopenharmony_ci	int rc = 0;
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	while (wr) {
281662306a36Sopenharmony_ci		/* House keeping */
281762306a36Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci		/* Common */
282062306a36Sopenharmony_ci		wqe.num_sge = wr->num_sge;
282162306a36Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.rq.max_sge) {
282262306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev,
282362306a36Sopenharmony_ci				  "Limit exceeded for Receive SGEs");
282462306a36Sopenharmony_ci			rc = -EINVAL;
282562306a36Sopenharmony_ci			break;
282662306a36Sopenharmony_ci		}
282762306a36Sopenharmony_ci		bnxt_re_build_sgl(wr->sg_list, wqe.sg_list, wr->num_sge);
282862306a36Sopenharmony_ci		wqe.wr_id = wr->wr_id;
282962306a36Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci		rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe);
283262306a36Sopenharmony_ci		if (rc)
283362306a36Sopenharmony_ci			break;
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci		wr = wr->next;
283662306a36Sopenharmony_ci	}
283762306a36Sopenharmony_ci	if (!rc)
283862306a36Sopenharmony_ci		bnxt_qplib_post_recv_db(&qp->qplib_qp);
283962306a36Sopenharmony_ci	return rc;
284062306a36Sopenharmony_ci}
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ciint bnxt_re_post_recv(struct ib_qp *ib_qp, const struct ib_recv_wr *wr,
284362306a36Sopenharmony_ci		      const struct ib_recv_wr **bad_wr)
284462306a36Sopenharmony_ci{
284562306a36Sopenharmony_ci	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
284662306a36Sopenharmony_ci	struct bnxt_qplib_swqe wqe;
284762306a36Sopenharmony_ci	int rc = 0, payload_sz = 0;
284862306a36Sopenharmony_ci	unsigned long flags;
284962306a36Sopenharmony_ci	u32 count = 0;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	spin_lock_irqsave(&qp->rq_lock, flags);
285262306a36Sopenharmony_ci	while (wr) {
285362306a36Sopenharmony_ci		/* House keeping */
285462306a36Sopenharmony_ci		memset(&wqe, 0, sizeof(wqe));
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci		/* Common */
285762306a36Sopenharmony_ci		wqe.num_sge = wr->num_sge;
285862306a36Sopenharmony_ci		if (wr->num_sge > qp->qplib_qp.rq.max_sge) {
285962306a36Sopenharmony_ci			ibdev_err(&qp->rdev->ibdev,
286062306a36Sopenharmony_ci				  "Limit exceeded for Receive SGEs");
286162306a36Sopenharmony_ci			rc = -EINVAL;
286262306a36Sopenharmony_ci			*bad_wr = wr;
286362306a36Sopenharmony_ci			break;
286462306a36Sopenharmony_ci		}
286562306a36Sopenharmony_ci
286662306a36Sopenharmony_ci		payload_sz = bnxt_re_build_sgl(wr->sg_list, wqe.sg_list,
286762306a36Sopenharmony_ci					       wr->num_sge);
286862306a36Sopenharmony_ci		wqe.wr_id = wr->wr_id;
286962306a36Sopenharmony_ci		wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci		if (ib_qp->qp_type == IB_QPT_GSI &&
287262306a36Sopenharmony_ci		    qp->qplib_qp.type != CMDQ_CREATE_QP_TYPE_GSI)
287362306a36Sopenharmony_ci			rc = bnxt_re_build_qp1_shadow_qp_recv(qp, wr, &wqe,
287462306a36Sopenharmony_ci							      payload_sz);
287562306a36Sopenharmony_ci		if (!rc)
287662306a36Sopenharmony_ci			rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe);
287762306a36Sopenharmony_ci		if (rc) {
287862306a36Sopenharmony_ci			*bad_wr = wr;
287962306a36Sopenharmony_ci			break;
288062306a36Sopenharmony_ci		}
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_ci		/* Ring DB if the RQEs posted reaches a threshold value */
288362306a36Sopenharmony_ci		if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) {
288462306a36Sopenharmony_ci			bnxt_qplib_post_recv_db(&qp->qplib_qp);
288562306a36Sopenharmony_ci			count = 0;
288662306a36Sopenharmony_ci		}
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci		wr = wr->next;
288962306a36Sopenharmony_ci	}
289062306a36Sopenharmony_ci
289162306a36Sopenharmony_ci	if (count)
289262306a36Sopenharmony_ci		bnxt_qplib_post_recv_db(&qp->qplib_qp);
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->rq_lock, flags);
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_ci	return rc;
289762306a36Sopenharmony_ci}
289862306a36Sopenharmony_ci
289962306a36Sopenharmony_ci/* Completion Queues */
290062306a36Sopenharmony_ciint bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
290162306a36Sopenharmony_ci{
290262306a36Sopenharmony_ci	struct bnxt_re_cq *cq;
290362306a36Sopenharmony_ci	struct bnxt_qplib_nq *nq;
290462306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
290762306a36Sopenharmony_ci	rdev = cq->rdev;
290862306a36Sopenharmony_ci	nq = cq->qplib_cq.nq;
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci	bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
291162306a36Sopenharmony_ci	ib_umem_release(cq->umem);
291262306a36Sopenharmony_ci
291362306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.cq_count);
291462306a36Sopenharmony_ci	nq->budget--;
291562306a36Sopenharmony_ci	kfree(cq->cql);
291662306a36Sopenharmony_ci	return 0;
291762306a36Sopenharmony_ci}
291862306a36Sopenharmony_ci
291962306a36Sopenharmony_ciint bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
292062306a36Sopenharmony_ci		      struct ib_udata *udata)
292162306a36Sopenharmony_ci{
292262306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibcq->device, ibdev);
292362306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
292462306a36Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ibcq, struct bnxt_re_cq, ib_cq);
292562306a36Sopenharmony_ci	int rc, entries;
292662306a36Sopenharmony_ci	int cqe = attr->cqe;
292762306a36Sopenharmony_ci	struct bnxt_qplib_nq *nq = NULL;
292862306a36Sopenharmony_ci	unsigned int nq_alloc_cnt;
292962306a36Sopenharmony_ci	u32 active_cqs;
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci	if (attr->flags)
293262306a36Sopenharmony_ci		return -EOPNOTSUPP;
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci	/* Validate CQ fields */
293562306a36Sopenharmony_ci	if (cqe < 1 || cqe > dev_attr->max_cq_wqes) {
293662306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create CQ -max exceeded");
293762306a36Sopenharmony_ci		return -EINVAL;
293862306a36Sopenharmony_ci	}
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	cq->rdev = rdev;
294162306a36Sopenharmony_ci	cq->qplib_cq.cq_handle = (u64)(unsigned long)(&cq->qplib_cq);
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_ci	entries = roundup_pow_of_two(cqe + 1);
294462306a36Sopenharmony_ci	if (entries > dev_attr->max_cq_wqes + 1)
294562306a36Sopenharmony_ci		entries = dev_attr->max_cq_wqes + 1;
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	cq->qplib_cq.sg_info.pgsize = PAGE_SIZE;
294862306a36Sopenharmony_ci	cq->qplib_cq.sg_info.pgshft = PAGE_SHIFT;
294962306a36Sopenharmony_ci	if (udata) {
295062306a36Sopenharmony_ci		struct bnxt_re_cq_req req;
295162306a36Sopenharmony_ci		struct bnxt_re_ucontext *uctx = rdma_udata_to_drv_context(
295262306a36Sopenharmony_ci			udata, struct bnxt_re_ucontext, ib_uctx);
295362306a36Sopenharmony_ci		if (ib_copy_from_udata(&req, udata, sizeof(req))) {
295462306a36Sopenharmony_ci			rc = -EFAULT;
295562306a36Sopenharmony_ci			goto fail;
295662306a36Sopenharmony_ci		}
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci		cq->umem = ib_umem_get(&rdev->ibdev, req.cq_va,
295962306a36Sopenharmony_ci				       entries * sizeof(struct cq_base),
296062306a36Sopenharmony_ci				       IB_ACCESS_LOCAL_WRITE);
296162306a36Sopenharmony_ci		if (IS_ERR(cq->umem)) {
296262306a36Sopenharmony_ci			rc = PTR_ERR(cq->umem);
296362306a36Sopenharmony_ci			goto fail;
296462306a36Sopenharmony_ci		}
296562306a36Sopenharmony_ci		cq->qplib_cq.sg_info.umem = cq->umem;
296662306a36Sopenharmony_ci		cq->qplib_cq.dpi = &uctx->dpi;
296762306a36Sopenharmony_ci	} else {
296862306a36Sopenharmony_ci		cq->max_cql = min_t(u32, entries, MAX_CQL_PER_POLL);
296962306a36Sopenharmony_ci		cq->cql = kcalloc(cq->max_cql, sizeof(struct bnxt_qplib_cqe),
297062306a36Sopenharmony_ci				  GFP_KERNEL);
297162306a36Sopenharmony_ci		if (!cq->cql) {
297262306a36Sopenharmony_ci			rc = -ENOMEM;
297362306a36Sopenharmony_ci			goto fail;
297462306a36Sopenharmony_ci		}
297562306a36Sopenharmony_ci
297662306a36Sopenharmony_ci		cq->qplib_cq.dpi = &rdev->dpi_privileged;
297762306a36Sopenharmony_ci	}
297862306a36Sopenharmony_ci	/*
297962306a36Sopenharmony_ci	 * Allocating the NQ in a round robin fashion. nq_alloc_cnt is a
298062306a36Sopenharmony_ci	 * used for getting the NQ index.
298162306a36Sopenharmony_ci	 */
298262306a36Sopenharmony_ci	nq_alloc_cnt = atomic_inc_return(&rdev->nq_alloc_cnt);
298362306a36Sopenharmony_ci	nq = &rdev->nq[nq_alloc_cnt % (rdev->num_msix - 1)];
298462306a36Sopenharmony_ci	cq->qplib_cq.max_wqe = entries;
298562306a36Sopenharmony_ci	cq->qplib_cq.cnq_hw_ring_id = nq->ring_id;
298662306a36Sopenharmony_ci	cq->qplib_cq.nq	= nq;
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	rc = bnxt_qplib_create_cq(&rdev->qplib_res, &cq->qplib_cq);
298962306a36Sopenharmony_ci	if (rc) {
299062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to create HW CQ");
299162306a36Sopenharmony_ci		goto fail;
299262306a36Sopenharmony_ci	}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci	cq->ib_cq.cqe = entries;
299562306a36Sopenharmony_ci	cq->cq_period = cq->qplib_cq.period;
299662306a36Sopenharmony_ci	nq->budget++;
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	active_cqs = atomic_inc_return(&rdev->stats.res.cq_count);
299962306a36Sopenharmony_ci	if (active_cqs > rdev->stats.res.cq_watermark)
300062306a36Sopenharmony_ci		rdev->stats.res.cq_watermark = active_cqs;
300162306a36Sopenharmony_ci	spin_lock_init(&cq->cq_lock);
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	if (udata) {
300462306a36Sopenharmony_ci		struct bnxt_re_cq_resp resp;
300562306a36Sopenharmony_ci
300662306a36Sopenharmony_ci		resp.cqid = cq->qplib_cq.id;
300762306a36Sopenharmony_ci		resp.tail = cq->qplib_cq.hwq.cons;
300862306a36Sopenharmony_ci		resp.phase = cq->qplib_cq.period;
300962306a36Sopenharmony_ci		resp.rsvd = 0;
301062306a36Sopenharmony_ci		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
301162306a36Sopenharmony_ci		if (rc) {
301262306a36Sopenharmony_ci			ibdev_err(&rdev->ibdev, "Failed to copy CQ udata");
301362306a36Sopenharmony_ci			bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
301462306a36Sopenharmony_ci			goto c2fail;
301562306a36Sopenharmony_ci		}
301662306a36Sopenharmony_ci	}
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	return 0;
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_cic2fail:
302162306a36Sopenharmony_ci	ib_umem_release(cq->umem);
302262306a36Sopenharmony_cifail:
302362306a36Sopenharmony_ci	kfree(cq->cql);
302462306a36Sopenharmony_ci	return rc;
302562306a36Sopenharmony_ci}
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_cistatic void bnxt_re_resize_cq_complete(struct bnxt_re_cq *cq)
302862306a36Sopenharmony_ci{
302962306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = cq->rdev;
303062306a36Sopenharmony_ci
303162306a36Sopenharmony_ci	bnxt_qplib_resize_cq_complete(&rdev->qplib_res, &cq->qplib_cq);
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	cq->qplib_cq.max_wqe = cq->resize_cqe;
303462306a36Sopenharmony_ci	if (cq->resize_umem) {
303562306a36Sopenharmony_ci		ib_umem_release(cq->umem);
303662306a36Sopenharmony_ci		cq->umem = cq->resize_umem;
303762306a36Sopenharmony_ci		cq->resize_umem = NULL;
303862306a36Sopenharmony_ci		cq->resize_cqe = 0;
303962306a36Sopenharmony_ci	}
304062306a36Sopenharmony_ci}
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ciint bnxt_re_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
304362306a36Sopenharmony_ci{
304462306a36Sopenharmony_ci	struct bnxt_qplib_sg_info sg_info = {};
304562306a36Sopenharmony_ci	struct bnxt_qplib_dpi *orig_dpi = NULL;
304662306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr;
304762306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx = NULL;
304862306a36Sopenharmony_ci	struct bnxt_re_resize_cq_req req;
304962306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
305062306a36Sopenharmony_ci	struct bnxt_re_cq *cq;
305162306a36Sopenharmony_ci	int rc, entries;
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci	cq =  container_of(ibcq, struct bnxt_re_cq, ib_cq);
305462306a36Sopenharmony_ci	rdev = cq->rdev;
305562306a36Sopenharmony_ci	dev_attr = &rdev->dev_attr;
305662306a36Sopenharmony_ci	if (!ibcq->uobject) {
305762306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Kernel CQ Resize not supported");
305862306a36Sopenharmony_ci		return -EOPNOTSUPP;
305962306a36Sopenharmony_ci	}
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ci	if (cq->resize_umem) {
306262306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Resize CQ %#x failed - Busy",
306362306a36Sopenharmony_ci			  cq->qplib_cq.id);
306462306a36Sopenharmony_ci		return -EBUSY;
306562306a36Sopenharmony_ci	}
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	/* Check the requested cq depth out of supported depth */
306862306a36Sopenharmony_ci	if (cqe < 1 || cqe > dev_attr->max_cq_wqes) {
306962306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Resize CQ %#x failed - out of range cqe %d",
307062306a36Sopenharmony_ci			  cq->qplib_cq.id, cqe);
307162306a36Sopenharmony_ci		return -EINVAL;
307262306a36Sopenharmony_ci	}
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci	entries = roundup_pow_of_two(cqe + 1);
307562306a36Sopenharmony_ci	if (entries > dev_attr->max_cq_wqes + 1)
307662306a36Sopenharmony_ci		entries = dev_attr->max_cq_wqes + 1;
307762306a36Sopenharmony_ci
307862306a36Sopenharmony_ci	uctx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext,
307962306a36Sopenharmony_ci					 ib_uctx);
308062306a36Sopenharmony_ci	/* uverbs consumer */
308162306a36Sopenharmony_ci	if (ib_copy_from_udata(&req, udata, sizeof(req))) {
308262306a36Sopenharmony_ci		rc = -EFAULT;
308362306a36Sopenharmony_ci		goto fail;
308462306a36Sopenharmony_ci	}
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci	cq->resize_umem = ib_umem_get(&rdev->ibdev, req.cq_va,
308762306a36Sopenharmony_ci				      entries * sizeof(struct cq_base),
308862306a36Sopenharmony_ci				      IB_ACCESS_LOCAL_WRITE);
308962306a36Sopenharmony_ci	if (IS_ERR(cq->resize_umem)) {
309062306a36Sopenharmony_ci		rc = PTR_ERR(cq->resize_umem);
309162306a36Sopenharmony_ci		cq->resize_umem = NULL;
309262306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "%s: ib_umem_get failed! rc = %d\n",
309362306a36Sopenharmony_ci			  __func__, rc);
309462306a36Sopenharmony_ci		goto fail;
309562306a36Sopenharmony_ci	}
309662306a36Sopenharmony_ci	cq->resize_cqe = entries;
309762306a36Sopenharmony_ci	memcpy(&sg_info, &cq->qplib_cq.sg_info, sizeof(sg_info));
309862306a36Sopenharmony_ci	orig_dpi = cq->qplib_cq.dpi;
309962306a36Sopenharmony_ci
310062306a36Sopenharmony_ci	cq->qplib_cq.sg_info.umem = cq->resize_umem;
310162306a36Sopenharmony_ci	cq->qplib_cq.sg_info.pgsize = PAGE_SIZE;
310262306a36Sopenharmony_ci	cq->qplib_cq.sg_info.pgshft = PAGE_SHIFT;
310362306a36Sopenharmony_ci	cq->qplib_cq.dpi = &uctx->dpi;
310462306a36Sopenharmony_ci
310562306a36Sopenharmony_ci	rc = bnxt_qplib_resize_cq(&rdev->qplib_res, &cq->qplib_cq, entries);
310662306a36Sopenharmony_ci	if (rc) {
310762306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Resize HW CQ %#x failed!",
310862306a36Sopenharmony_ci			  cq->qplib_cq.id);
310962306a36Sopenharmony_ci		goto fail;
311062306a36Sopenharmony_ci	}
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	cq->ib_cq.cqe = cq->resize_cqe;
311362306a36Sopenharmony_ci	atomic_inc(&rdev->stats.res.resize_count);
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	return 0;
311662306a36Sopenharmony_ci
311762306a36Sopenharmony_cifail:
311862306a36Sopenharmony_ci	if (cq->resize_umem) {
311962306a36Sopenharmony_ci		ib_umem_release(cq->resize_umem);
312062306a36Sopenharmony_ci		cq->resize_umem = NULL;
312162306a36Sopenharmony_ci		cq->resize_cqe = 0;
312262306a36Sopenharmony_ci		memcpy(&cq->qplib_cq.sg_info, &sg_info, sizeof(sg_info));
312362306a36Sopenharmony_ci		cq->qplib_cq.dpi = orig_dpi;
312462306a36Sopenharmony_ci	}
312562306a36Sopenharmony_ci	return rc;
312662306a36Sopenharmony_ci}
312762306a36Sopenharmony_ci
312862306a36Sopenharmony_cistatic u8 __req_to_ib_wc_status(u8 qstatus)
312962306a36Sopenharmony_ci{
313062306a36Sopenharmony_ci	switch (qstatus) {
313162306a36Sopenharmony_ci	case CQ_REQ_STATUS_OK:
313262306a36Sopenharmony_ci		return IB_WC_SUCCESS;
313362306a36Sopenharmony_ci	case CQ_REQ_STATUS_BAD_RESPONSE_ERR:
313462306a36Sopenharmony_ci		return IB_WC_BAD_RESP_ERR;
313562306a36Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_LENGTH_ERR:
313662306a36Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
313762306a36Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_QP_OPERATION_ERR:
313862306a36Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
313962306a36Sopenharmony_ci	case CQ_REQ_STATUS_LOCAL_PROTECTION_ERR:
314062306a36Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
314162306a36Sopenharmony_ci	case CQ_REQ_STATUS_MEMORY_MGT_OPERATION_ERR:
314262306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
314362306a36Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_INVALID_REQUEST_ERR:
314462306a36Sopenharmony_ci		return IB_WC_REM_INV_REQ_ERR;
314562306a36Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_ACCESS_ERR:
314662306a36Sopenharmony_ci		return IB_WC_REM_ACCESS_ERR;
314762306a36Sopenharmony_ci	case CQ_REQ_STATUS_REMOTE_OPERATION_ERR:
314862306a36Sopenharmony_ci		return IB_WC_REM_OP_ERR;
314962306a36Sopenharmony_ci	case CQ_REQ_STATUS_RNR_NAK_RETRY_CNT_ERR:
315062306a36Sopenharmony_ci		return IB_WC_RNR_RETRY_EXC_ERR;
315162306a36Sopenharmony_ci	case CQ_REQ_STATUS_TRANSPORT_RETRY_CNT_ERR:
315262306a36Sopenharmony_ci		return IB_WC_RETRY_EXC_ERR;
315362306a36Sopenharmony_ci	case CQ_REQ_STATUS_WORK_REQUEST_FLUSHED_ERR:
315462306a36Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
315562306a36Sopenharmony_ci	default:
315662306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
315762306a36Sopenharmony_ci	}
315862306a36Sopenharmony_ci	return 0;
315962306a36Sopenharmony_ci}
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_cistatic u8 __rawqp1_to_ib_wc_status(u8 qstatus)
316262306a36Sopenharmony_ci{
316362306a36Sopenharmony_ci	switch (qstatus) {
316462306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_OK:
316562306a36Sopenharmony_ci		return IB_WC_SUCCESS;
316662306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_ACCESS_ERROR:
316762306a36Sopenharmony_ci		return IB_WC_LOC_ACCESS_ERR;
316862306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_HW_LOCAL_LENGTH_ERR:
316962306a36Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
317062306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_PROTECTION_ERR:
317162306a36Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
317262306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_LOCAL_QP_OPERATION_ERR:
317362306a36Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
317462306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_MEMORY_MGT_OPERATION_ERR:
317562306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
317662306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_WORK_REQUEST_FLUSHED_ERR:
317762306a36Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
317862306a36Sopenharmony_ci	case CQ_RES_RAWETH_QP1_STATUS_HW_FLUSH_ERR:
317962306a36Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
318062306a36Sopenharmony_ci	default:
318162306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
318262306a36Sopenharmony_ci	}
318362306a36Sopenharmony_ci}
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_cistatic u8 __rc_to_ib_wc_status(u8 qstatus)
318662306a36Sopenharmony_ci{
318762306a36Sopenharmony_ci	switch (qstatus) {
318862306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_OK:
318962306a36Sopenharmony_ci		return IB_WC_SUCCESS;
319062306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_ACCESS_ERROR:
319162306a36Sopenharmony_ci		return IB_WC_LOC_ACCESS_ERR;
319262306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_LENGTH_ERR:
319362306a36Sopenharmony_ci		return IB_WC_LOC_LEN_ERR;
319462306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_PROTECTION_ERR:
319562306a36Sopenharmony_ci		return IB_WC_LOC_PROT_ERR;
319662306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_LOCAL_QP_OPERATION_ERR:
319762306a36Sopenharmony_ci		return IB_WC_LOC_QP_OP_ERR;
319862306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_MEMORY_MGT_OPERATION_ERR:
319962306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
320062306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_REMOTE_INVALID_REQUEST_ERR:
320162306a36Sopenharmony_ci		return IB_WC_REM_INV_REQ_ERR;
320262306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_WORK_REQUEST_FLUSHED_ERR:
320362306a36Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
320462306a36Sopenharmony_ci	case CQ_RES_RC_STATUS_HW_FLUSH_ERR:
320562306a36Sopenharmony_ci		return IB_WC_WR_FLUSH_ERR;
320662306a36Sopenharmony_ci	default:
320762306a36Sopenharmony_ci		return IB_WC_GENERAL_ERR;
320862306a36Sopenharmony_ci	}
320962306a36Sopenharmony_ci}
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_cistatic void bnxt_re_process_req_wc(struct ib_wc *wc, struct bnxt_qplib_cqe *cqe)
321262306a36Sopenharmony_ci{
321362306a36Sopenharmony_ci	switch (cqe->type) {
321462306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND:
321562306a36Sopenharmony_ci		wc->opcode = IB_WC_SEND;
321662306a36Sopenharmony_ci		break;
321762306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM:
321862306a36Sopenharmony_ci		wc->opcode = IB_WC_SEND;
321962306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
322062306a36Sopenharmony_ci		break;
322162306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV:
322262306a36Sopenharmony_ci		wc->opcode = IB_WC_SEND;
322362306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_INVALIDATE;
322462306a36Sopenharmony_ci		break;
322562306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE:
322662306a36Sopenharmony_ci		wc->opcode = IB_WC_RDMA_WRITE;
322762306a36Sopenharmony_ci		break;
322862306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM:
322962306a36Sopenharmony_ci		wc->opcode = IB_WC_RDMA_WRITE;
323062306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
323162306a36Sopenharmony_ci		break;
323262306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_RDMA_READ:
323362306a36Sopenharmony_ci		wc->opcode = IB_WC_RDMA_READ;
323462306a36Sopenharmony_ci		break;
323562306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP:
323662306a36Sopenharmony_ci		wc->opcode = IB_WC_COMP_SWAP;
323762306a36Sopenharmony_ci		break;
323862306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD:
323962306a36Sopenharmony_ci		wc->opcode = IB_WC_FETCH_ADD;
324062306a36Sopenharmony_ci		break;
324162306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_LOCAL_INV:
324262306a36Sopenharmony_ci		wc->opcode = IB_WC_LOCAL_INV;
324362306a36Sopenharmony_ci		break;
324462306a36Sopenharmony_ci	case BNXT_QPLIB_SWQE_TYPE_REG_MR:
324562306a36Sopenharmony_ci		wc->opcode = IB_WC_REG_MR;
324662306a36Sopenharmony_ci		break;
324762306a36Sopenharmony_ci	default:
324862306a36Sopenharmony_ci		wc->opcode = IB_WC_SEND;
324962306a36Sopenharmony_ci		break;
325062306a36Sopenharmony_ci	}
325162306a36Sopenharmony_ci
325262306a36Sopenharmony_ci	wc->status = __req_to_ib_wc_status(cqe->status);
325362306a36Sopenharmony_ci}
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_cistatic int bnxt_re_check_packet_type(u16 raweth_qp1_flags,
325662306a36Sopenharmony_ci				     u16 raweth_qp1_flags2)
325762306a36Sopenharmony_ci{
325862306a36Sopenharmony_ci	bool is_ipv6 = false, is_ipv4 = false;
325962306a36Sopenharmony_ci
326062306a36Sopenharmony_ci	/* raweth_qp1_flags Bit 9-6 indicates itype */
326162306a36Sopenharmony_ci	if ((raweth_qp1_flags & CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE)
326262306a36Sopenharmony_ci	    != CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE)
326362306a36Sopenharmony_ci		return -1;
326462306a36Sopenharmony_ci
326562306a36Sopenharmony_ci	if (raweth_qp1_flags2 &
326662306a36Sopenharmony_ci	    CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_CS_CALC &&
326762306a36Sopenharmony_ci	    raweth_qp1_flags2 &
326862306a36Sopenharmony_ci	    CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_L4_CS_CALC) {
326962306a36Sopenharmony_ci		/* raweth_qp1_flags2 Bit 8 indicates ip_type. 0-v4 1 - v6 */
327062306a36Sopenharmony_ci		(raweth_qp1_flags2 &
327162306a36Sopenharmony_ci		 CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_TYPE) ?
327262306a36Sopenharmony_ci			(is_ipv6 = true) : (is_ipv4 = true);
327362306a36Sopenharmony_ci		return ((is_ipv6) ?
327462306a36Sopenharmony_ci			 BNXT_RE_ROCEV2_IPV6_PACKET :
327562306a36Sopenharmony_ci			 BNXT_RE_ROCEV2_IPV4_PACKET);
327662306a36Sopenharmony_ci	} else {
327762306a36Sopenharmony_ci		return BNXT_RE_ROCE_V1_PACKET;
327862306a36Sopenharmony_ci	}
327962306a36Sopenharmony_ci}
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_cistatic int bnxt_re_to_ib_nw_type(int nw_type)
328262306a36Sopenharmony_ci{
328362306a36Sopenharmony_ci	u8 nw_hdr_type = 0xFF;
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci	switch (nw_type) {
328662306a36Sopenharmony_ci	case BNXT_RE_ROCE_V1_PACKET:
328762306a36Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_ROCE_V1;
328862306a36Sopenharmony_ci		break;
328962306a36Sopenharmony_ci	case BNXT_RE_ROCEV2_IPV4_PACKET:
329062306a36Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_IPV4;
329162306a36Sopenharmony_ci		break;
329262306a36Sopenharmony_ci	case BNXT_RE_ROCEV2_IPV6_PACKET:
329362306a36Sopenharmony_ci		nw_hdr_type = RDMA_NETWORK_IPV6;
329462306a36Sopenharmony_ci		break;
329562306a36Sopenharmony_ci	}
329662306a36Sopenharmony_ci	return nw_hdr_type;
329762306a36Sopenharmony_ci}
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_cistatic bool bnxt_re_is_loopback_packet(struct bnxt_re_dev *rdev,
330062306a36Sopenharmony_ci				       void *rq_hdr_buf)
330162306a36Sopenharmony_ci{
330262306a36Sopenharmony_ci	u8 *tmp_buf = NULL;
330362306a36Sopenharmony_ci	struct ethhdr *eth_hdr;
330462306a36Sopenharmony_ci	u16 eth_type;
330562306a36Sopenharmony_ci	bool rc = false;
330662306a36Sopenharmony_ci
330762306a36Sopenharmony_ci	tmp_buf = (u8 *)rq_hdr_buf;
330862306a36Sopenharmony_ci	/*
330962306a36Sopenharmony_ci	 * If dest mac is not same as I/F mac, this could be a
331062306a36Sopenharmony_ci	 * loopback address or multicast address, check whether
331162306a36Sopenharmony_ci	 * it is a loopback packet
331262306a36Sopenharmony_ci	 */
331362306a36Sopenharmony_ci	if (!ether_addr_equal(tmp_buf, rdev->netdev->dev_addr)) {
331462306a36Sopenharmony_ci		tmp_buf += 4;
331562306a36Sopenharmony_ci		/* Check the  ether type */
331662306a36Sopenharmony_ci		eth_hdr = (struct ethhdr *)tmp_buf;
331762306a36Sopenharmony_ci		eth_type = ntohs(eth_hdr->h_proto);
331862306a36Sopenharmony_ci		switch (eth_type) {
331962306a36Sopenharmony_ci		case ETH_P_IBOE:
332062306a36Sopenharmony_ci			rc = true;
332162306a36Sopenharmony_ci			break;
332262306a36Sopenharmony_ci		case ETH_P_IP:
332362306a36Sopenharmony_ci		case ETH_P_IPV6: {
332462306a36Sopenharmony_ci			u32 len;
332562306a36Sopenharmony_ci			struct udphdr *udp_hdr;
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci			len = (eth_type == ETH_P_IP ? sizeof(struct iphdr) :
332862306a36Sopenharmony_ci						      sizeof(struct ipv6hdr));
332962306a36Sopenharmony_ci			tmp_buf += sizeof(struct ethhdr) + len;
333062306a36Sopenharmony_ci			udp_hdr = (struct udphdr *)tmp_buf;
333162306a36Sopenharmony_ci			if (ntohs(udp_hdr->dest) ==
333262306a36Sopenharmony_ci				    ROCE_V2_UDP_DPORT)
333362306a36Sopenharmony_ci				rc = true;
333462306a36Sopenharmony_ci			break;
333562306a36Sopenharmony_ci			}
333662306a36Sopenharmony_ci		default:
333762306a36Sopenharmony_ci			break;
333862306a36Sopenharmony_ci		}
333962306a36Sopenharmony_ci	}
334062306a36Sopenharmony_ci
334162306a36Sopenharmony_ci	return rc;
334262306a36Sopenharmony_ci}
334362306a36Sopenharmony_ci
334462306a36Sopenharmony_cistatic int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp,
334562306a36Sopenharmony_ci					 struct bnxt_qplib_cqe *cqe)
334662306a36Sopenharmony_ci{
334762306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = gsi_qp->rdev;
334862306a36Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
334962306a36Sopenharmony_ci	struct bnxt_re_qp *gsi_sqp = rdev->gsi_ctx.gsi_sqp;
335062306a36Sopenharmony_ci	dma_addr_t shrq_hdr_buf_map;
335162306a36Sopenharmony_ci	struct ib_sge s_sge[2] = {};
335262306a36Sopenharmony_ci	struct ib_sge r_sge[2] = {};
335362306a36Sopenharmony_ci	struct bnxt_re_ah *gsi_sah;
335462306a36Sopenharmony_ci	struct ib_recv_wr rwr = {};
335562306a36Sopenharmony_ci	dma_addr_t rq_hdr_buf_map;
335662306a36Sopenharmony_ci	struct ib_ud_wr udwr = {};
335762306a36Sopenharmony_ci	struct ib_send_wr *swr;
335862306a36Sopenharmony_ci	u32 skip_bytes = 0;
335962306a36Sopenharmony_ci	int pkt_type = 0;
336062306a36Sopenharmony_ci	void *rq_hdr_buf;
336162306a36Sopenharmony_ci	u32 offset = 0;
336262306a36Sopenharmony_ci	u32 tbl_idx;
336362306a36Sopenharmony_ci	int rc;
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	swr = &udwr.wr;
336662306a36Sopenharmony_ci	tbl_idx = cqe->wr_id;
336762306a36Sopenharmony_ci
336862306a36Sopenharmony_ci	rq_hdr_buf = gsi_qp->qplib_qp.rq_hdr_buf +
336962306a36Sopenharmony_ci			(tbl_idx * gsi_qp->qplib_qp.rq_hdr_buf_size);
337062306a36Sopenharmony_ci	rq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
337162306a36Sopenharmony_ci							  tbl_idx);
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci	/* Shadow QP header buffer */
337462306a36Sopenharmony_ci	shrq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
337562306a36Sopenharmony_ci							    tbl_idx);
337662306a36Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
337762306a36Sopenharmony_ci
337862306a36Sopenharmony_ci	/* Store this cqe */
337962306a36Sopenharmony_ci	memcpy(&sqp_entry->cqe, cqe, sizeof(struct bnxt_qplib_cqe));
338062306a36Sopenharmony_ci	sqp_entry->qp1_qp = gsi_qp;
338162306a36Sopenharmony_ci
338262306a36Sopenharmony_ci	/* Find packet type from the cqe */
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_ci	pkt_type = bnxt_re_check_packet_type(cqe->raweth_qp1_flags,
338562306a36Sopenharmony_ci					     cqe->raweth_qp1_flags2);
338662306a36Sopenharmony_ci	if (pkt_type < 0) {
338762306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Invalid packet\n");
338862306a36Sopenharmony_ci		return -EINVAL;
338962306a36Sopenharmony_ci	}
339062306a36Sopenharmony_ci
339162306a36Sopenharmony_ci	/* Adjust the offset for the user buffer and post in the rq */
339262306a36Sopenharmony_ci
339362306a36Sopenharmony_ci	if (pkt_type == BNXT_RE_ROCEV2_IPV4_PACKET)
339462306a36Sopenharmony_ci		offset = 20;
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci	/*
339762306a36Sopenharmony_ci	 * QP1 loopback packet has 4 bytes of internal header before
339862306a36Sopenharmony_ci	 * ether header. Skip these four bytes.
339962306a36Sopenharmony_ci	 */
340062306a36Sopenharmony_ci	if (bnxt_re_is_loopback_packet(rdev, rq_hdr_buf))
340162306a36Sopenharmony_ci		skip_bytes = 4;
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci	/* First send SGE . Skip the ether header*/
340462306a36Sopenharmony_ci	s_sge[0].addr = rq_hdr_buf_map + BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE
340562306a36Sopenharmony_ci			+ skip_bytes;
340662306a36Sopenharmony_ci	s_sge[0].lkey = 0xFFFFFFFF;
340762306a36Sopenharmony_ci	s_sge[0].length = offset ? BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV4 :
340862306a36Sopenharmony_ci				BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6;
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_ci	/* Second Send SGE */
341162306a36Sopenharmony_ci	s_sge[1].addr = s_sge[0].addr + s_sge[0].length +
341262306a36Sopenharmony_ci			BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE;
341362306a36Sopenharmony_ci	if (pkt_type != BNXT_RE_ROCE_V1_PACKET)
341462306a36Sopenharmony_ci		s_sge[1].addr += 8;
341562306a36Sopenharmony_ci	s_sge[1].lkey = 0xFFFFFFFF;
341662306a36Sopenharmony_ci	s_sge[1].length = 256;
341762306a36Sopenharmony_ci
341862306a36Sopenharmony_ci	/* First recv SGE */
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_ci	r_sge[0].addr = shrq_hdr_buf_map;
342162306a36Sopenharmony_ci	r_sge[0].lkey = 0xFFFFFFFF;
342262306a36Sopenharmony_ci	r_sge[0].length = 40;
342362306a36Sopenharmony_ci
342462306a36Sopenharmony_ci	r_sge[1].addr = sqp_entry->sge.addr + offset;
342562306a36Sopenharmony_ci	r_sge[1].lkey = sqp_entry->sge.lkey;
342662306a36Sopenharmony_ci	r_sge[1].length = BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6 + 256 - offset;
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci	/* Create receive work request */
342962306a36Sopenharmony_ci	rwr.num_sge = 2;
343062306a36Sopenharmony_ci	rwr.sg_list = r_sge;
343162306a36Sopenharmony_ci	rwr.wr_id = tbl_idx;
343262306a36Sopenharmony_ci	rwr.next = NULL;
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ci	rc = bnxt_re_post_recv_shadow_qp(rdev, gsi_sqp, &rwr);
343562306a36Sopenharmony_ci	if (rc) {
343662306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
343762306a36Sopenharmony_ci			  "Failed to post Rx buffers to shadow QP");
343862306a36Sopenharmony_ci		return -ENOMEM;
343962306a36Sopenharmony_ci	}
344062306a36Sopenharmony_ci
344162306a36Sopenharmony_ci	swr->num_sge = 2;
344262306a36Sopenharmony_ci	swr->sg_list = s_sge;
344362306a36Sopenharmony_ci	swr->wr_id = tbl_idx;
344462306a36Sopenharmony_ci	swr->opcode = IB_WR_SEND;
344562306a36Sopenharmony_ci	swr->next = NULL;
344662306a36Sopenharmony_ci	gsi_sah = rdev->gsi_ctx.gsi_sah;
344762306a36Sopenharmony_ci	udwr.ah = &gsi_sah->ib_ah;
344862306a36Sopenharmony_ci	udwr.remote_qpn = gsi_sqp->qplib_qp.id;
344962306a36Sopenharmony_ci	udwr.remote_qkey = gsi_sqp->qplib_qp.qkey;
345062306a36Sopenharmony_ci
345162306a36Sopenharmony_ci	/* post data received  in the send queue */
345262306a36Sopenharmony_ci	return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
345362306a36Sopenharmony_ci}
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_cistatic void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
345662306a36Sopenharmony_ci					  struct bnxt_qplib_cqe *cqe)
345762306a36Sopenharmony_ci{
345862306a36Sopenharmony_ci	wc->opcode = IB_WC_RECV;
345962306a36Sopenharmony_ci	wc->status = __rawqp1_to_ib_wc_status(cqe->status);
346062306a36Sopenharmony_ci	wc->wc_flags |= IB_WC_GRH;
346162306a36Sopenharmony_ci}
346262306a36Sopenharmony_ci
346362306a36Sopenharmony_cistatic bool bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev,
346462306a36Sopenharmony_ci					u16 vlan_id)
346562306a36Sopenharmony_ci{
346662306a36Sopenharmony_ci	/*
346762306a36Sopenharmony_ci	 * Check if the vlan is configured in the host.  If not configured, it
346862306a36Sopenharmony_ci	 * can be a transparent VLAN. So dont report the vlan id.
346962306a36Sopenharmony_ci	 */
347062306a36Sopenharmony_ci	if (!__vlan_find_dev_deep_rcu(rdev->netdev,
347162306a36Sopenharmony_ci				      htons(ETH_P_8021Q), vlan_id))
347262306a36Sopenharmony_ci		return false;
347362306a36Sopenharmony_ci	return true;
347462306a36Sopenharmony_ci}
347562306a36Sopenharmony_ci
347662306a36Sopenharmony_cistatic bool bnxt_re_is_vlan_pkt(struct bnxt_qplib_cqe *orig_cqe,
347762306a36Sopenharmony_ci				u16 *vid, u8 *sl)
347862306a36Sopenharmony_ci{
347962306a36Sopenharmony_ci	bool ret = false;
348062306a36Sopenharmony_ci	u32 metadata;
348162306a36Sopenharmony_ci	u16 tpid;
348262306a36Sopenharmony_ci
348362306a36Sopenharmony_ci	metadata = orig_cqe->raweth_qp1_metadata;
348462306a36Sopenharmony_ci	if (orig_cqe->raweth_qp1_flags2 &
348562306a36Sopenharmony_ci		CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_VLAN) {
348662306a36Sopenharmony_ci		tpid = ((metadata &
348762306a36Sopenharmony_ci			 CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_MASK) >>
348862306a36Sopenharmony_ci			 CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_SFT);
348962306a36Sopenharmony_ci		if (tpid == ETH_P_8021Q) {
349062306a36Sopenharmony_ci			*vid = metadata &
349162306a36Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_VID_MASK;
349262306a36Sopenharmony_ci			*sl = (metadata &
349362306a36Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_MASK) >>
349462306a36Sopenharmony_ci			       CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_SFT;
349562306a36Sopenharmony_ci			ret = true;
349662306a36Sopenharmony_ci		}
349762306a36Sopenharmony_ci	}
349862306a36Sopenharmony_ci
349962306a36Sopenharmony_ci	return ret;
350062306a36Sopenharmony_ci}
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_cistatic void bnxt_re_process_res_rc_wc(struct ib_wc *wc,
350362306a36Sopenharmony_ci				      struct bnxt_qplib_cqe *cqe)
350462306a36Sopenharmony_ci{
350562306a36Sopenharmony_ci	wc->opcode = IB_WC_RECV;
350662306a36Sopenharmony_ci	wc->status = __rc_to_ib_wc_status(cqe->status);
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_ci	if (cqe->flags & CQ_RES_RC_FLAGS_IMM)
350962306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
351062306a36Sopenharmony_ci	if (cqe->flags & CQ_RES_RC_FLAGS_INV)
351162306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_INVALIDATE;
351262306a36Sopenharmony_ci	if ((cqe->flags & (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM)) ==
351362306a36Sopenharmony_ci	    (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM))
351462306a36Sopenharmony_ci		wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
351562306a36Sopenharmony_ci}
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_cistatic void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
351862306a36Sopenharmony_ci					     struct ib_wc *wc,
351962306a36Sopenharmony_ci					     struct bnxt_qplib_cqe *cqe)
352062306a36Sopenharmony_ci{
352162306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = gsi_sqp->rdev;
352262306a36Sopenharmony_ci	struct bnxt_re_qp *gsi_qp = NULL;
352362306a36Sopenharmony_ci	struct bnxt_qplib_cqe *orig_cqe = NULL;
352462306a36Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
352562306a36Sopenharmony_ci	int nw_type;
352662306a36Sopenharmony_ci	u32 tbl_idx;
352762306a36Sopenharmony_ci	u16 vlan_id;
352862306a36Sopenharmony_ci	u8 sl;
352962306a36Sopenharmony_ci
353062306a36Sopenharmony_ci	tbl_idx = cqe->wr_id;
353162306a36Sopenharmony_ci
353262306a36Sopenharmony_ci	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
353362306a36Sopenharmony_ci	gsi_qp = sqp_entry->qp1_qp;
353462306a36Sopenharmony_ci	orig_cqe = &sqp_entry->cqe;
353562306a36Sopenharmony_ci
353662306a36Sopenharmony_ci	wc->wr_id = sqp_entry->wrid;
353762306a36Sopenharmony_ci	wc->byte_len = orig_cqe->length;
353862306a36Sopenharmony_ci	wc->qp = &gsi_qp->ib_qp;
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_ci	wc->ex.imm_data = orig_cqe->immdata;
354162306a36Sopenharmony_ci	wc->src_qp = orig_cqe->src_qp;
354262306a36Sopenharmony_ci	memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
354362306a36Sopenharmony_ci	if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
354462306a36Sopenharmony_ci		if (bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
354562306a36Sopenharmony_ci			wc->vlan_id = vlan_id;
354662306a36Sopenharmony_ci			wc->sl = sl;
354762306a36Sopenharmony_ci			wc->wc_flags |= IB_WC_WITH_VLAN;
354862306a36Sopenharmony_ci		}
354962306a36Sopenharmony_ci	}
355062306a36Sopenharmony_ci	wc->port_num = 1;
355162306a36Sopenharmony_ci	wc->vendor_err = orig_cqe->status;
355262306a36Sopenharmony_ci
355362306a36Sopenharmony_ci	wc->opcode = IB_WC_RECV;
355462306a36Sopenharmony_ci	wc->status = __rawqp1_to_ib_wc_status(orig_cqe->status);
355562306a36Sopenharmony_ci	wc->wc_flags |= IB_WC_GRH;
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_ci	nw_type = bnxt_re_check_packet_type(orig_cqe->raweth_qp1_flags,
355862306a36Sopenharmony_ci					    orig_cqe->raweth_qp1_flags2);
355962306a36Sopenharmony_ci	if (nw_type >= 0) {
356062306a36Sopenharmony_ci		wc->network_hdr_type = bnxt_re_to_ib_nw_type(nw_type);
356162306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_NETWORK_HDR_TYPE;
356262306a36Sopenharmony_ci	}
356362306a36Sopenharmony_ci}
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_cistatic void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp,
356662306a36Sopenharmony_ci				      struct ib_wc *wc,
356762306a36Sopenharmony_ci				      struct bnxt_qplib_cqe *cqe)
356862306a36Sopenharmony_ci{
356962306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
357062306a36Sopenharmony_ci	u16 vlan_id = 0;
357162306a36Sopenharmony_ci	u8 nw_type;
357262306a36Sopenharmony_ci
357362306a36Sopenharmony_ci	rdev = qp->rdev;
357462306a36Sopenharmony_ci	wc->opcode = IB_WC_RECV;
357562306a36Sopenharmony_ci	wc->status = __rc_to_ib_wc_status(cqe->status);
357662306a36Sopenharmony_ci
357762306a36Sopenharmony_ci	if (cqe->flags & CQ_RES_UD_FLAGS_IMM)
357862306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_IMM;
357962306a36Sopenharmony_ci	/* report only on GSI QP for Thor */
358062306a36Sopenharmony_ci	if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_GSI) {
358162306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_GRH;
358262306a36Sopenharmony_ci		memcpy(wc->smac, cqe->smac, ETH_ALEN);
358362306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_SMAC;
358462306a36Sopenharmony_ci		if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) {
358562306a36Sopenharmony_ci			vlan_id = (cqe->cfa_meta & 0xFFF);
358662306a36Sopenharmony_ci		}
358762306a36Sopenharmony_ci		/* Mark only if vlan_id is non zero */
358862306a36Sopenharmony_ci		if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
358962306a36Sopenharmony_ci			wc->vlan_id = vlan_id;
359062306a36Sopenharmony_ci			wc->wc_flags |= IB_WC_WITH_VLAN;
359162306a36Sopenharmony_ci		}
359262306a36Sopenharmony_ci		nw_type = (cqe->flags & CQ_RES_UD_FLAGS_ROCE_IP_VER_MASK) >>
359362306a36Sopenharmony_ci			   CQ_RES_UD_FLAGS_ROCE_IP_VER_SFT;
359462306a36Sopenharmony_ci		wc->network_hdr_type = bnxt_re_to_ib_nw_type(nw_type);
359562306a36Sopenharmony_ci		wc->wc_flags |= IB_WC_WITH_NETWORK_HDR_TYPE;
359662306a36Sopenharmony_ci	}
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci}
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_cistatic int send_phantom_wqe(struct bnxt_re_qp *qp)
360162306a36Sopenharmony_ci{
360262306a36Sopenharmony_ci	struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp;
360362306a36Sopenharmony_ci	unsigned long flags;
360462306a36Sopenharmony_ci	int rc;
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci	spin_lock_irqsave(&qp->sq_lock, flags);
360762306a36Sopenharmony_ci
360862306a36Sopenharmony_ci	rc = bnxt_re_bind_fence_mw(lib_qp);
360962306a36Sopenharmony_ci	if (!rc) {
361062306a36Sopenharmony_ci		lib_qp->sq.phantom_wqe_cnt++;
361162306a36Sopenharmony_ci		ibdev_dbg(&qp->rdev->ibdev,
361262306a36Sopenharmony_ci			  "qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n",
361362306a36Sopenharmony_ci			  lib_qp->id, lib_qp->sq.hwq.prod,
361462306a36Sopenharmony_ci			  HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq),
361562306a36Sopenharmony_ci			  lib_qp->sq.phantom_wqe_cnt);
361662306a36Sopenharmony_ci	}
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->sq_lock, flags);
361962306a36Sopenharmony_ci	return rc;
362062306a36Sopenharmony_ci}
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ciint bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
362362306a36Sopenharmony_ci{
362462306a36Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
362562306a36Sopenharmony_ci	struct bnxt_re_qp *qp, *sh_qp;
362662306a36Sopenharmony_ci	struct bnxt_qplib_cqe *cqe;
362762306a36Sopenharmony_ci	int i, ncqe, budget;
362862306a36Sopenharmony_ci	struct bnxt_qplib_q *sq;
362962306a36Sopenharmony_ci	struct bnxt_qplib_qp *lib_qp;
363062306a36Sopenharmony_ci	u32 tbl_idx;
363162306a36Sopenharmony_ci	struct bnxt_re_sqp_entries *sqp_entry = NULL;
363262306a36Sopenharmony_ci	unsigned long flags;
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	/* User CQ; the only processing we do is to
363562306a36Sopenharmony_ci	 * complete any pending CQ resize operation.
363662306a36Sopenharmony_ci	 */
363762306a36Sopenharmony_ci	if (cq->umem) {
363862306a36Sopenharmony_ci		if (cq->resize_umem)
363962306a36Sopenharmony_ci			bnxt_re_resize_cq_complete(cq);
364062306a36Sopenharmony_ci		return 0;
364162306a36Sopenharmony_ci	}
364262306a36Sopenharmony_ci
364362306a36Sopenharmony_ci	spin_lock_irqsave(&cq->cq_lock, flags);
364462306a36Sopenharmony_ci	budget = min_t(u32, num_entries, cq->max_cql);
364562306a36Sopenharmony_ci	num_entries = budget;
364662306a36Sopenharmony_ci	if (!cq->cql) {
364762306a36Sopenharmony_ci		ibdev_err(&cq->rdev->ibdev, "POLL CQ : no CQL to use");
364862306a36Sopenharmony_ci		goto exit;
364962306a36Sopenharmony_ci	}
365062306a36Sopenharmony_ci	cqe = &cq->cql[0];
365162306a36Sopenharmony_ci	while (budget) {
365262306a36Sopenharmony_ci		lib_qp = NULL;
365362306a36Sopenharmony_ci		ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp);
365462306a36Sopenharmony_ci		if (lib_qp) {
365562306a36Sopenharmony_ci			sq = &lib_qp->sq;
365662306a36Sopenharmony_ci			if (sq->send_phantom) {
365762306a36Sopenharmony_ci				qp = container_of(lib_qp,
365862306a36Sopenharmony_ci						  struct bnxt_re_qp, qplib_qp);
365962306a36Sopenharmony_ci				if (send_phantom_wqe(qp) == -ENOMEM)
366062306a36Sopenharmony_ci					ibdev_err(&cq->rdev->ibdev,
366162306a36Sopenharmony_ci						  "Phantom failed! Scheduled to send again\n");
366262306a36Sopenharmony_ci				else
366362306a36Sopenharmony_ci					sq->send_phantom = false;
366462306a36Sopenharmony_ci			}
366562306a36Sopenharmony_ci		}
366662306a36Sopenharmony_ci		if (ncqe < budget)
366762306a36Sopenharmony_ci			ncqe += bnxt_qplib_process_flush_list(&cq->qplib_cq,
366862306a36Sopenharmony_ci							      cqe + ncqe,
366962306a36Sopenharmony_ci							      budget - ncqe);
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_ci		if (!ncqe)
367262306a36Sopenharmony_ci			break;
367362306a36Sopenharmony_ci
367462306a36Sopenharmony_ci		for (i = 0; i < ncqe; i++, cqe++) {
367562306a36Sopenharmony_ci			/* Transcribe each qplib_wqe back to ib_wc */
367662306a36Sopenharmony_ci			memset(wc, 0, sizeof(*wc));
367762306a36Sopenharmony_ci
367862306a36Sopenharmony_ci			wc->wr_id = cqe->wr_id;
367962306a36Sopenharmony_ci			wc->byte_len = cqe->length;
368062306a36Sopenharmony_ci			qp = container_of
368162306a36Sopenharmony_ci				((struct bnxt_qplib_qp *)
368262306a36Sopenharmony_ci				 (unsigned long)(cqe->qp_handle),
368362306a36Sopenharmony_ci				 struct bnxt_re_qp, qplib_qp);
368462306a36Sopenharmony_ci			wc->qp = &qp->ib_qp;
368562306a36Sopenharmony_ci			wc->ex.imm_data = cqe->immdata;
368662306a36Sopenharmony_ci			wc->src_qp = cqe->src_qp;
368762306a36Sopenharmony_ci			memcpy(wc->smac, cqe->smac, ETH_ALEN);
368862306a36Sopenharmony_ci			wc->port_num = 1;
368962306a36Sopenharmony_ci			wc->vendor_err = cqe->status;
369062306a36Sopenharmony_ci
369162306a36Sopenharmony_ci			switch (cqe->opcode) {
369262306a36Sopenharmony_ci			case CQ_BASE_CQE_TYPE_REQ:
369362306a36Sopenharmony_ci				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
369462306a36Sopenharmony_ci				if (sh_qp &&
369562306a36Sopenharmony_ci				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
369662306a36Sopenharmony_ci					/* Handle this completion with
369762306a36Sopenharmony_ci					 * the stored completion
369862306a36Sopenharmony_ci					 */
369962306a36Sopenharmony_ci					memset(wc, 0, sizeof(*wc));
370062306a36Sopenharmony_ci					continue;
370162306a36Sopenharmony_ci				}
370262306a36Sopenharmony_ci				bnxt_re_process_req_wc(wc, cqe);
370362306a36Sopenharmony_ci				break;
370462306a36Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_RAWETH_QP1:
370562306a36Sopenharmony_ci				if (!cqe->status) {
370662306a36Sopenharmony_ci					int rc = 0;
370762306a36Sopenharmony_ci
370862306a36Sopenharmony_ci					rc = bnxt_re_process_raw_qp_pkt_rx
370962306a36Sopenharmony_ci								(qp, cqe);
371062306a36Sopenharmony_ci					if (!rc) {
371162306a36Sopenharmony_ci						memset(wc, 0, sizeof(*wc));
371262306a36Sopenharmony_ci						continue;
371362306a36Sopenharmony_ci					}
371462306a36Sopenharmony_ci					cqe->status = -1;
371562306a36Sopenharmony_ci				}
371662306a36Sopenharmony_ci				/* Errors need not be looped back.
371762306a36Sopenharmony_ci				 * But change the wr_id to the one
371862306a36Sopenharmony_ci				 * stored in the table
371962306a36Sopenharmony_ci				 */
372062306a36Sopenharmony_ci				tbl_idx = cqe->wr_id;
372162306a36Sopenharmony_ci				sqp_entry = &cq->rdev->gsi_ctx.sqp_tbl[tbl_idx];
372262306a36Sopenharmony_ci				wc->wr_id = sqp_entry->wrid;
372362306a36Sopenharmony_ci				bnxt_re_process_res_rawqp1_wc(wc, cqe);
372462306a36Sopenharmony_ci				break;
372562306a36Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_RC:
372662306a36Sopenharmony_ci				bnxt_re_process_res_rc_wc(wc, cqe);
372762306a36Sopenharmony_ci				break;
372862306a36Sopenharmony_ci			case CQ_BASE_CQE_TYPE_RES_UD:
372962306a36Sopenharmony_ci				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
373062306a36Sopenharmony_ci				if (sh_qp &&
373162306a36Sopenharmony_ci				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
373262306a36Sopenharmony_ci					/* Handle this completion with
373362306a36Sopenharmony_ci					 * the stored completion
373462306a36Sopenharmony_ci					 */
373562306a36Sopenharmony_ci					if (cqe->status) {
373662306a36Sopenharmony_ci						continue;
373762306a36Sopenharmony_ci					} else {
373862306a36Sopenharmony_ci						bnxt_re_process_res_shadow_qp_wc
373962306a36Sopenharmony_ci								(qp, wc, cqe);
374062306a36Sopenharmony_ci						break;
374162306a36Sopenharmony_ci					}
374262306a36Sopenharmony_ci				}
374362306a36Sopenharmony_ci				bnxt_re_process_res_ud_wc(qp, wc, cqe);
374462306a36Sopenharmony_ci				break;
374562306a36Sopenharmony_ci			default:
374662306a36Sopenharmony_ci				ibdev_err(&cq->rdev->ibdev,
374762306a36Sopenharmony_ci					  "POLL CQ : type 0x%x not handled",
374862306a36Sopenharmony_ci					  cqe->opcode);
374962306a36Sopenharmony_ci				continue;
375062306a36Sopenharmony_ci			}
375162306a36Sopenharmony_ci			wc++;
375262306a36Sopenharmony_ci			budget--;
375362306a36Sopenharmony_ci		}
375462306a36Sopenharmony_ci	}
375562306a36Sopenharmony_ciexit:
375662306a36Sopenharmony_ci	spin_unlock_irqrestore(&cq->cq_lock, flags);
375762306a36Sopenharmony_ci	return num_entries - budget;
375862306a36Sopenharmony_ci}
375962306a36Sopenharmony_ci
376062306a36Sopenharmony_ciint bnxt_re_req_notify_cq(struct ib_cq *ib_cq,
376162306a36Sopenharmony_ci			  enum ib_cq_notify_flags ib_cqn_flags)
376262306a36Sopenharmony_ci{
376362306a36Sopenharmony_ci	struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
376462306a36Sopenharmony_ci	int type = 0, rc = 0;
376562306a36Sopenharmony_ci	unsigned long flags;
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	spin_lock_irqsave(&cq->cq_lock, flags);
376862306a36Sopenharmony_ci	/* Trigger on the very next completion */
376962306a36Sopenharmony_ci	if (ib_cqn_flags & IB_CQ_NEXT_COMP)
377062306a36Sopenharmony_ci		type = DBC_DBC_TYPE_CQ_ARMALL;
377162306a36Sopenharmony_ci	/* Trigger on the next solicited completion */
377262306a36Sopenharmony_ci	else if (ib_cqn_flags & IB_CQ_SOLICITED)
377362306a36Sopenharmony_ci		type = DBC_DBC_TYPE_CQ_ARMSE;
377462306a36Sopenharmony_ci
377562306a36Sopenharmony_ci	/* Poll to see if there are missed events */
377662306a36Sopenharmony_ci	if ((ib_cqn_flags & IB_CQ_REPORT_MISSED_EVENTS) &&
377762306a36Sopenharmony_ci	    !(bnxt_qplib_is_cq_empty(&cq->qplib_cq))) {
377862306a36Sopenharmony_ci		rc = 1;
377962306a36Sopenharmony_ci		goto exit;
378062306a36Sopenharmony_ci	}
378162306a36Sopenharmony_ci	bnxt_qplib_req_notify_cq(&cq->qplib_cq, type);
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_ciexit:
378462306a36Sopenharmony_ci	spin_unlock_irqrestore(&cq->cq_lock, flags);
378562306a36Sopenharmony_ci	return rc;
378662306a36Sopenharmony_ci}
378762306a36Sopenharmony_ci
378862306a36Sopenharmony_ci/* Memory Regions */
378962306a36Sopenharmony_cistruct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags)
379062306a36Sopenharmony_ci{
379162306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
379262306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
379362306a36Sopenharmony_ci	struct bnxt_re_mr *mr;
379462306a36Sopenharmony_ci	u32 active_mrs;
379562306a36Sopenharmony_ci	int rc;
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
379862306a36Sopenharmony_ci	if (!mr)
379962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
380062306a36Sopenharmony_ci
380162306a36Sopenharmony_ci	mr->rdev = rdev;
380262306a36Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
380362306a36Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
380462306a36Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
380562306a36Sopenharmony_ci
380662306a36Sopenharmony_ci	/* Allocate and register 0 as the address */
380762306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
380862306a36Sopenharmony_ci	if (rc)
380962306a36Sopenharmony_ci		goto fail;
381062306a36Sopenharmony_ci
381162306a36Sopenharmony_ci	mr->qplib_mr.hwq.level = PBL_LVL_MAX;
381262306a36Sopenharmony_ci	mr->qplib_mr.total_size = -1; /* Infinte length */
381362306a36Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, NULL, 0,
381462306a36Sopenharmony_ci			       PAGE_SIZE);
381562306a36Sopenharmony_ci	if (rc)
381662306a36Sopenharmony_ci		goto fail_mr;
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
381962306a36Sopenharmony_ci	if (mr_access_flags & (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ |
382062306a36Sopenharmony_ci			       IB_ACCESS_REMOTE_ATOMIC))
382162306a36Sopenharmony_ci		mr->ib_mr.rkey = mr->ib_mr.lkey;
382262306a36Sopenharmony_ci	active_mrs = atomic_inc_return(&rdev->stats.res.mr_count);
382362306a36Sopenharmony_ci	if (active_mrs > rdev->stats.res.mr_watermark)
382462306a36Sopenharmony_ci		rdev->stats.res.mr_watermark = active_mrs;
382562306a36Sopenharmony_ci
382662306a36Sopenharmony_ci	return &mr->ib_mr;
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_cifail_mr:
382962306a36Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
383062306a36Sopenharmony_cifail:
383162306a36Sopenharmony_ci	kfree(mr);
383262306a36Sopenharmony_ci	return ERR_PTR(rc);
383362306a36Sopenharmony_ci}
383462306a36Sopenharmony_ci
383562306a36Sopenharmony_ciint bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
383662306a36Sopenharmony_ci{
383762306a36Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
383862306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = mr->rdev;
383962306a36Sopenharmony_ci	int rc;
384062306a36Sopenharmony_ci
384162306a36Sopenharmony_ci	rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
384262306a36Sopenharmony_ci	if (rc) {
384362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Dereg MR failed: %#x\n", rc);
384462306a36Sopenharmony_ci		return rc;
384562306a36Sopenharmony_ci	}
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_ci	if (mr->pages) {
384862306a36Sopenharmony_ci		rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
384962306a36Sopenharmony_ci							&mr->qplib_frpl);
385062306a36Sopenharmony_ci		kfree(mr->pages);
385162306a36Sopenharmony_ci		mr->npages = 0;
385262306a36Sopenharmony_ci		mr->pages = NULL;
385362306a36Sopenharmony_ci	}
385462306a36Sopenharmony_ci	ib_umem_release(mr->ib_umem);
385562306a36Sopenharmony_ci
385662306a36Sopenharmony_ci	kfree(mr);
385762306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.mr_count);
385862306a36Sopenharmony_ci	return rc;
385962306a36Sopenharmony_ci}
386062306a36Sopenharmony_ci
386162306a36Sopenharmony_cistatic int bnxt_re_set_page(struct ib_mr *ib_mr, u64 addr)
386262306a36Sopenharmony_ci{
386362306a36Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci	if (unlikely(mr->npages == mr->qplib_frpl.max_pg_ptrs))
386662306a36Sopenharmony_ci		return -ENOMEM;
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_ci	mr->pages[mr->npages++] = addr;
386962306a36Sopenharmony_ci	return 0;
387062306a36Sopenharmony_ci}
387162306a36Sopenharmony_ci
387262306a36Sopenharmony_ciint bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
387362306a36Sopenharmony_ci		      unsigned int *sg_offset)
387462306a36Sopenharmony_ci{
387562306a36Sopenharmony_ci	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_ci	mr->npages = 0;
387862306a36Sopenharmony_ci	return ib_sg_to_pages(ib_mr, sg, sg_nents, sg_offset, bnxt_re_set_page);
387962306a36Sopenharmony_ci}
388062306a36Sopenharmony_ci
388162306a36Sopenharmony_cistruct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
388262306a36Sopenharmony_ci			       u32 max_num_sg)
388362306a36Sopenharmony_ci{
388462306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
388562306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
388662306a36Sopenharmony_ci	struct bnxt_re_mr *mr = NULL;
388762306a36Sopenharmony_ci	u32 active_mrs;
388862306a36Sopenharmony_ci	int rc;
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci	if (type != IB_MR_TYPE_MEM_REG) {
389162306a36Sopenharmony_ci		ibdev_dbg(&rdev->ibdev, "MR type 0x%x not supported", type);
389262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
389362306a36Sopenharmony_ci	}
389462306a36Sopenharmony_ci	if (max_num_sg > MAX_PBL_LVL_1_PGS)
389562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
389662306a36Sopenharmony_ci
389762306a36Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
389862306a36Sopenharmony_ci	if (!mr)
389962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
390062306a36Sopenharmony_ci
390162306a36Sopenharmony_ci	mr->rdev = rdev;
390262306a36Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
390362306a36Sopenharmony_ci	mr->qplib_mr.flags = BNXT_QPLIB_FR_PMR;
390462306a36Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
390562306a36Sopenharmony_ci
390662306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
390762306a36Sopenharmony_ci	if (rc)
390862306a36Sopenharmony_ci		goto bail;
390962306a36Sopenharmony_ci
391062306a36Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
391162306a36Sopenharmony_ci	mr->ib_mr.rkey = mr->ib_mr.lkey;
391262306a36Sopenharmony_ci
391362306a36Sopenharmony_ci	mr->pages = kcalloc(max_num_sg, sizeof(u64), GFP_KERNEL);
391462306a36Sopenharmony_ci	if (!mr->pages) {
391562306a36Sopenharmony_ci		rc = -ENOMEM;
391662306a36Sopenharmony_ci		goto fail;
391762306a36Sopenharmony_ci	}
391862306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_fast_reg_page_list(&rdev->qplib_res,
391962306a36Sopenharmony_ci						 &mr->qplib_frpl, max_num_sg);
392062306a36Sopenharmony_ci	if (rc) {
392162306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev,
392262306a36Sopenharmony_ci			  "Failed to allocate HW FR page list");
392362306a36Sopenharmony_ci		goto fail_mr;
392462306a36Sopenharmony_ci	}
392562306a36Sopenharmony_ci
392662306a36Sopenharmony_ci	active_mrs = atomic_inc_return(&rdev->stats.res.mr_count);
392762306a36Sopenharmony_ci	if (active_mrs > rdev->stats.res.mr_watermark)
392862306a36Sopenharmony_ci		rdev->stats.res.mr_watermark = active_mrs;
392962306a36Sopenharmony_ci	return &mr->ib_mr;
393062306a36Sopenharmony_ci
393162306a36Sopenharmony_cifail_mr:
393262306a36Sopenharmony_ci	kfree(mr->pages);
393362306a36Sopenharmony_cifail:
393462306a36Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
393562306a36Sopenharmony_cibail:
393662306a36Sopenharmony_ci	kfree(mr);
393762306a36Sopenharmony_ci	return ERR_PTR(rc);
393862306a36Sopenharmony_ci}
393962306a36Sopenharmony_ci
394062306a36Sopenharmony_cistruct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
394162306a36Sopenharmony_ci			       struct ib_udata *udata)
394262306a36Sopenharmony_ci{
394362306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
394462306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
394562306a36Sopenharmony_ci	struct bnxt_re_mw *mw;
394662306a36Sopenharmony_ci	u32 active_mws;
394762306a36Sopenharmony_ci	int rc;
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	mw = kzalloc(sizeof(*mw), GFP_KERNEL);
395062306a36Sopenharmony_ci	if (!mw)
395162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
395262306a36Sopenharmony_ci	mw->rdev = rdev;
395362306a36Sopenharmony_ci	mw->qplib_mw.pd = &pd->qplib_pd;
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci	mw->qplib_mw.type = (type == IB_MW_TYPE_1 ?
395662306a36Sopenharmony_ci			       CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 :
395762306a36Sopenharmony_ci			       CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B);
395862306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw);
395962306a36Sopenharmony_ci	if (rc) {
396062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Allocate MW failed!");
396162306a36Sopenharmony_ci		goto fail;
396262306a36Sopenharmony_ci	}
396362306a36Sopenharmony_ci	mw->ib_mw.rkey = mw->qplib_mw.rkey;
396462306a36Sopenharmony_ci
396562306a36Sopenharmony_ci	active_mws = atomic_inc_return(&rdev->stats.res.mw_count);
396662306a36Sopenharmony_ci	if (active_mws > rdev->stats.res.mw_watermark)
396762306a36Sopenharmony_ci		rdev->stats.res.mw_watermark = active_mws;
396862306a36Sopenharmony_ci	return &mw->ib_mw;
396962306a36Sopenharmony_ci
397062306a36Sopenharmony_cifail:
397162306a36Sopenharmony_ci	kfree(mw);
397262306a36Sopenharmony_ci	return ERR_PTR(rc);
397362306a36Sopenharmony_ci}
397462306a36Sopenharmony_ci
397562306a36Sopenharmony_ciint bnxt_re_dealloc_mw(struct ib_mw *ib_mw)
397662306a36Sopenharmony_ci{
397762306a36Sopenharmony_ci	struct bnxt_re_mw *mw = container_of(ib_mw, struct bnxt_re_mw, ib_mw);
397862306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = mw->rdev;
397962306a36Sopenharmony_ci	int rc;
398062306a36Sopenharmony_ci
398162306a36Sopenharmony_ci	rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw);
398262306a36Sopenharmony_ci	if (rc) {
398362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Free MW failed: %#x\n", rc);
398462306a36Sopenharmony_ci		return rc;
398562306a36Sopenharmony_ci	}
398662306a36Sopenharmony_ci
398762306a36Sopenharmony_ci	kfree(mw);
398862306a36Sopenharmony_ci	atomic_dec(&rdev->stats.res.mw_count);
398962306a36Sopenharmony_ci	return rc;
399062306a36Sopenharmony_ci}
399162306a36Sopenharmony_ci
399262306a36Sopenharmony_cistatic struct ib_mr *__bnxt_re_user_reg_mr(struct ib_pd *ib_pd, u64 length, u64 virt_addr,
399362306a36Sopenharmony_ci					   int mr_access_flags, struct ib_umem *umem)
399462306a36Sopenharmony_ci{
399562306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
399662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
399762306a36Sopenharmony_ci	unsigned long page_size;
399862306a36Sopenharmony_ci	struct bnxt_re_mr *mr;
399962306a36Sopenharmony_ci	int umem_pgs, rc;
400062306a36Sopenharmony_ci	u32 active_mrs;
400162306a36Sopenharmony_ci
400262306a36Sopenharmony_ci	if (length > BNXT_RE_MAX_MR_SIZE) {
400362306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "MR Size: %lld > Max supported:%lld\n",
400462306a36Sopenharmony_ci			  length, BNXT_RE_MAX_MR_SIZE);
400562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
400662306a36Sopenharmony_ci	}
400762306a36Sopenharmony_ci
400862306a36Sopenharmony_ci	page_size = ib_umem_find_best_pgsz(umem, BNXT_RE_PAGE_SIZE_SUPPORTED, virt_addr);
400962306a36Sopenharmony_ci	if (!page_size) {
401062306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "umem page size unsupported!");
401162306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
401262306a36Sopenharmony_ci	}
401362306a36Sopenharmony_ci
401462306a36Sopenharmony_ci	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
401562306a36Sopenharmony_ci	if (!mr)
401662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
401762306a36Sopenharmony_ci
401862306a36Sopenharmony_ci	mr->rdev = rdev;
401962306a36Sopenharmony_ci	mr->qplib_mr.pd = &pd->qplib_pd;
402062306a36Sopenharmony_ci	mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
402162306a36Sopenharmony_ci	mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR;
402262306a36Sopenharmony_ci
402362306a36Sopenharmony_ci	rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
402462306a36Sopenharmony_ci	if (rc) {
402562306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to allocate MR rc = %d", rc);
402662306a36Sopenharmony_ci		rc = -EIO;
402762306a36Sopenharmony_ci		goto free_mr;
402862306a36Sopenharmony_ci	}
402962306a36Sopenharmony_ci	/* The fixed portion of the rkey is the same as the lkey */
403062306a36Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.rkey;
403162306a36Sopenharmony_ci	mr->ib_umem = umem;
403262306a36Sopenharmony_ci	mr->qplib_mr.va = virt_addr;
403362306a36Sopenharmony_ci	mr->qplib_mr.total_size = length;
403462306a36Sopenharmony_ci
403562306a36Sopenharmony_ci	umem_pgs = ib_umem_num_dma_blocks(umem, page_size);
403662306a36Sopenharmony_ci	rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, umem,
403762306a36Sopenharmony_ci			       umem_pgs, page_size);
403862306a36Sopenharmony_ci	if (rc) {
403962306a36Sopenharmony_ci		ibdev_err(&rdev->ibdev, "Failed to register user MR - rc = %d\n", rc);
404062306a36Sopenharmony_ci		rc = -EIO;
404162306a36Sopenharmony_ci		goto free_mrw;
404262306a36Sopenharmony_ci	}
404362306a36Sopenharmony_ci
404462306a36Sopenharmony_ci	mr->ib_mr.lkey = mr->qplib_mr.lkey;
404562306a36Sopenharmony_ci	mr->ib_mr.rkey = mr->qplib_mr.lkey;
404662306a36Sopenharmony_ci	active_mrs = atomic_inc_return(&rdev->stats.res.mr_count);
404762306a36Sopenharmony_ci	if (active_mrs > rdev->stats.res.mr_watermark)
404862306a36Sopenharmony_ci		rdev->stats.res.mr_watermark = active_mrs;
404962306a36Sopenharmony_ci
405062306a36Sopenharmony_ci	return &mr->ib_mr;
405162306a36Sopenharmony_ci
405262306a36Sopenharmony_cifree_mrw:
405362306a36Sopenharmony_ci	bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
405462306a36Sopenharmony_cifree_mr:
405562306a36Sopenharmony_ci	kfree(mr);
405662306a36Sopenharmony_ci	return ERR_PTR(rc);
405762306a36Sopenharmony_ci}
405862306a36Sopenharmony_ci
405962306a36Sopenharmony_cistruct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
406062306a36Sopenharmony_ci				  u64 virt_addr, int mr_access_flags,
406162306a36Sopenharmony_ci				  struct ib_udata *udata)
406262306a36Sopenharmony_ci{
406362306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
406462306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
406562306a36Sopenharmony_ci	struct ib_umem *umem;
406662306a36Sopenharmony_ci	struct ib_mr *ib_mr;
406762306a36Sopenharmony_ci
406862306a36Sopenharmony_ci	umem = ib_umem_get(&rdev->ibdev, start, length, mr_access_flags);
406962306a36Sopenharmony_ci	if (IS_ERR(umem))
407062306a36Sopenharmony_ci		return ERR_CAST(umem);
407162306a36Sopenharmony_ci
407262306a36Sopenharmony_ci	ib_mr = __bnxt_re_user_reg_mr(ib_pd, length, virt_addr, mr_access_flags, umem);
407362306a36Sopenharmony_ci	if (IS_ERR(ib_mr))
407462306a36Sopenharmony_ci		ib_umem_release(umem);
407562306a36Sopenharmony_ci	return ib_mr;
407662306a36Sopenharmony_ci}
407762306a36Sopenharmony_ci
407862306a36Sopenharmony_cistruct ib_mr *bnxt_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
407962306a36Sopenharmony_ci					 u64 length, u64 virt_addr, int fd,
408062306a36Sopenharmony_ci					 int mr_access_flags, struct ib_udata *udata)
408162306a36Sopenharmony_ci{
408262306a36Sopenharmony_ci	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
408362306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = pd->rdev;
408462306a36Sopenharmony_ci	struct ib_umem_dmabuf *umem_dmabuf;
408562306a36Sopenharmony_ci	struct ib_umem *umem;
408662306a36Sopenharmony_ci	struct ib_mr *ib_mr;
408762306a36Sopenharmony_ci
408862306a36Sopenharmony_ci	umem_dmabuf = ib_umem_dmabuf_get_pinned(&rdev->ibdev, start, length,
408962306a36Sopenharmony_ci						fd, mr_access_flags);
409062306a36Sopenharmony_ci	if (IS_ERR(umem_dmabuf))
409162306a36Sopenharmony_ci		return ERR_CAST(umem_dmabuf);
409262306a36Sopenharmony_ci
409362306a36Sopenharmony_ci	umem = &umem_dmabuf->umem;
409462306a36Sopenharmony_ci
409562306a36Sopenharmony_ci	ib_mr = __bnxt_re_user_reg_mr(ib_pd, length, virt_addr, mr_access_flags, umem);
409662306a36Sopenharmony_ci	if (IS_ERR(ib_mr))
409762306a36Sopenharmony_ci		ib_umem_release(umem);
409862306a36Sopenharmony_ci	return ib_mr;
409962306a36Sopenharmony_ci}
410062306a36Sopenharmony_ci
410162306a36Sopenharmony_ciint bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
410262306a36Sopenharmony_ci{
410362306a36Sopenharmony_ci	struct ib_device *ibdev = ctx->device;
410462306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx =
410562306a36Sopenharmony_ci		container_of(ctx, struct bnxt_re_ucontext, ib_uctx);
410662306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
410762306a36Sopenharmony_ci	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
410862306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *entry;
410962306a36Sopenharmony_ci	struct bnxt_re_uctx_resp resp = {};
411062306a36Sopenharmony_ci	u32 chip_met_rev_num = 0;
411162306a36Sopenharmony_ci	int rc;
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_ci	ibdev_dbg(ibdev, "ABI version requested %u", ibdev->ops.uverbs_abi_ver);
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ci	if (ibdev->ops.uverbs_abi_ver != BNXT_RE_ABI_VERSION) {
411662306a36Sopenharmony_ci		ibdev_dbg(ibdev, " is different from the device %d ",
411762306a36Sopenharmony_ci			  BNXT_RE_ABI_VERSION);
411862306a36Sopenharmony_ci		return -EPERM;
411962306a36Sopenharmony_ci	}
412062306a36Sopenharmony_ci
412162306a36Sopenharmony_ci	uctx->rdev = rdev;
412262306a36Sopenharmony_ci
412362306a36Sopenharmony_ci	uctx->shpg = (void *)__get_free_page(GFP_KERNEL);
412462306a36Sopenharmony_ci	if (!uctx->shpg) {
412562306a36Sopenharmony_ci		rc = -ENOMEM;
412662306a36Sopenharmony_ci		goto fail;
412762306a36Sopenharmony_ci	}
412862306a36Sopenharmony_ci	spin_lock_init(&uctx->sh_lock);
412962306a36Sopenharmony_ci
413062306a36Sopenharmony_ci	resp.comp_mask = BNXT_RE_UCNTX_CMASK_HAVE_CCTX;
413162306a36Sopenharmony_ci	chip_met_rev_num = rdev->chip_ctx->chip_num;
413262306a36Sopenharmony_ci	chip_met_rev_num |= ((u32)rdev->chip_ctx->chip_rev & 0xFF) <<
413362306a36Sopenharmony_ci			     BNXT_RE_CHIP_ID0_CHIP_REV_SFT;
413462306a36Sopenharmony_ci	chip_met_rev_num |= ((u32)rdev->chip_ctx->chip_metal & 0xFF) <<
413562306a36Sopenharmony_ci			     BNXT_RE_CHIP_ID0_CHIP_MET_SFT;
413662306a36Sopenharmony_ci	resp.chip_id0 = chip_met_rev_num;
413762306a36Sopenharmony_ci	/*Temp, Use xa_alloc instead */
413862306a36Sopenharmony_ci	resp.dev_id = rdev->en_dev->pdev->devfn;
413962306a36Sopenharmony_ci	resp.max_qp = rdev->qplib_ctx.qpc_count;
414062306a36Sopenharmony_ci	resp.pg_size = PAGE_SIZE;
414162306a36Sopenharmony_ci	resp.cqe_sz = sizeof(struct cq_base);
414262306a36Sopenharmony_ci	resp.max_cqd = dev_attr->max_cq_wqes;
414362306a36Sopenharmony_ci
414462306a36Sopenharmony_ci	resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE;
414562306a36Sopenharmony_ci	resp.mode = rdev->chip_ctx->modes.wqe_mode;
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci	if (rdev->chip_ctx->modes.db_push)
414862306a36Sopenharmony_ci		resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED;
414962306a36Sopenharmony_ci
415062306a36Sopenharmony_ci	entry = bnxt_re_mmap_entry_insert(uctx, 0, BNXT_RE_MMAP_SH_PAGE, NULL);
415162306a36Sopenharmony_ci	if (!entry) {
415262306a36Sopenharmony_ci		rc = -ENOMEM;
415362306a36Sopenharmony_ci		goto cfail;
415462306a36Sopenharmony_ci	}
415562306a36Sopenharmony_ci	uctx->shpage_mmap = &entry->rdma_entry;
415662306a36Sopenharmony_ci	if (rdev->pacing.dbr_pacing)
415762306a36Sopenharmony_ci		resp.comp_mask |= BNXT_RE_UCNTX_CMASK_DBR_PACING_ENABLED;
415862306a36Sopenharmony_ci
415962306a36Sopenharmony_ci	rc = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp)));
416062306a36Sopenharmony_ci	if (rc) {
416162306a36Sopenharmony_ci		ibdev_err(ibdev, "Failed to copy user context");
416262306a36Sopenharmony_ci		rc = -EFAULT;
416362306a36Sopenharmony_ci		goto cfail;
416462306a36Sopenharmony_ci	}
416562306a36Sopenharmony_ci
416662306a36Sopenharmony_ci	return 0;
416762306a36Sopenharmony_cicfail:
416862306a36Sopenharmony_ci	free_page((unsigned long)uctx->shpg);
416962306a36Sopenharmony_ci	uctx->shpg = NULL;
417062306a36Sopenharmony_cifail:
417162306a36Sopenharmony_ci	return rc;
417262306a36Sopenharmony_ci}
417362306a36Sopenharmony_ci
417462306a36Sopenharmony_civoid bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
417562306a36Sopenharmony_ci{
417662306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx = container_of(ib_uctx,
417762306a36Sopenharmony_ci						   struct bnxt_re_ucontext,
417862306a36Sopenharmony_ci						   ib_uctx);
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci	struct bnxt_re_dev *rdev = uctx->rdev;
418162306a36Sopenharmony_ci
418262306a36Sopenharmony_ci	rdma_user_mmap_entry_remove(uctx->shpage_mmap);
418362306a36Sopenharmony_ci	uctx->shpage_mmap = NULL;
418462306a36Sopenharmony_ci	if (uctx->shpg)
418562306a36Sopenharmony_ci		free_page((unsigned long)uctx->shpg);
418662306a36Sopenharmony_ci
418762306a36Sopenharmony_ci	if (uctx->dpi.dbr) {
418862306a36Sopenharmony_ci		/* Free DPI only if this is the first PD allocated by the
418962306a36Sopenharmony_ci		 * application and mark the context dpi as NULL
419062306a36Sopenharmony_ci		 */
419162306a36Sopenharmony_ci		bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->dpi);
419262306a36Sopenharmony_ci		uctx->dpi.dbr = NULL;
419362306a36Sopenharmony_ci	}
419462306a36Sopenharmony_ci}
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci/* Helper function to mmap the virtual memory from user app */
419762306a36Sopenharmony_ciint bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)
419862306a36Sopenharmony_ci{
419962306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx = container_of(ib_uctx,
420062306a36Sopenharmony_ci						   struct bnxt_re_ucontext,
420162306a36Sopenharmony_ci						   ib_uctx);
420262306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *bnxt_entry;
420362306a36Sopenharmony_ci	struct rdma_user_mmap_entry *rdma_entry;
420462306a36Sopenharmony_ci	int ret = 0;
420562306a36Sopenharmony_ci	u64 pfn;
420662306a36Sopenharmony_ci
420762306a36Sopenharmony_ci	rdma_entry = rdma_user_mmap_entry_get(&uctx->ib_uctx, vma);
420862306a36Sopenharmony_ci	if (!rdma_entry)
420962306a36Sopenharmony_ci		return -EINVAL;
421062306a36Sopenharmony_ci
421162306a36Sopenharmony_ci	bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry,
421262306a36Sopenharmony_ci				  rdma_entry);
421362306a36Sopenharmony_ci
421462306a36Sopenharmony_ci	switch (bnxt_entry->mmap_flag) {
421562306a36Sopenharmony_ci	case BNXT_RE_MMAP_WC_DB:
421662306a36Sopenharmony_ci		pfn = bnxt_entry->mem_offset >> PAGE_SHIFT;
421762306a36Sopenharmony_ci		ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE,
421862306a36Sopenharmony_ci					pgprot_writecombine(vma->vm_page_prot),
421962306a36Sopenharmony_ci					rdma_entry);
422062306a36Sopenharmony_ci		break;
422162306a36Sopenharmony_ci	case BNXT_RE_MMAP_UC_DB:
422262306a36Sopenharmony_ci		pfn = bnxt_entry->mem_offset >> PAGE_SHIFT;
422362306a36Sopenharmony_ci		ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE,
422462306a36Sopenharmony_ci					pgprot_noncached(vma->vm_page_prot),
422562306a36Sopenharmony_ci				rdma_entry);
422662306a36Sopenharmony_ci		break;
422762306a36Sopenharmony_ci	case BNXT_RE_MMAP_SH_PAGE:
422862306a36Sopenharmony_ci		ret = vm_insert_page(vma, vma->vm_start, virt_to_page(uctx->shpg));
422962306a36Sopenharmony_ci		break;
423062306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_BAR:
423162306a36Sopenharmony_ci		pfn = bnxt_entry->mem_offset >> PAGE_SHIFT;
423262306a36Sopenharmony_ci		ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE,
423362306a36Sopenharmony_ci					pgprot_noncached(vma->vm_page_prot),
423462306a36Sopenharmony_ci					rdma_entry);
423562306a36Sopenharmony_ci		break;
423662306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_PAGE:
423762306a36Sopenharmony_ci		/* Driver doesn't expect write access for user space */
423862306a36Sopenharmony_ci		if (vma->vm_flags & VM_WRITE)
423962306a36Sopenharmony_ci			return -EFAULT;
424062306a36Sopenharmony_ci		ret = vm_insert_page(vma, vma->vm_start,
424162306a36Sopenharmony_ci				     virt_to_page((void *)bnxt_entry->mem_offset));
424262306a36Sopenharmony_ci		break;
424362306a36Sopenharmony_ci	default:
424462306a36Sopenharmony_ci		ret = -EINVAL;
424562306a36Sopenharmony_ci		break;
424662306a36Sopenharmony_ci	}
424762306a36Sopenharmony_ci
424862306a36Sopenharmony_ci	rdma_user_mmap_entry_put(rdma_entry);
424962306a36Sopenharmony_ci	return ret;
425062306a36Sopenharmony_ci}
425162306a36Sopenharmony_ci
425262306a36Sopenharmony_civoid bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
425362306a36Sopenharmony_ci{
425462306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *bnxt_entry;
425562306a36Sopenharmony_ci
425662306a36Sopenharmony_ci	bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry,
425762306a36Sopenharmony_ci				  rdma_entry);
425862306a36Sopenharmony_ci
425962306a36Sopenharmony_ci	kfree(bnxt_entry);
426062306a36Sopenharmony_ci}
426162306a36Sopenharmony_ci
426262306a36Sopenharmony_cistatic int UVERBS_HANDLER(BNXT_RE_METHOD_NOTIFY_DRV)(struct uverbs_attr_bundle *attrs)
426362306a36Sopenharmony_ci{
426462306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx;
426562306a36Sopenharmony_ci
426662306a36Sopenharmony_ci	uctx = container_of(ib_uverbs_get_ucontext(attrs), struct bnxt_re_ucontext, ib_uctx);
426762306a36Sopenharmony_ci	bnxt_re_pacing_alert(uctx->rdev);
426862306a36Sopenharmony_ci	return 0;
426962306a36Sopenharmony_ci}
427062306a36Sopenharmony_ci
427162306a36Sopenharmony_cistatic int UVERBS_HANDLER(BNXT_RE_METHOD_ALLOC_PAGE)(struct uverbs_attr_bundle *attrs)
427262306a36Sopenharmony_ci{
427362306a36Sopenharmony_ci	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
427462306a36Sopenharmony_ci	enum bnxt_re_alloc_page_type alloc_type;
427562306a36Sopenharmony_ci	struct bnxt_re_user_mmap_entry *entry;
427662306a36Sopenharmony_ci	enum bnxt_re_mmap_flag mmap_flag;
427762306a36Sopenharmony_ci	struct bnxt_qplib_chip_ctx *cctx;
427862306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx;
427962306a36Sopenharmony_ci	struct bnxt_re_dev *rdev;
428062306a36Sopenharmony_ci	u64 mmap_offset;
428162306a36Sopenharmony_ci	u32 length;
428262306a36Sopenharmony_ci	u32 dpi;
428362306a36Sopenharmony_ci	u64 addr;
428462306a36Sopenharmony_ci	int err;
428562306a36Sopenharmony_ci
428662306a36Sopenharmony_ci	uctx = container_of(ib_uverbs_get_ucontext(attrs), struct bnxt_re_ucontext, ib_uctx);
428762306a36Sopenharmony_ci	if (IS_ERR(uctx))
428862306a36Sopenharmony_ci		return PTR_ERR(uctx);
428962306a36Sopenharmony_ci
429062306a36Sopenharmony_ci	err = uverbs_get_const(&alloc_type, attrs, BNXT_RE_ALLOC_PAGE_TYPE);
429162306a36Sopenharmony_ci	if (err)
429262306a36Sopenharmony_ci		return err;
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_ci	rdev = uctx->rdev;
429562306a36Sopenharmony_ci	cctx = rdev->chip_ctx;
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_ci	switch (alloc_type) {
429862306a36Sopenharmony_ci	case BNXT_RE_ALLOC_WC_PAGE:
429962306a36Sopenharmony_ci		if (cctx->modes.db_push)  {
430062306a36Sopenharmony_ci			if (bnxt_qplib_alloc_dpi(&rdev->qplib_res, &uctx->wcdpi,
430162306a36Sopenharmony_ci						 uctx, BNXT_QPLIB_DPI_TYPE_WC))
430262306a36Sopenharmony_ci				return -ENOMEM;
430362306a36Sopenharmony_ci			length = PAGE_SIZE;
430462306a36Sopenharmony_ci			dpi = uctx->wcdpi.dpi;
430562306a36Sopenharmony_ci			addr = (u64)uctx->wcdpi.umdbr;
430662306a36Sopenharmony_ci			mmap_flag = BNXT_RE_MMAP_WC_DB;
430762306a36Sopenharmony_ci		} else {
430862306a36Sopenharmony_ci			return -EINVAL;
430962306a36Sopenharmony_ci		}
431062306a36Sopenharmony_ci
431162306a36Sopenharmony_ci		break;
431262306a36Sopenharmony_ci	case BNXT_RE_ALLOC_DBR_BAR_PAGE:
431362306a36Sopenharmony_ci		length = PAGE_SIZE;
431462306a36Sopenharmony_ci		addr = (u64)rdev->pacing.dbr_bar_addr;
431562306a36Sopenharmony_ci		mmap_flag = BNXT_RE_MMAP_DBR_BAR;
431662306a36Sopenharmony_ci		break;
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci	case BNXT_RE_ALLOC_DBR_PAGE:
431962306a36Sopenharmony_ci		length = PAGE_SIZE;
432062306a36Sopenharmony_ci		addr = (u64)rdev->pacing.dbr_page;
432162306a36Sopenharmony_ci		mmap_flag = BNXT_RE_MMAP_DBR_PAGE;
432262306a36Sopenharmony_ci		break;
432362306a36Sopenharmony_ci
432462306a36Sopenharmony_ci	default:
432562306a36Sopenharmony_ci		return -EOPNOTSUPP;
432662306a36Sopenharmony_ci	}
432762306a36Sopenharmony_ci
432862306a36Sopenharmony_ci	entry = bnxt_re_mmap_entry_insert(uctx, addr, mmap_flag, &mmap_offset);
432962306a36Sopenharmony_ci	if (!entry)
433062306a36Sopenharmony_ci		return -ENOMEM;
433162306a36Sopenharmony_ci
433262306a36Sopenharmony_ci	uobj->object = entry;
433362306a36Sopenharmony_ci	uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
433462306a36Sopenharmony_ci	err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
433562306a36Sopenharmony_ci			     &mmap_offset, sizeof(mmap_offset));
433662306a36Sopenharmony_ci	if (err)
433762306a36Sopenharmony_ci		return err;
433862306a36Sopenharmony_ci
433962306a36Sopenharmony_ci	err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
434062306a36Sopenharmony_ci			     &length, sizeof(length));
434162306a36Sopenharmony_ci	if (err)
434262306a36Sopenharmony_ci		return err;
434362306a36Sopenharmony_ci
434462306a36Sopenharmony_ci	err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_DPI,
434562306a36Sopenharmony_ci			     &dpi, sizeof(length));
434662306a36Sopenharmony_ci	if (err)
434762306a36Sopenharmony_ci		return err;
434862306a36Sopenharmony_ci
434962306a36Sopenharmony_ci	return 0;
435062306a36Sopenharmony_ci}
435162306a36Sopenharmony_ci
435262306a36Sopenharmony_cistatic int alloc_page_obj_cleanup(struct ib_uobject *uobject,
435362306a36Sopenharmony_ci				  enum rdma_remove_reason why,
435462306a36Sopenharmony_ci			    struct uverbs_attr_bundle *attrs)
435562306a36Sopenharmony_ci{
435662306a36Sopenharmony_ci	struct  bnxt_re_user_mmap_entry *entry = uobject->object;
435762306a36Sopenharmony_ci	struct bnxt_re_ucontext *uctx = entry->uctx;
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_ci	switch (entry->mmap_flag) {
436062306a36Sopenharmony_ci	case BNXT_RE_MMAP_WC_DB:
436162306a36Sopenharmony_ci		if (uctx && uctx->wcdpi.dbr) {
436262306a36Sopenharmony_ci			struct bnxt_re_dev *rdev = uctx->rdev;
436362306a36Sopenharmony_ci
436462306a36Sopenharmony_ci			bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->wcdpi);
436562306a36Sopenharmony_ci			uctx->wcdpi.dbr = NULL;
436662306a36Sopenharmony_ci		}
436762306a36Sopenharmony_ci		break;
436862306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_BAR:
436962306a36Sopenharmony_ci	case BNXT_RE_MMAP_DBR_PAGE:
437062306a36Sopenharmony_ci		break;
437162306a36Sopenharmony_ci	default:
437262306a36Sopenharmony_ci		goto exit;
437362306a36Sopenharmony_ci	}
437462306a36Sopenharmony_ci	rdma_user_mmap_entry_remove(&entry->rdma_entry);
437562306a36Sopenharmony_ciexit:
437662306a36Sopenharmony_ci	return 0;
437762306a36Sopenharmony_ci}
437862306a36Sopenharmony_ci
437962306a36Sopenharmony_ciDECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_ALLOC_PAGE,
438062306a36Sopenharmony_ci			    UVERBS_ATTR_IDR(BNXT_RE_ALLOC_PAGE_HANDLE,
438162306a36Sopenharmony_ci					    BNXT_RE_OBJECT_ALLOC_PAGE,
438262306a36Sopenharmony_ci					    UVERBS_ACCESS_NEW,
438362306a36Sopenharmony_ci					    UA_MANDATORY),
438462306a36Sopenharmony_ci			    UVERBS_ATTR_CONST_IN(BNXT_RE_ALLOC_PAGE_TYPE,
438562306a36Sopenharmony_ci						 enum bnxt_re_alloc_page_type,
438662306a36Sopenharmony_ci						 UA_MANDATORY),
438762306a36Sopenharmony_ci			    UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
438862306a36Sopenharmony_ci						UVERBS_ATTR_TYPE(u64),
438962306a36Sopenharmony_ci						UA_MANDATORY),
439062306a36Sopenharmony_ci			    UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
439162306a36Sopenharmony_ci						UVERBS_ATTR_TYPE(u32),
439262306a36Sopenharmony_ci						UA_MANDATORY),
439362306a36Sopenharmony_ci			    UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_DPI,
439462306a36Sopenharmony_ci						UVERBS_ATTR_TYPE(u32),
439562306a36Sopenharmony_ci						UA_MANDATORY));
439662306a36Sopenharmony_ci
439762306a36Sopenharmony_ciDECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DESTROY_PAGE,
439862306a36Sopenharmony_ci				    UVERBS_ATTR_IDR(BNXT_RE_DESTROY_PAGE_HANDLE,
439962306a36Sopenharmony_ci						    BNXT_RE_OBJECT_ALLOC_PAGE,
440062306a36Sopenharmony_ci						    UVERBS_ACCESS_DESTROY,
440162306a36Sopenharmony_ci						    UA_MANDATORY));
440262306a36Sopenharmony_ci
440362306a36Sopenharmony_ciDECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_ALLOC_PAGE,
440462306a36Sopenharmony_ci			    UVERBS_TYPE_ALLOC_IDR(alloc_page_obj_cleanup),
440562306a36Sopenharmony_ci			    &UVERBS_METHOD(BNXT_RE_METHOD_ALLOC_PAGE),
440662306a36Sopenharmony_ci			    &UVERBS_METHOD(BNXT_RE_METHOD_DESTROY_PAGE));
440762306a36Sopenharmony_ci
440862306a36Sopenharmony_ciDECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_NOTIFY_DRV);
440962306a36Sopenharmony_ci
441062306a36Sopenharmony_ciDECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_NOTIFY_DRV,
441162306a36Sopenharmony_ci			      &UVERBS_METHOD(BNXT_RE_METHOD_NOTIFY_DRV));
441262306a36Sopenharmony_ci
441362306a36Sopenharmony_ciconst struct uapi_definition bnxt_re_uapi_defs[] = {
441462306a36Sopenharmony_ci	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_ALLOC_PAGE),
441562306a36Sopenharmony_ci	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_NOTIFY_DRV),
441662306a36Sopenharmony_ci	{}
441762306a36Sopenharmony_ci};
4418