1 /* 2 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33 #include "rdma_core.h" 34 #include "uverbs.h" 35 #include <rdma/uverbs_std_types.h> 36 37 static int uverbs_free_mr(struct ib_uobject *uobject, 38 enum rdma_remove_reason why, 39 struct uverbs_attr_bundle *attrs) 40 { 41 return ib_dereg_mr_user((struct ib_mr *)uobject->object, 42 &attrs->driver_udata); 43 } 44 45 static int UVERBS_HANDLER(UVERBS_METHOD_ADVISE_MR)( 46 struct uverbs_attr_bundle *attrs) 47 { 48 struct ib_pd *pd = 49 uverbs_attr_get_obj(attrs, UVERBS_ATTR_ADVISE_MR_PD_HANDLE); 50 enum ib_uverbs_advise_mr_advice advice; 51 struct ib_device *ib_dev = pd->device; 52 struct ib_sge *sg_list; 53 int num_sge; 54 u32 flags; 55 int ret; 56 57 /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */ 58 if (!ib_dev->ops.advise_mr) 59 return -EOPNOTSUPP; 60 61 ret = uverbs_get_const(&advice, attrs, UVERBS_ATTR_ADVISE_MR_ADVICE); 62 if (ret) 63 return ret; 64 65 ret = uverbs_get_flags32(&flags, attrs, UVERBS_ATTR_ADVISE_MR_FLAGS, 66 IB_UVERBS_ADVISE_MR_FLAG_FLUSH); 67 if (ret) 68 return ret; 69 70 num_sge = uverbs_attr_ptr_get_array_size( 71 attrs, UVERBS_ATTR_ADVISE_MR_SGE_LIST, sizeof(struct ib_sge)); 72 if (num_sge <= 0) 73 return num_sge; 74 75 sg_list = uverbs_attr_get_alloced_ptr(attrs, 76 UVERBS_ATTR_ADVISE_MR_SGE_LIST); 77 return ib_dev->ops.advise_mr(pd, advice, flags, sg_list, num_sge, 78 attrs); 79 } 80 81 static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)( 82 struct uverbs_attr_bundle *attrs) 83 { 84 struct ib_dm_mr_attr attr = {}; 85 struct ib_uobject *uobj = 86 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_REG_DM_MR_HANDLE); 87 struct ib_dm *dm = 88 uverbs_attr_get_obj(attrs, UVERBS_ATTR_REG_DM_MR_DM_HANDLE); 89 struct ib_pd *pd = 90 uverbs_attr_get_obj(attrs, UVERBS_ATTR_REG_DM_MR_PD_HANDLE); 91 struct ib_device *ib_dev = pd->device; 92 93 struct ib_mr *mr; 94 int ret; 95 96 if (!ib_dev->ops.reg_dm_mr) 97 return -EOPNOTSUPP; 98 99 ret = uverbs_copy_from(&attr.offset, attrs, UVERBS_ATTR_REG_DM_MR_OFFSET); 100 if (ret) 101 return ret; 102 103 ret = uverbs_copy_from(&attr.length, attrs, 104 UVERBS_ATTR_REG_DM_MR_LENGTH); 105 if (ret) 106 return ret; 107 108 ret = uverbs_get_flags32(&attr.access_flags, attrs, 109 UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS, 110 IB_ACCESS_SUPPORTED); 111 if (ret) 112 return ret; 113 114 if (!(attr.access_flags & IB_ZERO_BASED)) 115 return -EINVAL; 116 117 ret = ib_check_mr_access(attr.access_flags); 118 if (ret) 119 return ret; 120 121 if (attr.offset > dm->length || attr.length > dm->length || 122 attr.length > dm->length - attr.offset) 123 return -EINVAL; 124 125 mr = pd->device->ops.reg_dm_mr(pd, dm, &attr, attrs); 126 if (IS_ERR(mr)) 127 return PTR_ERR(mr); 128 129 mr->device = pd->device; 130 mr->pd = pd; 131 mr->type = IB_MR_TYPE_DM; 132 mr->dm = dm; 133 mr->uobject = uobj; 134 atomic_inc(&pd->usecnt); 135 atomic_inc(&dm->usecnt); 136 137 uobj->object = mr; 138 139 uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_REG_DM_MR_HANDLE); 140 141 ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_DM_MR_RESP_LKEY, &mr->lkey, 142 sizeof(mr->lkey)); 143 if (ret) 144 return ret; 145 146 ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_DM_MR_RESP_RKEY, 147 &mr->rkey, sizeof(mr->rkey)); 148 return ret; 149 } 150 151 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_MR)( 152 struct uverbs_attr_bundle *attrs) 153 { 154 struct ib_mr *mr = 155 uverbs_attr_get_obj(attrs, UVERBS_ATTR_QUERY_MR_HANDLE); 156 int ret; 157 158 ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_LKEY, &mr->lkey, 159 sizeof(mr->lkey)); 160 if (ret) 161 return ret; 162 163 ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_RKEY, 164 &mr->rkey, sizeof(mr->rkey)); 165 166 if (ret) 167 return ret; 168 169 ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_LENGTH, 170 &mr->length, sizeof(mr->length)); 171 172 if (ret) 173 return ret; 174 175 ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_IOVA, 176 &mr->iova, sizeof(mr->iova)); 177 178 return IS_UVERBS_COPY_ERR(ret) ? ret : 0; 179 } 180 181 DECLARE_UVERBS_NAMED_METHOD( 182 UVERBS_METHOD_ADVISE_MR, 183 UVERBS_ATTR_IDR(UVERBS_ATTR_ADVISE_MR_PD_HANDLE, 184 UVERBS_OBJECT_PD, 185 UVERBS_ACCESS_READ, 186 UA_MANDATORY), 187 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_ADVISE_MR_ADVICE, 188 enum ib_uverbs_advise_mr_advice, 189 UA_MANDATORY), 190 UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_ADVISE_MR_FLAGS, 191 enum ib_uverbs_advise_mr_flag, 192 UA_MANDATORY), 193 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_ADVISE_MR_SGE_LIST, 194 UVERBS_ATTR_MIN_SIZE(sizeof(struct ib_uverbs_sge)), 195 UA_MANDATORY, 196 UA_ALLOC_AND_COPY)); 197 198 DECLARE_UVERBS_NAMED_METHOD( 199 UVERBS_METHOD_QUERY_MR, 200 UVERBS_ATTR_IDR(UVERBS_ATTR_QUERY_MR_HANDLE, 201 UVERBS_OBJECT_MR, 202 UVERBS_ACCESS_READ, 203 UA_MANDATORY), 204 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_RKEY, 205 UVERBS_ATTR_TYPE(u32), 206 UA_MANDATORY), 207 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_LKEY, 208 UVERBS_ATTR_TYPE(u32), 209 UA_MANDATORY), 210 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_LENGTH, 211 UVERBS_ATTR_TYPE(u64), 212 UA_MANDATORY), 213 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_IOVA, 214 UVERBS_ATTR_TYPE(u64), 215 UA_OPTIONAL)); 216 217 DECLARE_UVERBS_NAMED_METHOD( 218 UVERBS_METHOD_DM_MR_REG, 219 UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DM_MR_HANDLE, 220 UVERBS_OBJECT_MR, 221 UVERBS_ACCESS_NEW, 222 UA_MANDATORY), 223 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DM_MR_OFFSET, 224 UVERBS_ATTR_TYPE(u64), 225 UA_MANDATORY), 226 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DM_MR_LENGTH, 227 UVERBS_ATTR_TYPE(u64), 228 UA_MANDATORY), 229 UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DM_MR_PD_HANDLE, 230 UVERBS_OBJECT_PD, 231 UVERBS_ACCESS_READ, 232 UA_MANDATORY), 233 UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS, 234 enum ib_access_flags), 235 UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DM_MR_DM_HANDLE, 236 UVERBS_OBJECT_DM, 237 UVERBS_ACCESS_READ, 238 UA_MANDATORY), 239 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_REG_DM_MR_RESP_LKEY, 240 UVERBS_ATTR_TYPE(u32), 241 UA_MANDATORY), 242 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_REG_DM_MR_RESP_RKEY, 243 UVERBS_ATTR_TYPE(u32), 244 UA_MANDATORY)); 245 246 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 247 UVERBS_METHOD_MR_DESTROY, 248 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_MR_HANDLE, 249 UVERBS_OBJECT_MR, 250 UVERBS_ACCESS_DESTROY, 251 UA_MANDATORY)); 252 253 DECLARE_UVERBS_NAMED_OBJECT( 254 UVERBS_OBJECT_MR, 255 UVERBS_TYPE_ALLOC_IDR(uverbs_free_mr), 256 &UVERBS_METHOD(UVERBS_METHOD_DM_MR_REG), 257 &UVERBS_METHOD(UVERBS_METHOD_MR_DESTROY), 258 &UVERBS_METHOD(UVERBS_METHOD_ADVISE_MR), 259 &UVERBS_METHOD(UVERBS_METHOD_QUERY_MR)); 260 261 const struct uapi_definition uverbs_def_obj_mr[] = { 262 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MR, 263 UAPI_DEF_OBJ_NEEDS_FN(dereg_mr)), 264 {} 265 }; 266