Skip to content

Commit b037c29

Browse files
Eli CohenSaeed Mahameed
authored andcommitted
IB/mlx5: Allow future extension of libmlx5 input data
Current check requests that new fields in struct mlx5_ib_alloc_ucontext_req_v2 that are not known to the driver be zero. This was introduced so new libraries passing additional information to the kernel through struct mlx5_ib_alloc_ucontext_req_v2 will be notified by old kernels that do not support their request by failing the operation. This schecme is problematic since it requires libmlx5 to issue the requests with descending input size for struct mlx5_ib_alloc_ucontext_req_v2. To avoid this, we require that new features that will obey the following rules: If the feature requires one or more fields in the response and the at least one of the fields can be encoded such that a zero value means the kernel ignored the request then this field will provide the indication to the library. If no response is required or if zero is a valid response, a new field should be added that indicates to the library whether its request was processed. Fixes: b368d7c ('IB/mlx5: Add hca_core_clock_offset to udata in init_ucontext') Signed-off-by: Eli Cohen <[email protected]> Reviewed-by: Matan Barak <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 5fe9dec commit b037c29

File tree

6 files changed

+209
-166
lines changed

6 files changed

+209
-166
lines changed

drivers/infiniband/hw/mlx5/cq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata,
788788
MLX5_SET(cqc, cqc, log_page_size,
789789
page_shift - MLX5_ADAPTER_PAGE_SHIFT);
790790

791-
*index = to_mucontext(context)->bfregi.uars[0].index;
791+
*index = to_mucontext(context)->bfregi.sys_pages[0];
792792

793793
if (ucmd.cqe_comp_en == 1) {
794794
if (unlikely((*cqe_size != 64) ||

drivers/infiniband/hw/mlx5/main.c

Lines changed: 126 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,80 @@ static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
992992
return err;
993993
}
994994

995+
static int calc_total_bfregs(struct mlx5_ib_dev *dev, bool lib_uar_4k,
996+
struct mlx5_ib_alloc_ucontext_req_v2 *req,
997+
u32 *num_sys_pages)
998+
{
999+
int uars_per_sys_page;
1000+
int bfregs_per_sys_page;
1001+
int ref_bfregs = req->total_num_bfregs;
1002+
1003+
if (req->total_num_bfregs == 0)
1004+
return -EINVAL;
1005+
1006+
BUILD_BUG_ON(MLX5_MAX_BFREGS % MLX5_NON_FP_BFREGS_IN_PAGE);
1007+
BUILD_BUG_ON(MLX5_MAX_BFREGS < MLX5_NON_FP_BFREGS_IN_PAGE);
1008+
1009+
if (req->total_num_bfregs > MLX5_MAX_BFREGS)
1010+
return -ENOMEM;
1011+
1012+
uars_per_sys_page = get_uars_per_sys_page(dev, lib_uar_4k);
1013+
bfregs_per_sys_page = uars_per_sys_page * MLX5_NON_FP_BFREGS_PER_UAR;
1014+
req->total_num_bfregs = ALIGN(req->total_num_bfregs, bfregs_per_sys_page);
1015+
*num_sys_pages = req->total_num_bfregs / bfregs_per_sys_page;
1016+
1017+
if (req->num_low_latency_bfregs > req->total_num_bfregs - 1)
1018+
return -EINVAL;
1019+
1020+
mlx5_ib_dbg(dev, "uar_4k: fw support %s, lib support %s, user requested %d bfregs, alloated %d, using %d sys pages\n",
1021+
MLX5_CAP_GEN(dev->mdev, uar_4k) ? "yes" : "no",
1022+
lib_uar_4k ? "yes" : "no", ref_bfregs,
1023+
req->total_num_bfregs, *num_sys_pages);
1024+
1025+
return 0;
1026+
}
1027+
1028+
static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1029+
{
1030+
struct mlx5_bfreg_info *bfregi;
1031+
int err;
1032+
int i;
1033+
1034+
bfregi = &context->bfregi;
1035+
for (i = 0; i < bfregi->num_sys_pages; i++) {
1036+
err = mlx5_cmd_alloc_uar(dev->mdev, &bfregi->sys_pages[i]);
1037+
if (err)
1038+
goto error;
1039+
1040+
mlx5_ib_dbg(dev, "allocated uar %d\n", bfregi->sys_pages[i]);
1041+
}
1042+
return 0;
1043+
1044+
error:
1045+
for (--i; i >= 0; i--)
1046+
if (mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]))
1047+
mlx5_ib_warn(dev, "failed to free uar %d\n", i);
1048+
1049+
return err;
1050+
}
1051+
1052+
static int deallocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1053+
{
1054+
struct mlx5_bfreg_info *bfregi;
1055+
int err;
1056+
int i;
1057+
1058+
bfregi = &context->bfregi;
1059+
for (i = 0; i < bfregi->num_sys_pages; i++) {
1060+
err = mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]);
1061+
if (err) {
1062+
mlx5_ib_warn(dev, "failed to free uar %d\n", i);
1063+
return err;
1064+
}
1065+
}
1066+
return 0;
1067+
}
1068+
9951069
static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
9961070
struct ib_udata *udata)
9971071
{
@@ -1000,16 +1074,12 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
10001074
struct mlx5_ib_alloc_ucontext_resp resp = {};
10011075
struct mlx5_ib_ucontext *context;
10021076
struct mlx5_bfreg_info *bfregi;
1003-
struct mlx5_uar *uars;
1004-
int gross_bfregs;
1005-
int num_uars;
10061077
int ver;
1007-
int bfregn;
10081078
int err;
1009-
int i;
10101079
size_t reqlen;
10111080
size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2,
10121081
max_cqe_version);
1082+
bool lib_uar_4k;
10131083

