diff mbox series

[12/15] RDMA/hbl: direct verbs support

Message ID 20240613082208.1439968-13-oshpigelman@habana.ai (mailing list archive)
State Changes Requested
Headers show
Series Introduce HabanaLabs network drivers | expand

Commit Message

Omer Shpigelman June 13, 2024, 8:22 a.m. UTC
Add direct verbs (DV) uAPI.
The added operations are:
query_port: query vendor specific port attributes.
set_port_ex: set port extended settings.
usr_fifo: set user FIFO object for triggering HW doorbells.
encap: set port encapsulation (UDP/IPv4).

Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
Co-developed-by: Abhilash K V <kvabhilash@habana.ai>
Signed-off-by: Abhilash K V <kvabhilash@habana.ai>
Co-developed-by: Andrey Agranovich <aagranovich@habana.ai>
Signed-off-by: Andrey Agranovich <aagranovich@habana.ai>
Co-developed-by: Bharat Jauhari <bjauhari@habana.ai>
Signed-off-by: Bharat Jauhari <bjauhari@habana.ai>
Co-developed-by: David Meriin <dmeriin@habana.ai>
Signed-off-by: David Meriin <dmeriin@habana.ai>
Co-developed-by: Sagiv Ozeri <sozeri@habana.ai>
Signed-off-by: Sagiv Ozeri <sozeri@habana.ai>
Co-developed-by: Zvika Yehudai <zyehudai@habana.ai>
Signed-off-by: Zvika Yehudai <zyehudai@habana.ai>
---
 drivers/infiniband/hw/hbl/Kconfig           |   1 +
 drivers/infiniband/hw/hbl/Makefile          |   4 +
 drivers/infiniband/hw/hbl/hbl_encap.c       | 216 +++++++++++++++++
 drivers/infiniband/hw/hbl/hbl_main.c        |  15 ++
 drivers/infiniband/hw/hbl/hbl_query_port.c  |  96 ++++++++
 drivers/infiniband/hw/hbl/hbl_set_port_ex.c |  96 ++++++++
 drivers/infiniband/hw/hbl/hbl_usr_fifo.c    | 252 ++++++++++++++++++++
 7 files changed, 680 insertions(+)
 create mode 100644 drivers/infiniband/hw/hbl/hbl_encap.c
 create mode 100644 drivers/infiniband/hw/hbl/hbl_query_port.c
 create mode 100644 drivers/infiniband/hw/hbl/hbl_set_port_ex.c
 create mode 100644 drivers/infiniband/hw/hbl/hbl_usr_fifo.c

Comments

Omer Shpigelman July 4, 2024, 10:31 a.m. UTC | #1
On 6/13/24 11:22, Omer Shpigelman wrote:
> Add direct verbs (DV) uAPI.
> The added operations are:
> query_port: query vendor specific port attributes.
> set_port_ex: set port extended settings.
> usr_fifo: set user FIFO object for triggering HW doorbells.
> encap: set port encapsulation (UDP/IPv4).
> 
> Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
> Co-developed-by: Abhilash K V <kvabhilash@habana.ai>
> Signed-off-by: Abhilash K V <kvabhilash@habana.ai>
> Co-developed-by: Andrey Agranovich <aagranovich@habana.ai>
> Signed-off-by: Andrey Agranovich <aagranovich@habana.ai>
> Co-developed-by: Bharat Jauhari <bjauhari@habana.ai>
> Signed-off-by: Bharat Jauhari <bjauhari@habana.ai>
> Co-developed-by: David Meriin <dmeriin@habana.ai>
> Signed-off-by: David Meriin <dmeriin@habana.ai>
> Co-developed-by: Sagiv Ozeri <sozeri@habana.ai>
> Signed-off-by: Sagiv Ozeri <sozeri@habana.ai>
> Co-developed-by: Zvika Yehudai <zyehudai@habana.ai>
> Signed-off-by: Zvika Yehudai <zyehudai@habana.ai>
> ---

<..>

Hi Leon,
 
I'd like to ask if it will be possible to add a DV for dumping a QP. The
standard way to dump a QP is with rdma resource tool but it might not be
available for us on all environments. Hence it will be best for us to add
a direct uAPI for exposing this info, similarly to our query port DV.
Will that be acceptable? or maybe is there any other way we can achieve
this ability?
 
Thanks
Leon Romanovsky July 7, 2024, 7:57 a.m. UTC | #2
On Thu, Jul 04, 2024 at 10:31:18AM +0000, Omer Shpigelman wrote:
> On 6/13/24 11:22, Omer Shpigelman wrote:
> > Add direct verbs (DV) uAPI.
> > The added operations are:
> > query_port: query vendor specific port attributes.
> > set_port_ex: set port extended settings.
> > usr_fifo: set user FIFO object for triggering HW doorbells.
> > encap: set port encapsulation (UDP/IPv4).
> > 
> > Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
> > Co-developed-by: Abhilash K V <kvabhilash@habana.ai>
> > Signed-off-by: Abhilash K V <kvabhilash@habana.ai>
> > Co-developed-by: Andrey Agranovich <aagranovich@habana.ai>
> > Signed-off-by: Andrey Agranovich <aagranovich@habana.ai>
> > Co-developed-by: Bharat Jauhari <bjauhari@habana.ai>
> > Signed-off-by: Bharat Jauhari <bjauhari@habana.ai>
> > Co-developed-by: David Meriin <dmeriin@habana.ai>
> > Signed-off-by: David Meriin <dmeriin@habana.ai>
> > Co-developed-by: Sagiv Ozeri <sozeri@habana.ai>
> > Signed-off-by: Sagiv Ozeri <sozeri@habana.ai>
> > Co-developed-by: Zvika Yehudai <zyehudai@habana.ai>
> > Signed-off-by: Zvika Yehudai <zyehudai@habana.ai>
> > ---
> 
> <..>
> 
> Hi Leon,
>  
> I'd like to ask if it will be possible to add a DV for dumping a QP. The
> standard way to dump a QP is with rdma resource tool but it might not be
> available for us on all environments. Hence it will be best for us to add
> a direct uAPI for exposing this info, similarly to our query port DV.
> Will that be acceptable? or maybe is there any other way we can achieve
> this ability?

