192 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2022, Microsoft Corporation. All rights reserved.4 */5 6#include "mana_ib.h"7 8#define VALID_MR_FLAGS \9 (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ)10 11static enum gdma_mr_access_flags12mana_ib_verbs_to_gdma_access_flags(int access_flags)13{14 enum gdma_mr_access_flags flags = GDMA_ACCESS_FLAG_LOCAL_READ;15 16 if (access_flags & IB_ACCESS_LOCAL_WRITE)17 flags |= GDMA_ACCESS_FLAG_LOCAL_WRITE;18 19 if (access_flags & IB_ACCESS_REMOTE_WRITE)20 flags |= GDMA_ACCESS_FLAG_REMOTE_WRITE;21 22 if (access_flags & IB_ACCESS_REMOTE_READ)23 flags |= GDMA_ACCESS_FLAG_REMOTE_READ;24 25 return flags;26}27 28static int mana_ib_gd_create_mr(struct mana_ib_dev *dev, struct mana_ib_mr *mr,29 struct gdma_create_mr_params *mr_params)30{31 struct gdma_create_mr_response resp = {};32 struct gdma_create_mr_request req = {};33 struct gdma_context *gc = mdev_to_gc(dev);34 int err;35 36 mana_gd_init_req_hdr(&req.hdr, GDMA_CREATE_MR, sizeof(req),37 sizeof(resp));38 req.pd_handle = mr_params->pd_handle;39 req.mr_type = mr_params->mr_type;40 41 switch (mr_params->mr_type) {42 case GDMA_MR_TYPE_GVA:43 req.gva.dma_region_handle = mr_params->gva.dma_region_handle;44 req.gva.virtual_address = mr_params->gva.virtual_address;45 req.gva.access_flags = mr_params->gva.access_flags;46 break;47 48 default:49 ibdev_dbg(&dev->ib_dev,50 "invalid param (GDMA_MR_TYPE) passed, type %d\n",51 req.mr_type);52 return -EINVAL;53 }54 55 err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);56 57 if (err || resp.hdr.status) {58 ibdev_dbg(&dev->ib_dev, "Failed to create mr %d, %u", err,59 resp.hdr.status);60 if (!err)61 err = -EPROTO;62 63 return err;64 }65 66 mr->ibmr.lkey = resp.lkey;67 mr->ibmr.rkey = resp.rkey;68 mr->mr_handle = resp.mr_handle;69 70 return 0;71}72 73static int mana_ib_gd_destroy_mr(struct mana_ib_dev *dev, u64 mr_handle)74{75 struct gdma_destroy_mr_response resp = {};76 struct gdma_destroy_mr_request req = {};77 struct gdma_context *gc = mdev_to_gc(dev);78 int err;79 80 mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_MR, sizeof(req),81 sizeof(resp));82 83 req.mr_handle = mr_handle;84 85 err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);86 if (err || resp.hdr.status) {87 dev_err(gc->dev, "Failed to destroy MR: %d, 0x%x\n", err,88 resp.hdr.status);89 if (!err)90 err = -EPROTO;91 return err;92 }93 94 return 0;95}96 97struct ib_mr *mana_ib_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length,98 u64 iova, int access_flags,99 struct ib_udata *udata)100{101 struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd);102 struct gdma_create_mr_params mr_params = {};103 struct ib_device *ibdev = ibpd->device;104 struct mana_ib_dev *dev;105 struct mana_ib_mr *mr;106 u64 dma_region_handle;107 int err;108 109 dev = container_of(ibdev, struct mana_ib_dev, ib_dev);110 111 ibdev_dbg(ibdev,112 "start 0x%llx, iova 0x%llx length 0x%llx access_flags 0x%x",113 start, iova, length, access_flags);114 115 access_flags &= ~IB_ACCESS_OPTIONAL;116 if (access_flags & ~VALID_MR_FLAGS)117 return ERR_PTR(-EINVAL);118 119 mr = kzalloc(sizeof(*mr), GFP_KERNEL);120 if (!mr)121 return ERR_PTR(-ENOMEM);122 123 mr->umem = ib_umem_get(ibdev, start, length, access_flags);124 if (IS_ERR(mr->umem)) {125 err = PTR_ERR(mr->umem);126 ibdev_dbg(ibdev,127 "Failed to get umem for register user-mr, %d\n", err);128 goto err_free;129 }130 131 err = mana_ib_create_dma_region(dev, mr->umem, &dma_region_handle, iova);132 if (err) {133 ibdev_dbg(ibdev, "Failed create dma region for user-mr, %d\n",134 err);135 goto err_umem;136 }137 138 ibdev_dbg(ibdev,139 "created dma region for user-mr 0x%llx\n",140 dma_region_handle);141 142 mr_params.pd_handle = pd->pd_handle;143 mr_params.mr_type = GDMA_MR_TYPE_GVA;144 mr_params.gva.dma_region_handle = dma_region_handle;145 mr_params.gva.virtual_address = iova;146 mr_params.gva.access_flags =147 mana_ib_verbs_to_gdma_access_flags(access_flags);148 149 err = mana_ib_gd_create_mr(dev, mr, &mr_params);150 if (err)151 goto err_dma_region;152 153 /*154 * There is no need to keep track of dma_region_handle after MR is155 * successfully created. The dma_region_handle is tracked in the PF156 * as part of the lifecycle of this MR.157 */158 159 return &mr->ibmr;160 161err_dma_region:162 mana_gd_destroy_dma_region(mdev_to_gc(dev), dma_region_handle);163 164err_umem:165 ib_umem_release(mr->umem);166 167err_free:168 kfree(mr);169 return ERR_PTR(err);170}171 172int mana_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)173{174 struct mana_ib_mr *mr = container_of(ibmr, struct mana_ib_mr, ibmr);175 struct ib_device *ibdev = ibmr->device;176 struct mana_ib_dev *dev;177 int err;178 179 dev = container_of(ibdev, struct mana_ib_dev, ib_dev);180 181 err = mana_ib_gd_destroy_mr(dev, mr->mr_handle);182 if (err)183 return err;184 185 if (mr->umem)186 ib_umem_release(mr->umem);187 188 kfree(mr);189 190 return 0;191}192