Skip to content

Commit 9fb3dd8

Browse files
mrgolinrleon
authored andcommitted
RDMA/efa: Add CQ with external memory support
Add an option to create CQ using external memory instead of allocating in the driver. The memory can be passed from userspace by dmabuf fd and an offset or a VA. One of the possible usages is creating CQs that reside in accelerator memory, allowing low latency asynchronous direct polling from the accelerator device. Add a capability bit to reflect on the feature support. Reviewed-by: Daniel Kranzdorf <[email protected]> Reviewed-by: Yonatan Nachum <[email protected]> Signed-off-by: Michael Margolin <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]>
1 parent c897c2c commit 9fb3dd8

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

drivers/infiniband/hw/efa/efa.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct efa_cq {
107107
u16 cq_idx;
108108
/* NULL when no interrupts requested */
109109
struct efa_eq *eq;
110+
struct ib_umem *umem;
110111
};
111112

112113
struct efa_qp {
@@ -162,6 +163,8 @@ int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
162163
int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
163164
int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
164165
struct uverbs_attr_bundle *attrs);
166+
int efa_create_cq_umem(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
167+
struct ib_umem *umem, struct uverbs_attr_bundle *attrs);
165168
struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
166169
u64 virt_addr, int access_flags,
167170
struct ib_udata *udata);

drivers/infiniband/hw/efa/efa_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ static const struct ib_device_ops efa_dev_ops = {
372372
.alloc_pd = efa_alloc_pd,
373373
.alloc_ucontext = efa_alloc_ucontext,
374374
.create_cq = efa_create_cq,
375+
.create_cq_umem = efa_create_cq_umem,
375376
.create_qp = efa_create_qp,
376377
.create_user_ah = efa_create_ah,
377378
.dealloc_pd = efa_dealloc_pd,

drivers/infiniband/hw/efa/efa_verbs.c

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ int efa_query_device(struct ib_device *ibdev,
254254
resp.max_rdma_size = dev_attr->max_rdma_size;
255255

256256
resp.device_caps |= EFA_QUERY_DEVICE_CAPS_CQ_WITH_SGID;
257+
resp.device_caps |= EFA_QUERY_DEVICE_CAPS_CQ_WITH_EXT_MEM;
257258
if (EFA_DEV_CAP(dev, RDMA_READ))
258259
resp.device_caps |= EFA_QUERY_DEVICE_CAPS_RDMA_READ;
259260

@@ -1087,8 +1088,11 @@ int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
10871088
xa_erase(&dev->cqs_xa, cq->cq_idx);
10881089
synchronize_irq(cq->eq->irq.irqn);
10891090
}
1090-
efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size,
1091-
DMA_FROM_DEVICE);
1091+
1092+
if (cq->umem)
1093+
ib_umem_release(cq->umem);
1094+
else
1095+
efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size, DMA_FROM_DEVICE);
10921096
return 0;
10931097
}
10941098

@@ -1127,8 +1131,8 @@ static int cq_mmap_entries_setup(struct efa_dev *dev, struct efa_cq *cq,
11271131
return 0;
11281132
}
11291133

