Skip to content

Commit 968e78d

Browse files
haggaierolandd
authored andcommitted
IB/mlx5: Enhance UMR support to allow partial page table update
The current UMR interface doesn't allow partial updates to a memory region's page tables. This patch changes the interface to allow that. It also changes the way the UMR operation validates the memory region's state. When set, IB_SEND_UMR_FAIL_IF_FREE will cause the UMR operation to fail if the MKEY is in the free state. When it is unchecked the operation will check that it isn't in the free state. Signed-off-by: Haggai Eran <[email protected]> Signed-off-by: Shachar Raindel <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent 21af2c3 commit 968e78d

File tree

4 files changed

+109
-48
lines changed

4 files changed

+109
-48
lines changed

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ struct mlx5_ib_pd {
111111
*/
112112

113113
#define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START
114+
#define MLX5_IB_SEND_UMR_FAIL_IF_FREE (IB_SEND_RESERVED_START << 1)
115+
#define MLX5_IB_SEND_UMR_UPDATE_MTT (IB_SEND_RESERVED_START << 2)
114116
#define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1
115117
#define MLX5_IB_WR_UMR IB_WR_RESERVED1
116118

@@ -206,6 +208,19 @@ enum mlx5_ib_qp_flags {
206208
MLX5_IB_QP_SIGNATURE_HANDLING = 1 << 1,
207209
};
208210

211+
struct mlx5_umr_wr {
212+
union {
213+
u64 virt_addr;
214+
u64 offset;
215+
} target;
216+
struct ib_pd *pd;
217+
unsigned int page_shift;
218+
unsigned int npages;
219+
u32 length;
220+
int access_flags;
221+
u32 mkey;
222+
};
223+
209224
struct mlx5_shared_mr_info {
210225
int mr_id;
211226
struct ib_umem *umem;

drivers/infiniband/hw/mlx5/mr.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/export.h>
3838
#include <linux/delay.h>
3939
#include <rdma/ib_umem.h>
40+
#include <rdma/ib_verbs.h>
4041
#include "mlx5_ib.h"
4142

4243
enum {
@@ -146,7 +147,7 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
146147
mr->order = ent->order;
147148
mr->umred = 1;
148149
mr->dev = dev;
149-
in->seg.status = 1 << 6;
150+
in->seg.status = MLX5_MKEY_STATUS_FREE;
150151
in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2);
151152
in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
152153
in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN;
@@ -678,6 +679,7 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr,
678679
{
679680
struct mlx5_ib_dev *dev = to_mdev(pd->device);
680681
struct ib_mr *mr = dev->umrc.mr;
682+
struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
681683

682684
sg->addr = dma;
683685
sg->length = ALIGN(sizeof(u64) * n, 64);
@@ -692,21 +694,24 @@ static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr,
692694
wr->num_sge = 0;
693695

694696
wr->opcode = MLX5_IB_WR_UMR;
695-
wr->wr.fast_reg.page_list_len = n;
696-
wr->wr.fast_reg.page_shift = page_shift;
697-
wr->wr.fast_reg.rkey = key;
698-
wr->wr.fast_reg.iova_start = virt_addr;
699-
wr->wr.fast_reg.length = len;
700-
wr->wr.fast_reg.access_flags = access_flags;
701-
wr->wr.fast_reg.page_list = (struct ib_fast_reg_page_list *)pd;
697+
698+
umrwr->npages = n;
699+
umrwr->page_shift = page_shift;
700+
umrwr->mkey = key;
701+
umrwr->target.virt_addr = virt_addr;
702+
umrwr->length = len;
703+
umrwr->access_flags = access_flags;
704+
umrwr->pd = pd;
702705
}
703706

704707
static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev,
705708
struct ib_send_wr *wr, u32 key)
706709
{
707-
wr->send_flags = MLX5_IB_SEND_UMR_UNREG;
710+
struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
711+
712+
wr->send_flags = MLX5_IB_SEND_UMR_UNREG | MLX5_IB_SEND_UMR_FAIL_IF_FREE;
708713
wr->opcode = MLX5_IB_WR_UMR;
709-
wr->wr.fast_reg.rkey = key;
714+
umrwr->mkey = key;
710715
}
711716

712717
void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context)
@@ -1031,7 +1036,7 @@ struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd,
10311036
goto err_free;
10321037
}
10331038