10141084
if (!dev->ib_active)
10151085
return ERR_PTR(-EAGAIN);
@@ -1032,27 +1102,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
10321102
if (req.flags)
10331103
return ERR_PTR(-EINVAL);
10341104

1035-
if (req.total_num_bfregs > MLX5_MAX_BFREGS)
1036-
return ERR_PTR(-ENOMEM);
1037-
1038-
if (req.total_num_bfregs == 0)
1039-
return ERR_PTR(-EINVAL);
1040-
10411105
if (req.comp_mask || req.reserved0 || req.reserved1 || req.reserved2)
10421106
return ERR_PTR(-EOPNOTSUPP);
10431107

1044-
if (reqlen > sizeof(req) &&
1045-
!ib_is_udata_cleared(udata, sizeof(req),
1046-
reqlen - sizeof(req)))
1047-
return ERR_PTR(-EOPNOTSUPP);
1048-
10491108
req.total_num_bfregs = ALIGN(req.total_num_bfregs,
10501109
MLX5_NON_FP_BFREGS_PER_UAR);
10511110
if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)
10521111
return ERR_PTR(-EINVAL);
10531112

1054-
num_uars = req.total_num_bfregs / MLX5_NON_FP_BFREGS_PER_UAR;
1055-
gross_bfregs = num_uars * MLX5_BFREGS_PER_UAR;
10561113
resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
10571114
if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
10581115
resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
@@ -1072,42 +1129,34 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
10721129
if (!context)
10731130
return ERR_PTR(-ENOMEM);
10741131

1132+
lib_uar_4k = false;
10751133
bfregi = &context->bfregi;
1076-
mutex_init(&bfregi->lock);
1077-
uars = kcalloc(num_uars, sizeof(*uars), GFP_KERNEL);
1078-
if (!uars) {
1079-
err = -ENOMEM;
1134+
1135+
/* updates req->total_num_bfregs */
1136+
err = calc_total_bfregs(dev, lib_uar_4k, &req, &bfregi->num_sys_pages);
1137+
if (err)
10801138
goto out_ctx;
1081-
}
10821139

