Skip to content

Commit dc2316e

Browse files
yishaihdledford
authored andcommitted
IB/mlx5: Fix device memory flows
Fix device memory flows so that only once there will be no live mmaped VA to a given allocation the matching object will be destroyed. This prevents a potential scenario that existing VA that was mmaped by one process might still be used post its deallocation despite that it's owned now by other process. The above is achieved by integrating with IB core APIs to manage mmap/munmap. Only once the refcount will become 0 the DM object and its underlay area will be freed. Fixes: 3b113a1 ("IB/mlx5: Support device memory type attribute") Signed-off-by: Yishai Hadas <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Doug Ledford <[email protected]>
1 parent 7a763d1 commit dc2316e

File tree

4 files changed

+105
-52
lines changed

4 files changed

+105
-52
lines changed

drivers/infiniband/hw/mlx5/cmd.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
157157
return -ENOMEM;
158158
}
159159

160-
int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
160+
void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
161161
{
162162
struct mlx5_core_dev *dev = dm->dev;
163163
u64 hw_start_addr = MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr);
@@ -175,15 +175,13 @@ int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
175175
MLX5_SET(dealloc_memic_in, in, memic_size, length);
176176

177177
err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
178+
if (err)
179+
return;
178180

179-
if (!err) {
180-
spin_lock(&dm->lock);
181-
bitmap_clear(dm->memic_alloc_pages,
182-
start_page_idx, num_pages);
183-
spin_unlock(&dm->lock);
184-
}
185-
186-
return err;
181+
spin_lock(&dm->lock);
182+
bitmap_clear(dm->memic_alloc_pages,
183+
start_page_idx, num_pages);
184+
spin_unlock(&dm->lock);
187185
}
188186

189187
int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out)

drivers/infiniband/hw/mlx5/cmd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev,
4646
void *in, int in_size);
4747
int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
4848
u64 length, u32 alignment);
49-
int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
49+
void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
5050
void mlx5_cmd_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn, u16 uid);
5151
void mlx5_cmd_destroy_tir(struct mlx5_core_dev *dev, u32 tirn, u16 uid);
5252
void mlx5_cmd_destroy_tis(struct mlx5_core_dev *dev, u32 tisn, u16 uid);

drivers/infiniband/hw/mlx5/main.c

Lines changed: 79 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,24 @@ static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,
20742074
virt_to_page(dev->mdev->clock_info));
20752075
}
20762076

2077+
static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
2078+
{
2079+
struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
2080+
struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
2081+
struct mlx5_ib_dm *mdm;
2082+
2083+
switch (mentry->mmap_flag) {
2084+
case MLX5_IB_MMAP_TYPE_MEMIC:
2085+
mdm = container_of(mentry, struct mlx5_ib_dm, mentry);
2086+
mlx5_cmd_dealloc_memic(&dev->dm, mdm->dev_addr,
2087+
mdm->size);
2088+
kfree(mdm);
2089+
break;
2090+
default:
2091+
WARN_ON(true);
2092+
}
2093+
}
2094+
20772095
static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
20782096
struct vm_area_struct *vma,
20792097
struct mlx5_ib_ucontext *context)
@@ -2186,26 +2204,55 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
21862204
return err;
21872205
}
21882206

