1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 32 /* 33 * 34 * MODULE: dapl_lmr_create.c 35 * 36 * PURPOSE: Memory management 37 * Description: Interfaces in this file are completely described in 38 * the DAPL 1.1 API, Chapter 6, section 6 39 * 40 */ 41 42 #include <dat/udat.h> 43 #include <dapl_lmr_util.h> 44 #include <dapl_adapter_util.h> 45 #include <libdevinfo.h> 46 47 /* 48 * Function Prototypes 49 */ 50 51 static DAT_RETURN 52 dapl_lmr_create_virtual(IN DAPL_IA *ia, 53 IN DAT_PVOID virt_addr, 54 IN DAT_VLEN length, 55 IN DAT_LMR_COOKIE shm_cookie, 56 IN DAPL_PZ *pz, 57 IN DAT_MEM_PRIV_FLAGS privileges, 58 OUT DAT_LMR_HANDLE *lmr_handle, 59 OUT DAT_LMR_CONTEXT *lmr_context, 60 OUT DAT_RMR_CONTEXT *rmr_context, 61 OUT DAT_VLEN *registered_length, 62 OUT DAT_VADDR *registered_address); 63 64 static DAT_RETURN 65 dapl_lmr_create_lmr(IN DAPL_IA *ia, 66 IN DAPL_LMR *original_lmr, 67 IN DAPL_PZ *pz, 68 IN DAT_MEM_PRIV_FLAGS privileges, 69 OUT DAT_LMR_HANDLE *lmr_handle, 70 OUT DAT_LMR_CONTEXT *lmr_context, 71 OUT DAT_RMR_CONTEXT *rmr_context, 72 OUT DAT_VLEN *registered_length, 73 OUT DAT_VADDR *registered_address); 74 75 /* 76 * Function Definitions 77 */ 78 79 static DAT_RETURN 80 dapl_lmr_create_virtual(IN DAPL_IA *ia, 81 IN DAT_PVOID virt_addr, 82 IN DAT_VLEN length, 83 IN DAT_LMR_COOKIE shm_cookie, 84 IN DAPL_PZ *pz, 85 IN DAT_MEM_PRIV_FLAGS privileges, 86 OUT DAT_LMR_HANDLE *lmr_handle, 87 OUT DAT_LMR_CONTEXT *lmr_context, 88 OUT DAT_RMR_CONTEXT *rmr_context, 89 OUT DAT_VLEN *registered_length, 90 OUT DAT_VADDR *registered_address) 91 { 92 DAPL_LMR *lmr; 93 DAT_REGION_DESCRIPTION reg_desc; 94 DAT_RETURN dat_status; 95 96 reg_desc.for_va = virt_addr; 97 dat_status = DAT_SUCCESS; 98 99 lmr = dapl_lmr_alloc(ia, DAT_MEM_TYPE_VIRTUAL, 100 reg_desc, length, (DAT_PZ_HANDLE) pz, privileges); 101 102 if (NULL == lmr) { 103 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 104 DAT_RESOURCE_MEMORY); 105 goto bail; 106 } 107 108 if (shm_cookie == NULL) { 109 dat_status = dapls_ib_mr_register(ia, lmr, virt_addr, 110 length, privileges); 111 } else { 112 dat_status = dapls_ib_mr_register_shared(ia, lmr, virt_addr, 113 length, shm_cookie, privileges); 114 } 115 116 if (DAT_SUCCESS != dat_status) { 117 dapl_lmr_dealloc(lmr); 118 goto bail; 119 } 120 121 /* if the LMR context is already in the hash table */ 122 dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table, 123 lmr->param.lmr_context, NULL); 124 if (dat_status == DAT_SUCCESS) { 125 (void) dapls_ib_mr_deregister(lmr); 126 dapl_lmr_dealloc(lmr); 127 128 dat_status = DAT_ERROR(DAT_INVALID_STATE, 129 DAT_INVALID_STATE_LMR_IN_USE); 130 goto bail; 131 } 132 133 dat_status = dapls_hash_insert(ia->hca_ptr->lmr_hash_table, 134 lmr->param.lmr_context, lmr); 135 if (dat_status != DAT_SUCCESS) { 136 (void) dapls_ib_mr_deregister(lmr); 137 dapl_lmr_dealloc(lmr); 138 /* 139 * The value returned by dapls_hash_insert(.) is not 140 * returned to the consumer because the spec. requires 141 * that dat_lmr_create(.) return only certain values. 142 */ 143 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 144 DAT_RESOURCE_MEMORY); 145 goto bail; 146 } 147 148 dapl_os_atomic_inc(&pz->pz_ref_count); 149 150 if (NULL != lmr_handle) { 151 *lmr_handle = (DAT_LMR_HANDLE) lmr; 152 } 153 if (NULL != lmr_context) { 154 *lmr_context = lmr->param.lmr_context; 155 } 156 if (NULL != rmr_context) { 157 *rmr_context = lmr->param.rmr_context; 158 } 159 if (NULL != registered_length) { 160 *registered_length = lmr->param.registered_size; 161 } 162 if (NULL != registered_address) { 163 *registered_address = lmr->param.registered_address; 164 } 165 166 bail: 167 return (dat_status); 168 } 169 170 171 static DAT_RETURN 172 dapl_lmr_create_lmr(IN DAPL_IA *ia, 173 IN DAPL_LMR *original_lmr, 174 IN DAPL_PZ *pz, 175 IN DAT_MEM_PRIV_FLAGS privileges, 176 OUT DAT_LMR_HANDLE *lmr_handle, 177 OUT DAT_LMR_CONTEXT *lmr_context, 178 OUT DAT_RMR_CONTEXT *rmr_context, 179 OUT DAT_VLEN *registered_length, 180 OUT DAT_VADDR *registered_address) 181 { 182 DAPL_LMR *lmr; 183 DAT_REGION_DESCRIPTION reg_desc; 184 DAT_RETURN dat_status; 185 186 dapl_dbg_log(DAPL_DBG_TYPE_API, 187 "dapl_lmr_create_lmr (%p, %p, %p, %x, %p, %p, %p, %p)\n", 188 ia, 189 original_lmr, 190 pz, privileges, 191 lmr_handle, 192 lmr_context, registered_length, registered_address); 193 194 dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table, 195 original_lmr->param.lmr_context, 196 (DAPL_HASH_DATA *) & lmr); 197 if (dat_status != DAT_SUCCESS) { 198 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, 199 DAT_INVALID_ARG2); 200 goto bail; 201 } 202 203 reg_desc.for_lmr_handle = (DAT_LMR_HANDLE) original_lmr; 204 205 lmr = dapl_lmr_alloc(ia, DAT_MEM_TYPE_LMR, reg_desc, 0, 206 (DAT_PZ_HANDLE) pz, privileges); 207 208 if (NULL == lmr) { 209 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 210 DAT_RESOURCE_MEMORY); 211 goto bail; 212 } 213 214 dat_status = dapls_ib_mr_register_lmr(ia, lmr, privileges); 215 216 if (DAT_SUCCESS != dat_status) { 217 dapl_lmr_dealloc(lmr); 218 goto bail; 219 } 220 221 /* if the LMR context is already in the hash table */ 222 dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table, 223 lmr->param.lmr_context, NULL); 224 if (dat_status == DAT_SUCCESS) { 225 (void) dapls_ib_mr_deregister(lmr); 226 dapl_lmr_dealloc(lmr); 227 228 dat_status = DAT_ERROR(DAT_INVALID_STATE, 229 DAT_INVALID_STATE_LMR_IN_USE); 230 goto bail; 231 } 232 233 dat_status = dapls_hash_insert(ia->hca_ptr->lmr_hash_table, 234 lmr->param.lmr_context, lmr); 235 if (dat_status != DAT_SUCCESS) { 236 (void) dapls_ib_mr_deregister(lmr); 237 dapl_lmr_dealloc(lmr); 238 239 /* 240 * The value returned by dapls_hash_insert(.) is not 241 * returned to the consumer because the spec. requires 242 * that dat_lmr_create(.) return only certain values. 243 */ 244 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 245 DAT_RESOURCE_MEMORY); 246 goto bail; 247 } 248 249 dapl_os_atomic_inc(&pz->pz_ref_count); 250 251 if (NULL != lmr_handle) { 252 *lmr_handle = (DAT_LMR_HANDLE)lmr; 253 } 254 if (NULL != lmr_context) { 255 *lmr_context = lmr->param.lmr_context; 256 } 257 if (NULL != rmr_context) { 258 *rmr_context = lmr->param.rmr_context; 259 } 260 if (NULL != registered_length) { 261 *registered_length = original_lmr->param.registered_size; 262 } 263 if (NULL != registered_address) { 264 *registered_address = original_lmr->param.registered_address; 265 } 266 267 bail: 268 return (dat_status); 269 } 270 271 272 /* 273 * dapl_lmr_create 274 * 275 * DAPL Requirements Version xxx, 6.6.3.1 276 * 277 * Register a memory region with an Interface Adaptor. 278 * 279 * Input: 280 * ia_handle 281 * mem_type 282 * region_description 283 * length 284 * pz_handle 285 * privileges 286 * 287 * Output: 288 * lmr_handle 289 * lmr_context 290 * registered_length 291 * registered_address 292 * 293 * Returns: 294 * DAT_SUCCESS 295 * DAT_INSUFFICIENT_RESOURCES 296 * DAT_INVALID_PARAMETER 297 * DAT_INVALID_STATE 298 * DAT_MODEL_NOT_SUPPORTED 299 * 300 */ 301 DAT_RETURN 302 dapl_lmr_create(IN DAT_IA_HANDLE ia_handle, 303 IN DAT_MEM_TYPE mem_type, 304 IN DAT_REGION_DESCRIPTION region_description, 305 IN DAT_VLEN length, 306 IN DAT_PZ_HANDLE pz_handle, 307 IN DAT_MEM_PRIV_FLAGS privileges, 308 OUT DAT_LMR_HANDLE *lmr_handle, 309 OUT DAT_LMR_CONTEXT *lmr_context, 310 OUT DAT_RMR_CONTEXT *rmr_context, 311 OUT DAT_VLEN *registered_length, 312 OUT DAT_VADDR *registered_address) 313 { 314 DAPL_IA *ia; 315 DAPL_PZ *pz; 316 317 if (DAPL_BAD_HANDLE(ia_handle, DAPL_MAGIC_IA) || 318 DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) { 319 return (DAT_INVALID_HANDLE); 320 } 321 322 if (length == 0) { 323 return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4)); 324 } 325 326 ia = (DAPL_IA *) ia_handle; 327 pz = (DAPL_PZ *) pz_handle; 328 329 /* Always ignore this bit as it is passed in */ 330 privileges &= ~DAT_MEM_PRIV_RO_DISABLE_FLAG; 331 332 /* 333 * If at open time we determined that RO should not be used, 334 * note it here. 335 */ 336 if (ia->dapl_flags & DAPL_DISABLE_RO) 337 privileges |= DAT_MEM_PRIV_RO_DISABLE_FLAG; 338 339 switch (mem_type) { 340 case DAT_MEM_TYPE_SO_VIRTUAL: 341 privileges |= DAT_MEM_PRIV_RO_DISABLE_FLAG; 342 /* FALLTHROUGH */ 343 case DAT_MEM_TYPE_VIRTUAL: 344 return (dapl_lmr_create_virtual(ia, region_description.for_va, 345 length, NULL, pz, privileges, 346 lmr_handle, lmr_context, 347 rmr_context, registered_length, 348 registered_address)); 349 /* NOTREACHED */ 350 case DAT_MEM_TYPE_LMR: { 351 DAPL_LMR *lmr; 352 353 if (DAPL_BAD_HANDLE 354 (region_description.for_lmr_handle, DAPL_MAGIC_LMR)) { 355 return (DAT_INVALID_HANDLE); 356 } 357 358 lmr = (DAPL_LMR *)region_description.for_lmr_handle; 359 360 return (dapl_lmr_create_lmr(ia, lmr, pz, privileges, lmr_handle, 361 lmr_context, rmr_context, 362 registered_length, registered_address)); 363 /* NOTREACHED */ 364 } 365 case DAT_MEM_TYPE_SHARED_VIRTUAL: 366 return (dapl_lmr_create_virtual(ia, 367 region_description. 368 for_shared_memory.virtual_address, 369 length, 370 region_description. 371 for_shared_memory.shared_memory_id, 372 pz, privileges, lmr_handle, 373 lmr_context, rmr_context, 374 registered_length, 375 registered_address)); 376 /* NOTREACHED */ 377 default: 378 return (DAT_INVALID_PARAMETER); 379 } 380 } 381