xref: /illumos-gate/usr/src/lib/udapl/udapl_tavor/common/dapl_lmr_create.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 	(void) 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 	(void) 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