Skip to content

Commit e088a68

Browse files
Yixian Liudledford
authored andcommitted
RDMA/hns: Support rq record doorbell for the user space
This patch adds interfaces and definitions to support the rq record doorbell for the user space. Signed-off-by: Yixian Liu <[email protected]> Signed-off-by: Lijun Ou <[email protected]> Signed-off-by: Wei Hu (Xavier) <[email protected]> Signed-off-by: Shaobo Xu <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 036ef0a commit e088a68

File tree

7 files changed

+200
-5
lines changed

7 files changed

+200
-5
lines changed

drivers/infiniband/hw/hns/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
77
obj-$(CONFIG_INFINIBAND_HNS) += hns-roce.o
88
hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
99
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
10-
hns_roce_cq.o hns_roce_alloc.o
10+
hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o
1111
obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
1212
hns-roce-hw-v1-objs := hns_roce_hw_v1.o
1313
obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
2+
/*
3+
* Copyright (c) 2017 Hisilicon Limited.
4+
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
5+
*/
6+
7+
#include <linux/platform_device.h>
8+
#include <rdma/ib_umem.h>
9+
#include "hns_roce_device.h"
10+
11+
int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
12+
struct hns_roce_db *db)
13+
{
14+
struct hns_roce_user_db_page *page;
15+
int ret = 0;
16+
17+
mutex_lock(&context->page_mutex);
18+
19+
list_for_each_entry(page, &context->page_list, list)
20+
if (page->user_virt == (virt & PAGE_MASK))
21+
goto found;
22+
23+
page = kmalloc(sizeof(*page), GFP_KERNEL);
24+
if (!page) {
25+
ret = -ENOMEM;
26+
goto out;
27+
}
28+
29+
refcount_set(&page->refcount, 1);
30+
page->user_virt = (virt & PAGE_MASK);
31+
page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK,
32+
PAGE_SIZE, 0, 0);
33+
if (IS_ERR(page->umem)) {
34+
ret = PTR_ERR(page->umem);
35+
kfree(page);
36+
goto out;
37+
}
38+
39+
list_add(&page->list, &context->page_list);
40+
41+
found:
42+
db->dma = sg_dma_address(page->umem->sg_head.sgl) +
43+
(virt & ~PAGE_MASK);
44+
db->u.user_page = page;
45+
refcount_inc(&page->refcount);
46+
47+
out:
48+
mutex_unlock(&context->page_mutex);
49+
50+
return ret;
51+
}
52+
EXPORT_SYMBOL(hns_roce_db_map_user);
53+
54+
void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
55+
struct hns_roce_db *db)
56+
{
57+
mutex_lock(&context->page_mutex);
58+
59+
refcount_dec(&db->u.user_page->refcount);
60+
if (refcount_dec_if_one(&db->u.user_page->refcount)) {
61+
list_del(&db->u.user_page->list);
62+
ib_umem_release(db->u.user_page->umem);
63+
kfree(db->u.user_page);
64+
}
65+
66+
mutex_unlock(&context->page_mutex);
67+
}
68+
EXPORT_SYMBOL(hns_roce_db_unmap_user);

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@
105105
#define PAGES_SHIFT_24 24
106106
#define PAGES_SHIFT_32 32
107107

