Skip to content

Commit ccd9d0d

Browse files
selvintxavierdledford
authored andcommitted
RDMA/bnxt_re: Enable RoCE on virtual functions
RoCE can be used by virtual functions (VFs) as well. Adding code changes to allow resource reservation, initialization and avail the resources to the RDMA applications running on those VFs. Currently, fifty percent of the total available resources are reserved for PF and remaining are equally divided among active VFs. Signed-off-by: Selvin Xavier <[email protected]> Signed-off-by: Devesh Sharma <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent f20d429 commit ccd9d0d

File tree

6 files changed

+182
-37
lines changed

6 files changed

+182
-37
lines changed

drivers/infiniband/hw/bnxt_re/bnxt_re.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@
5757
#define BNXT_RE_MAX_MRW_COUNT (64 * 1024)
5858
#define BNXT_RE_MAX_SRQC_COUNT (64 * 1024)
5959
#define BNXT_RE_MAX_CQ_COUNT (64 * 1024)
60+
#define BNXT_RE_MAX_MRW_COUNT_64K (64 * 1024)
61+
#define BNXT_RE_MAX_MRW_COUNT_256K (256 * 1024)
62+
63+
/* Number of MRs to reserve for PF, leaving remainder for VFs */
64+
#define BNXT_RE_RESVD_MR_FOR_PF (32 * 1024)
65+
#define BNXT_RE_MAX_GID_PER_VF 128
66+
67+
/*
68+
* Percentage of resources of each type reserved for PF.
69+
* Remaining resources are divided equally among VFs.
70+
* [0, 100]
71+
*/
72+
#define BNXT_RE_PCT_RSVD_FOR_PF 50
6073

6174
#define BNXT_RE_UD_QP_HW_STALL 0x400000
6275

@@ -145,6 +158,8 @@ struct bnxt_re_dev {
145158
struct bnxt_re_ah *sqp_ah;
146159
struct bnxt_re_sqp_entries sqp_tbl[1024];
147160
atomic_t nq_alloc_cnt;
161+
u32 is_virtfn;
162+
u32 num_vfs;
148163
};
149164

150165
#define to_bnxt_re_dev(ptr, member) \

drivers/infiniband/hw/bnxt_re/ib_verbs.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,10 +2295,14 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
22952295
/* Completion Queues */
22962296
int bnxt_re_destroy_cq(struct ib_cq *ib_cq)
22972297
{
2298-
struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
2299-
struct bnxt_re_dev *rdev = cq->rdev;
23002298
int rc;
2301-
struct bnxt_qplib_nq *nq = cq->qplib_cq.nq;
2299+
struct bnxt_re_cq *cq;
2300+
struct bnxt_qplib_nq *nq;
2301+
struct bnxt_re_dev *rdev;
2302+
2303+
cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
2304+
rdev = cq->rdev;
2305+
nq = cq->qplib_cq.nq;
23022306

23032307
rc = bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
23042308
if (rc) {
@@ -2308,12 +2312,11 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq)
23082312
if (!IS_ERR_OR_NULL(cq->umem))
23092313
ib_umem_release(cq->umem);
23102314

2311-
if (cq) {
2312-
kfree(cq->cql);
2313-
kfree(cq);
2314-
}
23152315
atomic_dec(&rdev->cq_count);
23162316
nq->budget--;
2317+
kfree(cq->cql);
2318+
kfree(cq);
2319+
23172320
return 0;
23182321
}
23192322

drivers/infiniband/hw/bnxt_re/main.c

Lines changed: 108 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,79 @@ static DEFINE_MUTEX(bnxt_re_dev_lock);
8080
static struct workqueue_struct *bnxt_re_wq;
8181
static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev, bool lock_wait);
8282

