1*9e39c5baSBill Taylor /*
2*9e39c5baSBill Taylor  * CDDL HEADER START
3*9e39c5baSBill Taylor  *
4*9e39c5baSBill Taylor  * The contents of this file are subject to the terms of the
5*9e39c5baSBill Taylor  * Common Development and Distribution License (the "License").
6*9e39c5baSBill Taylor  * You may not use this file except in compliance with the License.
7*9e39c5baSBill Taylor  *
8*9e39c5baSBill Taylor  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9e39c5baSBill Taylor  * or http://www.opensolaris.org/os/licensing.
10*9e39c5baSBill Taylor  * See the License for the specific language governing permissions
11*9e39c5baSBill Taylor  * and limitations under the License.
12*9e39c5baSBill Taylor  *
13*9e39c5baSBill Taylor  * When distributing Covered Code, include this CDDL HEADER in each
14*9e39c5baSBill Taylor  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9e39c5baSBill Taylor  * If applicable, add the following below this CDDL HEADER, with the
16*9e39c5baSBill Taylor  * fields enclosed by brackets "[]" replaced with your own identifying
17*9e39c5baSBill Taylor  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9e39c5baSBill Taylor  *
19*9e39c5baSBill Taylor  * CDDL HEADER END
20*9e39c5baSBill Taylor  */
21*9e39c5baSBill Taylor 
22*9e39c5baSBill Taylor /*
23*9e39c5baSBill Taylor  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24*9e39c5baSBill Taylor  */
25*9e39c5baSBill Taylor 
26*9e39c5baSBill Taylor /*
27*9e39c5baSBill Taylor  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
28*9e39c5baSBill Taylor  * Use is subject to license terms.
29*9e39c5baSBill Taylor  */
30*9e39c5baSBill Taylor 
31*9e39c5baSBill Taylor /*
32*9e39c5baSBill Taylor  *
33*9e39c5baSBill Taylor  * MODULE: dapl_ep_modify.c
34*9e39c5baSBill Taylor  *
35*9e39c5baSBill Taylor  * PURPOSE: Endpoint management
36*9e39c5baSBill Taylor  * Description: Interfaces in this file are completely described in
37*9e39c5baSBill Taylor  *		the DAPL 1.0 API, Chapter 6, section 5
38*9e39c5baSBill Taylor  *
39*9e39c5baSBill Taylor  * $Id: dapl_ep_modify.c,v 1.23 2003/07/11 18:42:17 hobie16 Exp $
40*9e39c5baSBill Taylor  */
41*9e39c5baSBill Taylor 
42*9e39c5baSBill Taylor #include "dapl.h"
43*9e39c5baSBill Taylor #include "dapl_cookie.h"
44*9e39c5baSBill Taylor #include "dapl_ep_util.h"
45*9e39c5baSBill Taylor #include "dapl_adapter_util.h"
46*9e39c5baSBill Taylor 
47*9e39c5baSBill Taylor /*
48*9e39c5baSBill Taylor  * Internal prototypes
49*9e39c5baSBill Taylor  */
50*9e39c5baSBill Taylor 
51*9e39c5baSBill Taylor static _INLINE_ DAT_RETURN
52*9e39c5baSBill Taylor dapli_ep_modify_validate_parameters(
53*9e39c5baSBill Taylor 	IN DAT_EP_HANDLE ep_handle,
54*9e39c5baSBill Taylor 	IN DAT_EP_PARAM_MASK ep_param_mask,
55*9e39c5baSBill Taylor 	IN const DAT_EP_PARAM *ep_param,
56*9e39c5baSBill Taylor 	OUT DAPL_IA **ia_ptr,
57*9e39c5baSBill Taylor 	OUT DAPL_EP **ep_ptr,
58*9e39c5baSBill Taylor 	OUT DAT_EP_ATTR	*ep_attr_ptr);
59*9e39c5baSBill Taylor 
60*9e39c5baSBill Taylor /*
61*9e39c5baSBill Taylor  * dapl_ep_modify
62*9e39c5baSBill Taylor  *
63*9e39c5baSBill Taylor  * DAPL Requirements Version xxx, 6.5.6
64*9e39c5baSBill Taylor  *
65*9e39c5baSBill Taylor  * Provide the consumer parameters, including attributes and status of
66*9e39c5baSBill Taylor  * the Endpoint.
67*9e39c5baSBill Taylor  *
68*9e39c5baSBill Taylor  * Input:
69*9e39c5baSBill Taylor  *	ep_handle
70*9e39c5baSBill Taylor  *	ep_args_mask
71*9e39c5baSBill Taylor  *
72*9e39c5baSBill Taylor  * Output:
73*9e39c5baSBill Taylor  *	ep_args
74*9e39c5baSBill Taylor  *
75*9e39c5baSBill Taylor  * Returns:
76*9e39c5baSBill Taylor  *	DAT_SUCCESS
77*9e39c5baSBill Taylor  *	DAT_INVALID_PARAMETER
78*9e39c5baSBill Taylor  *	DAT_INVALID_ATTRIBUTE
79*9e39c5baSBill Taylor  *	DAT_INVALID_STATE
80*9e39c5baSBill Taylor  */
81*9e39c5baSBill Taylor DAT_RETURN
dapl_ep_modify(IN DAT_EP_HANDLE ep_handle,IN DAT_EP_PARAM_MASK ep_param_mask,IN const DAT_EP_PARAM * ep_param)82*9e39c5baSBill Taylor dapl_ep_modify(
83*9e39c5baSBill Taylor 	IN DAT_EP_HANDLE ep_handle,
84*9e39c5baSBill Taylor 	IN DAT_EP_PARAM_MASK ep_param_mask,
85*9e39c5baSBill Taylor 	IN const DAT_EP_PARAM *ep_param)
86*9e39c5baSBill Taylor {
87*9e39c5baSBill Taylor 	DAPL_IA	*ia;
88*9e39c5baSBill Taylor 	DAPL_EP	*ep1, *ep2;
89*9e39c5baSBill Taylor 	DAT_EP_ATTR ep_attr1, ep_attr2;
90*9e39c5baSBill Taylor 	DAPL_EP	new_ep, copy_of_old_ep;
91*9e39c5baSBill Taylor 	DAPL_EP	alloc_ep; /* Holder for resources.  */
92*9e39c5baSBill Taylor 	DAPL_PZ	*tmp_pz;
93*9e39c5baSBill Taylor 	DAPL_EVD *tmp_evd;
94*9e39c5baSBill Taylor 	DAT_RETURN dat_status;
95*9e39c5baSBill Taylor 
96*9e39c5baSBill Taylor /* Flag indicating we've allocated a new one of these.  */
97*9e39c5baSBill Taylor 	DAT_BOOLEAN qp_allocated = DAT_FALSE;
98*9e39c5baSBill Taylor 	DAT_BOOLEAN rqst_cb_allocated = DAT_FALSE;
99*9e39c5baSBill Taylor 	DAT_BOOLEAN recv_cb_allocated = DAT_FALSE;
100*9e39c5baSBill Taylor 
101*9e39c5baSBill Taylor /* Flag indicating we've used (assigned to QP) a new one of these.  */
102*9e39c5baSBill Taylor 	DAT_BOOLEAN qp_used = DAT_FALSE;
103*9e39c5baSBill Taylor 	DAT_BOOLEAN rqst_cb_used = DAT_FALSE;
104*9e39c5baSBill Taylor 	DAT_BOOLEAN recv_cb_used = DAT_FALSE;
105*9e39c5baSBill Taylor 
106*9e39c5baSBill Taylor 	dat_status = dapli_ep_modify_validate_parameters(ep_handle,
107*9e39c5baSBill Taylor 	    ep_param_mask, ep_param, &ia, &ep1, &ep_attr1);
108*9e39c5baSBill Taylor 	if (DAT_SUCCESS != dat_status) {
109*9e39c5baSBill Taylor 		goto bail;
110*9e39c5baSBill Taylor 	}
111*9e39c5baSBill Taylor 
112*9e39c5baSBill Taylor 	/*
113*9e39c5baSBill Taylor 	 * Setup the alloc_ep with the appropriate parameters (primarily
114*9e39c5baSBill Taylor 	 * for allocating the QP.
115*9e39c5baSBill Taylor 	 */
116*9e39c5baSBill Taylor 	alloc_ep = *ep1;
117*9e39c5baSBill Taylor 	alloc_ep.param.ep_attr = ep_attr1;
118*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) {
119*9e39c5baSBill Taylor 		alloc_ep.param.pz_handle = ep_param->pz_handle;
120*9e39c5baSBill Taylor 	}
121*9e39c5baSBill Taylor 
122*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_RECV_EVD_HANDLE) {
123*9e39c5baSBill Taylor 		alloc_ep.param.recv_evd_handle = ep_param->recv_evd_handle;
124*9e39c5baSBill Taylor 	}
125*9e39c5baSBill Taylor 
126*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_REQUEST_EVD_HANDLE) {
127*9e39c5baSBill Taylor 		alloc_ep.param.request_evd_handle =
128*9e39c5baSBill Taylor 		    ep_param->request_evd_handle;
129*9e39c5baSBill Taylor 	}
130*9e39c5baSBill Taylor 
131*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_CONNECT_EVD_HANDLE) {
132*9e39c5baSBill Taylor 		alloc_ep.param.connect_evd_handle =
133*9e39c5baSBill Taylor 		    ep_param->connect_evd_handle;
134*9e39c5baSBill Taylor 	}
135*9e39c5baSBill Taylor 
136*9e39c5baSBill Taylor 	/*
137*9e39c5baSBill Taylor 	 * Allocate everything that might be needed.
138*9e39c5baSBill Taylor 	 * We allocate separately, and into a different "holding"
139*9e39c5baSBill Taylor 	 * ep, since we a) want the copy of the old ep into the new ep to
140*9e39c5baSBill Taylor 	 * be atomic with the assignment back (under lock), b) want the
141*9e39c5baSBill Taylor 	 * assignment of the allocated materials to be after the copy of the
142*9e39c5baSBill Taylor 	 * old ep into the new ep, and c) don't want the allocation done
143*9e39c5baSBill Taylor 	 * under lock.
144*9e39c5baSBill Taylor 	 */
145*9e39c5baSBill Taylor 	dat_status = dapls_cb_create(
146*9e39c5baSBill Taylor 	    &alloc_ep.req_buffer, ep1, DAPL_COOKIE_QUEUE_EP,
147*9e39c5baSBill Taylor 	    ep_attr1.max_request_dtos);
148*9e39c5baSBill Taylor 	if (DAT_SUCCESS != dat_status) {
149*9e39c5baSBill Taylor 		goto bail;
150*9e39c5baSBill Taylor 	}
151*9e39c5baSBill Taylor 	rqst_cb_allocated = DAT_TRUE;
152*9e39c5baSBill Taylor 
153*9e39c5baSBill Taylor 	if (!ep1->srq_attached) {
154*9e39c5baSBill Taylor 		dat_status = dapls_cb_create(&alloc_ep.recv_buffer, ep1,
155*9e39c5baSBill Taylor 		    DAPL_COOKIE_QUEUE_EP, ep_attr1.max_recv_dtos);
156*9e39c5baSBill Taylor 		if (DAT_SUCCESS != dat_status) {
157*9e39c5baSBill Taylor 			goto bail;
158*9e39c5baSBill Taylor 		}
159*9e39c5baSBill Taylor 		recv_cb_allocated = DAT_TRUE;
160*9e39c5baSBill Taylor 	}
161*9e39c5baSBill Taylor 
162*9e39c5baSBill Taylor 	dat_status = dapls_ib_qp_alloc(ia, &alloc_ep, ep1);
163*9e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
164*9e39c5baSBill Taylor 		goto bail;
165*9e39c5baSBill Taylor 	}
166*9e39c5baSBill Taylor 	qp_allocated = DAT_TRUE;
167*9e39c5baSBill Taylor 
168*9e39c5baSBill Taylor 	/*
169*9e39c5baSBill Taylor 	 * Now we atomically modify the EP, under lock
170*9e39c5baSBill Taylor 	 * There's a lot of work done here, but there should be no
171*9e39c5baSBill Taylor 	 * allocation or blocking.
172*9e39c5baSBill Taylor 	 */
173*9e39c5baSBill Taylor 	dapl_os_lock(&ep1->header.lock);
174*9e39c5baSBill Taylor 
175*9e39c5baSBill Taylor 	/*
176*9e39c5baSBill Taylor 	 * Revalidate parameters; make sure that races haven't
177*9e39c5baSBill Taylor 	 * changed anything important.
178*9e39c5baSBill Taylor 	 */
179*9e39c5baSBill Taylor 	dat_status = dapli_ep_modify_validate_parameters(ep_handle,
180*9e39c5baSBill Taylor 	    ep_param_mask, ep_param, &ia, &ep2, &ep_attr2);
181*9e39c5baSBill Taylor 	if (DAT_SUCCESS != dat_status) {
182*9e39c5baSBill Taylor 		dapl_os_unlock(&ep2->header.lock);
183*9e39c5baSBill Taylor 		goto bail;
184*9e39c5baSBill Taylor 	}
185*9e39c5baSBill Taylor 
186*9e39c5baSBill Taylor 	/*
187*9e39c5baSBill Taylor 	 * All of the following should be impossible, if validation
188*9e39c5baSBill Taylor 	 * occurred.  But they're important to the logic of this routine,
189*9e39c5baSBill Taylor 	 * so we check.
190*9e39c5baSBill Taylor 	 */
191*9e39c5baSBill Taylor 	dapl_os_assert(ep1 == ep2);
192*9e39c5baSBill Taylor 	dapl_os_assert(ep_attr2.max_recv_dtos == ep_attr1.max_recv_dtos);
193*9e39c5baSBill Taylor 	dapl_os_assert(ep_attr2.max_request_dtos == ep_attr1.max_request_dtos);
194*9e39c5baSBill Taylor 
195*9e39c5baSBill Taylor 	copy_of_old_ep = *ep2;
196*9e39c5baSBill Taylor 
197*9e39c5baSBill Taylor 	/*
198*9e39c5baSBill Taylor 	 * Setup new ep.
199*9e39c5baSBill Taylor 	 */
200*9e39c5baSBill Taylor 	new_ep = *ep2;
201*9e39c5baSBill Taylor 	new_ep.param.ep_attr = ep_attr2;
202*9e39c5baSBill Taylor 
203*9e39c5baSBill Taylor 	/*
204*9e39c5baSBill Taylor 	 * We can initialize the PZ and EVD handles from the alloc_ep because
205*9e39c5baSBill Taylor 	 * the only thing that could have changed since we setup the alloc_ep
206*9e39c5baSBill Taylor 	 * is stuff changed by dapl_cr_accept, and neither PZ nor EVD is in that
207*9e39c5baSBill Taylor 	 * list.
208*9e39c5baSBill Taylor 	 */
209*9e39c5baSBill Taylor 	new_ep.param.pz_handle = alloc_ep.param.pz_handle;
210*9e39c5baSBill Taylor 	new_ep.param.recv_evd_handle = alloc_ep.param.recv_evd_handle;
211*9e39c5baSBill Taylor 	new_ep.param.request_evd_handle = alloc_ep.param.request_evd_handle;
212*9e39c5baSBill Taylor 	new_ep.param.connect_evd_handle = alloc_ep.param.connect_evd_handle;
213*9e39c5baSBill Taylor 
214*9e39c5baSBill Taylor 	/* Deal with each of the allocation fields.  */
215*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS &&
216*9e39c5baSBill Taylor 	    (ep_param->ep_attr.max_recv_dtos !=
217*9e39c5baSBill Taylor 	    ep2->param.ep_attr.max_recv_dtos)) {
218*9e39c5baSBill Taylor 		new_ep.recv_buffer = alloc_ep.recv_buffer;
219*9e39c5baSBill Taylor 		recv_cb_used = DAT_TRUE;
220*9e39c5baSBill Taylor 	}
221*9e39c5baSBill Taylor 
222*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS &&
223*9e39c5baSBill Taylor 	    (ep_param->ep_attr.max_request_dtos !=
224*9e39c5baSBill Taylor 	    ep2->param.ep_attr.max_request_dtos)) {
225*9e39c5baSBill Taylor 		new_ep.req_buffer = alloc_ep.req_buffer;
226*9e39c5baSBill Taylor 		rqst_cb_used = DAT_TRUE;
227*9e39c5baSBill Taylor 	}
228*9e39c5baSBill Taylor 
229*9e39c5baSBill Taylor 	/*
230*9e39c5baSBill Taylor 	 * We need to change the QP only if there already was a QP
231*9e39c5baSBill Taylor 	 * (leave things the way you found them!) and one of the
232*9e39c5baSBill Taylor 	 * following has changed: send/recv EVD, send/recv reqs/IOV max.
233*9e39c5baSBill Taylor 	 */
234*9e39c5baSBill Taylor 	if (DAPL_QP_STATE_UNATTACHED != new_ep.qp_state && (ep_param_mask
235*9e39c5baSBill Taylor 	    & (DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV |
236*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV |
237*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS |
238*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS |
239*9e39c5baSBill Taylor 	    DAT_EP_FIELD_RECV_EVD_HANDLE |
240*9e39c5baSBill Taylor 	    DAT_EP_FIELD_REQUEST_EVD_HANDLE))) {
241*9e39c5baSBill Taylor 		/*
242*9e39c5baSBill Taylor 		 * We shouldn't be racing with connection establishment
243*9e39c5baSBill Taylor 		 * because the parameter validate routine should protect us,
244*9e39c5baSBill Taylor 		 * but it's an important enough point that we assert it.
245*9e39c5baSBill Taylor 		 */
246*9e39c5baSBill Taylor 		dapl_os_assert((ep2->param.ep_state !=
247*9e39c5baSBill Taylor 		    DAT_EP_STATE_PASSIVE_CONNECTION_PENDING) &&
248*9e39c5baSBill Taylor 		    (ep2->param.ep_state !=
249*9e39c5baSBill Taylor 		    DAT_EP_STATE_ACTIVE_CONNECTION_PENDING));
250*9e39c5baSBill Taylor 
251*9e39c5baSBill Taylor 		new_ep.qp_handle = alloc_ep.qp_handle;
252*9e39c5baSBill Taylor 		new_ep.qpn = alloc_ep.qpn;
253*9e39c5baSBill Taylor 		qp_used = DAT_TRUE;
254*9e39c5baSBill Taylor 	}
255*9e39c5baSBill Taylor 
256*9e39c5baSBill Taylor 	/*
257*9e39c5baSBill Taylor 	 * The actual assignment, including modifying QP parameters.
258*9e39c5baSBill Taylor 	 * Modifying QP parameters needs to come first, as if it fails
259*9e39c5baSBill Taylor 	 * we need to exit.
260*9e39c5baSBill Taylor 	 */
261*9e39c5baSBill Taylor 	if (DAPL_QP_STATE_UNATTACHED != new_ep.qp_state) {
262*9e39c5baSBill Taylor 		dat_status = dapls_ib_qp_modify(ia, ep2, &ep_attr2);
263*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS) {
264*9e39c5baSBill Taylor 			dapl_os_unlock(& ep2->header.lock);
265*9e39c5baSBill Taylor 			goto bail;
266*9e39c5baSBill Taylor 		}
267*9e39c5baSBill Taylor 	}
268*9e39c5baSBill Taylor 	*ep2 = new_ep;
269*9e39c5baSBill Taylor 
270*9e39c5baSBill Taylor 	dapl_os_unlock(&ep2->header.lock);
271*9e39c5baSBill Taylor 
272*9e39c5baSBill Taylor 	/*
273*9e39c5baSBill Taylor 	 * Modify reference counts, incrementing new ones
274*9e39c5baSBill Taylor 	 * and then decrementing old ones (so if they're the same
275*9e39c5baSBill Taylor 	 * the refcount never drops to zero).
276*9e39c5baSBill Taylor 	 */
277*9e39c5baSBill Taylor 	tmp_pz = (DAPL_PZ *) new_ep.param.pz_handle;
278*9e39c5baSBill Taylor 	if (NULL != tmp_pz) {
279*9e39c5baSBill Taylor 		dapl_os_atomic_inc(&tmp_pz->pz_ref_count);
280*9e39c5baSBill Taylor 	}
281*9e39c5baSBill Taylor 
282*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) new_ep.param.recv_evd_handle;
283*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
284*9e39c5baSBill Taylor 		dapl_os_atomic_inc(&tmp_evd->evd_ref_count);
285*9e39c5baSBill Taylor 	}
286*9e39c5baSBill Taylor 
287*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) new_ep.param.request_evd_handle;
288*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
289*9e39c5baSBill Taylor 		dapl_os_atomic_inc(&tmp_evd->evd_ref_count);
290*9e39c5baSBill Taylor 		}
291*9e39c5baSBill Taylor 
292*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) new_ep.param.connect_evd_handle;
293*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
294*9e39c5baSBill Taylor 		dapl_os_atomic_inc(&tmp_evd->evd_ref_count);
295*9e39c5baSBill Taylor 	}
296*9e39c5baSBill Taylor 
297*9e39c5baSBill Taylor 	/* decreament the old reference counts */
298*9e39c5baSBill Taylor 	tmp_pz = (DAPL_PZ *) copy_of_old_ep.param.pz_handle;
299*9e39c5baSBill Taylor 	if (NULL != tmp_pz) {
300*9e39c5baSBill Taylor 		dapl_os_atomic_dec(&tmp_pz->pz_ref_count);
301*9e39c5baSBill Taylor 	}
302*9e39c5baSBill Taylor 
303*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.recv_evd_handle;
304*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
305*9e39c5baSBill Taylor 		dapl_os_atomic_dec(&tmp_evd->evd_ref_count);
306*9e39c5baSBill Taylor 	}
307*9e39c5baSBill Taylor 
308*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.request_evd_handle;
309*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
310*9e39c5baSBill Taylor 		dapl_os_atomic_dec(&tmp_evd->evd_ref_count);
311*9e39c5baSBill Taylor 	}
312*9e39c5baSBill Taylor 
313*9e39c5baSBill Taylor 	tmp_evd = (DAPL_EVD *) copy_of_old_ep.param.connect_evd_handle;
314*9e39c5baSBill Taylor 	if (NULL != tmp_evd) {
315*9e39c5baSBill Taylor 		dapl_os_atomic_dec(&tmp_evd->evd_ref_count);
316*9e39c5baSBill Taylor 	}
317*9e39c5baSBill Taylor 
318*9e39c5baSBill Taylor bail:
319*9e39c5baSBill Taylor 	if (qp_allocated) {
320*9e39c5baSBill Taylor 		DAT_RETURN local_dat_status;
321*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS || !qp_used) {
322*9e39c5baSBill Taylor 			local_dat_status = dapls_ib_qp_free(ia, &alloc_ep);
323*9e39c5baSBill Taylor 		} else {
324*9e39c5baSBill Taylor 			local_dat_status = dapls_ib_qp_free(ia,
325*9e39c5baSBill Taylor 			    &copy_of_old_ep);
326*9e39c5baSBill Taylor 		}
327*9e39c5baSBill Taylor 		if (local_dat_status != DAT_SUCCESS) {
328*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_WARN,
329*9e39c5baSBill Taylor 			    "ep_modify: Failed to free QP; status %x\n",
330*9e39c5baSBill Taylor 			    local_dat_status);
331*9e39c5baSBill Taylor 		}
332*9e39c5baSBill Taylor 	}
333*9e39c5baSBill Taylor 
334*9e39c5baSBill Taylor 	if (rqst_cb_allocated) {
335*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS || !rqst_cb_used) {
336*9e39c5baSBill Taylor 			dapls_cb_free(&alloc_ep.req_buffer);
337*9e39c5baSBill Taylor 		} else {
338*9e39c5baSBill Taylor 			dapls_cb_free(&copy_of_old_ep.req_buffer);
339*9e39c5baSBill Taylor 		}
340*9e39c5baSBill Taylor 	}
341*9e39c5baSBill Taylor 
342*9e39c5baSBill Taylor 	if (recv_cb_allocated) {
343*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS || !recv_cb_used) {
344*9e39c5baSBill Taylor 			dapls_cb_free(&alloc_ep.recv_buffer);
345*9e39c5baSBill Taylor 		} else {
346*9e39c5baSBill Taylor 			dapls_cb_free(&copy_of_old_ep.recv_buffer);
347*9e39c5baSBill Taylor 		}
348*9e39c5baSBill Taylor 	}
349*9e39c5baSBill Taylor 
350*9e39c5baSBill Taylor 	return (dat_status);
351*9e39c5baSBill Taylor }
352*9e39c5baSBill Taylor 
353*9e39c5baSBill Taylor 
354*9e39c5baSBill Taylor /*
355*9e39c5baSBill Taylor  * dapli_ep_modify_validate_parameters
356*9e39c5baSBill Taylor  *
357*9e39c5baSBill Taylor  * Validate parameters
358*9e39c5baSBill Taylor  *
359*9e39c5baSBill Taylor  * The space for the ep_attr_ptr parameter should be allocated by the
360*9e39c5baSBill Taylor  * consumer. Upon success, this parameter will contain the current ep
361*9e39c5baSBill Taylor  * attribute values with the requested modifications made.
362*9e39c5baSBill Taylor  *
363*9e39c5baSBill Taylor  */
364*9e39c5baSBill Taylor 
365*9e39c5baSBill Taylor static DAT_RETURN
dapli_ep_modify_validate_parameters(IN DAT_EP_HANDLE ep_handle,IN DAT_EP_PARAM_MASK ep_param_mask,IN const DAT_EP_PARAM * ep_param,OUT DAPL_IA ** ia_ptr,OUT DAPL_EP ** ep_ptr,OUT DAT_EP_ATTR * ep_attr_ptr)366*9e39c5baSBill Taylor dapli_ep_modify_validate_parameters(
367*9e39c5baSBill Taylor 	IN DAT_EP_HANDLE ep_handle,
368*9e39c5baSBill Taylor 	IN DAT_EP_PARAM_MASK ep_param_mask,
369*9e39c5baSBill Taylor 	IN const DAT_EP_PARAM *ep_param,
370*9e39c5baSBill Taylor 	OUT DAPL_IA **ia_ptr,
371*9e39c5baSBill Taylor 	OUT DAPL_EP **ep_ptr,
372*9e39c5baSBill Taylor 	OUT DAT_EP_ATTR	*ep_attr_ptr)
373*9e39c5baSBill Taylor {
374*9e39c5baSBill Taylor 	DAPL_IA	*ia;
375*9e39c5baSBill Taylor 	DAPL_EP	*ep;
376*9e39c5baSBill Taylor 	DAT_EP_ATTR ep_attr;
377*9e39c5baSBill Taylor 	DAT_EP_ATTR ep_attr_limit;
378*9e39c5baSBill Taylor 	DAT_EP_ATTR ep_attr_request;
379*9e39c5baSBill Taylor 	DAT_RETURN dat_status;
380*9e39c5baSBill Taylor 
381*9e39c5baSBill Taylor 	*ia_ptr = NULL;
382*9e39c5baSBill Taylor 	*ep_ptr = NULL;
383*9e39c5baSBill Taylor 	dat_status = DAT_SUCCESS;
384*9e39c5baSBill Taylor 
385*9e39c5baSBill Taylor 	if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {
386*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
387*9e39c5baSBill Taylor 		    DAT_INVALID_HANDLE_EP);
388*9e39c5baSBill Taylor 		goto bail;
389*9e39c5baSBill Taylor 	}
390*9e39c5baSBill Taylor 
391*9e39c5baSBill Taylor 	ep = (DAPL_EP *) ep_handle;
392*9e39c5baSBill Taylor 	ia = ep->header.owner_ia;
393*9e39c5baSBill Taylor 
394*9e39c5baSBill Taylor 	/*
395*9e39c5baSBill Taylor 	 * Verify parameters valid in current EP state
396*9e39c5baSBill Taylor 	 */
397*9e39c5baSBill Taylor 	if (ep_param_mask & (DAT_EP_FIELD_IA_HANDLE |
398*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_STATE |
399*9e39c5baSBill Taylor 	    DAT_EP_FIELD_LOCAL_IA_ADDRESS_PTR |
400*9e39c5baSBill Taylor 	    DAT_EP_FIELD_LOCAL_PORT_QUAL |
401*9e39c5baSBill Taylor 	    DAT_EP_FIELD_REMOTE_IA_ADDRESS_PTR |
402*9e39c5baSBill Taylor 	    DAT_EP_FIELD_REMOTE_PORT_QUAL |
403*9e39c5baSBill Taylor 	    DAT_EP_FIELD_SRQ_HANDLE |
404*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_SRQ_SOFT_HW)) {
405*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
406*9e39c5baSBill Taylor 		goto bail;
407*9e39c5baSBill Taylor 	}
408*9e39c5baSBill Taylor 
409*9e39c5baSBill Taylor 	/*
410*9e39c5baSBill Taylor 	 * Can only change the PZ handle if we are UNCONNECTED or
411*9e39c5baSBill Taylor 	 * TENTATIVE_CONNECTION_PENDING(psp PROVIDER allocated EP)
412*9e39c5baSBill Taylor 	 */
413*9e39c5baSBill Taylor 	if ((ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) &&
414*9e39c5baSBill Taylor 	    (ep->param.ep_state != DAT_EP_STATE_UNCONNECTED &&
415*9e39c5baSBill Taylor 	    ep->param.ep_state !=
416*9e39c5baSBill Taylor 	    DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING)) {
417*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_STATE,
418*9e39c5baSBill Taylor 		    dapls_ep_state_subtype(ep));
419*9e39c5baSBill Taylor 		goto bail;
420*9e39c5baSBill Taylor 	}
421*9e39c5baSBill Taylor 
422*9e39c5baSBill Taylor 	if ((ep_param_mask & (DAT_EP_FIELD_RECV_EVD_HANDLE |
423*9e39c5baSBill Taylor 	    DAT_EP_FIELD_REQUEST_EVD_HANDLE |
424*9e39c5baSBill Taylor 	    DAT_EP_FIELD_CONNECT_EVD_HANDLE |
425*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_SERVICE_TYPE |
426*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_MESSAGE_SIZE |
427*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_RDMA_SIZE |
428*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_QOS |
429*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_REQUEST_COMPLETION_FLAGS |
430*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_RECV_COMPLETION_FLAGS |
431*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS |
432*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS |
433*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV |
434*9e39c5baSBill Taylor 	    DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV)) &&
435*9e39c5baSBill Taylor 	    (ep->param.ep_state != DAT_EP_STATE_UNCONNECTED &&
436*9e39c5baSBill Taylor 	    ep->param.ep_state != DAT_EP_STATE_RESERVED &&
437*9e39c5baSBill Taylor 	    ep->param.ep_state !=
438*9e39c5baSBill Taylor 	    DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING)) {
439*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_STATE,
440*9e39c5baSBill Taylor 		    dapls_ep_state_subtype(ep));
441*9e39c5baSBill Taylor 		goto bail;
442*9e39c5baSBill Taylor 	}
443*9e39c5baSBill Taylor 
444*9e39c5baSBill Taylor 	/*
445*9e39c5baSBill Taylor 	 * Validate handles being modified
446*9e39c5baSBill Taylor 	 */
447*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_PZ_HANDLE) {
448*9e39c5baSBill Taylor 		if (ep_param->pz_handle != NULL &&
449*9e39c5baSBill Taylor 		    DAPL_BAD_HANDLE(ep_param->pz_handle, DAPL_MAGIC_PZ)) {
450*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
451*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
452*9e39c5baSBill Taylor 			goto bail;
453*9e39c5baSBill Taylor 		}
454*9e39c5baSBill Taylor 	}
455*9e39c5baSBill Taylor 
456*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_RECV_EVD_HANDLE) {
457*9e39c5baSBill Taylor 		if (ep_param->recv_evd_handle != NULL &&
458*9e39c5baSBill Taylor 		    (DAPL_BAD_HANDLE(ep_param->recv_evd_handle,
459*9e39c5baSBill Taylor 		    DAPL_MAGIC_EVD) ||
460*9e39c5baSBill Taylor 		    !((DAPL_EVD *)ep_param->recv_evd_handle)->evd_flags &
461*9e39c5baSBill Taylor 		    DAT_EVD_DTO_FLAG)) {
462*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
463*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
464*9e39c5baSBill Taylor 			goto bail;
465*9e39c5baSBill Taylor 		}
466*9e39c5baSBill Taylor 	}
467*9e39c5baSBill Taylor 
468*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_REQUEST_EVD_HANDLE) {
469*9e39c5baSBill Taylor 		if (ep_param->request_evd_handle != NULL &&
470*9e39c5baSBill Taylor 		    DAPL_BAD_HANDLE(ep_param->request_evd_handle,
471*9e39c5baSBill Taylor 		    DAPL_MAGIC_EVD)) {
472*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
473*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
474*9e39c5baSBill Taylor 			goto bail;
475*9e39c5baSBill Taylor 		}
476*9e39c5baSBill Taylor 	}
477*9e39c5baSBill Taylor 
478*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_CONNECT_EVD_HANDLE) {
479*9e39c5baSBill Taylor 		if (ep_param->connect_evd_handle != NULL &&
480*9e39c5baSBill Taylor 		    DAPL_BAD_HANDLE(ep_param->connect_evd_handle,
481*9e39c5baSBill Taylor 		    DAPL_MAGIC_EVD) &&
482*9e39c5baSBill Taylor 		    !(((DAPL_EVD *)ep_param->connect_evd_handle)->evd_flags &
483*9e39c5baSBill Taylor 		    DAT_EVD_CONNECTION_FLAG)) {
484*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
485*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
486*9e39c5baSBill Taylor 			goto bail;
487*9e39c5baSBill Taylor 		}
488*9e39c5baSBill Taylor 	}
489*9e39c5baSBill Taylor 
490*9e39c5baSBill Taylor 	/*
491*9e39c5baSBill Taylor 	 * Validate the attributes against the HCA limits
492*9e39c5baSBill Taylor 	 */
493*9e39c5baSBill Taylor 	ep_attr = ep->param.ep_attr;
494*9e39c5baSBill Taylor 
495*9e39c5baSBill Taylor 	(void) dapl_os_memzero(&ep_attr_limit, sizeof (DAT_EP_ATTR));
496*9e39c5baSBill Taylor 	dat_status = dapls_ib_query_hca(ia->hca_ptr, NULL,
497*9e39c5baSBill Taylor 	    &ep_attr_limit, NULL, NULL);
498*9e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
499*9e39c5baSBill Taylor 		goto bail;
500*9e39c5baSBill Taylor 	}
501*9e39c5baSBill Taylor 
502*9e39c5baSBill Taylor 	ep_attr_request = ep_param->ep_attr;
503*9e39c5baSBill Taylor 
504*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_SERVICE_TYPE) {
505*9e39c5baSBill Taylor 		if (ep_attr_request.service_type != DAT_SERVICE_TYPE_RC) {
506*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
507*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
508*9e39c5baSBill Taylor 			goto bail;
509*9e39c5baSBill Taylor 		}
510*9e39c5baSBill Taylor 	}
511*9e39c5baSBill Taylor 
512*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_MESSAGE_SIZE) {
513*9e39c5baSBill Taylor 		if (ep_attr_request.max_mtu_size > ep_attr_limit.max_mtu_size) {
514*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
515*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
516*9e39c5baSBill Taylor 			goto bail;
517*9e39c5baSBill Taylor 		} else {
518*9e39c5baSBill Taylor 			ep_attr.max_mtu_size = ep_attr_request.max_mtu_size;
519*9e39c5baSBill Taylor 		}
520*9e39c5baSBill Taylor 	}
521*9e39c5baSBill Taylor 
522*9e39c5baSBill Taylor 	/*
523*9e39c5baSBill Taylor 	 * Do nothing if the DAT_EP_FIELD_EP_ATTR_MAX_RDMA_SIZE flag is
524*9e39c5baSBill Taylor 	 * set. Each RDMA transport/provider may or may not have a limit
525*9e39c5baSBill Taylor 	 * on the size of an RDMA DTO. For InfiniBand, this parameter is
526*9e39c5baSBill Taylor 	 * validated in the implementation of the dapls_ib_qp_modify()
527*9e39c5baSBill Taylor 	 * function.
528*9e39c5baSBill Taylor 	 */
529*9e39c5baSBill Taylor 	/* LINTED: E_NOP_IF_STMT */
530*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_QOS) {
531*9e39c5baSBill Taylor 		/* Do nothing, not defined in the spec yet */
532*9e39c5baSBill Taylor 	}
533*9e39c5baSBill Taylor 
534*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_RECV_COMPLETION_FLAGS) {
535*9e39c5baSBill Taylor 		dat_status = dapl_ep_check_recv_completion_flags(
536*9e39c5baSBill Taylor 		    ep_attr_request.recv_completion_flags);
537*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS) {
538*9e39c5baSBill Taylor 			goto bail;
539*9e39c5baSBill Taylor 		} else {
540*9e39c5baSBill Taylor 			ep_attr.recv_completion_flags =
541*9e39c5baSBill Taylor 			    ep_attr_request.recv_completion_flags;
542*9e39c5baSBill Taylor 		}
543*9e39c5baSBill Taylor 	}
544*9e39c5baSBill Taylor 
545*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_REQUEST_COMPLETION_FLAGS) {
546*9e39c5baSBill Taylor 		dat_status = dapl_ep_check_request_completion_flags(
547*9e39c5baSBill Taylor 		    ep_attr_request.request_completion_flags);
548*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS) {
549*9e39c5baSBill Taylor 			goto bail;
550*9e39c5baSBill Taylor 		} else {
551*9e39c5baSBill Taylor 			ep_attr.request_completion_flags =
552*9e39c5baSBill Taylor 			    ep_attr_request.request_completion_flags;
553*9e39c5baSBill Taylor 		}
554*9e39c5baSBill Taylor 	}
555*9e39c5baSBill Taylor 
556*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_DTOS) {
557*9e39c5baSBill Taylor 		if ((ep->param.srq_handle != NULL) ||
558*9e39c5baSBill Taylor 		    (ep_attr_request.max_recv_dtos >
559*9e39c5baSBill Taylor 		    ep_attr_limit.max_recv_dtos) ||
560*9e39c5baSBill Taylor 		    (ep_param->recv_evd_handle  == DAT_HANDLE_NULL &&
561*9e39c5baSBill Taylor 		    (ep_attr_request.max_recv_dtos > 0))) {
562*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
563*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
564*9e39c5baSBill Taylor 			goto bail;
565*9e39c5baSBill Taylor 		} else {
566*9e39c5baSBill Taylor 			ep_attr.max_recv_dtos = ep_attr_request.max_recv_dtos;
567*9e39c5baSBill Taylor 		}
568*9e39c5baSBill Taylor 	}
569*9e39c5baSBill Taylor 
570*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_DTOS) {
571*9e39c5baSBill Taylor 		if (ep_attr_request.max_request_dtos >
572*9e39c5baSBill Taylor 		    ep_attr_limit.max_request_dtos ||
573*9e39c5baSBill Taylor 		    (ep_param->request_evd_handle  == DAT_HANDLE_NULL &&
574*9e39c5baSBill Taylor 		    (ep_attr_request.max_request_dtos > 0))) {
575*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
576*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
577*9e39c5baSBill Taylor 			goto bail;
578*9e39c5baSBill Taylor 		} else {
579*9e39c5baSBill Taylor 			ep_attr.max_request_dtos =
580*9e39c5baSBill Taylor 			    ep_attr_request.max_request_dtos;
581*9e39c5baSBill Taylor 		}
582*9e39c5baSBill Taylor 	}
583*9e39c5baSBill Taylor 
584*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_RECV_IOV) {
585*9e39c5baSBill Taylor 		if ((ep->param.srq_handle != NULL) ||
586*9e39c5baSBill Taylor 		    (ep_attr_request.max_recv_iov >
587*9e39c5baSBill Taylor 		    ep_attr_limit.max_recv_iov)) {
588*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
589*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
590*9e39c5baSBill Taylor 			goto bail;
591*9e39c5baSBill Taylor 		} else {
592*9e39c5baSBill Taylor 			ep_attr.max_recv_iov = ep_attr_request.max_recv_iov;
593*9e39c5baSBill Taylor 		}
594*9e39c5baSBill Taylor 	}
595*9e39c5baSBill Taylor 
596*9e39c5baSBill Taylor 	if (ep_param_mask & DAT_EP_FIELD_EP_ATTR_MAX_REQUEST_IOV) {
597*9e39c5baSBill Taylor 		if (ep_attr_request.max_request_iov >
598*9e39c5baSBill Taylor 		    ep_attr_limit.max_request_iov) {
599*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
600*9e39c5baSBill Taylor 			    DAT_INVALID_ARG3);
601*9e39c5baSBill Taylor 			goto bail;
602*9e39c5baSBill Taylor 		} else {
603*9e39c5baSBill Taylor 			ep_attr.max_request_iov =
604*9e39c5baSBill Taylor 			    ep_attr_request.max_request_iov;
605*9e39c5baSBill Taylor 		}
606*9e39c5baSBill Taylor 	}
607*9e39c5baSBill Taylor 
608*9e39c5baSBill Taylor 	*ia_ptr = ia;
609*9e39c5baSBill Taylor 	*ep_ptr = ep;
610*9e39c5baSBill Taylor 	*ep_attr_ptr = ep_attr;
611*9e39c5baSBill Taylor 
612*9e39c5baSBill Taylor bail:
613*9e39c5baSBill Taylor 	return (dat_status);
614*9e39c5baSBill Taylor }
615