I don't know, new rdma-core library with new API will be available,
but stdnalone tool which can be statically linked won't. How is it possible?

Thanks

>  
> Thanks
Omer Shpigelman July 7, 2024, 8:42 a.m. UTC | #3
On 7/7/24 10:57, Leon Romanovsky wrote:
> On Thu, Jul 04, 2024 at 10:31:18AM +0000, Omer Shpigelman wrote:
>> On 6/13/24 11:22, Omer Shpigelman wrote:
>>> Add direct verbs (DV) uAPI.
>>> The added operations are:
>>> query_port: query vendor specific port attributes.
>>> set_port_ex: set port extended settings.
>>> usr_fifo: set user FIFO object for triggering HW doorbells.
>>> encap: set port encapsulation (UDP/IPv4).
>>>
>>> Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
>>> Co-developed-by: Abhilash K V <kvabhilash@habana.ai>
>>> Signed-off-by: Abhilash K V <kvabhilash@habana.ai>
>>> Co-developed-by: Andrey Agranovich <aagranovich@habana.ai>
>>> Signed-off-by: Andrey Agranovich <aagranovich@habana.ai>
>>> Co-developed-by: Bharat Jauhari <bjauhari@habana.ai>
>>> Signed-off-by: Bharat Jauhari <bjauhari@habana.ai>
>>> Co-developed-by: David Meriin <dmeriin@habana.ai>
>>> Signed-off-by: David Meriin <dmeriin@habana.ai>
>>> Co-developed-by: Sagiv Ozeri <sozeri@habana.ai>
>>> Signed-off-by: Sagiv Ozeri <sozeri@habana.ai>
>>> Co-developed-by: Zvika Yehudai <zyehudai@habana.ai>
>>> Signed-off-by: Zvika Yehudai <zyehudai@habana.ai>
>>> ---
>>
>> <..>
>>
>> Hi Leon,
>>  
>> I'd like to ask if it will be possible to add a DV for dumping a QP. The
>> standard way to dump a QP is with rdma resource tool but it might not be
>> available for us on all environments. Hence it will be best for us to add
>> a direct uAPI for exposing this info, similarly to our query port DV.
>> Will that be acceptable? or maybe is there any other way we can achieve
>> this ability?
> 
> I don't know, new rdma-core library with new API will be available,
> but stdnalone tool which can be statically linked won't. How is it possible?
> 

If iproute2 package was manually removed from some reason.

> Thanks
> 
>>  
>> Thanks
Leon Romanovsky July 7, 2024, 9 a.m. UTC | #4
On Sun, Jul 07, 2024 at 08:42:59AM +0000, Omer Shpigelman wrote:
> On 7/7/24 10:57, Leon Romanovsky wrote:
> > On Thu, Jul 04, 2024 at 10:31:18AM +0000, Omer Shpigelman wrote:
> >> On 6/13/24 11:22, Omer Shpigelman wrote:
> >>> Add direct verbs (DV) uAPI.
> >>> The added operations are:
> >>> query_port: query vendor specific port attributes.
> >>> set_port_ex: set port extended settings.
> >>> usr_fifo: set user FIFO object for triggering HW doorbells.
> >>> encap: set port encapsulation (UDP/IPv4).
> >>>
> >>> Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
> >>> Co-developed-by: Abhilash K V <kvabhilash@habana.ai>
> >>> Signed-off-by: Abhilash K V <kvabhilash@habana.ai>
> >>> Co-developed-by: Andrey Agranovich <aagranovich@habana.ai>
> >>> Signed-off-by: Andrey Agranovich <aagranovich@habana.ai>
> >>> Co-developed-by: Bharat Jauhari <bjauhari@habana.ai>
> >>> Signed-off-by: Bharat Jauhari <bjauhari@habana.ai>
> >>> Co-developed-by: David Meriin <dmeriin@habana.ai>
> >>> Signed-off-by: David Meriin <dmeriin@habana.ai>
> >>> Co-developed-by: Sagiv Ozeri <sozeri@habana.ai>
> >>> Signed-off-by: Sagiv Ozeri <sozeri@habana.ai>
> >>> Co-developed-by: Zvika Yehudai <zyehudai@habana.ai>
> >>> Signed-off-by: Zvika Yehudai <zyehudai@habana.ai>
> >>> ---
> >>
> >> <..>
> >>
> >> Hi Leon,
> >>  
> >> I'd like to ask if it will be possible to add a DV for dumping a QP. The
> >> standard way to dump a QP is with rdma resource tool but it might not be
> >> available for us on all environments. Hence it will be best for us to add
> >> a direct uAPI for exposing this info, similarly to our query port DV.
> >> Will that be acceptable? or maybe is there any other way we can achieve
> >> this ability?
> > 
> > I don't know, new rdma-core library with new API will be available,
> > but stdnalone tool which can be statically linked won't. How is it possible?
> > 
> 
> If iproute2 package was manually removed from some reason.