83+
/* SR-IOV helper functions */
84+
85+
static void bnxt_re_get_sriov_func_type(struct bnxt_re_dev *rdev)
86+
{
87+
struct bnxt *bp;
88+
89+
bp = netdev_priv(rdev->en_dev->net);
90+
if (BNXT_VF(bp))
91+
rdev->is_virtfn = 1;
92+
}
93+
94+
/* Set the maximum number of each resource that the driver actually wants
95+
* to allocate. This may be up to the maximum number the firmware has
96+
* reserved for the function. The driver may choose to allocate fewer
97+
* resources than the firmware maximum.
98+
*/
99+
static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev)
100+
{
101+
u32 vf_qps = 0, vf_srqs = 0, vf_cqs = 0, vf_mrws = 0, vf_gids = 0;
102+
u32 i;
103+
u32 vf_pct;
104+
u32 num_vfs;
105+
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
106+
107+
rdev->qplib_ctx.qpc_count = min_t(u32, BNXT_RE_MAX_QPC_COUNT,
108+
dev_attr->max_qp);
109+
110+
rdev->qplib_ctx.mrw_count = BNXT_RE_MAX_MRW_COUNT_256K;
111+
/* Use max_mr from fw since max_mrw does not get set */
112+
rdev->qplib_ctx.mrw_count = min_t(u32, rdev->qplib_ctx.mrw_count,
113+
dev_attr->max_mr);
114+
rdev->qplib_ctx.srqc_count = min_t(u32, BNXT_RE_MAX_SRQC_COUNT,
115+
dev_attr->max_srq);
116+
rdev->qplib_ctx.cq_count = min_t(u32, BNXT_RE_MAX_CQ_COUNT,
117+
dev_attr->max_cq);
118+
119+
for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
120+
rdev->qplib_ctx.tqm_count[i] =
121+
rdev->dev_attr.tqm_alloc_reqs[i];
122+
123+
if (rdev->num_vfs) {
124+
/*
125+
* Reserve a set of resources for the PF. Divide the remaining
126+
* resources among the VFs
127+
*/
128+
vf_pct = 100 - BNXT_RE_PCT_RSVD_FOR_PF;
129+
num_vfs = 100 * rdev->num_vfs;
130+
vf_qps = (rdev->qplib_ctx.qpc_count * vf_pct) / num_vfs;
131+
vf_srqs = (rdev->qplib_ctx.srqc_count * vf_pct) / num_vfs;
132+
vf_cqs = (rdev->qplib_ctx.cq_count * vf_pct) / num_vfs;
133+
/*
134+
* The driver allows many more MRs than other resources. If the
135+
* firmware does also, then reserve a fixed amount for the PF
136+
* and divide the rest among VFs. VFs may use many MRs for NFS
137+
* mounts, ISER, NVME applications, etc. If the firmware
138+
* severely restricts the number of MRs, then let PF have
139+
* half and divide the rest among VFs, as for the other
140+
* resource types.
141+
*/
142+
if (rdev->qplib_ctx.mrw_count < BNXT_RE_MAX_MRW_COUNT_64K)
143+
vf_mrws = rdev->qplib_ctx.mrw_count * vf_pct / num_vfs;
144+
else
145+
vf_mrws = (rdev->qplib_ctx.mrw_count -
146+
BNXT_RE_RESVD_MR_FOR_PF) / rdev->num_vfs;
147+
vf_gids = BNXT_RE_MAX_GID_PER_VF;
148+
}
149+
rdev->qplib_ctx.vf_res.max_mrw_per_vf = vf_mrws;
150+
rdev->qplib_ctx.vf_res.max_gid_per_vf = vf_gids;
151+
rdev->qplib_ctx.vf_res.max_qp_per_vf = vf_qps;
152+
rdev->qplib_ctx.vf_res.max_srq_per_vf = vf_srqs;
153+
rdev->qplib_ctx.vf_res.max_cq_per_vf = vf_cqs;
154+
}
155+
83156
/* for handling bnxt_en callbacks later */
84157
static void bnxt_re_stop(void *p)
85158
{
@@ -91,6 +164,15 @@ static void bnxt_re_start(void *p)
91164

92165
static void bnxt_re_sriov_config(void *p, int num_vfs)
93166
{
167+
struct bnxt_re_dev *rdev = p;
168+
169+
if (!rdev)
170+
return;
171+
172+
rdev->num_vfs = num_vfs;
173+
bnxt_re_set_resource_limits(rdev);
174+
bnxt_qplib_set_func_resources(&rdev->qplib_res, &rdev->rcfw,
175+
&rdev->qplib_ctx);
94176
}
95177

96178
static void bnxt_re_shutdown(void *p)
@@ -734,7 +816,8 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
734816

735817
/* Configure and allocate resources for qplib */
736818
rdev->qplib_res.rcfw = &rdev->rcfw;
737-
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr);
819+
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr,
820+
rdev->is_virtfn);
738821
if (rc)
739822
goto fail;
740823

