Skip to content

Commit 0071b13

Browse files
dtatuleamstsirkin
authored andcommitted
vdpa/mlx5: Create direct MKEYs in parallel
Use the async interface to issue MTT MKEY creation. Extra care is taken at the allocation of FW input commands due to the MTT tables having variable sizes depending on MR. The indirect MKEY is still created synchronously at the end as the direct MKEYs need to be filled in. This makes create_user_mr() 3-5x faster, depending on the size of the MR. Signed-off-by: Dragos Tatulea <[email protected]> Reviewed-by: Cosmin Ratiu <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent db0a314 commit 0071b13

File tree

1 file changed

+98
-22
lines changed
  • drivers/vdpa/mlx5/core

1 file changed

+98
-22
lines changed

drivers/vdpa/mlx5/core/mr.c

Lines changed: 98 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,18 @@ static void populate_mtts(struct mlx5_vdpa_direct_mr *mr, __be64 *mtt)
4949
}
5050
}
5151

52-
static int create_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr)
52+
struct mlx5_create_mkey_mem {
53+
u8 out[MLX5_ST_SZ_BYTES(create_mkey_out)];
54+
u8 in[MLX5_ST_SZ_BYTES(create_mkey_in)];
55+
__be64 mtt[];
56+
};
57+
58+
static void fill_create_direct_mr(struct mlx5_vdpa_dev *mvdev,
59+
struct mlx5_vdpa_direct_mr *mr,
60+
struct mlx5_create_mkey_mem *mem)
5361
{
54-
int inlen;
62+
void *in = &mem->in;
5563
void *mkc;
56-
void *in;
57-
int err;
58-
59-
inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + roundup(MLX5_ST_SZ_BYTES(mtt) * mr->nsg, 16);
60-
in = kvzalloc(inlen, GFP_KERNEL);
61-
if (!in)
62-
return -ENOMEM;
6364

6465
MLX5_SET(create_mkey_in, in, uid, mvdev->res.uid);
6566
mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
@@ -76,18 +77,25 @@ static int create_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct
7677
MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
7778
get_octo_len(mr->end - mr->start, mr->log_size));
7879
populate_mtts(mr, MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt));
79-
err = mlx5_vdpa_create_mkey(mvdev, &mr->mr, in, inlen);
80-
kvfree(in);
81-
if (err) {
82-
mlx5_vdpa_warn(mvdev, "Failed to create direct MR\n");
83-
return err;
84-
}
8580

86-
return 0;
81+
MLX5_SET(create_mkey_in, in, opcode, MLX5_CMD_OP_CREATE_MKEY);
82+
MLX5_SET(create_mkey_in, in, uid, mvdev->res.uid);
83+
}
84+
85+
static void create_direct_mr_end(struct mlx5_vdpa_dev *mvdev,
86+
struct mlx5_vdpa_direct_mr *mr,
87+
struct mlx5_create_mkey_mem *mem)
88+
{
89+
u32 mkey_index = MLX5_GET(create_mkey_out, mem->out, mkey_index);
90+
91+
mr->mr = mlx5_idx_to_mkey(mkey_index);
8792
}
8893

8994
static void destroy_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr)
9095
{
96+
if (!mr->mr)
97+
return;
98+
9199
mlx5_vdpa_destroy_mkey(mvdev, mr->mr);
92100
}
93101

@@ -179,6 +187,76 @@ static int klm_byte_size(int nklms)
179187
return 16 * ALIGN(nklms, 4);
180188
}
181189

190+
#define MLX5_VDPA_MTT_ALIGN 16
191+
192+
static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
193+
{
194+
struct mlx5_vdpa_async_cmd *cmds;
195+
struct mlx5_vdpa_direct_mr *dmr;
196+
int err = 0;
197+
int i = 0;
198+
199+
cmds = kvcalloc(mr->num_directs, sizeof(*cmds), GFP_KERNEL);
200+
if (!cmds)
201+
return -ENOMEM;
202+
203+
list_for_each_entry(dmr, &mr->head, list) {
204+
struct mlx5_create_mkey_mem *cmd_mem;
205+
int mttlen, mttcount;
206+
207+
mttlen = roundup(MLX5_ST_SZ_BYTES(mtt) * dmr->nsg, MLX5_VDPA_MTT_ALIGN);
208+
mttcount = mttlen / sizeof(cmd_mem->mtt[0]);
209+
cmd_mem = kvcalloc(1, struct_size(cmd_mem, mtt, mttcount), GFP_KERNEL);
210+
if (!cmd_mem) {
211+
err = -ENOMEM;
212+
goto done;
213+
}
214+
215+
cmds[i].out = cmd_mem->out;
216+
cmds[i].outlen = sizeof(cmd_mem->out);
217+
cmds[i].in = cmd_mem->in;
218+
cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount);
219+
220+
fill_create_direct_mr(mvdev, dmr, cmd_mem);
221+
222+
i++;
223+
}
224+
225+
err = mlx5_vdpa_exec_async_cmds(mvdev, cmds, mr->num_directs);
226+
if (err) {
227+
228+
mlx5_vdpa_err(mvdev, "error issuing MTT mkey creation for direct mrs: %d\n", err);
229+
goto done;
230+
}
231+
232+
i = 0;
233+
list_for_each_entry(dmr, &mr->head, list) {
234+
struct mlx5_vdpa_async_cmd *cmd = &cmds[i++];
235+
struct mlx5_create_mkey_mem *cmd_mem;
236+
237+
cmd_mem = container_of(cmd->out, struct mlx5_create_mkey_mem, out);
238+
239+
if (!cmd->err) {
240+
create_direct_mr_end(mvdev, dmr, cmd_mem);
241+
} else {
242+
err = err ? err : cmd->err;
243+
mlx5_vdpa_err(mvdev, "error creating MTT mkey [0x%llx, 0x%llx]: %d\n",
244+
dmr->start, dmr->end, cmd->err);
245+
}
246+
}
247+
248+
done:
249+
for (i = i-1; i >= 0; i--) {
250+
struct mlx5_create_mkey_mem *cmd_mem;
251+
252+
cmd_mem = container_of(cmds[i].out, struct mlx5_create_mkey_mem, out);
253+
kvfree(cmd_mem);
254+
}
255+
256+
kvfree(cmds);
257+
return err;
258+
}
259+
182260
static int create_indirect_key(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
183261
{
184262
int inlen;
@@ -279,14 +357,8 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
279357
goto err_map;
280358
}
281359

282-
err = create_direct_mr(mvdev, mr);
283-
if (err)
284-
goto err_direct;
285-
286360
return 0;
287361

288-
err_direct:
289-
dma_unmap_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
290362
err_map:
291363
sg_free_table(&mr->sg_head);
292364
return err;
@@ -401,6 +473,10 @@ static int create_user_mr(struct mlx5_vdpa_dev *mvdev,
401473
if (err)
402474
goto err_chain;
403475

476+
err = create_direct_keys(mvdev, mr);
477+
if (err)
478+
goto err_chain;
479+
404480
/* Create the memory key that defines the guests's address space. This
405481
* memory key refers to the direct keys that contain the MTT
406482
* translations

0 commit comments

Comments
 (0)