1083-
bfregi->bitmap = kcalloc(BITS_TO_LONGS(gross_bfregs),
1084-
sizeof(*bfregi->bitmap),
1140+
mutex_init(&bfregi->lock);
1141+
bfregi->lib_uar_4k = lib_uar_4k;
1142+
bfregi->count = kcalloc(req.total_num_bfregs, sizeof(*bfregi->count),
10851143
GFP_KERNEL);
1086-
if (!bfregi->bitmap) {
1144+
if (!bfregi->count) {
10871145
err = -ENOMEM;
1088-
goto out_uar_ctx;
1089-
}
1090-
/*
1091-
* clear all fast path bfregs
1092-
*/
1093-
for (i = 0; i < gross_bfregs; i++) {
1094-
bfregn = i & 3;
1095-
if (bfregn == 2 || bfregn == 3)
1096-
set_bit(i, bfregi->bitmap);
1146+
goto out_ctx;
10971147
}
10981148

1099-
bfregi->count = kcalloc(gross_bfregs,
1100-
sizeof(*bfregi->count), GFP_KERNEL);
1101-
if (!bfregi->count) {
1149+
bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
1150+
sizeof(*bfregi->sys_pages),
1151+
GFP_KERNEL);
1152+
if (!bfregi->sys_pages) {
11021153
err = -ENOMEM;
1103-
goto out_bitmap;
1154+
goto out_count;
11041155
}
11051156

1106-
for (i = 0; i < num_uars; i++) {
1107-
err = mlx5_cmd_alloc_uar(dev->mdev, &uars[i].index);
1108-
if (err)
1109-
goto out_count;
1110-
}
1157+
err = allocate_uars(dev, context);
1158+
if (err)
1159+
goto out_sys_pages;
11111160

11121161
#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
11131162
context->ibucontext.invalidate_range = &mlx5_ib_invalidate_range;
@@ -1166,9 +1215,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
11661215

11671216
bfregi->ver = ver;
11681217
bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs;
1169-
bfregi->uars = uars;
1170-
bfregi->num_uars = num_uars;
11711218
context->cqe_version = resp.cqe_version;
1219+
context->lib_caps = false;
11721220

11731221
return &context->ibucontext;
11741222

@@ -1180,51 +1228,49 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
11801228
free_page(context->upd_xlt_page);
11811229

11821230
out_uars:
1183-
for (i--; i >= 0; i--)
1184-
mlx5_cmd_free_uar(dev->mdev, uars[i].index);
1185-
out_count:
1186-
kfree(bfregi->count);
1231+
deallocate_uars(dev, context);
11871232

1188-
out_bitmap:
1189-
kfree(bfregi->bitmap);
1233+
out_sys_pages:
1234+
kfree(bfregi->sys_pages);
11901235

1191-
out_uar_ctx:
1192-
kfree(uars);
1236+
out_count:
1237+
kfree(bfregi->count);
11931238

11941239
out_ctx:
11951240
kfree(context);
1241+
11961242
return ERR_PTR(err);
11971243
}
11981244

11991245
static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
12001246
{
12011247
struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
12021248
struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
1203-
struct mlx5_bfreg_info *bfregi = &context->bfregi;
1204-
int i;
1249+
struct mlx5_bfreg_info *bfregi;
12051250

1251+
bfregi = &context->bfregi;
12061252
if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
12071253
mlx5_core_dealloc_transport_domain(dev->mdev, context->tdn);
12081254

12091255
free_page(context->upd_xlt_page);
1210-
1211-
for (i = 0; i < bfregi->num_uars; i++) {
1212-
if (mlx5_cmd_free_uar(dev->mdev, bfregi->uars[i].index))
1213-
mlx5_ib_warn(dev, "Failed to free UAR 0x%x\n",
1214-
bfregi->uars[i].index);
1215-
}
1216-
1256+
deallocate_uars(dev, context);
1257+
kfree(bfregi->sys_pages);
12171258
kfree(bfregi->count);
1218-
kfree(bfregi->bitmap);
1219-
kfree(bfregi->uars);
12201259
kfree(context);
12211260

12221261
return 0;
12231262
}
12241263

1225-
static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev, int index)
1264+
static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
1265+
struct mlx5_bfreg_info *bfregi,
1266+
int idx)
12261267
{
1227-
return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + index;
1268+
int fw_uars_per_page;
1269+
1270+
fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? MLX5_UARS_IN_PAGE : 1;
1271+
1272+
return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) +
1273+
bfregi->sys_pages[idx] / fw_uars_per_page;
12281274
}
12291275

