Skip to content

Commit 472bc0f

Browse files
Yixian Liudledford
authored andcommitted
RDMA/hns: Support rq record doorbell for kernel space
This patch updates to support rq record doorbell for the kernel 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 9b44703 commit 472bc0f

File tree

5 files changed

+142
-13
lines changed

5 files changed

+142
-13
lines changed

drivers/infiniband/hw/hns/hns_roce_db.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,115 @@ void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
6666
mutex_unlock(&context->page_mutex);
6767
}
6868
EXPORT_SYMBOL(hns_roce_db_unmap_user);
69+
70+
static struct hns_roce_db_pgdir *hns_roce_alloc_db_pgdir(
71+
struct device *dma_device)
72+
{
73+
struct hns_roce_db_pgdir *pgdir;
74+
75+
pgdir = kzalloc(sizeof(*pgdir), GFP_KERNEL);
76+
if (!pgdir)
77+
return NULL;
78+
79+
bitmap_fill(pgdir->order1, HNS_ROCE_DB_PER_PAGE / 2);
80+
pgdir->bits[0] = pgdir->order0;
81+
pgdir->bits[1] = pgdir->order1;
82+
pgdir->page = dma_alloc_coherent(dma_device, PAGE_SIZE,
83+
&pgdir->db_dma, GFP_KERNEL);
84+
if (!pgdir->page) {
85+
kfree(pgdir);
86+
return NULL;
87+
}
88+
89+
return pgdir;
90+
}
91+
92+
static int hns_roce_alloc_db_from_pgdir(struct hns_roce_db_pgdir *pgdir,
93+
struct hns_roce_db *db, int order)
94+
{
95+
int o;
96+
int i;
97+
98+
for (o = order; o <= 1; ++o) {
99+
i = find_first_bit(pgdir->bits[o], HNS_ROCE_DB_PER_PAGE >> o);
100+
if (i < HNS_ROCE_DB_PER_PAGE >> o)
101+
goto found;
102+
}
103+
104+
return -ENOMEM;
105+
106+
found:
107+
clear_bit(i, pgdir->bits[o]);
108+
109+
i <<= o;
110+
111+
if (o > order)
112+
set_bit(i ^ 1, pgdir->bits[order]);
113+
114+
db->u.pgdir = pgdir;
115+
db->index = i;
116+
db->db_record = pgdir->page + db->index;
117+
db->dma = pgdir->db_dma + db->index * 4;
118+
db->order = order;
119+
120+
return 0;
121+
}
122+
123+
int hns_roce_alloc_db(struct hns_roce_dev *hr_dev, struct hns_roce_db *db,
124+
int order)
125+
{
126+
struct hns_roce_db_pgdir *pgdir;
127+
int ret = 0;
128+
129+
mutex_lock(&hr_dev->pgdir_mutex);
130+
131+
list_for_each_entry(pgdir, &hr_dev->pgdir_list, list)
132+
if (!hns_roce_alloc_db_from_pgdir(pgdir, db, order))
133+
goto out;
134+
135+
pgdir = hns_roce_alloc_db_pgdir(hr_dev->dev);
136+
if (!pgdir) {
137+
ret = -ENOMEM;
138+
goto out;
139+
}
140+
141+
list_add(&pgdir->list, &hr_dev->pgdir_list);
142+
143+
/* This should never fail -- we just allocated an empty page: */
144+
WARN_ON(hns_roce_alloc_db_from_pgdir(pgdir, db, order));
145+
146+
out:
147+
mutex_unlock(&hr_dev->pgdir_mutex);
148+
149+
return ret;
150+
}
151+
EXPORT_SYMBOL_GPL(hns_roce_alloc_db);
152+
153+
void hns_roce_free_db(struct hns_roce_dev *hr_dev, struct hns_roce_db *db)
154+
{
155+
int o;
156+
int i;
157+
158+
mutex_lock(&hr_dev->pgdir_mutex);
159+
160+
o = db->order;
161+
i = db->index;
162+
163+
if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
164+
clear_bit(i ^ 1, db->u.pgdir->order0);
165+
++o;
166+
}
167+
168+
i >>= o;
169+
set_bit(i, db->u.pgdir->bits[o]);
170+
171+
if (bitmap_full(db->u.pgdir->order1, HNS_ROCE_DB_PER_PAGE / 2)) {
172+
dma_free_coherent(hr_dev->dev, PAGE_SIZE, db->u.pgdir->page,
173+
db->u.pgdir->db_dma);
174+
list_del(&db->u.pgdir->list);
175+
kfree(db->u.pgdir);
176+
}
177+
178+
mutex_unlock(&hr_dev->pgdir_mutex);
179+
}
180+
EXPORT_SYMBOL_GPL(hns_roce_free_db);

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@ struct hns_roce_dev {
771771
spinlock_t bt_cmd_lock;
772772
struct hns_roce_ib_iboe iboe;
773773

774+
struct list_head pgdir_list;
775+
struct mutex pgdir_mutex;
774776
int irq[HNS_ROCE_MAX_IRQ_NUM];
775777
u8 __iomem *reg_base;
776778
struct hns_roce_caps caps;
@@ -980,6 +982,10 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
980982
struct hns_roce_db *db);
981983
void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
982984
struct hns_roce_db *db);
985+
int hns_roce_alloc_db(struct hns_roce_dev *hr_dev, struct hns_roce_db *db,
986+
int order);
987+
void hns_roce_free_db(struct hns_roce_dev *hr_dev, struct hns_roce_db *db);
988+
983989
void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
984990
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
985991
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: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
498498
struct hns_roce_v2_wqe_data_seg *dseg;
499499
struct hns_roce_rinl_sge *sge_list;
500500
struct device *dev = hr_dev->dev;
501-
struct hns_roce_v2_db rq_db;
502501
unsigned long flags;
503502
void *wqe = NULL;
504503
int ret = 0;
@@ -564,17 +563,7 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
564563
/* Memory barrier */
565564
wmb();
566565

