dapl_rmr_bind.c revision 9517:b4839b0aa7a4
12116Sjkh/*
22116Sjkh * CDDL HEADER START
32116Sjkh *
42116Sjkh * The contents of this file are subject to the terms of the
52116Sjkh * Common Development and Distribution License (the "License").
62116Sjkh * You may not use this file except in compliance with the License.
72116Sjkh *
82116Sjkh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92116Sjkh * or http://www.opensolaris.org/os/licensing.
102116Sjkh * See the License for the specific language governing permissions
112116Sjkh * and limitations under the License.
122116Sjkh *
132116Sjkh * When distributing Covered Code, include this CDDL HEADER in each
142116Sjkh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152116Sjkh * If applicable, add the following below this CDDL HEADER, with the
162116Sjkh * fields enclosed by brackets "[]" replaced with your own identifying
172116Sjkh * information: Portions Copyright [yyyy] [name of copyright owner]
182116Sjkh *
192116Sjkh * CDDL HEADER END
202116Sjkh */
212116Sjkh
222116Sjkh/*
232116Sjkh * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
242116Sjkh */
252116Sjkh
262116Sjkh/*
272116Sjkh * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
282116Sjkh * Use is subject to license terms.
292116Sjkh */
302116Sjkh
312116Sjkh/*
322116Sjkh *
332116Sjkh * MODULE: dapl_rmr_bind.c
342116Sjkh *
352116Sjkh * PURPOSE: Memory management
3623577Sbde * Description: Interfaces in this file are completely described in
37213337Sdim *		the DAPL 1.1 API, Chapter 6, section 6
382116Sjkh *
392116Sjkh * $Id: dapl_rmr_bind.c,v 1.14 2003/07/11 18:23:31 jlentini Exp $
402116Sjkh */
412116Sjkh
4261335Sbde#include "dapl.h"
432116Sjkh#include "dapl_rmr_util.h"
44192760Sattilio#include "dapl_ep_util.h"
45217108Skib#include "dapl_cookie.h"
46217108Skib#include "dapl_adapter_util.h"
47
48/*
49 *
50 * Function Prototypes
51 *
52 */
53
54static DAT_RETURN
55dapli_rmr_bind_fuse(
56    IN  DAPL_RMR		*rmr,
57    IN  const DAT_LMR_TRIPLET 	*lmr_triplet,
58    IN  DAT_MEM_PRIV_FLAGS 	mem_priv,
59    IN  DAPL_EP 		*ep,
60    IN  DAT_RMR_COOKIE 		user_cookie,
61    IN  DAT_COMPLETION_FLAGS	completion_flags,
62    OUT DAT_RMR_CONTEXT 	*rmr_context);
63
64static DAT_RETURN
65dapli_rmr_bind_unfuse(
66    IN  DAPL_RMR		*rmr,
67    IN  const DAT_LMR_TRIPLET 	*lmr_triplet,
68    IN  DAPL_EP 		*ep,
69    IN  DAT_RMR_COOKIE 		user_cookie,
70    IN  DAT_COMPLETION_FLAGS 	completion_flags);
71
72
73/*
74 *
75 * Function Definitions
76 *
77 */
78
79static DAT_RETURN
80dapli_rmr_bind_fuse(
81    IN  DAPL_RMR		*rmr,
82    IN  const DAT_LMR_TRIPLET* 	lmr_triplet,
83    IN  DAT_MEM_PRIV_FLAGS 	mem_priv,
84    IN  DAPL_EP 		*ep_ptr,
85    IN  DAT_RMR_COOKIE 		user_cookie,
86    IN  DAT_COMPLETION_FLAGS	completion_flags,
87    OUT DAT_RMR_CONTEXT 	*rmr_context)
88{
89	DAPL_LMR 			*lmr;
90	DAPL_COOKIE			*cookie;
91	DAT_RETURN 			dat_status;
92
93	dat_status = dapls_hash_search(
94	    rmr->header.owner_ia->hca_ptr->lmr_hash_table,
95	    lmr_triplet->lmr_context,
96	    (DAPL_HASH_DATA *) &lmr);
97	if (DAT_SUCCESS != dat_status) {
98		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
99		goto bail;
100	}
101
102	/*
103	 * if the ep in unconnected return an error. IB requires that the
104	 * QP be connected to change a memory window binding since:
105	 *
106	 * - memory window bind operations are WQEs placed on a QP's
107	 *   send queue
108	 *
109	 * - QP's only process WQEs on the send queue when the QP is in
110	 *   the RTS state
111	 */
112	if (DAT_EP_STATE_CONNECTED != ep_ptr->param.ep_state) {
113		dat_status = DAT_ERROR(DAT_INVALID_STATE,
114		    dapls_ep_state_subtype(ep_ptr));
115		goto bail;
116	}
117
118	if (DAT_FALSE == dapl_mr_bounds_check(
119	    dapl_mr_get_address(lmr->param.region_desc, lmr->param.mem_type),
120	    lmr->param.length,
121	    lmr_triplet->virtual_address,
122	    lmr_triplet->segment_length)) {
123		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
124		    DAT_INVALID_ARG2);
125		goto bail;
126	}
127
128	/* If the LMR, RMR, and EP are not in the same PZ, there is an error */
129	if ((ep_ptr->param.pz_handle != lmr->param.pz_handle) ||
130	    (ep_ptr->param.pz_handle != rmr->param.pz_handle)) {
131		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
132		goto bail;
133	}
134
135	if (!dapl_rmr_validate_completion_flag(DAT_COMPLETION_SUPPRESS_FLAG,
136	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags) ||
137	    !dapl_rmr_validate_completion_flag(DAT_COMPLETION_UNSIGNALLED_FLAG,
138	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags) ||
139	    !dapl_rmr_validate_completion_flag(
140	    DAT_COMPLETION_BARRIER_FENCE_FLAG,
141	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags)) {
142		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
143		goto bail;
144	}
145
146	dat_status = dapls_rmr_cookie_alloc(&ep_ptr->req_buffer,
147	    rmr, user_cookie, &cookie);
148	if (DAT_SUCCESS != dat_status) {
149		goto bail;
150	}
151
152	dat_status = dapls_ib_mw_bind(rmr,
153	    lmr_triplet->lmr_context,
154	    ep_ptr,
155	    cookie,
156	    lmr_triplet->virtual_address,
157	    lmr_triplet->segment_length,
158	    mem_priv,
159	    completion_flags);
160	if (DAT_SUCCESS != dat_status) {
161		dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
162		goto bail;
163	}
164
165	(void) dapl_os_atomic_inc(&lmr->lmr_ref_count);
166
167	/* if the RMR was previously bound */
168	if (NULL != rmr->lmr) {
169		(void) dapl_os_atomic_dec(&rmr->lmr->lmr_ref_count);
170	}
171
172	rmr->param.mem_priv = mem_priv;
173	rmr->param.lmr_triplet = *lmr_triplet;
174	rmr->ep = ep_ptr;
175	rmr->lmr = lmr;
176
177	dapl_os_atomic_inc(&ep_ptr->req_count);
178
179	if (NULL != rmr_context) { *rmr_context = rmr->param.rmr_context; }
180bail:
181	return (dat_status);
182}
183
184
185static DAT_RETURN
186dapli_rmr_bind_unfuse(
187    IN  DAPL_RMR		*rmr,
188    IN  const DAT_LMR_TRIPLET 	*lmr_triplet,
189    IN  DAPL_EP 		*ep_ptr,
190    IN  DAT_RMR_COOKIE 		user_cookie,
191    IN  DAT_COMPLETION_FLAGS 	completion_flags)
192{
193	DAPL_COOKIE			*cookie;
194	DAT_RETURN 			dat_status;
195
196	dat_status = DAT_SUCCESS;
197	/*
198	 * if the ep in unconnected return an error. IB requires that the
199	 * QP be connected to change a memory window binding since:
200	 *
201	 * - memory window bind operations are WQEs placed on a QP's
202	 *   send queue
203	 *
204	 * - QP's only process WQEs on the send queue when the QP is in
205	 *   the RTS state
206	 */
207	if (DAT_EP_STATE_CONNECTED != ep_ptr->param.ep_state) {
208		dat_status = DAT_ERROR(DAT_INVALID_STATE,
209		    dapls_ep_state_subtype(ep_ptr));
210		goto bail1;
211	}
212
213	/* If the RMR and EP are not in the same PZ, there is an error */
214	if (ep_ptr->param.pz_handle != rmr->param.pz_handle) {
215		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
216		goto bail1;
217	}
218
219	if (!dapl_rmr_validate_completion_flag(DAT_COMPLETION_SUPPRESS_FLAG,
220	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags) ||
221	    !dapl_rmr_validate_completion_flag(DAT_COMPLETION_UNSIGNALLED_FLAG,
222	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags) ||
223	    !dapl_rmr_validate_completion_flag(
224	    DAT_COMPLETION_BARRIER_FENCE_FLAG,
225	    ep_ptr->param.ep_attr.request_completion_flags, completion_flags)) {
226		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
227		goto bail1;
228	}
229
230	dat_status = dapls_rmr_cookie_alloc(&ep_ptr->req_buffer, rmr,
231	    user_cookie, &cookie);
232	if (DAT_SUCCESS != dat_status) {
233		goto bail1;
234	}
235
236
237	dat_status = dapls_ib_mw_unbind(rmr, lmr_triplet->lmr_context,
238	    ep_ptr, cookie, completion_flags);
239
240	if (DAT_SUCCESS != dat_status) {
241		dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
242		goto bail1;
243	}
244
245	/* if the RMR was previously bound */
246	if (NULL != rmr->lmr) {
247		(void) dapl_os_atomic_dec(&rmr->lmr->lmr_ref_count);
248	}
249
250	rmr->param.mem_priv = DAT_MEM_PRIV_NONE_FLAG;
251	rmr->param.lmr_triplet.lmr_context = 0;
252	rmr->param.lmr_triplet.virtual_address = 0;
253	rmr->param.lmr_triplet.segment_length = 0;
254	rmr->ep = ep_ptr;
255	rmr->lmr = NULL;
256
257	dapl_os_atomic_inc(&ep_ptr->req_count);
258
259bail1:
260	return (dat_status);
261}
262
263
264/*
265 * dapl_rmr_bind
266 *
267 * DAPL Requirements Version xxx, 6.6.4.4
268 *
269 * Bind the RMR to the specified memory region within the LMR and
270 * provide a new rmr_context value.
271 *
272 * Input:
273 * Output:
274 */
275DAT_RETURN
276dapl_rmr_bind(
277	IN	DAT_RMR_HANDLE		rmr_handle,
278	IN	const DAT_LMR_TRIPLET	*lmr_triplet,
279	IN	DAT_MEM_PRIV_FLAGS	mem_priv,
280	IN	DAT_EP_HANDLE		ep_handle,
281	IN	DAT_RMR_COOKIE		user_cookie,
282	IN	DAT_COMPLETION_FLAGS 	completion_flags,
283	OUT	DAT_RMR_CONTEXT		*rmr_context)
284{
285	DAPL_RMR				*rmr;
286	DAPL_EP 				*ep_ptr;
287
288	if (DAPL_BAD_HANDLE(rmr_handle, DAPL_MAGIC_RMR)) {
289		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_RMR));
290	}
291	if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {
292		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP));
293	}
294
295	rmr = (DAPL_RMR *) rmr_handle;
296	ep_ptr = (DAPL_EP *) ep_handle;
297
298	/* if the rmr should be bound */
299	if (0 != lmr_triplet->segment_length) {
300		return (dapli_rmr_bind_fuse(rmr,
301		    lmr_triplet,
302		    mem_priv,
303		    ep_ptr,
304		    user_cookie,
305		    completion_flags,
306		    rmr_context));
307	} else { /* the rmr should be unbound */
308		return (dapli_rmr_bind_unfuse(rmr,
309		    lmr_triplet,
310		    ep_ptr,
311		    user_cookie,
312		    completion_flags));
313	}
314}
315