12301276
static int get_command(unsigned long offset)
@@ -1384,6 +1430,18 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
13841430
unsigned long idx;
13851431
phys_addr_t pfn, pa;
13861432
pgprot_t prot;
1433+
int uars_per_page;
1434+
1435+
if (vma->vm_end - vma->vm_start != PAGE_SIZE)
1436+
return -EINVAL;
1437+
1438+
uars_per_page = get_uars_per_sys_page(dev, bfregi->lib_uar_4k);
1439+
idx = get_index(vma->vm_pgoff);
1440+
if (idx % uars_per_page ||
1441+
idx * uars_per_page >= bfregi->num_sys_pages) {
1442+
mlx5_ib_warn(dev, "invalid uar index %lu\n", idx);
1443+
return -EINVAL;
1444+
}
13871445

13881446
switch (cmd) {
13891447
case MLX5_IB_MMAP_WC_PAGE:
@@ -1406,14 +1464,7 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
14061464
return -EINVAL;
14071465
}
14081466

1409-
if (vma->vm_end - vma->vm_start != PAGE_SIZE)
1410-
return -EINVAL;
1411-
1412-
idx = get_index(vma->vm_pgoff);
1413-
if (idx >= bfregi->num_uars)
1414-
return -EINVAL;
1415-
1416-
pfn = uar_index2pfn(dev, bfregi->uars[idx].index);
1467+
pfn = uar_index2pfn(dev, bfregi, idx);
14171468
mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);
14181469

14191470
vma->vm_page_prot = prot;

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ enum mlx5_ib_latency_class {
9090
MLX5_IB_LATENCY_CLASS_LOW,
9191
MLX5_IB_LATENCY_CLASS_MEDIUM,
9292
MLX5_IB_LATENCY_CLASS_HIGH,
93-
MLX5_IB_LATENCY_CLASS_FAST_PATH
9493
};
9594

9695
enum mlx5_ib_mad_ifc_flags {
@@ -129,6 +128,7 @@ struct mlx5_ib_ucontext {
129128
unsigned long upd_xlt_page;
130129
/* protect ODP/KSM */
131130
struct mutex upd_xlt_page_mutex;
131+
u64 lib_caps;
132132
};
133133

134134
static inline struct mlx5_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext)
@@ -975,4 +975,17 @@ static inline int get_srq_user_index(struct mlx5_ib_ucontext *ucontext,
975975

976976
return verify_assign_uidx(cqe_version, ucmd->uidx, user_index);
977977
}
978+
979+
static inline int get_uars_per_sys_page(struct mlx5_ib_dev *dev, bool lib_support)
980+
{
981+
return lib_support && MLX5_CAP_GEN(dev->mdev, uar_4k) ?
982+
MLX5_UARS_IN_PAGE : 1;
983+
}
984+
985+
static inline int get_num_uars(struct mlx5_ib_dev *dev,
986+
struct mlx5_bfreg_info *bfregi)
987+
{
988+
return get_uars_per_sys_page(dev, bfregi->lib_uar_4k) * bfregi->num_sys_pages;
989+
}
990+
978991
#endif /* MLX5_IB_H */

0 commit comments

Comments
 (0)