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
dapl_lmr_create_virtual(IN DAPL_IA * ia,IN DAT_PVOID virt_addr,IN DAT_VLEN length,IN DAT_LMR_COOKIE shm_cookie,IN DAPL_PZ * pz,IN DAT_MEM_PRIV_FLAGS privileges,OUT DAT_LMR_HANDLE * lmr_handle,OUT DAT_LMR_CONTEXT * lmr_context,OUT DAT_RMR_CONTEXT * rmr_context,OUT DAT_VLEN * registered_length,OUT DAT_VADDR * registered_address)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
dapl_lmr_create_lmr(IN DAPL_IA * ia,IN DAPL_LMR * original_lmr,IN DAPL_PZ * pz,IN DAT_MEM_PRIV_FLAGS privileges,OUT DAT_LMR_HANDLE * lmr_handle,OUT DAT_LMR_CONTEXT * lmr_context,OUT DAT_RMR_CONTEXT * rmr_context,OUT DAT_VLEN * registered_length,OUT DAT_VADDR * registered_address)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
dapl_lmr_create(IN DAT_IA_HANDLE ia_handle,IN DAT_MEM_TYPE mem_type,IN DAT_REGION_DESCRIPTION region_description,IN DAT_VLEN length,IN DAT_PZ_HANDLE pz_handle,IN DAT_MEM_PRIV_FLAGS privileges,OUT DAT_LMR_HANDLE * lmr_handle,OUT DAT_LMR_CONTEXT * lmr_context,OUT DAT_RMR_CONTEXT * rmr_context,OUT DAT_VLEN * registered_length,OUT DAT_VADDR * registered_address)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