1130-
int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
1131-
struct uverbs_attr_bundle *attrs)
1134+
int efa_create_cq_umem(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
1135+
struct ib_umem *umem, struct uverbs_attr_bundle *attrs)
11321136
{
11331137
struct ib_udata *udata = &attrs->driver_udata;
11341138
struct efa_ucontext *ucontext = rdma_udata_to_drv_context(
@@ -1207,11 +1211,30 @@ int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
12071211

12081212
cq->ucontext = ucontext;
12091213
cq->size = PAGE_ALIGN(cmd.cq_entry_size * entries * cmd.num_sub_cqs);
1210-
cq->cpu_addr = efa_zalloc_mapped(dev, &cq->dma_addr, cq->size,
1211-
DMA_FROM_DEVICE);
1212-
if (!cq->cpu_addr) {
1213-
err = -ENOMEM;
1214-
goto err_out;
1214+
1215+
if (umem) {
1216+
if (umem->length < cq->size) {
1217+
ibdev_dbg(&dev->ibdev, "External memory too small\n");
1218+
err = -EINVAL;
1219+
goto err_free_mem;
1220+
}
1221+
1222+
if (!ib_umem_is_contiguous(umem)) {
1223+
ibdev_dbg(&dev->ibdev, "Non contiguous CQ unsupported\n");
1224+
err = -EINVAL;
1225+
goto err_free_mem;
1226+
}
1227+
1228+
cq->cpu_addr = NULL;
1229+
cq->dma_addr = ib_umem_start_dma_addr(umem);
1230+
cq->umem = umem;
1231+
} else {
1232+
cq->cpu_addr = efa_zalloc_mapped(dev, &cq->dma_addr, cq->size,
1233+
DMA_FROM_DEVICE);
1234+
if (!cq->cpu_addr) {
1235+
err = -ENOMEM;
1236+
goto err_out;
1237+
}
12151238
}
12161239

12171240
params.uarn = cq->ucontext->uarn;
@@ -1228,15 +1251,17 @@ int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
12281251

12291252
err = efa_com_create_cq(&dev->edev, &params, &result);
12301253
if (err)
1231-
goto err_free_mapped;
1254+
goto err_free_mem;
12321255

12331256
resp.db_off = result.db_off;
12341257
resp.cq_idx = result.cq_idx;
12351258
cq->cq_idx = result.cq_idx;
12361259
cq->ibcq.cqe = result.actual_depth;
12371260
WARN_ON_ONCE(entries != result.actual_depth);
12381261

1239-
err = cq_mmap_entries_setup(dev, cq, &resp, result.db_valid);
1262+
if (!umem)
1263+
err = cq_mmap_entries_setup(dev, cq, &resp, result.db_valid);
1264+
12401265
if (err) {
12411266
ibdev_dbg(ibdev, "Could not setup cq[%u] mmap entries\n",
12421267
cq->cq_idx);
@@ -1274,15 +1299,23 @@ int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
12741299
efa_cq_user_mmap_entries_remove(cq);
12751300
err_destroy_cq:
12761301
efa_destroy_cq_idx(dev, cq->cq_idx);
1277-
err_free_mapped:
1278-
efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size,
1279-
DMA_FROM_DEVICE);
1302+
err_free_mem:
1303+
if (umem)
1304+
ib_umem_release(umem);
1305+
else
1306+
efa_free_mapped(dev, cq->cpu_addr, cq->dma_addr, cq->size, DMA_FROM_DEVICE);
12801307

12811308
err_out:
12821309
atomic64_inc(&dev->stats.create_cq_err);
12831310
return err;
12841311
}
12851312

1313+
int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
1314+
struct uverbs_attr_bundle *attrs)
1315+
{
1316+
return efa_create_cq_umem(ibcq, attr, NULL, attrs);
1317+
}
1318+
12861319
static int umem_to_page_list(struct efa_dev *dev,
12871320
struct ib_umem *umem,
12881321
u64 *page_list,

include/uapi/rdma/efa-abi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
22
/*
3-
* Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.
3+
* Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
44
*/
55

66
#ifndef EFA_ABI_USER_H
@@ -131,6 +131,7 @@ enum {
131131
EFA_QUERY_DEVICE_CAPS_DATA_POLLING_128 = 1 << 4,
132132
EFA_QUERY_DEVICE_CAPS_RDMA_WRITE = 1 << 5,
133133
EFA_QUERY_DEVICE_CAPS_UNSOLICITED_WRITE_RECV = 1 << 6,
134+
EFA_QUERY_DEVICE_CAPS_CQ_WITH_EXT_MEM = 1 << 7,
134135
};
135136

136137
struct efa_ibv_ex_query_device_resp {

0 commit comments

Comments
 (0)