567-
rq_db.byte_4 = 0;
568-
rq_db.parameter = 0;
569-
570-
roce_set_field(rq_db.byte_4, V2_DB_BYTE_4_TAG_M,
571-
V2_DB_BYTE_4_TAG_S, hr_qp->qpn);
572-
roce_set_field(rq_db.byte_4, V2_DB_BYTE_4_CMD_M,
573-
V2_DB_BYTE_4_CMD_S, HNS_ROCE_V2_RQ_DB);
574-
roce_set_field(rq_db.parameter, V2_DB_PARAMETER_CONS_IDX_M,
575-
V2_DB_PARAMETER_CONS_IDX_S, hr_qp->rq.head);
576-
577-
hns_roce_write64_k((__le32 *)&rq_db, hr_qp->rq.db_reg_l);
566+
*hr_qp->rdb.db_record = hr_qp->rq.head & 0xffff;
578567
}
579568
spin_unlock_irqrestore(&hr_qp->rq.lock, flags);
580569

@@ -3476,6 +3465,8 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
34763465
kfree(hr_qp->sq.wrid);
34773466
kfree(hr_qp->rq.wrid);
34783467
hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
3468+
if (hr_qp->rq.wqe_cnt)
3469+
hns_roce_free_db(hr_dev, &hr_qp->rdb);
34793470
}
34803471

34813472
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) {

drivers/infiniband/hw/hns/hns_roce_main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,11 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
665665
spin_lock_init(&hr_dev->sm_lock);
666666
spin_lock_init(&hr_dev->bt_cmd_lock);
667667

668+
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) {
669+
INIT_LIST_HEAD(&hr_dev->pgdir_list);
670+
mutex_init(&hr_dev->pgdir_mutex);
671+
}
672+
668673
ret = hns_roce_init_uar_table(hr_dev);
669674
if (ret) {
670675
dev_err(dev, "Failed to initialize uar table. aborting\n");

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,14 +652,24 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
652652
hr_qp->rq.db_reg_l = hr_dev->reg_base + hr_dev->odb_offset +
653653
DB_REG_OFFSET * hr_dev->priv_uar.index;
654654

655+
if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
656+
hns_roce_qp_has_rq(init_attr)) {
657+
ret = hns_roce_alloc_db(hr_dev, &hr_qp->rdb, 0);
658+
if (ret) {
659+
dev_err(dev, "rq record doorbell alloc failed!\n");
660+
goto err_rq_sge_list;
661+
}
662+
*hr_qp->rdb.db_record = 0;
663+
}
664+
655665
/* Allocate QP buf */
656666
page_shift = PAGE_SHIFT + hr_dev->caps.mtt_buf_pg_sz;
657667
if (hns_roce_buf_alloc(hr_dev, hr_qp->buff_size,
658668
(1 << page_shift) * 2,
659669
&hr_qp->hr_buf, page_shift)) {
660670
dev_err(dev, "hns_roce_buf_alloc error!\n");
661671
ret = -ENOMEM;
662-
goto err_rq_sge_list;
672+
goto err_db;
663673
}
664674

665675
hr_qp->mtt.mtt_type = MTT_TYPE_WQE;
@@ -768,6 +778,11 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
768778
else
769779
hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
770780

781+
err_db:
782+
if (!ib_pd->uobject && hns_roce_qp_has_rq(init_attr) &&
783+
(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB))
784+
hns_roce_free_db(hr_dev, &hr_qp->rdb);
785+
771786
err_rq_sge_list:
772787
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE)
773788
kfree(hr_qp->rq_inl_buf.wqe_list[0].sg_list);

0 commit comments

Comments
 (0)