aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoa Osherovich <noaos@mellanox.com>2016-02-29 09:46:51 -0500
committerDoug Ledford <dledford@redhat.com>2016-03-01 11:04:31 -0500
commit56e11d628c5d0553d9fc2ca1855144970e6b9eb6 (patch)
treeeee07d6af5a1f127a902b7f14bbb4e5407105a4d
parent395a8e4c32ea2d032cf803f52f2e00983f91722d (diff)
IB/mlx5: Added support for re-registration of MRs
This patch adds support for re-registration of memory regions in MLX5. The functionality is basically the same as deregister followed by register, but attempts to reuse the existing resources as much as possible. Original memory keys are kept if possible, saving the need to communicate new ones to remote peers. Signed-off-by: Noa Osherovich <noaos@mellanox.com> Reviewed-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/mlx5/main.c2
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h9
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c168
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c51
4 files changed, 227 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index d4224fab98f7..16f7d0b41c04 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2233,6 +2233,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
2233 (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | 2233 (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
2234 (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | 2234 (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
2235 (1ull << IB_USER_VERBS_CMD_REG_MR) | 2235 (1ull << IB_USER_VERBS_CMD_REG_MR) |
2236 (1ull << IB_USER_VERBS_CMD_REREG_MR) |
2236 (1ull << IB_USER_VERBS_CMD_DEREG_MR) | 2237 (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
2237 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | 2238 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
2238 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | 2239 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
@@ -2293,6 +2294,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
2293 dev->ib_dev.req_notify_cq = mlx5_ib_arm_cq; 2294 dev->ib_dev.req_notify_cq = mlx5_ib_arm_cq;
2294 dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr; 2295 dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr;
2295 dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr; 2296 dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr;
2297 dev->ib_dev.rereg_user_mr = mlx5_ib_rereg_user_mr;
2296 dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr; 2298 dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr;
2297 dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach; 2299 dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach;
2298 dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach; 2300 dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 0142efb5dd9c..f84ec2b6425c 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -162,6 +162,11 @@ struct mlx5_ib_flow_db {
162#define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START 162#define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START
163#define MLX5_IB_SEND_UMR_FAIL_IF_FREE (IB_SEND_RESERVED_START << 1) 163#define MLX5_IB_SEND_UMR_FAIL_IF_FREE (IB_SEND_RESERVED_START << 1)
164#define MLX5_IB_SEND_UMR_UPDATE_MTT (IB_SEND_RESERVED_START << 2) 164#define MLX5_IB_SEND_UMR_UPDATE_MTT (IB_SEND_RESERVED_START << 2)
165
166#define MLX5_IB_SEND_UMR_UPDATE_TRANSLATION (IB_SEND_RESERVED_START << 3)
167#define MLX5_IB_SEND_UMR_UPDATE_PD (IB_SEND_RESERVED_START << 4)
168#define MLX5_IB_SEND_UMR_UPDATE_ACCESS IB_SEND_RESERVED_END
169
165#define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1 170#define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1
166/* 171/*
167 * IB_QPT_GSI creates the software wrapper around GSI, and MLX5_IB_QPT_HW_GSI 172 * IB_QPT_GSI creates the software wrapper around GSI, and MLX5_IB_QPT_HW_GSI
@@ -453,6 +458,7 @@ struct mlx5_ib_mr {
453 struct mlx5_core_sig_ctx *sig; 458 struct mlx5_core_sig_ctx *sig;
454 int live; 459 int live;
455 void *descs_alloc; 460 void *descs_alloc;
461 int access_flags; /* Needed for rereg MR */
456}; 462};
457 463
458struct mlx5_ib_umr_context { 464struct mlx5_ib_umr_context {
@@ -689,6 +695,9 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
689 struct ib_udata *udata); 695 struct ib_udata *udata);
690int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index, 696int mlx5_ib_update_mtt(struct mlx5_ib_mr *mr, u64 start_page_index,
691 int npages, int zap); 697 int npages, int zap);
698int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
699 u64 length, u64 virt_addr, int access_flags,
700 struct ib_pd *pd, struct ib_udata *udata);
692int mlx5_ib_dereg_mr(struct ib_mr *ibmr); 701int mlx5_ib_dereg_mr(struct ib_mr *ibmr);
693struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd, 702struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
694 enum ib_mr_type mr_type, 703 enum ib_mr_type mr_type,
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 9d6dade31b5f..cf26cd1f1fa2 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -77,6 +77,12 @@ static int order2idx(struct mlx5_ib_dev *dev, int order)
77 return order - cache->ent[0].order; 77 return order - cache->ent[0].order;
78} 78}
79 79
80static bool use_umr_mtt_update(struct mlx5_ib_mr *mr, u64 start, u64 length)
81{
82 return ((u64)1 << mr->order) * MLX5_ADAPTER_PAGE_SIZE >=
83 length + (start & (MLX5_ADAPTER_PAGE_SIZE - 1));
84}
85
80#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING 86#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
81static void update_odp_mr(struct mlx5_ib_mr *mr) 87static void update_odp_mr(struct mlx5_ib_mr *mr)
82{ 88{
@@ -1127,6 +1133,7 @@ static void set_mr_fileds(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
1127 mr->ibmr.lkey = mr->mmr.key; 1133 mr->ibmr.lkey = mr->mmr.key;
1128 mr->ibmr.rkey = mr->mmr.key; 1134 mr->ibmr.rkey = mr->mmr.key;
1129 mr->ibmr.length = length; 1135 mr->ibmr.length = length;
1136 mr->access_flags = access_flags;
1130} 1137}
1131 1138
1132struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, 1139struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
@@ -1222,6 +1229,167 @@ error:
1222 return err; 1229 return err;
1223} 1230}
1224 1231
1232static int rereg_umr(struct ib_pd *pd, struct mlx5_ib_mr *mr, u64 virt_addr,
1233 u64 length, int npages, int page_shift, int order,
1234 int access_flags, int flags)
1235{
1236 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1237 struct device *ddev = dev->ib_dev.dma_device;
1238 struct mlx5_ib_umr_context umr_context;
1239 struct ib_send_wr *bad;
1240 struct mlx5_umr_wr umrwr = {};
1241 struct ib_sge sg;
1242 struct umr_common *umrc = &dev->umrc;
1243 dma_addr_t dma = 0;
1244 __be64 *mr_pas = NULL;
1245 int size;
1246 int err;
1247
1248 umrwr.wr.wr_id = (u64)(unsigned long)&umr_context;
1249 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1250
1251 if (flags & IB_MR_REREG_TRANS) {
1252 err = dma_map_mr_pas(dev, mr->umem, npages, page_shift, &size,
1253 &mr_pas, &dma);
1254 if (err)
1255 return err;
1256
1257 umrwr.target.virt_addr = virt_addr;
1258 umrwr.length = length;
1259 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_TRANSLATION;
1260 }
1261
1262 prep_umr_wqe_common(pd, &umrwr.wr, &sg, dma, npages, mr->mmr.key,
1263 page_shift);
1264
1265 if (flags & IB_MR_REREG_PD) {
1266 umrwr.pd = pd;
1267 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_PD;
1268 }
1269
1270 if (flags & IB_MR_REREG_ACCESS) {
1271 umrwr.access_flags = access_flags;
1272 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_ACCESS;
1273 }
1274
1275 mlx5_ib_init_umr_context(&umr_context);
1276
1277 /* post send request to UMR QP */
1278 down(&umrc->sem);
1279 err = ib_post_send(umrc->qp, &umrwr.wr, &bad);
1280
1281 if (err) {
1282 mlx5_ib_warn(dev, "post send failed, err %d\n", err);
1283 } else {
1284 wait_for_completion(&umr_context.done);
1285 if (umr_context.status != IB_WC_SUCCESS) {
1286 mlx5_ib_warn(dev, "reg umr failed (%u)\n",
1287 umr_context.status);
1288 err = -EFAULT;
1289 }
1290 }
1291
1292 up(&umrc->sem);
1293 if (flags & IB_MR_REREG_TRANS) {
1294 dma_unmap_single(ddev, dma, size, DMA_TO_DEVICE);
1295 kfree(mr_pas);
1296 }
1297 return err;
1298}
1299
1300int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
1301 u64 length, u64 virt_addr, int new_access_flags,
1302 struct ib_pd *new_pd, struct ib_udata *udata)
1303{
1304 struct mlx5_ib_dev *dev = to_mdev(ib_mr->device);
1305 struct mlx5_ib_mr *mr = to_mmr(ib_mr);
1306 struct ib_pd *pd = (flags & IB_MR_REREG_PD) ? new_pd : ib_mr->pd;
1307 int access_flags = flags & IB_MR_REREG_ACCESS ?
1308 new_access_flags :
1309 mr->access_flags;
1310 u64 addr = (flags & IB_MR_REREG_TRANS) ? virt_addr : mr->umem->address;
1311 u64 len = (flags & IB_MR_REREG_TRANS) ? length : mr->umem->length;
1312 int page_shift = 0;
1313 int npages = 0;
1314 int ncont = 0;
1315 int order = 0;
1316 int err;
1317
1318 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1319 start, virt_addr, length, access_flags);
1320
1321 if (flags != IB_MR_REREG_PD) {
1322 /*
1323 * Replace umem. This needs to be done whether or not UMR is
1324 * used.
1325 */
1326 flags |= IB_MR_REREG_TRANS;
1327 ib_umem_release(mr->umem);
1328 mr->umem = mr_umem_get(pd, addr, len, access_flags, &npages,
1329 &page_shift, &ncont, &order);
1330 if (IS_ERR(mr->umem)) {
1331 err = PTR_ERR(mr->umem);
1332 mr->umem = NULL;
1333 return err;
1334 }
1335 }
1336
1337 if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
1338 /*
1339 * UMR can't be used - MKey needs to be replaced.
1340 */
1341 if (mr->umred) {
1342 err = unreg_umr(dev, mr);
1343 if (err)
1344 mlx5_ib_warn(dev, "Failed to unregister MR\n");
1345 } else {
1346 err = destroy_mkey(dev, mr);
1347 if (err)
1348 mlx5_ib_warn(dev, "Failed to destroy MKey\n");
1349 }
1350 if (err)
1351 return err;
1352
1353 mr = reg_create(ib_mr, pd, addr, len, mr->umem, ncont,
1354 page_shift, access_flags);
1355
1356 if (IS_ERR(mr))
1357 return PTR_ERR(mr);
1358
1359 mr->umred = 0;
1360 } else {
1361 /*
1362 * Send a UMR WQE
1363 */
1364 err = rereg_umr(pd, mr, addr, len, npages, page_shift,
1365 order, access_flags, flags);
1366 if (err) {
1367 mlx5_ib_warn(dev, "Failed to rereg UMR\n");
1368 return err;
1369 }
1370 }
1371
1372 if (flags & IB_MR_REREG_PD) {
1373 ib_mr->pd = pd;
1374 mr->mmr.pd = to_mpd(pd)->pdn;
1375 }
1376
1377 if (flags & IB_MR_REREG_ACCESS)
1378 mr->access_flags = access_flags;
1379
1380 if (flags & IB_MR_REREG_TRANS) {
1381 atomic_sub(mr->npages, &dev->mdev->priv.reg_pages);
1382 set_mr_fileds(dev, mr, npages, len, access_flags);
1383 mr->mmr.iova = addr;
1384 mr->mmr.size = len;
1385 }
1386#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
1387 update_odp_mr(mr);
1388#endif
1389
1390 return 0;
1391}
1392
1225static int 1393static int
1226mlx5_alloc_priv_descs(struct ib_device *device, 1394mlx5_alloc_priv_descs(struct ib_device *device,
1227 struct mlx5_ib_mr *mr, 1395 struct mlx5_ib_mr *mr,
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 85cf9c4a9500..295eb2a54851 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -2678,6 +2678,44 @@ static __be64 get_umr_update_mtt_mask(void)
2678 return cpu_to_be64(result); 2678 return cpu_to_be64(result);
2679} 2679}
2680 2680
2681static __be64 get_umr_update_translation_mask(void)
2682{
2683 u64 result;
2684
2685 result = MLX5_MKEY_MASK_LEN |
2686 MLX5_MKEY_MASK_PAGE_SIZE |
2687 MLX5_MKEY_MASK_START_ADDR |
2688 MLX5_MKEY_MASK_KEY |
2689 MLX5_MKEY_MASK_FREE;
2690
2691 return cpu_to_be64(result);
2692}
2693
2694static __be64 get_umr_update_access_mask(void)
2695{
2696 u64 result;
2697
2698 result = MLX5_MKEY_MASK_LW |
2699 MLX5_MKEY_MASK_RR |
2700 MLX5_MKEY_MASK_RW |
2701 MLX5_MKEY_MASK_A |
2702 MLX5_MKEY_MASK_KEY |
2703 MLX5_MKEY_MASK_FREE;
2704
2705 return cpu_to_be64(result);
2706}
2707
2708static __be64 get_umr_update_pd_mask(void)
2709{
2710 u64 result;
2711
2712 result = MLX5_MKEY_MASK_PD |
2713 MLX5_MKEY_MASK_KEY |
2714 MLX5_MKEY_MASK_FREE;
2715
2716 return cpu_to_be64(result);
2717}
2718
2681static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, 2719static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
2682 struct ib_send_wr *wr) 2720 struct ib_send_wr *wr)
2683{ 2721{
@@ -2696,9 +2734,15 @@ static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
2696 umr->mkey_mask = get_umr_update_mtt_mask(); 2734 umr->mkey_mask = get_umr_update_mtt_mask();
2697 umr->bsf_octowords = get_klm_octo(umrwr->target.offset); 2735 umr->bsf_octowords = get_klm_octo(umrwr->target.offset);
2698 umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; 2736 umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN;
2699 } else {
2700 umr->mkey_mask = get_umr_reg_mr_mask();
2701 } 2737 }
2738 if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION)
2739 umr->mkey_mask |= get_umr_update_translation_mask();
2740 if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_ACCESS)
2741 umr->mkey_mask |= get_umr_update_access_mask();
2742 if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD)
2743 umr->mkey_mask |= get_umr_update_pd_mask();
2744 if (!umr->mkey_mask)
2745 umr->mkey_mask = get_umr_reg_mr_mask();
2702 } else { 2746 } else {
2703 umr->mkey_mask = get_umr_unreg_mr_mask(); 2747 umr->mkey_mask = get_umr_unreg_mr_mask();
2704 } 2748 }
@@ -2750,7 +2794,8 @@ static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *w
2750 2794
2751 seg->flags = convert_access(umrwr->access_flags); 2795 seg->flags = convert_access(umrwr->access_flags);
2752 if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) { 2796 if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) {
2753 seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn); 2797 if (umrwr->pd)
2798 seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn);
2754 seg->start_addr = cpu_to_be64(umrwr->target.virt_addr); 2799 seg->start_addr = cpu_to_be64(umrwr->target.virt_addr);
2755 } 2800 }
2756 seg->len = cpu_to_be64(umrwr->length); 2801 seg->len = cpu_to_be64(umrwr->length);