104876c12SAharon Landau // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 204876c12SAharon Landau /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */ 304876c12SAharon Landau 404876c12SAharon Landau #include "mlx5_ib.h" 504876c12SAharon Landau #include "umr.h" 604876c12SAharon Landau 78a8a5d37SAharon Landau static __be64 get_umr_enable_mr_mask(void) 88a8a5d37SAharon Landau { 98a8a5d37SAharon Landau u64 result; 108a8a5d37SAharon Landau 118a8a5d37SAharon Landau result = MLX5_MKEY_MASK_KEY | 128a8a5d37SAharon Landau MLX5_MKEY_MASK_FREE; 138a8a5d37SAharon Landau 148a8a5d37SAharon Landau return cpu_to_be64(result); 158a8a5d37SAharon Landau } 168a8a5d37SAharon Landau 178a8a5d37SAharon Landau static __be64 get_umr_disable_mr_mask(void) 188a8a5d37SAharon Landau { 198a8a5d37SAharon Landau u64 result; 208a8a5d37SAharon Landau 218a8a5d37SAharon Landau result = MLX5_MKEY_MASK_FREE; 228a8a5d37SAharon Landau 238a8a5d37SAharon Landau return cpu_to_be64(result); 248a8a5d37SAharon Landau } 258a8a5d37SAharon Landau 268a8a5d37SAharon Landau static __be64 get_umr_update_translation_mask(void) 278a8a5d37SAharon Landau { 288a8a5d37SAharon Landau u64 result; 298a8a5d37SAharon Landau 308a8a5d37SAharon Landau result = MLX5_MKEY_MASK_LEN | 318a8a5d37SAharon Landau MLX5_MKEY_MASK_PAGE_SIZE | 328a8a5d37SAharon Landau MLX5_MKEY_MASK_START_ADDR; 338a8a5d37SAharon Landau 348a8a5d37SAharon Landau return cpu_to_be64(result); 358a8a5d37SAharon Landau } 368a8a5d37SAharon Landau 37*ba6a9c68SAharon Landau static __be64 get_umr_update_access_mask(struct mlx5_ib_dev *dev) 388a8a5d37SAharon Landau { 398a8a5d37SAharon Landau u64 result; 408a8a5d37SAharon Landau 418a8a5d37SAharon Landau result = MLX5_MKEY_MASK_LR | 428a8a5d37SAharon Landau MLX5_MKEY_MASK_LW | 438a8a5d37SAharon Landau MLX5_MKEY_MASK_RR | 448a8a5d37SAharon Landau MLX5_MKEY_MASK_RW; 458a8a5d37SAharon Landau 46*ba6a9c68SAharon Landau if (MLX5_CAP_GEN(dev->mdev, atomic)) 478a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_A; 488a8a5d37SAharon Landau 49*ba6a9c68SAharon Landau if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) 508a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE; 518a8a5d37SAharon Landau 52*ba6a9c68SAharon Landau if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) 538a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ; 548a8a5d37SAharon Landau 558a8a5d37SAharon Landau return cpu_to_be64(result); 568a8a5d37SAharon Landau } 578a8a5d37SAharon Landau 588a8a5d37SAharon Landau static __be64 get_umr_update_pd_mask(void) 598a8a5d37SAharon Landau { 608a8a5d37SAharon Landau u64 result; 618a8a5d37SAharon Landau 628a8a5d37SAharon Landau result = MLX5_MKEY_MASK_PD; 638a8a5d37SAharon Landau 648a8a5d37SAharon Landau return cpu_to_be64(result); 658a8a5d37SAharon Landau } 668a8a5d37SAharon Landau 678a8a5d37SAharon Landau static int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask) 688a8a5d37SAharon Landau { 698a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_PAGE_SIZE && 708a8a5d37SAharon Landau MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled)) 718a8a5d37SAharon Landau return -EPERM; 728a8a5d37SAharon Landau 738a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_A && 748a8a5d37SAharon Landau MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled)) 758a8a5d37SAharon Landau return -EPERM; 768a8a5d37SAharon Landau 778a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE && 788a8a5d37SAharon Landau !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) 798a8a5d37SAharon Landau return -EPERM; 808a8a5d37SAharon Landau 818a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ && 828a8a5d37SAharon Landau !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) 838a8a5d37SAharon Landau return -EPERM; 848a8a5d37SAharon Landau 858a8a5d37SAharon Landau return 0; 868a8a5d37SAharon Landau } 878a8a5d37SAharon Landau 888a8a5d37SAharon Landau int mlx5r_umr_set_umr_ctrl_seg(struct mlx5_ib_dev *dev, 898a8a5d37SAharon Landau struct mlx5_wqe_umr_ctrl_seg *umr, 908a8a5d37SAharon Landau const struct ib_send_wr *wr) 918a8a5d37SAharon Landau { 928a8a5d37SAharon Landau const struct mlx5_umr_wr *umrwr = umr_wr(wr); 938a8a5d37SAharon Landau 948a8a5d37SAharon Landau memset(umr, 0, sizeof(*umr)); 958a8a5d37SAharon Landau 968a8a5d37SAharon Landau if (!umrwr->ignore_free_state) { 978a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE) 988a8a5d37SAharon Landau /* fail if free */ 998a8a5d37SAharon Landau umr->flags = MLX5_UMR_CHECK_FREE; 1008a8a5d37SAharon Landau else 1018a8a5d37SAharon Landau /* fail if not free */ 1028a8a5d37SAharon Landau umr->flags = MLX5_UMR_CHECK_NOT_FREE; 1038a8a5d37SAharon Landau } 1048a8a5d37SAharon Landau 1058a8a5d37SAharon Landau umr->xlt_octowords = 1068a8a5d37SAharon Landau cpu_to_be16(mlx5r_umr_get_xlt_octo(umrwr->xlt_size)); 1078a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) { 1088a8a5d37SAharon Landau u64 offset = mlx5r_umr_get_xlt_octo(umrwr->offset); 1098a8a5d37SAharon Landau 1108a8a5d37SAharon Landau umr->xlt_offset = cpu_to_be16(offset & 0xffff); 1118a8a5d37SAharon Landau umr->xlt_offset_47_16 = cpu_to_be32(offset >> 16); 1128a8a5d37SAharon Landau umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; 1138a8a5d37SAharon Landau } 1148a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION) 1158a8a5d37SAharon Landau umr->mkey_mask |= get_umr_update_translation_mask(); 1168a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) { 117*ba6a9c68SAharon Landau umr->mkey_mask |= get_umr_update_access_mask(dev); 1188a8a5d37SAharon Landau umr->mkey_mask |= get_umr_update_pd_mask(); 1198a8a5d37SAharon Landau } 1208a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR) 1218a8a5d37SAharon Landau umr->mkey_mask |= get_umr_enable_mr_mask(); 1228a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR) 1238a8a5d37SAharon Landau umr->mkey_mask |= get_umr_disable_mr_mask(); 1248a8a5d37SAharon Landau 1258a8a5d37SAharon Landau if (!wr->num_sge) 1268a8a5d37SAharon Landau umr->flags |= MLX5_UMR_INLINE; 1278a8a5d37SAharon Landau 1288a8a5d37SAharon Landau return umr_check_mkey_mask(dev, be64_to_cpu(umr->mkey_mask)); 1298a8a5d37SAharon Landau } 1308a8a5d37SAharon Landau 13104876c12SAharon Landau enum { 13204876c12SAharon Landau MAX_UMR_WR = 128, 13304876c12SAharon Landau }; 13404876c12SAharon Landau 13504876c12SAharon Landau static int mlx5r_umr_qp_rst2rts(struct mlx5_ib_dev *dev, struct ib_qp *qp) 13604876c12SAharon Landau { 13704876c12SAharon Landau struct ib_qp_attr attr = {}; 13804876c12SAharon Landau int ret; 13904876c12SAharon Landau 14004876c12SAharon Landau attr.qp_state = IB_QPS_INIT; 14104876c12SAharon Landau attr.port_num = 1; 14204876c12SAharon Landau ret = ib_modify_qp(qp, &attr, 14304876c12SAharon Landau IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT); 14404876c12SAharon Landau if (ret) { 14504876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n"); 14604876c12SAharon Landau return ret; 14704876c12SAharon Landau } 14804876c12SAharon Landau 14904876c12SAharon Landau memset(&attr, 0, sizeof(attr)); 15004876c12SAharon Landau attr.qp_state = IB_QPS_RTR; 15104876c12SAharon Landau 15204876c12SAharon Landau ret = ib_modify_qp(qp, &attr, IB_QP_STATE); 15304876c12SAharon Landau if (ret) { 15404876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n"); 15504876c12SAharon Landau return ret; 15604876c12SAharon Landau } 15704876c12SAharon Landau 15804876c12SAharon Landau memset(&attr, 0, sizeof(attr)); 15904876c12SAharon Landau attr.qp_state = IB_QPS_RTS; 16004876c12SAharon Landau ret = ib_modify_qp(qp, &attr, IB_QP_STATE); 16104876c12SAharon Landau if (ret) { 16204876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n"); 16304876c12SAharon Landau return ret; 16404876c12SAharon Landau } 16504876c12SAharon Landau 16604876c12SAharon Landau return 0; 16704876c12SAharon Landau } 16804876c12SAharon Landau 16904876c12SAharon Landau int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev) 17004876c12SAharon Landau { 17104876c12SAharon Landau struct ib_qp_init_attr init_attr = {}; 17204876c12SAharon Landau struct ib_pd *pd; 17304876c12SAharon Landau struct ib_cq *cq; 17404876c12SAharon Landau struct ib_qp *qp; 17504876c12SAharon Landau int ret; 17604876c12SAharon Landau 17704876c12SAharon Landau pd = ib_alloc_pd(&dev->ib_dev, 0); 17804876c12SAharon Landau if (IS_ERR(pd)) { 17904876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n"); 18004876c12SAharon Landau return PTR_ERR(pd); 18104876c12SAharon Landau } 18204876c12SAharon Landau 18304876c12SAharon Landau cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ); 18404876c12SAharon Landau if (IS_ERR(cq)) { 18504876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); 18604876c12SAharon Landau ret = PTR_ERR(cq); 18704876c12SAharon Landau goto destroy_pd; 18804876c12SAharon Landau } 18904876c12SAharon Landau 19004876c12SAharon Landau init_attr.send_cq = cq; 19104876c12SAharon Landau init_attr.recv_cq = cq; 19204876c12SAharon Landau init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; 19304876c12SAharon Landau init_attr.cap.max_send_wr = MAX_UMR_WR; 19404876c12SAharon Landau init_attr.cap.max_send_sge = 1; 19504876c12SAharon Landau init_attr.qp_type = MLX5_IB_QPT_REG_UMR; 19604876c12SAharon Landau init_attr.port_num = 1; 19704876c12SAharon Landau qp = ib_create_qp(pd, &init_attr); 19804876c12SAharon Landau if (IS_ERR(qp)) { 19904876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n"); 20004876c12SAharon Landau ret = PTR_ERR(qp); 20104876c12SAharon Landau goto destroy_cq; 20204876c12SAharon Landau } 20304876c12SAharon Landau 20404876c12SAharon Landau ret = mlx5r_umr_qp_rst2rts(dev, qp); 20504876c12SAharon Landau if (ret) 20604876c12SAharon Landau goto destroy_qp; 20704876c12SAharon Landau 20804876c12SAharon Landau dev->umrc.qp = qp; 20904876c12SAharon Landau dev->umrc.cq = cq; 21004876c12SAharon Landau dev->umrc.pd = pd; 21104876c12SAharon Landau 21204876c12SAharon Landau sema_init(&dev->umrc.sem, MAX_UMR_WR); 21304876c12SAharon Landau 21404876c12SAharon Landau return 0; 21504876c12SAharon Landau 21604876c12SAharon Landau destroy_qp: 21704876c12SAharon Landau ib_destroy_qp(qp); 21804876c12SAharon Landau destroy_cq: 21904876c12SAharon Landau ib_free_cq(cq); 22004876c12SAharon Landau destroy_pd: 22104876c12SAharon Landau ib_dealloc_pd(pd); 22204876c12SAharon Landau return ret; 22304876c12SAharon Landau } 22404876c12SAharon Landau 22504876c12SAharon Landau void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev) 22604876c12SAharon Landau { 22704876c12SAharon Landau ib_destroy_qp(dev->umrc.qp); 22804876c12SAharon Landau ib_free_cq(dev->umrc.cq); 22904876c12SAharon Landau ib_dealloc_pd(dev->umrc.pd); 23004876c12SAharon Landau } 231