Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / ib / mgt / ibmf / ibmf_handlers.c
blob49596d58b2e285d3f1e427549ed7e84c3336b3fa
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file implements the callback handler logic common to send and receive
28 * handling in IBMF.
31 #include <sys/ib/mgt/ibmf/ibmf_impl.h>
33 extern int ibmf_trace_level;
34 extern ibmf_state_t *ibmf_statep;
35 extern void ibmf_saa_impl_ibt_async_handler(ibt_async_code_t code,
36 ibt_async_event_t *event);
38 static void ibmf_i_process_completion(ibmf_ci_t *cip, ibt_wc_t *wcp);
39 static void ibmf_i_callback_clients(ib_guid_t hca_guid,
40 ibmf_async_event_t evt);
43 * ibmf_ibt_async_handler():
44 * This function handles asynchronous events detected by the
45 * IBT framework.
47 /* ARGSUSED */
48 void
49 ibmf_ibt_async_handler(void *clnt_private, ibt_hca_hdl_t hca_hdl,
50 ibt_async_code_t code, ibt_async_event_t *event)
52 ibmf_ci_t *cip;
54 IBMF_TRACE_3(DPRINT_L3,
55 "ibmf_ibt_async_handler: Code %x HCA GUID %016"PRIx64" Port %d\n",
56 code, event->ev_hca_guid, event->ev_port);
59 * let ibmf_saa know events first hand
61 ibmf_saa_impl_ibt_async_handler(code, event);
64 * call client callbacks and then fail if ANY client remains.
66 if (code == IBT_HCA_DETACH_EVENT) {
68 ibmf_i_callback_clients(event->ev_hca_guid, IBMF_CI_OFFLINE);
70 mutex_enter(&ibmf_statep->ibmf_mutex);
71 cip = ibmf_statep->ibmf_ci_list;
73 while (cip != NULL) {
74 mutex_enter(&cip->ci_mutex);
76 if (cip->ci_node_guid == event->ev_hca_guid) {
78 mutex_exit(&cip->ci_mutex);
79 break;
82 mutex_exit(&cip->ci_mutex);
83 cip = cip->ci_next;
86 if (cip != NULL) {
88 * found the right ci, check
89 * if any clients are still registered
90 * (Note that if we found the ci, chances are that
91 * it was not released).
93 mutex_enter(&cip->ci_clients_mutex);
95 if (cip->ci_clients != NULL) {
97 IBMF_TRACE_1(DPRINT_L1,
98 "%s, returning failure\n",
99 "ibmf_ibt_async_handler: Found "
100 "clients still registered.");
102 mutex_exit(&cip->ci_clients_mutex);
104 mutex_exit(&ibmf_statep->ibmf_mutex);
105 } else if (code == IBT_EVENT_SQD) {
106 ibmf_ci_t *cip;
107 ibt_qp_hdl_t qphdl = (ibt_qp_hdl_t)event->ev_chan_hdl;
108 ibmf_alt_qp_t *altqpp;
109 boolean_t found = B_FALSE;
111 mutex_enter(&ibmf_statep->ibmf_mutex);
113 cip = ibmf_statep->ibmf_ci_list;
116 * An SQD event is received. We match the QP handle provided
117 * with all the alternate QP handles maintained on the lists
118 * of all the CI contexts. If a match is found, we wake
119 * up the thread waiting in ibmf_modify_qp().
121 while (cip != NULL) {
122 mutex_enter(&cip->ci_mutex);
123 altqpp = cip->ci_alt_qp_list;
124 while (altqpp != NULL) {
125 if (altqpp->isq_qp_handle == qphdl) {
126 mutex_enter(&altqpp->isq_mutex);
127 cv_signal(&altqpp->isq_sqd_cv);
128 mutex_exit(&altqpp->isq_mutex);
129 found = B_TRUE;
130 break;
132 altqpp = altqpp->isq_next;
134 mutex_exit(&cip->ci_mutex);
136 if (found)
137 break;
138 cip = cip->ci_next;
141 mutex_exit(&ibmf_statep->ibmf_mutex);
143 if (!found)
144 IBMF_TRACE_1(DPRINT_L1, "%s, ignoring event\n",
145 "ibmf_ibt_async_handler: SQD "
146 "event for unknown QP received");
149 IBMF_TRACE_0(DPRINT_L3, "ibmf_ibt_async_handler: exit.\n");
153 * ibmf_i_callback_clients():
154 * Finds the ci given in parameter.
155 * Calls the client callbacks with the event given in parameter.
156 * Note that client callbacks are called with all ibmf mutexes unlocked.
158 static void
159 ibmf_i_callback_clients(ib_guid_t hca_guid, ibmf_async_event_t evt)
161 ibmf_ci_t *cip;
162 ibmf_client_t *clientp;
164 int nclients = 0;
165 ibmf_async_event_cb_t *cb_array = NULL;
166 void **cb_args_array = NULL;
167 ibmf_handle_t *client_array = NULL;
168 int iclient;
170 IBMF_TRACE_0(DPRINT_L3, "ibmf_i_callback_clients() enter\n");
172 /* find ci */
173 mutex_enter(&ibmf_statep->ibmf_mutex);
174 cip = ibmf_statep->ibmf_ci_list;
176 while (cip != NULL) {
177 mutex_enter(&cip->ci_mutex);
179 if (cip->ci_node_guid == hca_guid) {
180 mutex_exit(&cip->ci_mutex);
181 break;
184 mutex_exit(&cip->ci_mutex);
185 cip = cip->ci_next;
188 if (cip == NULL) {
190 IBMF_TRACE_1(DPRINT_L1,
191 "ibmf_i_callback_clients: ci = %016"PRIx64"NOT found.\n",
192 hca_guid);
194 mutex_exit(&ibmf_statep->ibmf_mutex);
195 goto bail;
198 /* found the right ci, count clients */
199 mutex_enter(&cip->ci_clients_mutex);
201 /* empty counting loop */
202 for (clientp = cip->ci_clients, nclients = 0; clientp != NULL;
203 clientp = clientp->ic_next, nclients++)
206 IBMF_TRACE_2(DPRINT_L3,
207 "ibmf_i_callback_clients: found %d clients, on ci = %016"PRIx64"\n",
208 nclients, hca_guid);
210 /* no clients? bail */
211 if (nclients == 0) {
213 mutex_exit(&cip->ci_clients_mutex);
214 mutex_exit(&ibmf_statep->ibmf_mutex);
215 goto bail;
218 /* allocate callback, args, and client arrays */
220 cb_array = kmem_zalloc(
221 nclients * sizeof (ibmf_async_event_cb_t), KM_NOSLEEP);
223 cb_args_array = kmem_zalloc(
224 nclients * sizeof (void*), KM_NOSLEEP);
226 client_array = kmem_zalloc(
227 nclients * sizeof (ibmf_handle_t), KM_NOSLEEP);
229 if (cb_array == NULL || cb_args_array == NULL ||
230 client_array == NULL) {
232 IBMF_TRACE_1(DPRINT_L1, "ibmf_i_callback_clients: %s\n",
233 "could not allocate memory for callback arrays");
235 mutex_exit(&cip->ci_clients_mutex);
236 mutex_exit(&ibmf_statep->ibmf_mutex);
237 goto bail;
240 /* build callback list */
242 for (clientp = cip->ci_clients, iclient = 0;
243 clientp != NULL;
244 clientp = clientp->ic_next, iclient++) {
246 cb_array[iclient] = clientp->ic_async_cb;
247 cb_args_array[iclient] = clientp->ic_async_cb_arg;
248 client_array[iclient] = (ibmf_handle_t)clientp;
251 mutex_exit(&cip->ci_clients_mutex);
252 mutex_exit(&ibmf_statep->ibmf_mutex);
255 * All mutex unlocked, call back clients
257 for (iclient = 0; iclient < nclients; iclient++) {
259 IBMF_TRACE_4(DPRINT_L3,
260 "ibmf_i_callback_clients: client %d, handle = %016"PRIx64","
261 " callback = %016"PRIx64", args = %016"PRIx64"\n", iclient,
262 client_array[iclient], cb_array[iclient],
263 cb_args_array[iclient]);
265 if (cb_array[iclient] != NULL)
266 cb_array[iclient](client_array[iclient],
267 cb_args_array[iclient], evt);
270 bail:
272 if (cb_array != NULL)
273 kmem_free(cb_array, nclients * sizeof (ibmf_async_event_cb_t));
275 if (cb_args_array != NULL)
276 kmem_free(cb_args_array, nclients * sizeof (void*));
278 if (client_array != NULL)
279 kmem_free(client_array, nclients * sizeof (ibmf_handle_t));
281 IBMF_TRACE_0(DPRINT_L3, "ibmf_i_callback_clients: exit.\n");
285 * ibmf_i_mad_completions():
286 * Check for a completion entry on the specified CQ and process it
288 void
289 ibmf_i_mad_completions(ibt_cq_hdl_t cq_handle, void *arg)
291 ibt_wc_t cqe;
292 ibt_status_t status;
293 ibmf_ci_t *ibmf_cip;
295 IBMF_TRACE_1(DPRINT_L4,
296 "ibmf_i_mad_completions() enter, cq_hdl = %p\n", cq_handle);
298 ibmf_cip = arg;
300 ASSERT(ibmf_cip != NULL);
303 * Pull a completion and process it
305 for (;;) {
306 status = ibt_poll_cq(cq_handle, &cqe, 1, NULL);
307 ASSERT(status != IBT_CQ_HDL_INVALID &&
308 status != IBT_HCA_HDL_INVALID);
310 * Check if the status is IBT_SUCCESS or IBT_CQ_EMPTY
311 * either which can return from ibt_poll_cq(). In other
312 * cases, log the status for the further investigation.
314 if (status != IBT_SUCCESS) {
315 if (status != IBT_CQ_EMPTY) {
316 cmn_err(CE_NOTE, "!ibmf_i_mad_completions got "
317 "an error status (0x%x) from ibt_poll_cq.",
318 status);
320 break;
323 /* process the completion */
324 ibmf_i_process_completion(ibmf_cip, &cqe);
327 (void) ibt_enable_cq_notify(cq_handle, IBT_NEXT_COMPLETION);
330 * Look for more completions just in case some came in before
331 * we were able to reenable CQ notification
333 for (;;) {
334 status = ibt_poll_cq(cq_handle, &cqe, 1, NULL);
335 ASSERT(status != IBT_CQ_HDL_INVALID &&
336 status != IBT_HCA_HDL_INVALID);
338 * Check if the status is IBT_SUCCESS or IBT_CQ_EMPTY
339 * either which can return from ibt_poll_cq(). In other
340 * cases, log the status for the further investigation.
342 if (status != IBT_SUCCESS) {
343 if (status != IBT_CQ_EMPTY) {
344 cmn_err(CE_NOTE, "!ibmf_i_mad_completions got "
345 "an error status (0x%x) from ibt_poll_cq.",
346 status);
348 break;
351 /* process the completion */
352 ibmf_i_process_completion(ibmf_cip, &cqe);
357 * ibmf_i_process_completion():
358 * Process the send or receive completion
360 static void
361 ibmf_i_process_completion(ibmf_ci_t *cip, ibt_wc_t *wcp)
363 IBMF_TRACE_2(DPRINT_L4,
364 "ibmf_i_process_completion() enter, cip = %p, wcp = %p\n", cip,
365 wcp);
367 if (IBMF_IS_RECV_WR_ID(wcp->wc_id) == B_TRUE) {
368 /* completion from a receive queue */
369 ibmf_i_handle_recv_completion(cip, wcp);
370 } else {
371 /* completion from a send queue */
372 ibmf_i_handle_send_completion(cip, wcp);
376 #ifdef DEBUG
377 static int ibmf_i_dump_mad_size = 0x40;
378 static int ibmf_i_dump_wcp_enable = 0;
380 /* ARGSUSED */
381 void
382 ibmf_i_dump_wcp(ibmf_ci_t *cip, ibt_wc_t *wcp, ibmf_recv_wqe_t *recv_wqep)
384 uchar_t *ptr;
385 char buf[256], *sptr;
386 int i, j;
388 if (ibmf_i_dump_wcp_enable == 0)
389 return;
391 printf("wcp: sender lid %x port num %x path bits %x qp %x sl %x\n",
392 wcp->wc_slid, recv_wqep->recv_port_num, wcp->wc_path_bits,
393 wcp->wc_qpn, wcp->wc_sl);
395 ptr = (uchar_t *)((uintptr_t)recv_wqep->recv_mem +
396 sizeof (ib_grh_t));
398 printf("mad:\n");
399 /* first print multiples of 16bytes */
400 for (i = ibmf_i_dump_mad_size; i >= 16; i -= 16) {
401 for (sptr = buf, j = 0; j < 16; j++) {
402 (void) sprintf(sptr, "%02x ", *ptr++);
403 sptr += 3; /* 2 digits + space */
405 printf("%s\n", buf);
407 /* print the rest */
408 if (i < 16) {
409 for (sptr = buf, j = 0; j < i; j++) {
410 (void) sprintf(sptr, "%02x ", *ptr++);
411 sptr += 3; /* 2 digits + space */
413 printf("%s\n", buf);
416 #endif /* DEBUG */