108+
enum {
109+
HNS_ROCE_SUPPORT_RQ_RECORD_DB = 1 << 0,
110+
};
111+
108112
enum hns_roce_qp_state {
109113
HNS_ROCE_QP_STATE_RST,
110114
HNS_ROCE_QP_STATE_INIT,
@@ -178,14 +182,19 @@ enum {
178182
enum {
179183
HNS_ROCE_CAP_FLAG_REREG_MR = BIT(0),
180184
HNS_ROCE_CAP_FLAG_ROCE_V1_V2 = BIT(1),
181-
HNS_ROCE_CAP_FLAG_RQ_INLINE = BIT(2)
185+
HNS_ROCE_CAP_FLAG_RQ_INLINE = BIT(2),
186+
HNS_ROCE_CAP_FLAG_RECORD_DB = BIT(3)
182187
};
183188

184189
enum hns_roce_mtt_type {
185190
MTT_TYPE_WQE,
186191
MTT_TYPE_CQE,
187192
};
188193

194+
enum {
195+
HNS_ROCE_DB_PER_PAGE = PAGE_SIZE / 4
196+
};
197+
189198
#define HNS_ROCE_CMD_SUCCESS 1
190199

191200
#define HNS_ROCE_PORT_DOWN 0
@@ -203,6 +212,8 @@ struct hns_roce_uar {
203212
struct hns_roce_ucontext {
204213
struct ib_ucontext ibucontext;
205214
struct hns_roce_uar uar;
215+
struct list_head page_list;
216+
struct mutex page_mutex;
206217
};
207218

208219
struct hns_roce_pd {
@@ -335,6 +346,33 @@ struct hns_roce_buf {
335346
int page_shift;
336347
};
337348

349+
struct hns_roce_db_pgdir {
350+
struct list_head list;
351+
DECLARE_BITMAP(order0, HNS_ROCE_DB_PER_PAGE);
352+
DECLARE_BITMAP(order1, HNS_ROCE_DB_PER_PAGE / 2);
353+
unsigned long *bits[2];
354+
u32 *page;
355+
dma_addr_t db_dma;
356+
};
357+
358+
struct hns_roce_user_db_page {
359+
struct list_head list;
360+
struct ib_umem *umem;
361+
unsigned long user_virt;
362+
refcount_t refcount;
363+
};
364+
365+
struct hns_roce_db {
366+
u32 *db_record;
367+
union {
368+
struct hns_roce_db_pgdir *pgdir;
369+
struct hns_roce_user_db_page *user_page;
370+
} u;
371+
dma_addr_t dma;
372+
int index;
373+
int order;
374+
};
375+
338376
struct hns_roce_cq_buf {
339377
struct hns_roce_buf hr_buf;
340378
struct hns_roce_mtt hr_mtt;
@@ -466,6 +504,8 @@ struct hns_roce_qp {
466504
struct ib_qp ibqp;
467505
struct hns_roce_buf hr_buf;
468506
struct hns_roce_wq rq;
507+
struct hns_roce_db rdb;
508+
u8 rdb_en;
469509
u32 doorbell_qpn;
470510
__le32 sq_signal_bits;
471511
u32 sq_next_wqe;
@@ -930,6 +970,10 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
930970
int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq);
931971
void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq);
932972

973+
int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
974+
struct hns_roce_db *db);
975+
void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
976+
struct hns_roce_db *db);
933977
void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
934978
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
935979
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1168,7 +1168,8 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
11681168

11691169
caps->flags = HNS_ROCE_CAP_FLAG_REREG_MR |
11701170
HNS_ROCE_CAP_FLAG_ROCE_V1_V2 |
1171-
HNS_ROCE_CAP_FLAG_RQ_INLINE;
1171+
HNS_ROCE_CAP_FLAG_RQ_INLINE |
1172+
HNS_ROCE_CAP_FLAG_RECORD_DB;
11721173
caps->pkey_table_len[0] = 1;
11731174
caps->gid_table_len[0] = HNS_ROCE_V2_GID_INDEX_NUM;
11741175
caps->ceqe_depth = HNS_ROCE_V2_COMP_EQE_NUM;
@@ -2274,6 +2275,23 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp,
22742275
hr_qp->qkey = attr->qkey;
22752276
}
22762277

2278+
if (hr_qp->rdb_en) {
2279+
roce_set_bit(context->byte_68_rq_db,
2280+
V2_QPC_BYTE_68_RQ_RECORD_EN_S, 1);
2281+
roce_set_bit(qpc_mask->byte_68_rq_db,
2282+
V2_QPC_BYTE_68_RQ_RECORD_EN_S, 0);
2283+
}
2284+
2285+
roce_set_field(context->byte_68_rq_db,
2286+
V2_QPC_BYTE_68_RQ_DB_RECORD_ADDR_M,
2287+
V2_QPC_BYTE_68_RQ_DB_RECORD_ADDR_S,
2288+
((u32)hr_qp->rdb.dma) >> 1);
2289+
roce_set_field(qpc_mask->byte_68_rq_db,
2290+
V2_QPC_BYTE_68_RQ_DB_RECORD_ADDR_M,
2291+
V2_QPC_BYTE_68_RQ_DB_RECORD_ADDR_S, 0);
2292+
context->rq_db_record_addr = hr_qp->rdb.dma >> 32;
2293+
qpc_mask->rq_db_record_addr = 0;
2294+
22772295
roce_set_bit(context->byte_76_srqn_op_en, V2_QPC_BYTE_76_RQIE_S, 1);
22782296
roce_set_bit(qpc_mask->byte_76_srqn_op_en, V2_QPC_BYTE_76_RQIE_S, 0);
22792297

@@ -3211,6 +3229,8 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
32113229
hr_qp->sq.tail = 0;
32123230
hr_qp->sq_next_wqe = 0;
32133231
hr_qp->next_sge = 0;
3232+
if (hr_qp->rq.wqe_cnt)
3233+
*hr_qp->rdb.db_record = 0;
32143234
}
32153235

32163236
out:
@@ -3437,6 +3457,10 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
34373457
hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);
34383458

