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 2009 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_cr_accept.c
34*9e39c5baSBill Taylor  *
35*9e39c5baSBill Taylor  * PURPOSE: Connection management
36*9e39c5baSBill Taylor  * Description: Interfaces in this file are completely described in
37*9e39c5baSBill Taylor  *		the DAPL 1.1 API, Chapter 6, section 4
38*9e39c5baSBill Taylor  *
39*9e39c5baSBill Taylor  * $Id: dapl_cr_accept.c,v 1.21 2003/08/08 19:20:05 sjs2 Exp $
40*9e39c5baSBill Taylor  */
41*9e39c5baSBill Taylor 
42*9e39c5baSBill Taylor #include "dapl.h"
43*9e39c5baSBill Taylor #include "dapl_adapter_util.h"
44*9e39c5baSBill Taylor 
45*9e39c5baSBill Taylor /*
46*9e39c5baSBill Taylor  * dapl_cr_accept
47*9e39c5baSBill Taylor  *
48*9e39c5baSBill Taylor  * DAPL Requirements Version xxx, 6.4.2.1
49*9e39c5baSBill Taylor  *
50*9e39c5baSBill Taylor  * Establish a connection between active remote side requesting Endpoint
51*9e39c5baSBill Taylor  * and passic side local Endpoint.
52*9e39c5baSBill Taylor  *
53*9e39c5baSBill Taylor  * Input:
54*9e39c5baSBill Taylor  *	cr_handle
55*9e39c5baSBill Taylor  *	ep_handle
56*9e39c5baSBill Taylor  *	private_data_size
57*9e39c5baSBill Taylor  *	private_data
58*9e39c5baSBill Taylor  *
59*9e39c5baSBill Taylor  * Output:
60*9e39c5baSBill Taylor  *	none
61*9e39c5baSBill Taylor  *
62*9e39c5baSBill Taylor  * Returns:
63*9e39c5baSBill Taylor  *	DAT_SUCCESS
64*9e39c5baSBill Taylor  *	DAT_INVALID_PARAMETER
65*9e39c5baSBill Taylor  *	DAT_INVALID_ATTRIBUTE
66*9e39c5baSBill Taylor  */
67*9e39c5baSBill Taylor DAT_RETURN
dapl_cr_accept(IN DAT_CR_HANDLE cr_handle,IN DAT_EP_HANDLE ep_handle,IN DAT_COUNT private_data_size,IN const DAT_PVOID private_data)68*9e39c5baSBill Taylor dapl_cr_accept(
69*9e39c5baSBill Taylor 	IN	DAT_CR_HANDLE		cr_handle,
70*9e39c5baSBill Taylor 	IN	DAT_EP_HANDLE		ep_handle,
71*9e39c5baSBill Taylor 	IN	DAT_COUNT		private_data_size,
72*9e39c5baSBill Taylor 	IN	const DAT_PVOID		private_data)
73*9e39c5baSBill Taylor {
74*9e39c5baSBill Taylor 	DAPL_EP		*ep_ptr;
75*9e39c5baSBill Taylor 	DAT_RETURN	dat_status;
76*9e39c5baSBill Taylor 	DAPL_PRIVATE	prd;
77*9e39c5baSBill Taylor 	DAPL_CR		*cr_ptr;
78*9e39c5baSBill Taylor 	DAT_EP_STATE	entry_ep_state;
79*9e39c5baSBill Taylor 	DAT_EP_HANDLE	entry_ep_handle;
80*9e39c5baSBill Taylor 
81*9e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_API,
82*9e39c5baSBill Taylor 	    "dapl_cr_accept(%p, %p, %d, %p)\n",
83*9e39c5baSBill Taylor 	    cr_handle, ep_handle, private_data_size, private_data);
84*9e39c5baSBill Taylor 
85*9e39c5baSBill Taylor 	if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) {
86*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
87*9e39c5baSBill Taylor 		    DAT_INVALID_HANDLE_CR);
88*9e39c5baSBill Taylor 		goto bail;
89*9e39c5baSBill Taylor 	}
90*9e39c5baSBill Taylor 
91*9e39c5baSBill Taylor 	cr_ptr = (DAPL_CR *) cr_handle;
92*9e39c5baSBill Taylor 
93*9e39c5baSBill Taylor 	/*
94*9e39c5baSBill Taylor 	 * Return an error if we have an ep_handle and the CR already has an
95*9e39c5baSBill Taylor 	 * EP, indicating this is an RSP connection or PSP_PROVIDER_FLAG was
96*9e39c5baSBill Taylor 	 * specified.
97*9e39c5baSBill Taylor 	 */
98*9e39c5baSBill Taylor 	if (ep_handle != NULL &&
99*9e39c5baSBill Taylor 	    (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP) ||
100*9e39c5baSBill Taylor 	    cr_ptr->param.local_ep_handle != NULL)) {
101*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
102*9e39c5baSBill Taylor 		    DAT_INVALID_HANDLE_EP);
103*9e39c5baSBill Taylor 		goto bail;
104*9e39c5baSBill Taylor 	}
105*9e39c5baSBill Taylor 
106*9e39c5baSBill Taylor 	if ((0 != private_data_size) && (NULL == private_data)) {
107*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
108*9e39c5baSBill Taylor 		goto bail;
109*9e39c5baSBill Taylor 	}
110*9e39c5baSBill Taylor 
111*9e39c5baSBill Taylor 	/*
112*9e39c5baSBill Taylor 	 * Verify the private data size doesn't exceed the max
113*9e39c5baSBill Taylor 	 */
114*9e39c5baSBill Taylor 	if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) {
115*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
116*9e39c5baSBill Taylor 		goto bail;
117*9e39c5baSBill Taylor 	}
118*9e39c5baSBill Taylor 
119*9e39c5baSBill Taylor 	/*
120*9e39c5baSBill Taylor 	 * ep_handle is NULL if the user specified DAT_PSP_PROVIDER_FLAG
121*9e39c5baSBill Taylor 	 * OR this is an RSP connection; retrieve it from the cr.
122*9e39c5baSBill Taylor 	 */
123*9e39c5baSBill Taylor 	if (ep_handle == NULL) {
124*9e39c5baSBill Taylor 		ep_handle = cr_ptr->param.local_ep_handle;
125*9e39c5baSBill Taylor 		if ((((DAPL_EP *) ep_handle)->param.ep_state !=
126*9e39c5baSBill Taylor 		    DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING) &&
127*9e39c5baSBill Taylor 		    (((DAPL_EP *)ep_handle)->param.ep_state !=
128*9e39c5baSBill Taylor 		    DAT_EP_STATE_PASSIVE_CONNECTION_PENDING)) {
129*9e39c5baSBill Taylor 			return (DAT_INVALID_STATE);
130*9e39c5baSBill Taylor 		}
131*9e39c5baSBill Taylor 	} else {
132*9e39c5baSBill Taylor 		/* ensure this EP isn't connected or in use */
133*9e39c5baSBill Taylor 		if (((DAPL_EP *)ep_handle)->param.ep_state !=
134*9e39c5baSBill Taylor 		    DAT_EP_STATE_UNCONNECTED) {
135*9e39c5baSBill Taylor 			return (DAT_INVALID_STATE);
136*9e39c5baSBill Taylor 		}
137*9e39c5baSBill Taylor 	}
138*9e39c5baSBill Taylor 
139*9e39c5baSBill Taylor 	ep_ptr = (DAPL_EP *) ep_handle;
140*9e39c5baSBill Taylor 
141*9e39c5baSBill Taylor 	/*
142*9e39c5baSBill Taylor 	 * Verify the attributes of the EP handle before we connect it. Test
143*9e39c5baSBill Taylor 	 * all of the handles to make sure they are currently valid.
144*9e39c5baSBill Taylor 	 * Specifically:
145*9e39c5baSBill Taylor 	 *   pz_handle		required
146*9e39c5baSBill Taylor 	 *   recv_evd_handle	optional, but must be valid
147*9e39c5baSBill Taylor 	 *   request_evd_handle	optional, but must be valid
148*9e39c5baSBill Taylor 	 *   connect_evd_handle	required
149*9e39c5baSBill Taylor 	 * We do all verification and state change under lock, at which
150*9e39c5baSBill Taylor 	 * point the EP state should protect us from most races.
151*9e39c5baSBill Taylor 	 */
152*9e39c5baSBill Taylor 	dapl_os_lock(&ep_ptr->header.lock);
153*9e39c5baSBill Taylor 	if ((ep_ptr->param.pz_handle == NULL) ||
154*9e39c5baSBill Taylor 	    DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) ||
155*9e39c5baSBill Taylor 	    (ep_ptr->param.connect_evd_handle == NULL) ||
156*9e39c5baSBill Taylor 	    DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD) ||
157*9e39c5baSBill Taylor 	    !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags &
158*9e39c5baSBill Taylor 	    DAT_EVD_CONNECTION_FLAG) ||
159*9e39c5baSBill Taylor 	    (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&
160*9e39c5baSBill Taylor 	    (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD))) ||
161*9e39c5baSBill Taylor 	    (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL &&
162*9e39c5baSBill Taylor 	    (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle,
163*9e39c5baSBill Taylor 	    DAPL_MAGIC_EVD)))) {
164*9e39c5baSBill Taylor 		dapl_os_unlock(&ep_ptr->header.lock);
165*9e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
166*9e39c5baSBill Taylor 		    DAT_INVALID_HANDLE_EP);
167*9e39c5baSBill Taylor 		goto bail;
168*9e39c5baSBill Taylor 	}
169*9e39c5baSBill Taylor 
170*9e39c5baSBill Taylor 	if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
171*9e39c5baSBill Taylor 		/*
172*9e39c5baSBill Taylor 		 * If we are lazy attaching the QP then we may need to
173*9e39c5baSBill Taylor 		 * hook it up here. Typically, we run this code only for
174*9e39c5baSBill Taylor 		 * DAT_PSP_PROVIDER_FLAG
175*9e39c5baSBill Taylor 		 */
176*9e39c5baSBill Taylor 		dat_status = dapls_ib_qp_alloc(cr_ptr->header.owner_ia, ep_ptr,
177*9e39c5baSBill Taylor 		    ep_ptr);
178*9e39c5baSBill Taylor 
179*9e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS) {
180*9e39c5baSBill Taylor 			/* This is not a great error code, but spec allows */
181*9e39c5baSBill Taylor 			dapl_os_unlock(&ep_ptr->header.lock);
182*9e39c5baSBill Taylor 			dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
183*9e39c5baSBill Taylor 			    DAT_INVALID_HANDLE_EP);
184*9e39c5baSBill Taylor 			goto bail;
185*9e39c5baSBill Taylor 		}
186*9e39c5baSBill Taylor 	}
187*9e39c5baSBill Taylor 
188*9e39c5baSBill Taylor 	entry_ep_state = ep_ptr->param.ep_state;
189*9e39c5baSBill Taylor 	entry_ep_handle = cr_ptr->param.local_ep_handle;
190*9e39c5baSBill Taylor 	ep_ptr->param.ep_state = DAT_EP_STATE_COMPLETION_PENDING;
191*9e39c5baSBill Taylor 	ep_ptr->cm_handle = cr_ptr->ib_cm_handle;
192*9e39c5baSBill Taylor 	ep_ptr->cr_ptr = cr_ptr;
193*9e39c5baSBill Taylor 	ep_ptr->param.remote_ia_address_ptr = cr_ptr->param.
194*9e39c5baSBill Taylor 	    remote_ia_address_ptr;
195*9e39c5baSBill Taylor 	cr_ptr->param.local_ep_handle = ep_handle;
196*9e39c5baSBill Taylor 
197*9e39c5baSBill Taylor 	/*
198*9e39c5baSBill Taylor 	 * private data
199*9e39c5baSBill Taylor 	 */
200*9e39c5baSBill Taylor 	(void) dapl_os_memcpy(prd.private_data, private_data,
201*9e39c5baSBill Taylor 	    private_data_size);
202*9e39c5baSBill Taylor 	(void) dapl_os_memzero(prd.private_data + private_data_size,
203*9e39c5baSBill Taylor 	    sizeof (DAPL_PRIVATE) - private_data_size);
204*9e39c5baSBill Taylor 
205*9e39c5baSBill Taylor 	dapl_os_unlock(&ep_ptr->header.lock);
206*9e39c5baSBill Taylor 
207*9e39c5baSBill Taylor 	dat_status = dapls_ib_accept_connection(cr_handle, ep_handle, &prd);
208*9e39c5baSBill Taylor 
209*9e39c5baSBill Taylor 	/*
210*9e39c5baSBill Taylor 	 * If the provider failed, unwind the damage so we are back at
211*9e39c5baSBill Taylor 	 * the initial state.
212*9e39c5baSBill Taylor 	 */
213*9e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
214*9e39c5baSBill Taylor 		ep_ptr->param.ep_state = entry_ep_state;
215*9e39c5baSBill Taylor 		cr_ptr->param.local_ep_handle = entry_ep_handle;
216*9e39c5baSBill Taylor 	} else {
217*9e39c5baSBill Taylor 		/*
218*9e39c5baSBill Taylor 		 * Make this CR invalid. We need to hang on to it until
219*9e39c5baSBill Taylor 		 * the connection terminates, but it's destroyed from
220*9e39c5baSBill Taylor 		 * the app point of view.
221*9e39c5baSBill Taylor 		 */
222*9e39c5baSBill Taylor 		cr_ptr->header.magic = DAPL_MAGIC_CR_DESTROYED;
223*9e39c5baSBill Taylor 	}
224*9e39c5baSBill Taylor 
225*9e39c5baSBill Taylor bail:
226*9e39c5baSBill Taylor 	return (dat_status);
227*9e39c5baSBill Taylor }
228