2189-
static int dm_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
2207+
static int add_dm_mmap_entry(struct ib_ucontext *context,
2208+
struct mlx5_ib_dm *mdm,
2209+
u64 address)
2210+
{
2211+
mdm->mentry.mmap_flag = MLX5_IB_MMAP_TYPE_MEMIC;
2212+
mdm->mentry.address = address;
2213+
return rdma_user_mmap_entry_insert_range(
2214+
context, &mdm->mentry.rdma_entry,
2215+
mdm->size,
2216+
MLX5_IB_MMAP_DEVICE_MEM << 16,
2217+
(MLX5_IB_MMAP_DEVICE_MEM << 16) + (1UL << 16) - 1);
2218+
}
2219+
2220+
static unsigned long mlx5_vma_to_pgoff(struct vm_area_struct *vma)
2221+
{
2222+
unsigned long idx;
2223+
u8 command;
2224+
2225+
command = get_command(vma->vm_pgoff);
2226+
idx = get_extended_index(vma->vm_pgoff);
2227+
2228+
return (command << 16 | idx);
2229+
}
2230+
2231+
static int mlx5_ib_mmap_offset(struct mlx5_ib_dev *dev,
2232+
struct vm_area_struct *vma,
2233+
struct ib_ucontext *ucontext)
21902234
{
2191-
struct mlx5_ib_ucontext *mctx = to_mucontext(context);
2192-
struct mlx5_ib_dev *dev = to_mdev(context->device);
2193-
u16 page_idx = get_extended_index(vma->vm_pgoff);
2194-
size_t map_size = vma->vm_end - vma->vm_start;
2195-
u32 npages = map_size >> PAGE_SHIFT;
2235+
struct mlx5_user_mmap_entry *mentry;
2236+
struct rdma_user_mmap_entry *entry;
2237+
unsigned long pgoff;
2238+
pgprot_t prot;
21962239
phys_addr_t pfn;
2240+
int ret;
21972241

2198-
if (find_next_zero_bit(mctx->dm_pages, page_idx + npages, page_idx) !=
2199-
page_idx + npages)
2242+
pgoff = mlx5_vma_to_pgoff(vma);
2243+
entry = rdma_user_mmap_entry_get_pgoff(ucontext, pgoff);
2244+
if (!entry)
22002245
return -EINVAL;
22012246

2202-
pfn = ((dev->mdev->bar_addr +
2203-
MLX5_CAP64_DEV_MEM(dev->mdev, memic_bar_start_addr)) >>
2204-
PAGE_SHIFT) +
2205-
page_idx;
2206-
return rdma_user_mmap_io(context, vma, pfn, map_size,
2207-
pgprot_writecombine(vma->vm_page_prot),
2208-
NULL);
2247+
mentry = to_mmmap(entry);
2248+
pfn = (mentry->address >> PAGE_SHIFT);
2249+
prot = pgprot_writecombine(vma->vm_page_prot);
2250+
ret = rdma_user_mmap_io(ucontext, vma, pfn,
2251+
entry->npages * PAGE_SIZE,
2252+
prot,
2253+
entry);
2254+
rdma_user_mmap_entry_put(&mentry->rdma_entry);
2255+
return ret;
22092256
}
22102257

22112258
static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
@@ -2248,11 +2295,8 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
22482295
case MLX5_IB_MMAP_CLOCK_INFO:
22492296
return mlx5_ib_mmap_clock_info_page(dev, vma, context);
22502297

2251-
case MLX5_IB_MMAP_DEVICE_MEM:
2252-
return dm_mmap(ibcontext, vma);
2253-
22542298
default:
2255-
return -EINVAL;
2299+
return mlx5_ib_mmap_offset(dev, vma, ibcontext);
22562300
}
22572301

22582302
return 0;
@@ -2288,8 +2332,9 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
22882332
{
22892333
struct mlx5_dm *dm_db = &to_mdev(ctx->device)->dm;
22902334
u64 start_offset;
2291-
u32 page_idx;
2335+
u16 page_idx;
22922336
int err;
2337+
u64 address;
22932338

22942339
dm->size = roundup(attr->length, MLX5_MEMIC_BASE_SIZE);
22952340

@@ -2298,28 +2343,30 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
22982343
if (err)
22992344
return err;
23002345

2301-
page_idx = (dm->dev_addr - pci_resource_start(dm_db->dev->pdev, 0) -
2302-
MLX5_CAP64_DEV_MEM(dm_db->dev, memic_bar_start_addr)) >>
2303-
PAGE_SHIFT;
2346+
address = dm->dev_addr & PAGE_MASK;
2347+
err = add_dm_mmap_entry(ctx, dm, address);
2348+
if (err)
2349+
goto err_dealloc;
23042350

2351+
page_idx = dm->mentry.rdma_entry.start_pgoff & 0xFFFF;
23052352
err = uverbs_copy_to(attrs,
23062353
MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
2307-
&page_idx, sizeof(page_idx));
2354+
&page_idx,
2355+
sizeof(page_idx));
23082356
if (err)
2309-
goto err_dealloc;
2357+
goto err_copy;
23102358

23112359
start_offset = dm->dev_addr & ~PAGE_MASK;
23122360
err = uverbs_copy_to(attrs,
23132361
MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
23142362
&start_offset, sizeof(start_offset));
23152363
if (err)
2316-
goto err_dealloc;
2317-
2318-
bitmap_set(to_mucontext(ctx)->dm_pages, page_idx,
2319-
DIV_ROUND_UP(dm->size, PAGE_SIZE));
2364+
goto err_copy;
23202365