34393459
if (is_user) {
3460+
if (hr_qp->rq.wqe_cnt && (hr_qp->rdb_en == 1))
3461+
hns_roce_db_unmap_user(
3462+
to_hr_ucontext(hr_qp->ibqp.uobject->context),
3463+
&hr_qp->rdb);
34403464
ib_umem_release(hr_qp->umem);
34413465
} else {
34423466
kfree(hr_qp->sq.wrid);

drivers/infiniband/hw/hns/hns_roce_main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ static struct ib_ucontext *hns_roce_alloc_ucontext(struct ib_device *ib_dev,
351351
if (ret)
352352
goto error_fail_uar_alloc;
353353

354+
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) {
355+
INIT_LIST_HEAD(&context->page_list);
356+
mutex_init(&context->page_mutex);
357+
}
358+
354359
ret = ib_copy_to_udata(udata, &resp, sizeof(resp));
355360
if (ret)
356361
goto error_fail_copy_to_udata;

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,15 @@ static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,
489489
return 0;
490490
}
491491

492+
static int hns_roce_qp_has_rq(struct ib_qp_init_attr *attr)
493+
{
494+
if (attr->qp_type == IB_QPT_XRC_INI ||
495+
attr->qp_type == IB_QPT_XRC_TGT || attr->srq)
496+
return 0;
497+
498+
return 1;
499+
}
500+
492501
static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
493502
struct ib_pd *ib_pd,
494503
struct ib_qp_init_attr *init_attr,
@@ -497,6 +506,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
497506
{
498507
struct device *dev = hr_dev->dev;
499508
struct hns_roce_ib_create_qp ucmd;
509+
struct hns_roce_ib_create_qp_resp resp;
500510
unsigned long qpn = 0;
501511
int ret = 0;
502512
u32 page_shift;
@@ -602,6 +612,18 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
602612
dev_err(dev, "hns_roce_ib_umem_write_mtt error for create qp\n");
603613
goto err_mtt;
604614
}
615+
616+
if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
617+
(udata->outlen == sizeof(resp)) &&
618+
hns_roce_qp_has_rq(init_attr)) {
619+
ret = hns_roce_db_map_user(
620+
to_hr_ucontext(ib_pd->uobject->context),
621+
ucmd.db_addr, &hr_qp->rdb);
622+
if (ret) {
623+
dev_err(dev, "rp record doorbell map failed!\n");
624+
goto err_mtt;
625+
}
626+
}
605627
} else {
606628
if (init_attr->create_flags &
607629
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
@@ -698,17 +720,44 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
698720
else
699721
hr_qp->doorbell_qpn = cpu_to_le64(hr_qp->qpn);
700722

723+
if (ib_pd->uobject && (udata->outlen == sizeof(resp)) &&
724+
(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB)) {
725+
726+
/* indicate kernel supports record db */
727+
resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB;
728+
ret = ib_copy_to_udata(udata, &resp, sizeof(resp));
729+
if (ret)
730+
goto err_qp;
731+
732+
hr_qp->rdb_en = 1;
733+
}
701734
hr_qp->event = hns_roce_ib_qp_event;
702735

703736
return 0;
704737

738+
err_qp:
739+
if (init_attr->qp_type == IB_QPT_GSI &&
740+
hr_dev->hw_rev == HNS_ROCE_HW_VER1)
741+
hns_roce_qp_remove(hr_dev, hr_qp);
742+
else
743+
hns_roce_qp_free(hr_dev, hr_qp);
744+
705745
err_qpn:
706746
if (!sqpn)
707747
hns_roce_release_range_qp(hr_dev, qpn, 1);
708748

709749
err_wrid:
710-
kfree(hr_qp->sq.wrid);
711-
kfree(hr_qp->rq.wrid);
750+
if (ib_pd->uobject) {
751+
if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
752+
(udata->outlen == sizeof(resp)) &&
753+
hns_roce_qp_has_rq(init_attr))
754+
hns_roce_db_unmap_user(
755+
to_hr_ucontext(ib_pd->uobject->context),
756+
&hr_qp->rdb);
757+
} else {
758+
kfree(hr_qp->sq.wrid);
759+
kfree(hr_qp->rq.wrid);
760+
}
712761

713762
err_mtt:
714763
hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);

include/uapi/rdma/hns-abi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ struct hns_roce_ib_create_qp {
4949
__u8 reserved[5];
5050
};
5151

52+
struct hns_roce_ib_create_qp_resp {
53+
__u64 cap_flags;
54+
};
55+
5256
struct hns_roce_ib_alloc_ucontext_resp {
5357
__u32 qp_tab_size;
58+
__u32 reserved;
5459
};
5560
#endif /* HNS_ABI_USER_H */

0 commit comments

Comments
 (0)