If it is user's decision to remove it, it is user's responsibility to
deal with consequences.

Thanks

> 
> > Thanks
> > 
> >>  
> >> Thanks
>
Jason Gunthorpe July 12, 2024, 1:10 p.m. UTC | #5
On Sun, Jul 07, 2024 at 12:00:44PM +0300, Leon Romanovsky wrote:

> > >>
> > >> I'd like to ask if it will be possible to add a DV for dumping a QP. The
> > >> standard way to dump a QP is with rdma resource tool but it might not be
> > >> available for us on all environments. Hence it will be best for us to add
> > >> a direct uAPI for exposing this info, similarly to our query port DV.
> > >> Will that be acceptable? or maybe is there any other way we can achieve
> > >> this ability?
> > > 
> > > I don't know, new rdma-core library with new API will be available,
> > > but stdnalone tool which can be statically linked won't. How is it possible?
> > > 
> > 
> > If iproute2 package was manually removed from some reason.
> 
> If it is user's decision to remove it, it is user's responsibility to
> deal with consequences.

Yes, please don't bring backporting crazyness to upstream. Upstream is
supposed to be a technically clean self contained solution.

If you need software to be deployed in userspace in backport
environments then take care to get that software deployed, don't make
hacks in upstream to avoid deployment work.

Jason
Omer Shpigelman July 14, 2024, 6:05 a.m. UTC | #6
On 7/12/24 16:10, Jason Gunthorpe wrote:
> [You don't often get email from jgg@ziepe.ca. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> On Sun, Jul 07, 2024 at 12:00:44PM +0300, Leon Romanovsky wrote:
> 
>>>>>
>>>>> I'd like to ask if it will be possible to add a DV for dumping a QP. The
>>>>> standard way to dump a QP is with rdma resource tool but it might not be
>>>>> available for us on all environments. Hence it will be best for us to add
>>>>> a direct uAPI for exposing this info, similarly to our query port DV.
>>>>> Will that be acceptable? or maybe is there any other way we can achieve
>>>>> this ability?
>>>>
>>>> I don't know, new rdma-core library with new API will be available,
>>>> but stdnalone tool which can be statically linked won't. How is it possible?
>>>>
>>>
>>> If iproute2 package was manually removed from some reason.
>>
>> If it is user's decision to remove it, it is user's responsibility to
>> deal with consequences.
> 
> Yes, please don't bring backporting crazyness to upstream. Upstream is
> supposed to be a technically clean self contained solution.
> 
> If you need software to be deployed in userspace in backport
> environments then take care to get that software deployed, don't make
> hacks in upstream to avoid deployment work.
> 
> Jason

Yeah, makes sense. It was a long shot but still wanted to check for this
option.

Thanks
diff mbox series

Patch

diff --git a/drivers/infiniband/hw/hbl/Kconfig b/drivers/infiniband/hw/hbl/Kconfig
index 90c865a82540..db09ecb3968a 100644
--- a/drivers/infiniband/hw/hbl/Kconfig
+++ b/drivers/infiniband/hw/hbl/Kconfig
@@ -6,6 +6,7 @@ 
 config INFINIBAND_HBL
 	tristate "HabanaLabs (an Intel Company) InfiniBand driver"
 	depends on NETDEVICES && ETHERNET && PCI && INET
+	depends on INFINIBAND_USER_ACCESS
 	select HABANA_CN
 	help
 	  This driver enables InfiniBand functionality for the network
diff --git a/drivers/infiniband/hw/hbl/Makefile b/drivers/infiniband/hw/hbl/Makefile
index 659d4bbfec0f..86f53ca6b9d5 100644
--- a/drivers/infiniband/hw/hbl/Makefile
+++ b/drivers/infiniband/hw/hbl/Makefile
@@ -6,3 +6,7 @@ 
 obj-$(CONFIG_INFINIBAND_HBL) := habanalabs_ib.o
 
 habanalabs_ib-y += hbl_main.o hbl_verbs.o
+
+habanalabs_ib-$(CONFIG_INFINIBAND_USER_ACCESS) += hbl_encap.o hbl_query_port.o \
+                                                  hbl_set_port_ex.o \
+                                                  hbl_usr_fifo.o
diff --git a/drivers/infiniband/hw/hbl/hbl_encap.c b/drivers/infiniband/hw/hbl/hbl_encap.c
new file mode 100644
index 000000000000..bcc198059664
--- /dev/null
+++ b/drivers/infiniband/hw/hbl/hbl_encap.c
@@ -0,0 +1,216 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2022-2024 HabanaLabs, Ltd.
+ * Copyright (C) 2023-2024, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include "hbl.h"
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+#include <rdma/uverbs_ioctl.h>
+#include <linux/net/intel/cni.h>
+
+#include <rdma/uverbs_ioctl.h>
+#include <uapi/rdma/hbl_user_ioctl_cmds.h>
+
+#define UVERBS_MODULE_NAME hbl
+#include <rdma/uverbs_named_ioctl.h>
+
+struct hbl_encap {
+	u32 port_num;
+	u32 encap_num;
+};
+
+static int UVERBS_HANDLER(HBL_IB_METHOD_ENCAP_CREATE)(struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_cni_user_encap_alloc_out alloc_encap_out = {};
+	struct hbl_cni_user_encap_alloc_in alloc_encap_in = {};
+	struct hbl_cni_user_encap_unset_in unset_encap_in = {};
+	struct hbl_cni_user_encap_set_in set_encap_in = {};
+	struct hbl_uapi_encap_create_out out = {};
+	struct hbl_uapi_encap_create_in in = {};
+	u32 port, tnl_hdr_size, encap_num;
+	struct hbl_ib_aux_ops *aux_ops;
+	struct hbl_encap *encap_pdata;
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_aux_dev *aux_dev;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	struct ib_uobject *uobj;
+	u64 tnl_hdr_ptr;
+	u8 encap_type;
+	int rc;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	uobj = uverbs_attr_get_uobject(attrs, HBL_IB_ATTR_ENCAP_CREATE_HANDLE);
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+	aux_dev = hdev->aux_dev;
+	aux_ops = aux_dev->aux_ops;
+
+	rc = uverbs_copy_from(&in, attrs, HBL_IB_ATTR_ENCAP_CREATE_IN);
+	if (rc)
+		return rc;
+
+	rc = ib_to_hbl_port_num(hdev, in.port_num, &port);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "invalid IB port %u\n", in.port_num);
+		return rc;
+	}
+
+	if (!(hctx->ports_mask & BIT(port))) {
+		hbl_ibdev_dbg(ibdev, "port %d is not part of the context's ports mask 0x%llx\n",
+			      port, hctx->ports_mask);
+		return -EINVAL;
+	}
+
+	encap_pdata = kzalloc(sizeof(*encap_pdata), GFP_KERNEL);
+	if (!encap_pdata)
+		return -ENOMEM;
+
+	encap_type = in.encap_type;
+
+	alloc_encap_in.port = port;
+	rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_ENCAP_ALLOC, &alloc_encap_in,
+			       &alloc_encap_out);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "failed to alloc encap for port %d\n", port);
+		goto err_free_pdata;
+	}
+
+	encap_num = alloc_encap_out.id;
+
+	if (encap_type != HBL_CNI_ENCAP_NONE) {
+		tnl_hdr_ptr = in.tnl_hdr_ptr;
+		tnl_hdr_size = in.tnl_hdr_size;
+	} else {
+		tnl_hdr_ptr = 0;
+		tnl_hdr_size = 0;
+	}
+
+	encap_pdata->port_num = port;
+	encap_pdata->encap_num = encap_num;
+
+	set_encap_in.tnl_hdr_ptr = tnl_hdr_ptr;
+	set_encap_in.tnl_hdr_size = tnl_hdr_size;
+	set_encap_in.port = port;
+	set_encap_in.id = encap_num;
+	set_encap_in.encap_type = encap_type;
+
+	switch (encap_type) {
+	case HBL_CNI_ENCAP_NONE:
+		set_encap_in.ipv4_addr = in.ipv4_addr;
+		break;
+	case HBL_CNI_ENCAP_OVER_UDP:
+		set_encap_in.udp_dst_port = in.udp_dst_port;
+		break;
+	case HBL_CNI_ENCAP_OVER_IPV4:
+		set_encap_in.ip_proto = in.ip_proto;
+		break;
+	default:
+		break;
+	}
+
+	rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_ENCAP_SET, &set_encap_in,
+			       NULL);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "failed to set encap for port %d\n", port);
+		goto err_encap_unset;
+	}
+
+	out.encap_num = encap_num;
+	uobj->object = encap_pdata;
+
+	rc = uverbs_copy_to_struct_or_zero(attrs, HBL_IB_ATTR_ENCAP_CREATE_OUT, &out, sizeof(out));
+	if (rc)
+		goto err_encap_unset;
+
+	return 0;
+
+err_encap_unset:
+	unset_encap_in.port = port;
+	unset_encap_in.id = encap_num;
+
+	if (aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_ENCAP_UNSET, &unset_encap_in,
+			      NULL))
+		hbl_ibdev_dbg(ibdev, "failed to unset encap for port %d, encap_num %d\n", port,
+			      encap_num);
+
+err_free_pdata:
+	kfree(encap_pdata);
+
+	return rc;
+}
+
+static int hbl_free_encap(struct ib_uobject *uobject, enum rdma_remove_reason why,
+			  struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_cni_user_encap_unset_in unset_encap_in = {};
+	struct hbl_ib_aux_ops *aux_ops;
+	struct hbl_encap *encap_pdata;
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_aux_dev *aux_dev;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	int rc;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	encap_pdata = uobject->object;
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+	aux_dev = hdev->aux_dev;
+	aux_ops = aux_dev->aux_ops;
+
+	unset_encap_in.port = encap_pdata->port_num;
+	unset_encap_in.id = encap_pdata->encap_num;
+	if (aux_ops->device_operational(aux_dev)) {
+		rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_ENCAP_UNSET,
+				       &unset_encap_in, NULL);
+		if (rc) {
+			hbl_ibdev_dbg(ibdev, "failed to unset encap for port %d, id %d\n",
+				      unset_encap_in.port, unset_encap_in.id);
+			return rc;
+		}
+	}
+
+	kfree(encap_pdata);
+
+	return 0;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+	HBL_IB_METHOD_ENCAP_CREATE,
+	UVERBS_ATTR_IDR(HBL_IB_ATTR_ENCAP_CREATE_HANDLE,
+			HBL_IB_OBJECT_ENCAP,
+			UVERBS_ACCESS_NEW,
+			UA_MANDATORY),
+	UVERBS_ATTR_PTR_IN(HBL_IB_ATTR_ENCAP_CREATE_IN,
+			   UVERBS_ATTR_STRUCT(struct hbl_uapi_encap_create_in, reserved),
+			   UA_MANDATORY),
+	UVERBS_ATTR_PTR_OUT(HBL_IB_ATTR_ENCAP_CREATE_OUT,
+			    UVERBS_ATTR_STRUCT(struct hbl_uapi_encap_create_out, reserved),
+			    UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_METHOD_DESTROY(
+	HBL_IB_METHOD_ENCAP_DESTROY,
+	UVERBS_ATTR_IDR(HBL_IB_ATTR_ENCAP_DESTROY_HANDLE,
+			HBL_IB_OBJECT_ENCAP,
+			UVERBS_ACCESS_DESTROY,
+			UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(HBL_IB_OBJECT_ENCAP,
+			    UVERBS_TYPE_ALLOC_IDR(hbl_free_encap),
+			    &UVERBS_METHOD(HBL_IB_METHOD_ENCAP_CREATE),
+			    &UVERBS_METHOD(HBL_IB_METHOD_ENCAP_DESTROY));
+
+const struct uapi_definition hbl_encap_defs[] = {
+	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(HBL_IB_OBJECT_ENCAP),
+	{},
+};
diff --git a/drivers/infiniband/hw/hbl/hbl_main.c b/drivers/infiniband/hw/hbl/hbl_main.c
index 98d3ed46bfe2..6bee35695a06 100644
--- a/drivers/infiniband/hw/hbl/hbl_main.c
+++ b/drivers/infiniband/hw/hbl/hbl_main.c
@@ -22,6 +22,16 @@  MODULE_LICENSE("GPL");
 
 #define MTU_DEFAULT	SZ_4K
 
+static const struct uapi_definition hbl_defs[] = {
+#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
+	UAPI_DEF_CHAIN(hbl_usr_fifo_defs),
+	UAPI_DEF_CHAIN(hbl_set_port_ex_defs),
+	UAPI_DEF_CHAIN(hbl_query_port_defs),
+	UAPI_DEF_CHAIN(hbl_encap_defs),
+#endif
+	{}
+};
+
 static void hbl_ib_port_event(struct ib_device *ibdev, u32 port_num, enum ib_event_type reason)
 {
 	struct ib_event event;
@@ -166,6 +176,11 @@  static int hbl_ib_dev_init(struct hbl_ib_device *hdev)
 
 	ib_set_device_ops(ibdev, &hbl_ib_dev_ops);
 
+	if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))
+		ibdev->driver_def = hbl_defs;
+	else
+		dev_info(hdev->dev, "IB user access is disabled\n");
+
 	/* The CN driver might start calling the aux functions after registering the device so set
 	 * the callbacks here.
 	 */
diff --git a/drivers/infiniband/hw/hbl/hbl_query_port.c b/drivers/infiniband/hw/hbl/hbl_query_port.c
new file mode 100644
index 000000000000..1882507b0b58
--- /dev/null
+++ b/drivers/infiniband/hw/hbl/hbl_query_port.c
@@ -0,0 +1,96 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2022-2024 HabanaLabs, Ltd.
+ * Copyright (C) 2023-2024, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include "hbl.h"
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+#include <rdma/uverbs_ioctl.h>
+#include <linux/net/intel/cni.h>
+
+#include <rdma/uverbs_ioctl.h>
+#include <uapi/rdma/hbl_user_ioctl_cmds.h>
+#include <uapi/rdma/hbl_user_ioctl_verbs.h>
+
+#define UVERBS_MODULE_NAME hbl
+#include <rdma/uverbs_named_ioctl.h>
+
+static int UVERBS_HANDLER(HBL_IB_METHOD_QUERY_PORT)(struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_cni_get_user_app_params_out app_params_out = {};
+	struct hbl_cni_get_user_app_params_in app_params_in = {};
+	struct hbl_uapi_query_port_out out = {};
+	struct hbl_uapi_query_port_in in = {};
+	struct hbl_ib_aux_ops *aux_ops;
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_aux_dev *aux_dev;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	int rc;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+	aux_dev = hdev->aux_dev;
+	aux_ops = aux_dev->aux_ops;
+
+	rc = uverbs_copy_from(&in, attrs, HBL_IB_ATTR_QUERY_PORT_IN);
+	if (rc)
+		return rc;
+
+	rc = ib_to_hbl_port_num(hdev, in.port_num, &app_params_in.port);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "invalid IB port %u\n", in.port_num);
+		return rc;
+	}
+
+	if (!(hctx->ports_mask & BIT(app_params_in.port))) {
+		hbl_ibdev_dbg(ibdev, "port %d is not part of the context's ports mask 0x%llx\n",
+			      app_params_in.port, hctx->ports_mask);
+		return -EINVAL;
+	}
+
+	rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_GET_USER_APP_PARAMS,
+			       &app_params_in, &app_params_out);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "failed to get user params for port %d\n", app_params_in.port);
+		return rc;
+	}
+
+	out.max_num_of_qps = app_params_out.max_num_of_qps;
+	out.num_allocated_qps = app_params_out.num_allocated_qps;
+	out.max_allocated_qp_num = app_params_out.max_allocated_qp_idx;
+	out.max_cq_size = app_params_out.max_cq_size;
+	out.advanced = app_params_out.advanced;
+	out.max_num_of_cqs = app_params_out.max_num_of_cqs;
+	out.max_num_of_usr_fifos = app_params_out.max_num_of_db_fifos;
+	out.max_num_of_encaps = app_params_out.max_num_of_encaps;
+	out.nic_macro_idx = app_params_out.nic_macro_idx;
+	out.nic_phys_port_idx = app_params_out.nic_phys_port_idx;
+
+	rc = uverbs_copy_to_struct_or_zero(attrs, HBL_IB_ATTR_QUERY_PORT_OUT, &out, sizeof(out));
+
+	return rc;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+	HBL_IB_METHOD_QUERY_PORT,
+	UVERBS_ATTR_PTR_IN(HBL_IB_ATTR_QUERY_PORT_IN,
+			   UVERBS_ATTR_STRUCT(struct hbl_uapi_query_port_in, reserved),
+			   UA_MANDATORY),
+	UVERBS_ATTR_PTR_OUT(HBL_IB_ATTR_QUERY_PORT_OUT,
+			    UVERBS_ATTR_STRUCT(struct hbl_uapi_query_port_out, reserved),
+			    UA_MANDATORY));
+
+DECLARE_UVERBS_GLOBAL_METHODS(HBL_IB_OBJECT_QUERY_PORT, &UVERBS_METHOD(HBL_IB_METHOD_QUERY_PORT));
+
+const struct uapi_definition hbl_query_port_defs[] = {
+	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(HBL_IB_OBJECT_QUERY_PORT),
+	{},
+};
diff --git a/drivers/infiniband/hw/hbl/hbl_set_port_ex.c b/drivers/infiniband/hw/hbl/hbl_set_port_ex.c
new file mode 100644
index 000000000000..15b509506cca
--- /dev/null
+++ b/drivers/infiniband/hw/hbl/hbl_set_port_ex.c
@@ -0,0 +1,96 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2022-2024 HabanaLabs, Ltd.
+ * Copyright (C) 2023-2024, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include "hbl.h"
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+#include <rdma/uverbs_ioctl.h>
+#include <linux/net/intel/cni.h>
+
+#include <rdma/uverbs_ioctl.h>
+#include <uapi/rdma/hbl_user_ioctl_cmds.h>
+#include <uapi/rdma/hbl_user_ioctl_verbs.h>
+
+#define UVERBS_MODULE_NAME hbl
+#include <rdma/uverbs_named_ioctl.h>
+
+static int UVERBS_HANDLER(HBL_IB_METHOD_SET_PORT_EX)(struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_ib_port_init_params port_init_params = {};
+	struct hbl_uapi_set_port_ex_in in = {};
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	u32 hbl_port;
+	int rc, i;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+
+	rc = uverbs_copy_from(&in, attrs, HBL_IB_ATTR_SET_PORT_EX_IN);
+	if (rc)
+		return rc;
+
+	rc = ib_to_hbl_port_num(hdev, in.port_num, &hbl_port);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "invalid IB port %u\n", in.port_num);
+		return rc;
+	}
+
+	if (!(hctx->ports_mask & BIT(hbl_port))) {
+		hbl_ibdev_dbg(ibdev, "port %d is not part of the context's ports mask 0x%llx\n",
+			      hbl_port, hctx->ports_mask);
+		return -EINVAL;
+	}
+
+	if (!in.qp_wq_bp_offs && in.qp_wq_bp_offs_cnt > 0)
+		return -EINVAL;
+
+	port_init_params.hbl_port_num = hbl_port;
+
+	for (i = 0; i < HBL_IB_WQ_ARRAY_TYPE_MAX; i++) {
+		port_init_params.wq_arr_attr[i].max_num_of_wqs =
+						in.wq_arr_attr[i].max_num_of_wqs;
+		port_init_params.wq_arr_attr[i].max_num_of_wqes_in_wq =
+						in.wq_arr_attr[i].max_num_of_wqes_in_wq;
+		port_init_params.wq_arr_attr[i].mem_id = in.wq_arr_attr[i].mem_id;
+		port_init_params.wq_arr_attr[i].swq_granularity =
+						in.wq_arr_attr[i].swq_granularity;
+	}
+
+	if (copy_from_user(port_init_params.qp_wq_bp_offs, u64_to_user_ptr(in.qp_wq_bp_offs),
+			   sizeof(port_init_params.qp_wq_bp_offs[0]) *
+			   min((u32)HBL_IB_MAX_BP_OFFS, in.qp_wq_bp_offs_cnt)))
+		return -EFAULT;
+
+	port_init_params.advanced = in.advanced;
+	port_init_params.adaptive_timeout_en = in.adaptive_timeout_en;
+
+	rc = hbl_ib_port_init(hctx, &port_init_params);
+	if (rc)
+		hbl_ibdev_dbg(ibdev, "failed(%d) to set port %u extended params\n", rc, hbl_port);
+
+	return rc;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+	HBL_IB_METHOD_SET_PORT_EX,
+	UVERBS_ATTR_PTR_IN(HBL_IB_ATTR_SET_PORT_EX_IN,
+			   UVERBS_ATTR_STRUCT(struct hbl_uapi_set_port_ex_in, reserved3),
+			   UA_MANDATORY));
+
+DECLARE_UVERBS_GLOBAL_METHODS(HBL_IB_OBJECT_SET_PORT_EX,
+			      &UVERBS_METHOD(HBL_IB_METHOD_SET_PORT_EX));
+
+const struct uapi_definition hbl_set_port_ex_defs[] = {
+	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(HBL_IB_OBJECT_SET_PORT_EX),
+	{},
+};
diff --git a/drivers/infiniband/hw/hbl/hbl_usr_fifo.c b/drivers/infiniband/hw/hbl/hbl_usr_fifo.c
new file mode 100644
index 000000000000..37f387a99f40
--- /dev/null
+++ b/drivers/infiniband/hw/hbl/hbl_usr_fifo.c
@@ -0,0 +1,252 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2022-2024 HabanaLabs, Ltd.
+ * Copyright (C) 2023-2024, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include "hbl.h"
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+#include <rdma/uverbs_ioctl.h>
+#include <linux/net/intel/cni.h>
+
+#include <rdma/uverbs_ioctl.h>
+#include <uapi/rdma/hbl_user_ioctl_cmds.h>
+#include <uapi/rdma/hbl_user_ioctl_verbs.h>
+
+#define UVERBS_MODULE_NAME hbl
+#include <rdma/uverbs_named_ioctl.h>
+
+/**
+ * struct hbl_usr_fifo - This structure will be stored inside the uobject.
+ * @ci_entry: The rdma_user_mmap_entry for the mapped ci.
+ * @regs_entry: The rdma_user_mmap_entry for the mapped registers.
+ * @port: The port of this fifo.
+ * @id: The id of this fifo.
+ */
+struct hbl_usr_fifo {
+	struct rdma_user_mmap_entry *ci_entry;
+	struct rdma_user_mmap_entry *regs_entry;
+	u32 port;
+	u32 id;
+};
+
+static void user_fifo_mmap_entry_remove(struct hbl_usr_fifo *usr_fifo)
+{
+	rdma_user_mmap_entry_remove(usr_fifo->regs_entry);
+	if (usr_fifo->ci_entry)
+		rdma_user_mmap_entry_remove(usr_fifo->ci_entry);
+}
+
+static int user_fifo_mmap_entry_setup(struct hbl_ib_device *dev, struct hbl_ib_ucontext *hctx,
+				      struct hbl_usr_fifo *usr_fifo,
+				      struct hbl_uapi_usr_fifo_create_out *out)
+{
+	if (out->ci_handle) {
+		usr_fifo->ci_entry = hbl_ib_user_mmap_entry_insert(&hctx->ibucontext,
+								   out->ci_handle,
+								   PAGE_SIZE, &out->ci_handle);
+		if (IS_ERR(usr_fifo->ci_entry))
+			return PTR_ERR(usr_fifo->ci_entry);
+	}
+
+	usr_fifo->regs_entry = hbl_ib_user_mmap_entry_insert(&hctx->ibucontext, out->regs_handle,
+							     PAGE_SIZE, &out->regs_handle);
+	if (IS_ERR(usr_fifo->regs_entry))
+		goto err_free_ci;
+
+	return 0;
+
+err_free_ci:
+	if (usr_fifo->ci_entry)
+		rdma_user_mmap_entry_remove(usr_fifo->ci_entry);
+
+	return PTR_ERR(usr_fifo->regs_entry);
+}
+
+static int UVERBS_HANDLER(HBL_IB_METHOD_USR_FIFO_OBJ_CREATE)(struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_cni_alloc_user_db_fifo_out alloc_db_fifo_out = {};
+	struct hbl_cni_alloc_user_db_fifo_in alloc_db_fifo_in = {};
+	struct hbl_cni_user_db_fifo_unset_in db_fifo_unset_in = {};
+	struct hbl_cni_user_db_fifo_set_out db_fifo_set_out = {};
+	struct hbl_cni_user_db_fifo_set_in db_fifo_set_in = {};
+	struct hbl_uapi_usr_fifo_create_out out = {};
+	struct hbl_uapi_usr_fifo_create_in in = {};
+	struct hbl_usr_fifo *usr_fifo_pdata;
+	struct hbl_ib_aux_ops *aux_ops;
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_aux_dev *aux_dev;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	struct ib_uobject *uobj;
+	u32 port, id;
+	u8 mode;
+	int rc;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	uobj = uverbs_attr_get_uobject(attrs, HBL_IB_ATTR_USR_FIFO_CREATE_HANDLE);
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+	aux_dev = hdev->aux_dev;
+	aux_ops = aux_dev->aux_ops;
+
+	rc = uverbs_copy_from(&in, attrs, HBL_IB_ATTR_USR_FIFO_CREATE_IN);
+	if (rc)
+		return rc;
+
+	rc = ib_to_hbl_port_num(hdev, in.port_num, &port);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "invalid IB port %u\n", in.port_num);
+		return rc;
+	}
+
+	if (!(hctx->ports_mask & BIT(port))) {
+		hbl_ibdev_dbg(ibdev, "port %d is not part of the context's ports mask 0x%llx\n",
+			      port, hctx->ports_mask);
+		return -EINVAL;
+	}
+
+	usr_fifo_pdata = kzalloc(sizeof(*usr_fifo_pdata), GFP_KERNEL);
+	if (!usr_fifo_pdata)
+		return -ENOMEM;
+
+	mode = in.mode;
+
+	alloc_db_fifo_in.port = port;
+	alloc_db_fifo_in.id_hint = in.usr_fifo_num_hint;
+
+	rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_ALLOC_USER_DB_FIFO,
+			       &alloc_db_fifo_in, &alloc_db_fifo_out);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "failed to alloc db fifo, port %d\n", port);
+		goto err_free_pdata;
+	}
+
+	id = alloc_db_fifo_out.id;
+
+	usr_fifo_pdata->port = port;
+	usr_fifo_pdata->id = id;
+
+	db_fifo_set_in.port = port;
+	db_fifo_set_in.id = id;
+	db_fifo_set_in.mode = mode;
+
+	rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_DB_FIFO_SET, &db_fifo_set_in,
+			       &db_fifo_set_out);
+	if (rc) {
+		hbl_ibdev_dbg(ibdev, "failed to set db fifo %d, port %d\n", id, port);
+		goto err_usr_fifo_unset;
+	}
+
+	out.usr_fifo_num = id;
+	out.ci_handle = db_fifo_set_out.ci_handle;
+	out.regs_handle = db_fifo_set_out.regs_handle;
+	out.regs_offset = db_fifo_set_out.regs_offset;
+	out.size = db_fifo_set_out.fifo_size;
+	out.bp_thresh = db_fifo_set_out.fifo_bp_thresh;
+
+	rc = user_fifo_mmap_entry_setup(hdev, hctx, usr_fifo_pdata, &out);
+	if (rc)
+		goto err_usr_fifo_unset;
+
+	uobj->object = usr_fifo_pdata;
+
+	rc = uverbs_copy_to_struct_or_zero(attrs, HBL_IB_ATTR_USR_FIFO_CREATE_OUT, &out,
+					   sizeof(out));
+	if (rc)
+		goto err_remove_mmap_entries;
+
+	return 0;
+
+err_remove_mmap_entries:
+	user_fifo_mmap_entry_remove(usr_fifo_pdata);
+
+err_usr_fifo_unset:
+	db_fifo_unset_in.port = port;
+	db_fifo_unset_in.id = id;
+
+	if (aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_DB_FIFO_UNSET,
+			      &db_fifo_unset_in, NULL))
+		hbl_ibdev_dbg(ibdev, "failed to unset db fifo %d, port %d\n", id, port);
+
+err_free_pdata:
+	kfree(usr_fifo_pdata);
+	return rc;
+}
+
+static int hbl_free_usr_fifo(struct ib_uobject *uobject, enum rdma_remove_reason why,
+			     struct uverbs_attr_bundle *attrs)
+{
+	struct hbl_cni_user_db_fifo_unset_in db_fifo_unset_in = {};
+	struct hbl_usr_fifo *usr_fifo_pdata;
+	struct hbl_ib_aux_ops *aux_ops;
+	struct hbl_ib_ucontext *hctx;
+	struct hbl_aux_dev *aux_dev;
+	struct hbl_ib_device *hdev;
+	struct ib_device *ibdev;
+	int rc;
+
+	hctx = to_hbl_ib_ucontext(ib_uverbs_get_ucontext(attrs));
+	if (IS_ERR(hctx))
+		return PTR_ERR(hctx);
+
+	usr_fifo_pdata = uobject->object;
+	hdev = to_hbl_ib_dev(hctx->ibucontext.device);
+	ibdev = &hdev->ibdev;
+	aux_dev = hdev->aux_dev;
+	aux_ops = aux_dev->aux_ops;
+
+	db_fifo_unset_in.port = usr_fifo_pdata->port;
+	db_fifo_unset_in.id = usr_fifo_pdata->id;
+
+	user_fifo_mmap_entry_remove(usr_fifo_pdata);
+
+	if (aux_ops->device_operational(aux_dev)) {
+		rc = aux_ops->cmd_ctrl(aux_dev, hctx->cn_ctx, HBL_CNI_OP_USER_DB_FIFO_UNSET,
+				       &db_fifo_unset_in, NULL);
+		if (rc) {
+			hbl_ibdev_dbg(ibdev, "failed to unset db fifo %d, port %d\n",
+				      usr_fifo_pdata->id, usr_fifo_pdata->port);
+			return rc;
+		}
+	}
+
+	kfree(usr_fifo_pdata);
+
+	return 0;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+	HBL_IB_METHOD_USR_FIFO_OBJ_CREATE,
+	UVERBS_ATTR_IDR(HBL_IB_ATTR_USR_FIFO_CREATE_HANDLE,
+			HBL_IB_OBJECT_USR_FIFO,
+			UVERBS_ACCESS_NEW,
+			UA_MANDATORY),
+	UVERBS_ATTR_PTR_IN(HBL_IB_ATTR_USR_FIFO_CREATE_IN,
+			   UVERBS_ATTR_STRUCT(struct hbl_uapi_usr_fifo_create_in, reserved3),
+			   UA_MANDATORY),
+	UVERBS_ATTR_PTR_OUT(HBL_IB_ATTR_USR_FIFO_CREATE_OUT,
+			    UVERBS_ATTR_STRUCT(struct hbl_uapi_usr_fifo_create_out, bp_thresh),
+			    UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_METHOD_DESTROY(
+	HBL_IB_METHOD_USR_FIFO_OBJ_DESTROY,
+	UVERBS_ATTR_IDR(HBL_IB_ATTR_USR_FIFO_DESTROY_HANDLE,
+			HBL_IB_OBJECT_USR_FIFO,
+			UVERBS_ACCESS_DESTROY,
+			UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(HBL_IB_OBJECT_USR_FIFO,
+			    UVERBS_TYPE_ALLOC_IDR(hbl_free_usr_fifo),
+			    &UVERBS_METHOD(HBL_IB_METHOD_USR_FIFO_OBJ_CREATE),
+			    &UVERBS_METHOD(HBL_IB_METHOD_USR_FIFO_OBJ_DESTROY));
+
+const struct uapi_definition hbl_usr_fifo_defs[] = {
+	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(HBL_IB_OBJECT_USR_FIFO),
+	{},
+};