1034-
in->seg.status = 1 << 6; /* free */
1039+
in->seg.status = MLX5_MKEY_STATUS_FREE;
10351040
in->seg.xlt_oct_size = cpu_to_be32(ndescs);
10361041
in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
10371042
in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn);
@@ -1146,7 +1151,7 @@ struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd,
11461151
goto err_free;
11471152
}
11481153

1149-
in->seg.status = 1 << 6; /* free */
1154+
in->seg.status = MLX5_MKEY_STATUS_FREE;
11501155
in->seg.xlt_oct_size = cpu_to_be32((max_page_list_len + 1) / 2);
11511156
in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
11521157
in->seg.flags = MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT;

drivers/infiniband/hw/mlx5/qp.c

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,6 @@ static const u32 mlx5_ib_opcode[] = {
7070
[MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR,
7171
};
7272

73-
struct umr_wr {
74-
u64 virt_addr;
75-
struct ib_pd *pd;
76-
unsigned int page_shift;
77-
unsigned int npages;
78-
u32 length;
79-
int access_flags;
80-
u32 mkey;
81-
};
8273

8374
static int is_qp0(enum ib_qp_type qp_type)
8475
{
@@ -1848,37 +1839,70 @@ static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
18481839
umr->mkey_mask = frwr_mkey_mask();
18491840
}
18501841

1842+
static __be64 get_umr_reg_mr_mask(void)
1843+
{
1844+
u64 result;
1845+
1846+
result = MLX5_MKEY_MASK_LEN |
1847+
MLX5_MKEY_MASK_PAGE_SIZE |
1848+
MLX5_MKEY_MASK_START_ADDR |
1849+
MLX5_MKEY_MASK_PD |
1850+
MLX5_MKEY_MASK_LR |
1851+
MLX5_MKEY_MASK_LW |
1852+
MLX5_MKEY_MASK_KEY |
1853+
MLX5_MKEY_MASK_RR |
1854+
MLX5_MKEY_MASK_RW |
1855+
MLX5_MKEY_MASK_A |
1856+
MLX5_MKEY_MASK_FREE;
1857+
1858+
return cpu_to_be64(result);
1859+
}
1860+
1861+
static __be64 get_umr_unreg_mr_mask(void)
1862+
{
1863+
u64 result;
1864+
1865+
result = MLX5_MKEY_MASK_FREE;
1866+
1867+
return cpu_to_be64(result);
1868+
}
1869+
1870+
static __be64 get_umr_update_mtt_mask(void)
1871+
{
1872+
u64 result;
1873+
1874+
result = MLX5_MKEY_MASK_FREE;
1875+
1876+
return cpu_to_be64(result);
1877+
}
1878+
18511879
static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
18521880
struct ib_send_wr *wr)
18531881
{
1854-
struct umr_wr *umrwr = (struct umr_wr *)&wr->wr.fast_reg;
1855-
u64 mask;
1882+
struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
18561883

18571884
memset(umr, 0, sizeof(*umr));
18581885

1886+
if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
1887+
umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */
1888+
else
1889+
umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */
1890+
18591891
if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) {
1860-
umr->flags = 1 << 5; /* fail if not free */
18611892
umr->klm_octowords = get_klm_octo(umrwr->npages);
1862-
mask = MLX5_MKEY_MASK_LEN |
1863-
MLX5_MKEY_MASK_PAGE_SIZE |
1864-
MLX5_MKEY_MASK_START_ADDR |
1865-
MLX5_MKEY_MASK_PD |
1866-
MLX5_MKEY_MASK_LR |
1867-
MLX5_MKEY_MASK_LW |
1868-
MLX5_MKEY_MASK_KEY |
1869-
MLX5_MKEY_MASK_RR |
1870-
MLX5_MKEY_MASK_RW |
1871-
MLX5_MKEY_MASK_A |
1872-
MLX5_MKEY_MASK_FREE;
1873-
umr->mkey_mask = cpu_to_be64(mask);
1893+
if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT) {
1894+
umr->mkey_mask = get_umr_update_mtt_mask();
1895+
umr->bsf_octowords = get_klm_octo(umrwr->target.offset);
1896+
umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN;
1897+
} else {
1898+
umr->mkey_mask = get_umr_reg_mr_mask();
1899+
}
18741900
} else {
1875-
umr->flags = 2 << 5; /* fail if free */
1876-
mask = MLX5_MKEY_MASK_FREE;
1877-
umr->mkey_mask = cpu_to_be64(mask);
1901+
umr->mkey_mask = get_umr_unreg_mr_mask();
18781902
}
18791903

