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
67 void
dapl_evd_connection_callback(IN ib_cm_handle_t ib_cm_handle,IN const ib_cm_events_t ib_cm_event,IN const void * private_data_ptr,IN const void * context)68 dapl_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