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 7*8a8a5d37SAharon Landau static __be64 get_umr_enable_mr_mask(void) 8*8a8a5d37SAharon Landau { 9*8a8a5d37SAharon Landau u64 result; 10*8a8a5d37SAharon Landau 11*8a8a5d37SAharon Landau result = MLX5_MKEY_MASK_KEY | 12*8a8a5d37SAharon Landau MLX5_MKEY_MASK_FREE; 13*8a8a5d37SAharon Landau 14*8a8a5d37SAharon Landau return cpu_to_be64(result); 15*8a8a5d37SAharon Landau } 16*8a8a5d37SAharon Landau 17*8a8a5d37SAharon Landau static __be64 get_umr_disable_mr_mask(void) 18*8a8a5d37SAharon Landau { 19*8a8a5d37SAharon Landau u64 result; 20*8a8a5d37SAharon Landau 21*8a8a5d37SAharon Landau result = MLX5_MKEY_MASK_FREE; 22*8a8a5d37SAharon Landau 23*8a8a5d37SAharon Landau return cpu_to_be64(result); 24*8a8a5d37SAharon Landau } 25*8a8a5d37SAharon Landau 26*8a8a5d37SAharon Landau static __be64 get_umr_update_translation_mask(void) 27*8a8a5d37SAharon Landau { 28*8a8a5d37SAharon Landau u64 result; 29*8a8a5d37SAharon Landau 30*8a8a5d37SAharon Landau result = MLX5_MKEY_MASK_LEN | 31*8a8a5d37SAharon Landau MLX5_MKEY_MASK_PAGE_SIZE | 32*8a8a5d37SAharon Landau MLX5_MKEY_MASK_START_ADDR; 33*8a8a5d37SAharon Landau 34*8a8a5d37SAharon Landau return cpu_to_be64(result); 35*8a8a5d37SAharon Landau } 36*8a8a5d37SAharon Landau 37*8a8a5d37SAharon Landau static __be64 get_umr_update_access_mask(int atomic, 38*8a8a5d37SAharon Landau int relaxed_ordering_write, 39*8a8a5d37SAharon Landau int relaxed_ordering_read) 40*8a8a5d37SAharon Landau { 41*8a8a5d37SAharon Landau u64 result; 42*8a8a5d37SAharon Landau 43*8a8a5d37SAharon Landau result = MLX5_MKEY_MASK_LR | 44*8a8a5d37SAharon Landau MLX5_MKEY_MASK_LW | 45*8a8a5d37SAharon Landau MLX5_MKEY_MASK_RR | 46*8a8a5d37SAharon Landau MLX5_MKEY_MASK_RW; 47*8a8a5d37SAharon Landau 48*8a8a5d37SAharon Landau if (atomic) 49*8a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_A; 50*8a8a5d37SAharon Landau 51*8a8a5d37SAharon Landau if (relaxed_ordering_write) 52*8a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE; 53*8a8a5d37SAharon Landau 54*8a8a5d37SAharon Landau if (relaxed_ordering_read) 55*8a8a5d37SAharon Landau result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ; 56*8a8a5d37SAharon Landau 57*8a8a5d37SAharon Landau return cpu_to_be64(result); 58*8a8a5d37SAharon Landau } 59*8a8a5d37SAharon Landau 60*8a8a5d37SAharon Landau static __be64 get_umr_update_pd_mask(void) 61*8a8a5d37SAharon Landau { 62*8a8a5d37SAharon Landau u64 result; 63*8a8a5d37SAharon Landau 64*8a8a5d37SAharon Landau result = MLX5_MKEY_MASK_PD; 65*8a8a5d37SAharon Landau 66*8a8a5d37SAharon Landau return cpu_to_be64(result); 67*8a8a5d37SAharon Landau } 68*8a8a5d37SAharon Landau 69*8a8a5d37SAharon Landau static int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask) 70*8a8a5d37SAharon Landau { 71*8a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_PAGE_SIZE && 72*8a8a5d37SAharon Landau MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled)) 73*8a8a5d37SAharon Landau return -EPERM; 74*8a8a5d37SAharon Landau 75*8a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_A && 76*8a8a5d37SAharon Landau MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled)) 77*8a8a5d37SAharon Landau return -EPERM; 78*8a8a5d37SAharon Landau 79*8a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE && 80*8a8a5d37SAharon Landau !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) 81*8a8a5d37SAharon Landau return -EPERM; 82*8a8a5d37SAharon Landau 83*8a8a5d37SAharon Landau if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ && 84*8a8a5d37SAharon Landau !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) 85*8a8a5d37SAharon Landau return -EPERM; 86*8a8a5d37SAharon Landau 87*8a8a5d37SAharon Landau return 0; 88*8a8a5d37SAharon Landau } 89*8a8a5d37SAharon Landau 90*8a8a5d37SAharon Landau int mlx5r_umr_set_umr_ctrl_seg(struct mlx5_ib_dev *dev, 91*8a8a5d37SAharon Landau struct mlx5_wqe_umr_ctrl_seg *umr, 92*8a8a5d37SAharon Landau const struct ib_send_wr *wr) 93*8a8a5d37SAharon Landau { 94*8a8a5d37SAharon Landau const struct mlx5_umr_wr *umrwr = umr_wr(wr); 95*8a8a5d37SAharon Landau 96*8a8a5d37SAharon Landau memset(umr, 0, sizeof(*umr)); 97*8a8a5d37SAharon Landau 98*8a8a5d37SAharon Landau if (!umrwr->ignore_free_state) { 99*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE) 100*8a8a5d37SAharon Landau /* fail if free */ 101*8a8a5d37SAharon Landau umr->flags = MLX5_UMR_CHECK_FREE; 102*8a8a5d37SAharon Landau else 103*8a8a5d37SAharon Landau /* fail if not free */ 104*8a8a5d37SAharon Landau umr->flags = MLX5_UMR_CHECK_NOT_FREE; 105*8a8a5d37SAharon Landau } 106*8a8a5d37SAharon Landau 107*8a8a5d37SAharon Landau umr->xlt_octowords = 108*8a8a5d37SAharon Landau cpu_to_be16(mlx5r_umr_get_xlt_octo(umrwr->xlt_size)); 109*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) { 110*8a8a5d37SAharon Landau u64 offset = mlx5r_umr_get_xlt_octo(umrwr->offset); 111*8a8a5d37SAharon Landau 112*8a8a5d37SAharon Landau umr->xlt_offset = cpu_to_be16(offset & 0xffff); 113*8a8a5d37SAharon Landau umr->xlt_offset_47_16 = cpu_to_be32(offset >> 16); 114*8a8a5d37SAharon Landau umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; 115*8a8a5d37SAharon Landau } 116*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION) 117*8a8a5d37SAharon Landau umr->mkey_mask |= get_umr_update_translation_mask(); 118*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) { 119*8a8a5d37SAharon Landau umr->mkey_mask |= get_umr_update_access_mask( 120*8a8a5d37SAharon Landau !!MLX5_CAP_GEN(dev->mdev, atomic), 121*8a8a5d37SAharon Landau !!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr), 122*8a8a5d37SAharon Landau !!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)); 123*8a8a5d37SAharon Landau umr->mkey_mask |= get_umr_update_pd_mask(); 124*8a8a5d37SAharon Landau } 125*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR) 126*8a8a5d37SAharon Landau umr->mkey_mask |= get_umr_enable_mr_mask(); 127*8a8a5d37SAharon Landau if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR) 128*8a8a5d37SAharon Landau umr->mkey_mask |= get_umr_disable_mr_mask(); 129*8a8a5d37SAharon Landau 130*8a8a5d37SAharon Landau if (!wr->num_sge) 131*8a8a5d37SAharon Landau umr->flags |= MLX5_UMR_INLINE; 132*8a8a5d37SAharon Landau 133*8a8a5d37SAharon Landau return umr_check_mkey_mask(dev, be64_to_cpu(umr->mkey_mask)); 134*8a8a5d37SAharon Landau } 135*8a8a5d37SAharon Landau 13604876c12SAharon Landau enum { 13704876c12SAharon Landau MAX_UMR_WR = 128, 13804876c12SAharon Landau }; 13904876c12SAharon Landau 14004876c12SAharon Landau static int mlx5r_umr_qp_rst2rts(struct mlx5_ib_dev *dev, struct ib_qp *qp) 14104876c12SAharon Landau { 14204876c12SAharon Landau struct ib_qp_attr attr = {}; 14304876c12SAharon Landau int ret; 14404876c12SAharon Landau 14504876c12SAharon Landau attr.qp_state = IB_QPS_INIT; 14604876c12SAharon Landau attr.port_num = 1; 14704876c12SAharon Landau ret = ib_modify_qp(qp, &attr, 14804876c12SAharon Landau IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT); 14904876c12SAharon Landau if (ret) { 15004876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n"); 15104876c12SAharon Landau return ret; 15204876c12SAharon Landau } 15304876c12SAharon Landau 15404876c12SAharon Landau memset(&attr, 0, sizeof(attr)); 15504876c12SAharon Landau attr.qp_state = IB_QPS_RTR; 15604876c12SAharon Landau 15704876c12SAharon Landau ret = ib_modify_qp(qp, &attr, IB_QP_STATE); 15804876c12SAharon Landau if (ret) { 15904876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n"); 16004876c12SAharon Landau return ret; 16104876c12SAharon Landau } 16204876c12SAharon Landau 16304876c12SAharon Landau memset(&attr, 0, sizeof(attr)); 16404876c12SAharon Landau attr.qp_state = IB_QPS_RTS; 16504876c12SAharon Landau ret = ib_modify_qp(qp, &attr, IB_QP_STATE); 16604876c12SAharon Landau if (ret) { 16704876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n"); 16804876c12SAharon Landau return ret; 16904876c12SAharon Landau } 17004876c12SAharon Landau 17104876c12SAharon Landau return 0; 17204876c12SAharon Landau } 17304876c12SAharon Landau 17404876c12SAharon Landau int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev) 17504876c12SAharon Landau { 17604876c12SAharon Landau struct ib_qp_init_attr init_attr = {}; 17704876c12SAharon Landau struct ib_pd *pd; 17804876c12SAharon Landau struct ib_cq *cq; 17904876c12SAharon Landau struct ib_qp *qp; 18004876c12SAharon Landau int ret; 18104876c12SAharon Landau 18204876c12SAharon Landau pd = ib_alloc_pd(&dev->ib_dev, 0); 18304876c12SAharon Landau if (IS_ERR(pd)) { 18404876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n"); 18504876c12SAharon Landau return PTR_ERR(pd); 18604876c12SAharon Landau } 18704876c12SAharon Landau 18804876c12SAharon Landau cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ); 18904876c12SAharon Landau if (IS_ERR(cq)) { 19004876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); 19104876c12SAharon Landau ret = PTR_ERR(cq); 19204876c12SAharon Landau goto destroy_pd; 19304876c12SAharon Landau } 19404876c12SAharon Landau 19504876c12SAharon Landau init_attr.send_cq = cq; 19604876c12SAharon Landau init_attr.recv_cq = cq; 19704876c12SAharon Landau init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; 19804876c12SAharon Landau init_attr.cap.max_send_wr = MAX_UMR_WR; 19904876c12SAharon Landau init_attr.cap.max_send_sge = 1; 20004876c12SAharon Landau init_attr.qp_type = MLX5_IB_QPT_REG_UMR; 20104876c12SAharon Landau init_attr.port_num = 1; 20204876c12SAharon Landau qp = ib_create_qp(pd, &init_attr); 20304876c12SAharon Landau if (IS_ERR(qp)) { 20404876c12SAharon Landau mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n"); 20504876c12SAharon Landau ret = PTR_ERR(qp); 20604876c12SAharon Landau goto destroy_cq; 20704876c12SAharon Landau } 20804876c12SAharon Landau 20904876c12SAharon Landau ret = mlx5r_umr_qp_rst2rts(dev, qp); 21004876c12SAharon Landau if (ret) 21104876c12SAharon Landau goto destroy_qp; 21204876c12SAharon Landau 21304876c12SAharon Landau dev->umrc.qp = qp; 21404876c12SAharon Landau dev->umrc.cq = cq; 21504876c12SAharon Landau dev->umrc.pd = pd; 21604876c12SAharon Landau 21704876c12SAharon Landau sema_init(&dev->umrc.sem, MAX_UMR_WR); 21804876c12SAharon Landau 21904876c12SAharon Landau return 0; 22004876c12SAharon Landau 22104876c12SAharon Landau destroy_qp: 22204876c12SAharon Landau ib_destroy_qp(qp); 22304876c12SAharon Landau destroy_cq: 22404876c12SAharon Landau ib_free_cq(cq); 22504876c12SAharon Landau destroy_pd: 22604876c12SAharon Landau ib_dealloc_pd(pd); 22704876c12SAharon Landau return ret; 22804876c12SAharon Landau } 22904876c12SAharon Landau 23004876c12SAharon Landau void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev) 23104876c12SAharon Landau { 23204876c12SAharon Landau ib_destroy_qp(dev->umrc.qp); 23304876c12SAharon Landau ib_free_cq(dev->umrc.cq); 23404876c12SAharon Landau ib_dealloc_pd(dev->umrc.pd); 23504876c12SAharon Landau } 236