dapl_evd_connection_callb.c revision 9517:b4839b0aa7a4
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 * MODULE: dapl_evd_connection_callback.c
34 *
35 * PURPOSE: implements connection callbacks
36 *
37 * Description: Accepts asynchronous callbacks from the Communications Manager
38 *              for EVDs that have been specified as the connection_evd.
39 *
40 * $Id: dapl_evd_connection_callb.c,v 1.33 2003/07/30 18:13:38 hobie16 Exp $
41 */
42
43#include "dapl.h"
44#include "dapl_evd_util.h"
45#include "dapl_ep_util.h"
46
47
48/*
49 * dapl_evd_connection_callback
50 *
51 * Connection callback function for ACTIVE connection requests; callbacks
52 * generated by the Connection Manager in response to issuing a
53 * connect call.
54 *
55 * Input:
56 * 	ib_cm_handle,
57 * 	ib_cm_event
58 *	private_data_ptr
59 * 	context (evd)
60 *	cr_pp
61 *
62 * Output:
63 * 	None
64 *
65 */
66
67void
68dapl_evd_connection_callback(
69    IN    ib_cm_handle_t	ib_cm_handle,
70    IN    const ib_cm_events_t  ib_cm_event,
71    IN	  const void 		*private_data_ptr,
72    IN    const void		*context)
73{
74	DAPL_EP		*ep_ptr;
75	DAPL_EVD	*evd_ptr;
76	DAPL_PRIVATE	*prd_ptr;
77	DAT_EVENT_NUMBER event_type;
78
79	dapl_dbg_log(
80	    DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
81	    "--> dapl_evd_connection_callback: ctxt: %p event: %x"
82	    " cm_handle %p\n",
83	    context,
84	    ib_cm_event,
85	    ib_cm_handle);
86
87	/*
88	 * Determine the type of handle passed back to us in the context
89	 * and sort out key parameters.
90	 */
91	dapl_os_assert(((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP ||
92	    ((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP_EXIT);
93	/*
94	 * Active side of the connection, context is an EP and
95	 * PSP is irrelevant.
96	 */
97	ep_ptr  = (DAPL_EP *)context;
98	evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
99
100	prd_ptr = (DAPL_PRIVATE *)private_data_ptr;
101
102	switch (ib_cm_event) {
103	case IB_CME_CONNECTED:
104	{
105		/*
106		 * If we don't have an EP at this point we are very screwed
107		 * up
108		 */
109		DAT_RETURN dat_status;
110
111		if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {
112			/*
113			 * If someone pulled the plug on the connection, just
114			 * exit
115			 */
116			break;
117		}
118		dapls_ib_connected(ep_ptr);
119		ep_ptr->param.ep_state	= DAT_EP_STATE_CONNECTED;
120		ep_ptr->cm_handle	= ib_cm_handle;
121		/* copy in the private data */
122		(void) dapl_os_memcpy(ep_ptr->private_data,
123		    prd_ptr->private_data,
124		    IB_MAX_REQ_PDATA_SIZE);
125
126		dat_status = dapls_evd_post_connection_event(
127		    evd_ptr,
128		    DAT_CONNECTION_EVENT_ESTABLISHED,
129		    (DAT_HANDLE) ep_ptr,
130		    IB_MAX_REQ_PDATA_SIZE,
131		    ep_ptr->private_data);
132
133		if (dat_status != DAT_SUCCESS) {
134			(void) dapls_ib_disconnect(ep_ptr,
135			    DAT_CLOSE_ABRUPT_FLAG);
136			ep_ptr->param.ep_state =
137			    DAT_EP_STATE_DISCONNECT_PENDING;
138		}
139
140		/*
141		 * If we received any premature DTO completions and
142		 * post them to the recv evd now.
143		 * there is a race here - if events arrive after we change
144		 * the ep state to connected and before we process premature
145		 * events
146		 */
147		dapls_evd_post_premature_events(ep_ptr);
148
149		break;
150	}
151	case IB_CME_DISCONNECTED:
152	case IB_CME_DISCONNECTED_ON_LINK_DOWN:
153	{
154		/*
155		 * EP is now fully disconnected; initiate any post processing
156		 * to reset the underlying QP and get the EP ready for
157		 * another connection
158		 */
159		if (ep_ptr->param.ep_state  == DAT_EP_STATE_DISCONNECTED) {
160			/* DTO error caused this */
161			event_type = DAT_CONNECTION_EVENT_BROKEN;
162		} else {
163			ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
164			dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,
165			    ib_cm_event);
166			event_type = DAT_CONNECTION_EVENT_DISCONNECTED;
167		}
168
169		/* If the EP has been freed, the evd_ptr will be NULL */
170		if (evd_ptr != NULL) {
171			(void) dapls_evd_post_connection_event(
172			    evd_ptr, event_type, (DAT_HANDLE) ep_ptr, 0, 0);
173		}
174
175		/*
176		 * If the user has done an ep_free of the EP, we have been
177		 * waiting for the disconnect event; just clean it up now.
178		 */
179		if (ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT) {
180			(void) dapl_ep_free(ep_ptr);
181		}
182		break;
183	}
184	case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:
185	{
186		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
187		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
188		(void) dapls_evd_post_connection_event(
189		    evd_ptr,
190		    DAT_CONNECTION_EVENT_PEER_REJECTED,
191		    (DAT_HANDLE) ep_ptr,
192		    0,
193		    0);
194		break;
195	}
196	case IB_CME_DESTINATION_UNREACHABLE:
197	{
198		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
199		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
200		(void) dapls_evd_post_connection_event(
201		    evd_ptr,
202		    DAT_CONNECTION_EVENT_UNREACHABLE,
203		    (DAT_HANDLE) ep_ptr,
204		    0,
205		    0);
206		break;
207	}
208	case IB_CME_DESTINATION_REJECT:
209	case IB_CME_TOO_MANY_CONNECTION_REQUESTS:
210	case IB_CME_LOCAL_FAILURE:
211	{
212		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
213		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
214		(void) dapls_evd_post_connection_event(
215		    evd_ptr,
216		    DAT_CONNECTION_EVENT_NON_PEER_REJECTED,
217		    (DAT_HANDLE) ep_ptr,
218		    0,
219		    0);
220		break;
221	}
222	case IB_CME_TIMED_OUT:
223	{
224		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
225		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
226		(void) dapls_evd_post_connection_event(
227		    evd_ptr,
228		    DAT_CONNECTION_EVENT_TIMED_OUT,
229		    (DAT_HANDLE) ep_ptr,
230		    0,
231		    0);
232		break;
233	}
234	case IB_CME_CONNECTION_REQUEST_PENDING:
235	case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:
236	default:
237	{
238		dapl_os_assert(0);		/* shouldn't happen */
239		break;
240	}
241	}
242
243	dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
244	    "dapl_evd_connection_callback () returns\n");
245
246}
247
248
249/*
250 * Local variables:
251 *  c-indent-level: 4
252 *  c-basic-offset: 4
253 *  tab-width: 8
254 * End:
255 */
256