18801904
if (!wr->num_sge)
1881-
umr->flags |= (1 << 7); /* inline */
1905+
umr->flags |= MLX5_UMR_INLINE;
18821906
}
18831907

18841908
static u8 get_umr_flags(int acc)
@@ -1895,7 +1919,7 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr,
18951919
{
18961920
memset(seg, 0, sizeof(*seg));
18971921
if (li) {
1898-
seg->status = 1 << 6;
1922+
seg->status = MLX5_MKEY_STATUS_FREE;
18991923
return;
19001924
}
19011925

@@ -1912,19 +1936,23 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr,
19121936

19131937
static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr)
19141938
{
1939+
struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg;
1940+
19151941
memset(seg, 0, sizeof(*seg));
19161942
if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) {
1917-
seg->status = 1 << 6;
1943+
seg->status = MLX5_MKEY_STATUS_FREE;
19181944
return;
19191945
}
19201946

1921-
seg->flags = convert_access(wr->wr.fast_reg.access_flags);
1922-
seg->flags_pd = cpu_to_be32(to_mpd((struct ib_pd *)wr->wr.fast_reg.page_list)->pdn);
1923-
seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start);
1924-
seg->len = cpu_to_be64(wr->wr.fast_reg.length);
1925-
seg->log2_page_size = wr->wr.fast_reg.page_shift;
1947+
seg->flags = convert_access(umrwr->access_flags);
1948+
if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) {
1949+
seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn);
1950+
seg->start_addr = cpu_to_be64(umrwr->target.virt_addr);
1951+
}
1952+
seg->len = cpu_to_be64(umrwr->length);
1953+
seg->log2_page_size = umrwr->page_shift;
19261954
seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 |
1927-
mlx5_mkey_variant(wr->wr.fast_reg.rkey));
1955+
mlx5_mkey_variant(umrwr->mkey));
19281956
}
19291957

19301958
static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg,

include/linux/mlx5/device.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ enum {
180180
MLX5_MKEY_MASK_FREE = 1ull << 29,
181181
};
182182

183+
enum {
184+
MLX5_UMR_TRANSLATION_OFFSET_EN = (1 << 4),
185+
186+
MLX5_UMR_CHECK_NOT_FREE = (1 << 5),
187+
MLX5_UMR_CHECK_FREE = (2 << 5),
188+
189+
MLX5_UMR_INLINE = (1 << 7),
190+
};
191+
183192
enum mlx5_event {
184193
MLX5_EVENT_TYPE_COMP = 0x0,
185194

@@ -776,6 +785,10 @@ struct mlx5_query_eq_mbox_out {
776785
struct mlx5_eq_context ctx;
777786
};
778787

788+
enum {
789+
MLX5_MKEY_STATUS_FREE = 1 << 6,
790+
};
791+
779792
struct mlx5_mkey_seg {
780793
/* This is a two bit field occupying bits 31-30.
781794
* bit 31 is always 0,

0 commit comments

Comments
 (0)