@@ -1035,19 +1118,6 @@ static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev, bool lock_wait)
10351118
}
10361119
}
10371120

1038-
static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev)
1039-
{
1040-
u32 i;
1041-
1042-
rdev->qplib_ctx.qpc_count = BNXT_RE_MAX_QPC_COUNT;
1043-
rdev->qplib_ctx.mrw_count = BNXT_RE_MAX_MRW_COUNT;
1044-
rdev->qplib_ctx.srqc_count = BNXT_RE_MAX_SRQC_COUNT;
1045-
rdev->qplib_ctx.cq_count = BNXT_RE_MAX_CQ_COUNT;
1046-
for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
1047-
rdev->qplib_ctx.tqm_count[i] =
1048-
rdev->dev_attr.tqm_alloc_reqs[i];
1049-
}
1050-
10511121
/* worker thread for polling periodic events. Now used for QoS programming*/
10521122
static void bnxt_re_worker(struct work_struct *work)
10531123
{
@@ -1070,6 +1140,9 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
10701140
}
10711141
set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
10721142

1143+
/* Check whether VF or PF */
1144+
bnxt_re_get_sriov_func_type(rdev);
1145+
10731146
rc = bnxt_re_request_msix(rdev);
10741147
if (rc) {
10751148
pr_err("Failed to get MSI-X vectors: %#x\n", rc);
@@ -1101,16 +1174,18 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
11011174
(rdev->en_dev->pdev, &rdev->rcfw,
11021175
rdev->msix_entries[BNXT_RE_AEQ_IDX].vector,
11031176
rdev->msix_entries[BNXT_RE_AEQ_IDX].db_offset,
1104-
0, &bnxt_re_aeq_handler);
1177+
rdev->is_virtfn, &bnxt_re_aeq_handler);
11051178
if (rc) {
11061179
pr_err("Failed to enable RCFW channel: %#x\n", rc);
11071180
goto free_ring;
11081181
}
11091182

1110-
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr);
1183+
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr,
1184+
rdev->is_virtfn);
11111185
if (rc)
11121186
goto disable_rcfw;
1113-
bnxt_re_set_resource_limits(rdev);
1187+
if (!rdev->is_virtfn)
1188+
bnxt_re_set_resource_limits(rdev);
11141189

11151190
rc = bnxt_qplib_alloc_ctx(rdev->en_dev->pdev, &rdev->qplib_ctx, 0);
11161191
if (rc) {
@@ -1125,7 +1200,8 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
11251200
goto free_ctx;
11261201
}
11271202

1128-
rc = bnxt_qplib_init_rcfw(&rdev->rcfw, &rdev->qplib_ctx, 0);
1203+
rc = bnxt_qplib_init_rcfw(&rdev->rcfw, &rdev->qplib_ctx,
1204+
rdev->is_virtfn);
11291205
if (rc) {
11301206
pr_err("Failed to initialize RCFW: %#x\n", rc);
11311207
goto free_sctx;
@@ -1144,13 +1220,15 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
11441220
goto fail;
11451221
}
11461222

1147-
rc = bnxt_re_setup_qos(rdev);
1148-
if (rc)
1149-
pr_info("RoCE priority not yet configured\n");
1223+
if (!rdev->is_virtfn) {
1224+
rc = bnxt_re_setup_qos(rdev);
1225+
if (rc)
1226+
pr_info("RoCE priority not yet configured\n");
11501227

1151-
INIT_DELAYED_WORK(&rdev->worker, bnxt_re_worker);
1152-
set_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags);
1153-
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
1228+
INIT_DELAYED_WORK(&rdev->worker, bnxt_re_worker);
1229+
set_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags);
1230+
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
1231+
}
11541232

11551233
/* Register ib dev */
11561234
rc = bnxt_re_register_ib(rdev);
@@ -1400,16 +1478,19 @@ static int __init bnxt_re_mod_init(void)
14001478