23212366
return 0;
23222367

2368+
err_copy:
2369+
rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
23232370
err_dealloc:
23242371
mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
23252372

@@ -2423,23 +2470,13 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
24232470
struct mlx5_ib_ucontext *ctx = rdma_udata_to_drv_context(
24242471
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
24252472
struct mlx5_core_dev *dev = to_mdev(ibdm->device)->mdev;
2426-
struct mlx5_dm *dm_db = &to_mdev(ibdm->device)->dm;
24272473
struct mlx5_ib_dm *dm = to_mdm(ibdm);
2428-
u32 page_idx;
24292474
int ret;
24302475

24312476
switch (dm->type) {
24322477
case MLX5_IB_UAPI_DM_TYPE_MEMIC:
2433-
ret = mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
2434-
if (ret)
2435-
return ret;
2436-
2437-
page_idx = (dm->dev_addr - pci_resource_start(dev->pdev, 0) -
2438-
MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr)) >>
2439-
PAGE_SHIFT;
2440-
bitmap_clear(ctx->dm_pages, page_idx,
2441-
DIV_ROUND_UP(dm->size, PAGE_SIZE));
2442-
break;
2478+
rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
2479+
return 0;
24432480
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
24442481
ret = mlx5_dm_sw_icm_dealloc(dev, MLX5_SW_ICM_TYPE_STEERING,
24452482
dm->size, ctx->devx_uid, dm->dev_addr,
@@ -6235,6 +6272,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
62356272
.map_mr_sg = mlx5_ib_map_mr_sg,
62366273
.map_mr_sg_pi = mlx5_ib_map_mr_sg_pi,
62376274
.mmap = mlx5_ib_mmap,
6275+
.mmap_free = mlx5_ib_mmap_free,
62386276
.modify_cq = mlx5_ib_modify_cq,
62396277
.modify_device = mlx5_ib_modify_device,
62406278
.modify_port = mlx5_ib_modify_port,

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ enum {
118118
MLX5_MEMIC_BASE_SIZE = 1 << MLX5_MEMIC_BASE_ALIGN,
119119
};
120120

121+
enum mlx5_ib_mmap_type {
122+
MLX5_IB_MMAP_TYPE_MEMIC = 1,
123+
};
124+
121125
#define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev) \
122126
(MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity))
123127
#define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev))
@@ -135,7 +139,6 @@ struct mlx5_ib_ucontext {
135139
u32 tdn;
136140

137141
u64 lib_caps;
138-
DECLARE_BITMAP(dm_pages, MLX5_MAX_MEMIC_PAGES);
139142
u16 devx_uid;
140143
/* For RoCE LAG TX affinity */
141144
atomic_t tx_port_affinity;
@@ -556,6 +559,12 @@ enum mlx5_ib_mtt_access_flags {
556559
MLX5_IB_MTT_WRITE = (1 << 1),
557560
};
558561

562+
struct mlx5_user_mmap_entry {
563+
struct rdma_user_mmap_entry rdma_entry;
564+
u8 mmap_flag;
565+
u64 address;
566+
};
567+
559568
struct mlx5_ib_dm {
560569
struct ib_dm ibdm;
561570
phys_addr_t dev_addr;
@@ -567,6 +576,7 @@ struct mlx5_ib_dm {
567576
} icm_dm;
568577
/* other dm types specific params should be added here */
569578
};
579+
struct mlx5_user_mmap_entry mentry;
570580
};
571581

572582
#define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
@@ -1101,6 +1111,13 @@ to_mflow_act(struct ib_flow_action *ibact)
11011111
return container_of(ibact, struct mlx5_ib_flow_action, ib_action);
11021112
}
11031113

1114+
static inline struct mlx5_user_mmap_entry *
1115+
to_mmmap(struct rdma_user_mmap_entry *rdma_entry)
1116+
{
1117+
return container_of(rdma_entry,
1118+
struct mlx5_user_mmap_entry, rdma_entry);
1119+
}
1120+
11041121
int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context,
11051122
struct ib_udata *udata, unsigned long virt,
11061123
struct mlx5_db *db);

0 commit comments

Comments
 (0)