Skip to content

Commit 6a03ffb

Browse files
Ilya Lesokhinrleon
Ilya Lesokhin
authored andcommitted
IB/mlx5: Maintain a single emergency page
The mlx5 driver needs to be able to issue invalidation to ODP MRs even if it cannot allocate memory. To this end it preallocates emergency pages to use when the situation arises. This flow should be extremely rare enough, that we don't need to worry about contention and therefore a single emergency page is good enough. Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 55b4c60 commit 6a03ffb

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

drivers/infiniband/hw/mlx5/main.c

+29-13
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ static LIST_HEAD(mlx5_ib_dev_list);
9090
*/
9191
static DEFINE_MUTEX(mlx5_ib_multiport_mutex);
9292

93+
/* We can't use an array for xlt_emergency_page because dma_map_single
94+
* doesn't work on kernel modules memory
95+
*/
96+
static unsigned long xlt_emergency_page;
97+
static struct mutex xlt_emergency_page_mutex;
98+
9399
struct mlx5_ib_dev *mlx5_ib_get_ibdev_from_mpi(struct mlx5_ib_multiport_info *mpi)
94100
{
95101
struct mlx5_ib_dev *dev;
@@ -1671,17 +1677,10 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
16711677
context->ibucontext.invalidate_range = &mlx5_ib_invalidate_range;
16721678
#endif
16731679

1674-
context->upd_xlt_page = __get_free_page(GFP_KERNEL);
1675-
if (!context->upd_xlt_page) {
1676-
err = -ENOMEM;
1677-
goto out_uars;
1678-
}
1679-
mutex_init(&context->upd_xlt_page_mutex);
1680-
16811680
if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain)) {
16821681
err = mlx5_ib_alloc_transport_domain(dev, &context->tdn);
16831682
if (err)
1684-
goto out_page;
1683+
goto out_uars;
16851684
}
16861685

16871686
INIT_LIST_HEAD(&context->vma_private_list);
@@ -1758,9 +1757,6 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
17581757
if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
17591758
mlx5_ib_dealloc_transport_domain(dev, context->tdn);
17601759

1761-
out_page:
1762-
free_page(context->upd_xlt_page);
1763-
17641760
out_uars:
17651761
deallocate_uars(dev, context);
17661762

@@ -1786,7 +1782,6 @@ static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
17861782
if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
17871783
mlx5_ib_dealloc_transport_domain(dev, context->tdn);
17881784

1789-
free_page(context->upd_xlt_page);
17901785
deallocate_uars(dev, context);
17911786
kfree(bfregi->sys_pages);
17921787
kfree(bfregi->count);
@@ -5065,13 +5060,32 @@ static struct mlx5_interface mlx5_ib_interface = {
50655060
.protocol = MLX5_INTERFACE_PROTOCOL_IB,
50665061
};
50675062

5063+
unsigned long mlx5_ib_get_xlt_emergency_page(void)
5064+
{
5065+
mutex_lock(&xlt_emergency_page_mutex);
5066+
return xlt_emergency_page;
5067+
}
5068+
5069+
void mlx5_ib_put_xlt_emergency_page(void)
5070+
{
5071+
mutex_unlock(&xlt_emergency_page_mutex);
5072+
}
5073+
50685074
static int __init mlx5_ib_init(void)
50695075
{
50705076
int err;
50715077

5078+
xlt_emergency_page = __get_free_page(GFP_KERNEL);
5079+
if (!xlt_emergency_page)
5080+
return -ENOMEM;
5081+
5082+
mutex_init(&xlt_emergency_page_mutex);
5083+
50725084
mlx5_ib_event_wq = alloc_ordered_workqueue("mlx5_ib_event_wq", 0);
5073-
if (!mlx5_ib_event_wq)
5085+
if (!mlx5_ib_event_wq) {
5086+
free_page(xlt_emergency_page);
50745087
return -ENOMEM;
5088+
}
50755089

50765090
mlx5_ib_odp_init();
50775091

@@ -5084,6 +5098,8 @@ static void __exit mlx5_ib_cleanup(void)
50845098
{
50855099
mlx5_unregister_interface(&mlx5_ib_interface);
50865100
destroy_workqueue(mlx5_ib_event_wq);
5101+
mutex_destroy(&xlt_emergency_page_mutex);
5102+
free_page(xlt_emergency_page);
50875103
}
50885104

50895105
module_init(mlx5_ib_init);

drivers/infiniband/hw/mlx5/mlx5_ib.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ struct mlx5_ib_ucontext {
130130
/* protect vma_private_list add/del */
131131
struct mutex vma_private_list_mutex;
132132

133-
unsigned long upd_xlt_page;
134-
/* protect ODP/KSM */
135-
struct mutex upd_xlt_page_mutex;
136133
u64 lib_caps;
137134
};
138135

@@ -1190,4 +1187,7 @@ static inline int get_num_static_uars(struct mlx5_ib_dev *dev,
11901187
return get_uars_per_sys_page(dev, bfregi->lib_uar_4k) * bfregi->num_static_sys_pages;
11911188
}
11921189

1190+
unsigned long mlx5_ib_get_xlt_emergency_page(void);
1191+
void mlx5_ib_put_xlt_emergency_page(void);
1192+
11931193
#endif /* MLX5_IB_H */

drivers/infiniband/hw/mlx5/mr.c

+5-6
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,6 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
984984
{
985985
struct mlx5_ib_dev *dev = mr->dev;
986986
struct device *ddev = dev->ib_dev.dev.parent;
987-
struct mlx5_ib_ucontext *uctx = NULL;
988987
int size;
989988
void *xlt;
990989
dma_addr_t dma;
@@ -1000,6 +999,7 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
1000999
size_t pages_to_map = 0;
10011000
size_t pages_iter = 0;
10021001
gfp_t gfp;
1002+
bool use_emergency_page = false;
10031003

10041004
/* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes,
10051005
* so we need to align the offset and length accordingly
@@ -1026,12 +1026,11 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
10261026
}
10271027

10281028
if (!xlt) {
1029-
uctx = to_mucontext(mr->ibmr.pd->uobject->context);
10301029
mlx5_ib_warn(dev, "Using XLT emergency buffer\n");
1030+
xlt = (void *)mlx5_ib_get_xlt_emergency_page();
10311031
size = PAGE_SIZE;
1032-
xlt = (void *)uctx->upd_xlt_page;
1033-
mutex_lock(&uctx->upd_xlt_page_mutex);
10341032
memset(xlt, 0, size);
1033+
use_emergency_page = true;
10351034
}
10361035
pages_iter = size / desc_size;
10371036
dma = dma_map_single(ddev, xlt, size, DMA_TO_DEVICE);
@@ -1095,8 +1094,8 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
10951094
dma_unmap_single(ddev, dma, size, DMA_TO_DEVICE);
10961095

10971096
free_xlt:
1098-
if (uctx)
1099-
mutex_unlock(&uctx->upd_xlt_page_mutex);
1097+
if (use_emergency_page)
1098+
mlx5_ib_put_xlt_emergency_page();
11001099
else
11011100
free_pages((unsigned long)xlt, get_order(size));
11021101

0 commit comments

Comments
 (0)