14011479
static void __exit bnxt_re_mod_exit(void)
14021480
{
1403-
struct bnxt_re_dev *rdev;
1481+
struct bnxt_re_dev *rdev, *next;
14041482
LIST_HEAD(to_be_deleted);
14051483

14061484
mutex_lock(&bnxt_re_dev_lock);
14071485
/* Free all adapter allocated resources */
14081486
if (!list_empty(&bnxt_re_dev_list))
14091487
list_splice_init(&bnxt_re_dev_list, &to_be_deleted);
14101488
mutex_unlock(&bnxt_re_dev_lock);
1411-
1412-
list_for_each_entry(rdev, &to_be_deleted, list) {
1489+
/*
1490+
* Cleanup the devices in reverse order so that the VF device
1491+
* cleanup is done before PF cleanup
1492+
*/
1493+
list_for_each_entry_safe_reverse(rdev, next, &to_be_deleted, list) {
14131494
dev_info(rdev_to_dev(rdev), "Unregistering Device");
14141495
bnxt_re_dev_stop(rdev);
14151496
bnxt_re_ib_unreg(rdev, true);

drivers/infiniband/hw/bnxt_re/qplib_sp.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static bool bnxt_qplib_is_atomic_cap(struct bnxt_qplib_rcfw *rcfw)
6565
}
6666

6767
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
68-
struct bnxt_qplib_dev_attr *attr)
68+
struct bnxt_qplib_dev_attr *attr, bool vf)
6969
{
7070
struct cmdq_query_func req;
7171
struct creq_query_func_resp resp;
@@ -95,7 +95,8 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
9595
/* Extract the context from the side buffer */
9696
attr->max_qp = le32_to_cpu(sb->max_qp);
9797
/* max_qp value reported by FW for PF doesn't include the QP1 for PF */
98-
attr->max_qp += 1;
98+
if (!vf)
99+
attr->max_qp += 1;
99100
attr->max_qp_rd_atom =
100101
sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
101102
BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom;
@@ -150,6 +151,38 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
150151
return rc;
151152
}
152153

154+
int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
155+
struct bnxt_qplib_rcfw *rcfw,
156+
struct bnxt_qplib_ctx *ctx)
157+
{
158+
struct cmdq_set_func_resources req;
159+
struct creq_set_func_resources_resp resp;
160+
u16 cmd_flags = 0;
161+
int rc = 0;
162+
163+
RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags);
164+
165+
req.number_of_qp = cpu_to_le32(ctx->qpc_count);
166+
req.number_of_mrw = cpu_to_le32(ctx->mrw_count);
167+
req.number_of_srq = cpu_to_le32(ctx->srqc_count);
168+
req.number_of_cq = cpu_to_le32(ctx->cq_count);
169+
170+
req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
171+
req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
172+
req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
173+
req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf);
174+
req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf);
175+
176+
rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
177+
(void *)&resp,
178+
NULL, 0);
179+
if (rc) {
180+
dev_err(&res->pdev->dev,
181+
"QPLIB: Failed to set function resources");
182+
}
183+
return rc;
184+
}
185+
153186
/* SGID */
154187
int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
155188
struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,

drivers/infiniband/hw/bnxt_re/qplib_sp.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,10 @@ int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res,
147147
struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey,
148148
bool update);
149149
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
150-
struct bnxt_qplib_dev_attr *attr);
150+
struct bnxt_qplib_dev_attr *attr, bool vf);
151+
int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
152+
struct bnxt_qplib_rcfw *rcfw,
153+
struct bnxt_qplib_ctx *ctx);
151154
int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah);
152155
int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah);
153156
int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res,

drivers/infiniband/hw/bnxt_re/roce_hsi.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,16 @@ struct cmdq_set_func_resources {
17991799
u8 resp_size;
18001800
u8 reserved8;
18011801
__le64 resp_addr;
1802+
__le32 number_of_qp;
1803+
__le32 number_of_mrw;
1804+
__le32 number_of_srq;
1805+
__le32 number_of_cq;
1806+
__le32 max_qp_per_vf;
1807+
__le32 max_mrw_per_vf;
1808+
__le32 max_srq_per_vf;
1809+
__le32 max_cq_per_vf;
1810+
__le32 max_gid_per_vf;
1811+
__le32 stat_ctx_id;
18021812
};
18031813

18041814
/* Read hardware resource context command (24 bytes) */

0 commit comments

Comments
 (0)