Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/adapters/tavor/tavor_agents.c
+++ new/usr/src/uts/common/io/ib/adapters/tavor/tavor_agents.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * tavor_agents.c
29 29 * Tavor InfiniBand Management Agent (SMA, PMA, BMA) routines
30 30 *
31 31 * Implements all the routines necessary for initializing, handling,
32 32 * and (later) tearing down all the infrastructure necessary for Tavor
33 33 * MAD processing.
34 34 */
35 35
36 36 #include <sys/types.h>
37 37 #include <sys/conf.h>
38 38 #include <sys/ddi.h>
39 39 #include <sys/sunddi.h>
40 40 #include <sys/modctl.h>
41 41
42 42 #include <sys/ib/adapters/tavor/tavor.h>
43 43 #include <sys/ib/mgt/ibmf/ibmf.h>
44 44 #include <sys/disp.h>
45 45
46 46 static void tavor_agent_request_cb(ibmf_handle_t ibmf_handle,
47 47 ibmf_msg_t *msgp, void *args);
48 48 static void tavor_agent_handle_req(void *cb_args);
49 49 static void tavor_agent_response_cb(ibmf_handle_t ibmf_handle,
50 50 ibmf_msg_t *msgp, void *args);
51 51 static int tavor_agent_list_init(tavor_state_t *state);
52 52 static void tavor_agent_list_fini(tavor_state_t *state);
53 53 static int tavor_agent_register_all(tavor_state_t *state);
54 54 static int tavor_agent_unregister_all(tavor_state_t *state, int num_reg);
55 55 static void tavor_agent_mad_resp_handling(tavor_state_t *state,
56 56 ibmf_msg_t *msgp, uint_t port);
57 57
58 58 /*
59 59 * tavor_agent_handlers_init()
60 60 * Context: Only called from attach() and/or detach() path contexts
61 61 */
62 62 int
63 63 tavor_agent_handlers_init(tavor_state_t *state)
64 64 {
65 65 int status;
66 66 char *errormsg, *rsrc_name;
67 67
68 68 TAVOR_TNF_ENTER(tavor_agent_handlers_init);
69 69
70 70 /* Determine if we need to register any agents with the IBMF */
71 71 if ((state->ts_cfg_profile->cp_qp0_agents_in_fw) &&
72 72 (state->ts_cfg_profile->cp_qp1_agents_in_fw)) {
73 73 TAVOR_TNF_EXIT(tavor_agent_handlers_init);
74 74 return (DDI_SUCCESS);
75 75 }
76 76
77 77 /*
78 78 * Build a unique name for the Tavor task queue from the Tavor driver
79 79 * instance number and TAVOR_TASKQ_NAME
80 80 */
81 81 rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
82 82 TAVOR_RSRC_NAME(rsrc_name, TAVOR_TASKQ_NAME);
83 83
84 84 /* Initialize the Tavor IB management agent list */
85 85 status = tavor_agent_list_init(state);
86 86 if (status != DDI_SUCCESS) {
87 87 /* Set "status" and "errormsg" and goto failure */
88 88 TAVOR_TNF_FAIL(DDI_FAILURE, "failed agent list init");
89 89 goto agentsinit_fail;
90 90 }
91 91
92 92 /*
93 93 * Initialize the agent handling task queue. Note: We set the task
94 94 * queue priority to the minimum system priority. At this point this
95 95 * is considered acceptable because MADs are unreliable datagrams
96 96 * and could get lost (in general) anyway.
97 97 */
98 98 state->ts_taskq_agents = ddi_taskq_create(state->ts_dip,
99 99 rsrc_name, TAVOR_TASKQ_NTHREADS, TASKQ_DEFAULTPRI, 0);
100 100 if (state->ts_taskq_agents == NULL) {
101 101 tavor_agent_list_fini(state);
102 102 /* Set "status" and "errormsg" and goto failure */
103 103 TAVOR_TNF_FAIL(DDI_FAILURE, "failed task queue");
104 104 goto agentsinit_fail;
105 105 }
106 106
107 107 /* Now attempt to register all of the agents with the IBMF */
108 108 status = tavor_agent_register_all(state);
109 109 if (status != DDI_SUCCESS) {
110 110 ddi_taskq_destroy(state->ts_taskq_agents);
111 111 tavor_agent_list_fini(state);
112 112 /* Set "status" and "errormsg" and goto failure */
113 113 TAVOR_TNF_FAIL(DDI_FAILURE, "failed IBMF register");
114 114 goto agentsinit_fail;
115 115 }
116 116
117 117 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
118 118 TAVOR_TNF_EXIT(tavor_agent_handlers_init);
119 119 return (DDI_SUCCESS);
120 120
121 121 agentsinit_fail:
122 122 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
123 123 TNF_PROBE_1(tavor_agent_handlers_init_fail, TAVOR_TNF_ERROR, "",
124 124 tnf_string, msg, errormsg);
125 125 TAVOR_TNF_EXIT(tavor_agent_handlers_init);
126 126 return (status);
127 127 }
128 128
129 129
130 130 /*
131 131 * tavor_agent_handlers_fini()
132 132 * Context: Only called from detach() path context
133 133 */
134 134 int
135 135 tavor_agent_handlers_fini(tavor_state_t *state)
136 136 {
137 137 int status;
138 138
139 139 TAVOR_TNF_ENTER(tavor_agent_handlers_fini);
140 140
141 141 /* Determine if we need to unregister any agents from the IBMF */
142 142 if ((state->ts_cfg_profile->cp_qp0_agents_in_fw) &&
143 143 (state->ts_cfg_profile->cp_qp1_agents_in_fw)) {
144 144 TAVOR_TNF_EXIT(tavor_agent_handlers_fini);
145 145 return (DDI_SUCCESS);
146 146 }
147 147
148 148 /* Now attempt to unregister all of the agents from the IBMF */
149 149 status = tavor_agent_unregister_all(state, state->ts_num_agents);
150 150 if (status != DDI_SUCCESS) {
151 151 TNF_PROBE_0(tavor_agent_handlers_fini_unreg_fail,
152 152 TAVOR_TNF_ERROR, "");
153 153 TAVOR_TNF_EXIT(tavor_agent_handlers_fini);
154 154 return (DDI_FAILURE);
155 155 }
156 156
157 157 /*
158 158 * Destroy the task queue. The task queue destroy is guaranteed to
159 159 * wait until any scheduled tasks have completed. We are able to
160 160 * guarantee that no _new_ tasks will be added the task queue while
161 161 * we are in the ddi_taskq_destroy() call because we have
162 162 * (at this point) successfully unregistered from IBMF (in
163 163 * tavor_agent_unregister_all() above).
164 164 */
165 165 ddi_taskq_destroy(state->ts_taskq_agents);
166 166
167 167 /* Teardown the Tavor IB management agent list */
168 168 tavor_agent_list_fini(state);
169 169
170 170 TAVOR_TNF_EXIT(tavor_agent_handlers_fini);
171 171 return (DDI_SUCCESS);
172 172 }
173 173
174 174
175 175 /*
176 176 * tavor_agent_request_cb()
177 177 * Context: Called from the IBMF context
178 178 */
179 179 static void
180 180 tavor_agent_request_cb(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
181 181 void *args)
182 182 {
183 183 tavor_agent_handler_arg_t *cb_args;
184 184 tavor_agent_list_t *curr;
185 185 tavor_state_t *state;
186 186 int status;
187 187 int ibmf_status;
188 188
189 189 TAVOR_TNF_ENTER(tavor_agent_request_cb);
190 190
191 191 curr = (tavor_agent_list_t *)args;
192 192 state = curr->agl_state;
193 193
194 194 /*
195 195 * Allocate space to hold the callback args (for passing to the
196 196 * task queue). Note: If we are unable to allocate space for the
197 197 * the callback args here, then we just return. But we must ensure
198 198 * that we call ibmf_free_msg() to free up the message.
199 199 */
200 200 cb_args = (tavor_agent_handler_arg_t *)kmem_zalloc(
201 201 sizeof (tavor_agent_handler_arg_t), KM_NOSLEEP);
202 202 if (cb_args == NULL) {
203 203 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
↓ open down ↓ |
203 lines elided |
↑ open up ↑ |
204 204 if (ibmf_status != IBMF_SUCCESS) {
205 205 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
206 206 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
207 207 ibmf_status);
208 208 }
209 209 TNF_PROBE_0(tavor_agent_request_cb_kma_fail,
210 210 TAVOR_TNF_ERROR, "");
211 211 TAVOR_TNF_EXIT(tavor_agent_request_cb);
212 212 return;
213 213 }
214 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cb_args))
215 214
216 215 /* Fill in the callback args */
217 216 cb_args->ahd_ibmfhdl = ibmf_handle;
218 217 cb_args->ahd_ibmfmsg = msgp;
219 218 cb_args->ahd_agentlist = args;
220 219
221 220 /*
222 221 * Dispatch the message to the task queue. Note: Just like above,
223 222 * if this request fails for any reason then make sure to free up
224 223 * the IBMF message and then return
225 224 */
226 225 status = ddi_taskq_dispatch(state->ts_taskq_agents,
227 226 tavor_agent_handle_req, cb_args, DDI_NOSLEEP);
228 227 if (status == DDI_FAILURE) {
229 228 kmem_free(cb_args, sizeof (tavor_agent_handler_arg_t));
230 229 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
231 230 if (ibmf_status != IBMF_SUCCESS) {
232 231 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
233 232 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
234 233 ibmf_status);
235 234 }
236 235 TNF_PROBE_0(tavor_agent_request_cb_taskq_fail,
237 236 TAVOR_TNF_ERROR, "");
238 237 }
239 238 TAVOR_TNF_EXIT(tavor_agent_request_cb);
240 239 }
241 240
242 241 /*
243 242 * tavor_agent_handle_req()
244 243 * Context: Called with priority of taskQ thread
245 244 */
246 245 static void
247 246 tavor_agent_handle_req(void *cb_args)
248 247 {
249 248 tavor_agent_handler_arg_t *agent_args;
250 249 tavor_agent_list_t *curr;
251 250 tavor_state_t *state;
252 251 ibmf_handle_t ibmf_handle;
253 252 ibmf_msg_t *msgp;
254 253 ibmf_msg_bufs_t *recv_msgbufp;
255 254 ibmf_msg_bufs_t *send_msgbufp;
256 255 ibmf_retrans_t retrans;
257 256 uint_t port;
258 257 int status;
259 258
260 259 TAVOR_TNF_ENTER(tavor_agent_handle_req);
261 260
262 261 /* Extract the necessary info from the callback args parameter */
263 262 agent_args = (tavor_agent_handler_arg_t *)cb_args;
264 263 ibmf_handle = agent_args->ahd_ibmfhdl;
265 264 msgp = agent_args->ahd_ibmfmsg;
266 265 curr = agent_args->ahd_agentlist;
267 266 state = curr->agl_state;
268 267 port = curr->agl_port;
269 268
270 269 /*
271 270 * Set the message send buffer pointers to the message receive buffer
272 271 * pointers to reuse the IBMF provided buffers for the sender
273 272 * information.
274 273 */
275 274 recv_msgbufp = &msgp->im_msgbufs_recv;
276 275 send_msgbufp = &msgp->im_msgbufs_send;
277 276 bcopy(recv_msgbufp, send_msgbufp, sizeof (ibmf_msg_bufs_t));
278 277
279 278 /*
280 279 * Check if the incoming packet is a special "Tavor Trap" MAD. If it
281 280 * is, then do the special handling. If it isn't, then simply pass it
282 281 * on to the firmware and forward the response back to the IBMF.
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
283 282 *
284 283 * Note: Tavor has a unique method for handling internally generated
285 284 * Traps. All internally detected/generated Trap messages are
286 285 * automatically received by the IBMF (as receive completions on QP0),
287 286 * which (because all Tavor Trap MADs have SLID == 0) detects it as a
288 287 * special "Tavor Trap" and forwards it here to the driver's SMA.
289 288 * It is then our responsibility here to fill in the Trap MAD's DLID
290 289 * for forwarding to the real Master SM (as programmed in the port's
291 290 * PortInfo.MasterSMLID field.)
292 291 */
293 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(msgp->im_local_addr))
294 292 if (TAVOR_IS_SPECIAL_TRAP_MAD(msgp)) {
295 293 msgp->im_local_addr.ia_remote_lid =
296 294 TAVOR_PORT_MASTERSMLID_GET(state, port - 1);
297 295 } else {
298 296 /*
299 297 * Post the command to the firmware (using the MAD_IFC
300 298 * command). Note: We also reuse the command that was passed
301 299 * in. We pass the pointer to the original MAD payload as if
302 300 * it were both the source of the incoming MAD as well as the
303 301 * destination for the response. This is acceptable and saves
304 302 * us the step of one additional copy. Note: If this command
305 303 * fails for any reason other than TAVOR_CMD_BAD_PKT, it
306 304 * probably indicates a serious problem.
307 305 */
308 306 status = tavor_mad_ifc_cmd_post(state, port,
309 307 TAVOR_CMD_SLEEP_NOSPIN,
310 308 (uint32_t *)recv_msgbufp->im_bufs_mad_hdr,
311 309 (uint32_t *)send_msgbufp->im_bufs_mad_hdr);
312 310 if (status != TAVOR_CMD_SUCCESS) {
313 311 if ((status != TAVOR_CMD_BAD_PKT) &&
314 312 (status != TAVOR_CMD_INSUFF_RSRC)) {
315 313 cmn_err(CE_CONT, "Tavor: MAD_IFC (port %02d) "
316 314 "command failed: %08x\n", port, status);
317 315 TNF_PROBE_1(tavor_agent_handle_req_madifc_fail,
318 316 TAVOR_TNF_ERROR, "", tnf_uint, cmd_status,
319 317 status);
320 318 }
321 319
322 320 /* finish cleanup */
323 321 goto tavor_agent_handle_req_skip_response;
324 322 }
325 323 }
326 324
327 325 /*
328 326 * If incoming MAD was "TrapRepress", then no response is necessary.
329 327 * Free the IBMF message and return.
330 328 */
331 329 if (TAVOR_IS_TRAP_REPRESS_MAD(msgp)) {
332 330 goto tavor_agent_handle_req_skip_response;
333 331 }
334 332
335 333 /*
336 334 * Modify the response MAD as necessary (for any special cases).
337 335 * Specifically, if this MAD was a directed route MAD, then some
338 336 * additional packet manipulation may be necessary because the Tavor
339 337 * firmware does not do all the required steps to respond to the
340 338 * MAD.
341 339 */
342 340 tavor_agent_mad_resp_handling(state, msgp, port);
343 341
344 342 /*
345 343 * Send response (or forwarded "Trap" MAD) back to IBMF. We use the
346 344 * "response callback" to indicate when it is appropriate (later) to
347 345 * free the IBMF msg.
348 346 */
349 347 status = ibmf_msg_transport(ibmf_handle, IBMF_QP_HANDLE_DEFAULT,
350 348 msgp, &retrans, tavor_agent_response_cb, state, 0);
351 349 if (status != IBMF_SUCCESS) {
352 350 TNF_PROBE_1(tavor_ibmf_send_msg_fail, TAVOR_TNF_ERROR, "",
353 351 tnf_uint, ibmf_status, status);
354 352 goto tavor_agent_handle_req_skip_response;
355 353 }
356 354
357 355 /* Free up the callback args parameter */
358 356 kmem_free(agent_args, sizeof (tavor_agent_handler_arg_t));
359 357 TAVOR_TNF_EXIT(tavor_agent_handle_req);
360 358 return;
361 359
362 360 tavor_agent_handle_req_skip_response:
363 361 /* Free up the ibmf message */
364 362 status = ibmf_free_msg(ibmf_handle, &msgp);
365 363 if (status != IBMF_SUCCESS) {
366 364 TNF_PROBE_1(tavor_agent_handle_req_ibmf_free_msg_fail,
367 365 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
368 366 status);
369 367 }
370 368 /* Free up the callback args parameter */
371 369 kmem_free(agent_args, sizeof (tavor_agent_handler_arg_t));
372 370 TAVOR_TNF_EXIT(tavor_agent_handle_req);
373 371 }
374 372
375 373
376 374 /*
377 375 * tavor_agent_response_cb()
378 376 * Context: Called from the IBMF context
379 377 */
380 378 /* ARGSUSED */
381 379 static void
382 380 tavor_agent_response_cb(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
383 381 void *args)
384 382 {
385 383 int status;
386 384
387 385 TAVOR_TNF_ENTER(tavor_agent_response_cb);
388 386
389 387 /*
390 388 * It is the responsibility of each IBMF callback recipient to free
391 389 * the packets that it has been given. Now that we are in the
392 390 * response callback, we can be assured that it is safe to do so.
393 391 */
394 392 status = ibmf_free_msg(ibmf_handle, &msgp);
395 393 if (status != IBMF_SUCCESS) {
396 394 TNF_PROBE_1(tavor_agent_response_cb_ibmf_free_msg_fail,
397 395 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status, status);
398 396 }
399 397
400 398 TAVOR_TNF_EXIT(tavor_agent_response_cb);
401 399 }
402 400
403 401
404 402 /*
405 403 * tavor_agent_list_init()
406 404 * Context: Only called from attach() path context
407 405 */
408 406 static int
409 407 tavor_agent_list_init(tavor_state_t *state)
410 408 {
411 409 tavor_agent_list_t *curr;
412 410 uint_t num_ports, num_agents, num_agents_per_port;
413 411 uint_t num_sma_agents = 0;
414 412 uint_t num_pma_agents = 0;
415 413 uint_t num_bma_agents = 0;
416 414 uint_t do_qp0, do_qp1;
417 415 int i, j, indx;
418 416
419 417 TAVOR_TNF_ENTER(tavor_agent_list_init);
420 418
421 419 /*
422 420 * Calculate the number of registered agents for each port
423 421 * (SMA, PMA, and BMA) and determine whether or not to register
424 422 * a given agent with the IBMF (or whether to let the Tavor firmware
425 423 * handle it)
426 424 */
427 425 num_ports = state->ts_cfg_profile->cp_num_ports;
428 426 num_agents = 0;
429 427 num_agents_per_port = 0;
430 428 do_qp0 = state->ts_cfg_profile->cp_qp0_agents_in_fw;
431 429 do_qp1 = state->ts_cfg_profile->cp_qp1_agents_in_fw;
432 430 if (do_qp0 == 0) {
433 431 num_agents += (num_ports * TAVOR_NUM_QP0_AGENTS_PER_PORT);
434 432 num_agents_per_port += TAVOR_NUM_QP0_AGENTS_PER_PORT;
435 433 num_sma_agents = num_ports;
436 434 }
437 435 if (do_qp1 == 0) {
438 436 num_agents += (num_ports * TAVOR_NUM_QP1_AGENTS_PER_PORT);
439 437 num_agents_per_port += TAVOR_NUM_QP1_AGENTS_PER_PORT;
440 438 num_pma_agents = num_ports;
441 439 /*
442 440 * The following line is commented out because the Tavor
443 441 * firmware does not currently support a BMA. If it did,
444 442 * then we would want to register the agent with the IBMF.
445 443 * (We would also need to have TAVOR_NUM_QP1_AGENTS_PER_PORT
446 444 * set to 2, instead of 1.)
447 445 *
448 446 * num_bma_agents = num_ports;
449 447 */
450 448 }
451 449
452 450 state->ts_num_agents = num_agents;
453 451
454 452 /*
455 453 * Allocate the memory for all of the agent list entries
456 454 */
457 455 state->ts_agents = (tavor_agent_list_t *)kmem_zalloc(num_agents *
458 456 sizeof (tavor_agent_list_t), KM_SLEEP);
459 457 if (state->ts_agents == NULL) {
460 458 TNF_PROBE_0(tavor_agent_list_init_kma_fail,
461 459 TAVOR_TNF_ERROR, "");
462 460 TAVOR_TNF_EXIT(tavor_agent_list_init);
463 461 return (DDI_FAILURE);
464 462 }
465 463
466 464 /*
467 465 * Fill in each of the agent list entries with the agent's
468 466 * MgmtClass, port number, and Tavor softstate pointer
469 467 */
470 468 indx = 0;
471 469 for (i = 0; i < num_agents_per_port; i++) {
472 470 for (j = 0; j < num_ports; j++) {
473 471 curr = &state->ts_agents[indx];
474 472 curr->agl_state = state;
475 473 curr->agl_port = j + 1;
476 474
477 475 if ((do_qp0 == 0) && num_sma_agents) {
478 476 curr->agl_mgmtclass = SUBN_AGENT;
479 477 num_sma_agents--;
480 478 indx++;
481 479 } else if ((do_qp1 == 0) && (num_pma_agents)) {
482 480 curr->agl_mgmtclass = PERF_AGENT;
483 481 num_pma_agents--;
484 482 indx++;
485 483 } else if ((do_qp1 == 0) && (num_bma_agents)) {
486 484 curr->agl_mgmtclass = BM_AGENT;
487 485 num_bma_agents--;
488 486 indx++;
489 487 }
490 488 }
491 489 }
492 490
493 491 TAVOR_TNF_EXIT(tavor_agent_list_init);
494 492 return (DDI_SUCCESS);
495 493 }
496 494
497 495
498 496 /*
499 497 * tavor_agent_list_fini()
500 498 * Context: Only called from attach() and/or detach() path contexts
501 499 */
502 500 static void
503 501 tavor_agent_list_fini(tavor_state_t *state)
504 502 {
505 503 TAVOR_TNF_ENTER(tavor_agent_list_fini);
506 504
507 505 /* Free up the memory for the agent list entries */
508 506 kmem_free(state->ts_agents,
509 507 state->ts_num_agents * sizeof (tavor_agent_list_t));
510 508
511 509 TAVOR_TNF_EXIT(tavor_agent_list_fini);
512 510 }
513 511
514 512
515 513 /*
516 514 * tavor_agent_register_all()
517 515 * Context: Only called from attach() path context
518 516 */
519 517 static int
520 518 tavor_agent_register_all(tavor_state_t *state)
521 519 {
522 520 tavor_agent_list_t *curr;
523 521 ibmf_register_info_t ibmf_reg;
524 522 ibmf_impl_caps_t impl_caps;
525 523 ib_guid_t nodeguid;
526 524 int i, status, num_registered;
527 525
528 526 TAVOR_TNF_ENTER(tavor_agent_register_all);
529 527
530 528 /* Get the Tavor NodeGUID from the softstate */
531 529 nodeguid = state->ts_ibtfinfo.hca_attr->hca_node_guid;
532 530
533 531 /*
534 532 * Register each of the agents with the IBMF (and add callbacks for
535 533 * each to the tavor_agent_request_cb() routine). Note: If we
536 534 * fail somewhere along the line here, we attempt to cleanup as much
537 535 * of the mess as we can and then jump to tavor_agent_unregister_all()
538 536 * to cleanup the rest.
539 537 */
540 538 num_registered = 0;
541 539 for (i = 0; i < state->ts_num_agents; i++) {
542 540
543 541 /* Register each agent with the IBMF */
544 542 curr = &state->ts_agents[i];
545 543 ibmf_reg.ir_ci_guid = nodeguid;
546 544 ibmf_reg.ir_port_num = curr->agl_port;
547 545 ibmf_reg.ir_client_class = curr->agl_mgmtclass;
548 546 status = ibmf_register(&ibmf_reg, IBMF_VERSION, 0,
549 547 NULL, NULL, &curr->agl_ibmfhdl, &impl_caps);
550 548 if (status != IBMF_SUCCESS) {
551 549 TNF_PROBE_0(tavor_agent_register_all_ibmf_reg_fail,
552 550 TAVOR_TNF_ERROR, "");
553 551 goto agents_reg_fail;
554 552 }
555 553
556 554 /* Setup callbacks with the IBMF */
557 555 status = ibmf_setup_async_cb(curr->agl_ibmfhdl,
558 556 IBMF_QP_HANDLE_DEFAULT, tavor_agent_request_cb, curr, 0);
559 557 if (status != IBMF_SUCCESS) {
560 558 (void) ibmf_unregister(&curr->agl_ibmfhdl, 0);
561 559 TNF_PROBE_0(tavor_agent_register_all_ibmf_cb_fail,
562 560 TAVOR_TNF_ERROR, "");
563 561 goto agents_reg_fail;
564 562 }
565 563 num_registered++;
566 564 }
567 565
568 566 TAVOR_TNF_EXIT(tavor_agent_register_all);
569 567 return (DDI_SUCCESS);
570 568
571 569 agents_reg_fail:
572 570 (void) tavor_agent_unregister_all(state, num_registered);
573 571 TAVOR_TNF_EXIT(tavor_agent_register_all);
574 572 return (DDI_FAILURE);
575 573 }
576 574
577 575
578 576 /*
579 577 * tavor_agent_unregister_all()
580 578 * Context: Only called from detach() path context
581 579 */
582 580 static int
583 581 tavor_agent_unregister_all(tavor_state_t *state, int num_reg)
584 582 {
585 583 tavor_agent_list_t *curr;
586 584 int i, status;
587 585
588 586 TAVOR_TNF_ENTER(tavor_agent_unregister_all);
589 587
590 588 /*
591 589 * For each registered agent in the agent list, teardown the
592 590 * callbacks from the IBMF and unregister.
593 591 */
594 592 for (i = 0; i < num_reg; i++) {
595 593 curr = &state->ts_agents[i];
596 594
597 595 /* Teardown the IBMF callback */
598 596 status = ibmf_tear_down_async_cb(curr->agl_ibmfhdl,
599 597 IBMF_QP_HANDLE_DEFAULT, 0);
600 598 if (status != IBMF_SUCCESS) {
601 599 TNF_PROBE_0(tavor_agents_unreg_teardown_cb_fail,
602 600 TAVOR_TNF_ERROR, "");
603 601 TAVOR_TNF_EXIT(tavor_agent_unregister_all);
604 602 return (DDI_FAILURE);
605 603 }
606 604
607 605 /* Unregister the agent from the IBMF */
608 606 status = ibmf_unregister(&curr->agl_ibmfhdl, 0);
609 607 if (status != IBMF_SUCCESS) {
610 608 TNF_PROBE_0(tavor_agents_unreg_ibmf_fail,
611 609 TAVOR_TNF_ERROR, "");
612 610 TAVOR_TNF_EXIT(tavor_agent_unregister_all);
613 611 return (DDI_FAILURE);
614 612 }
615 613 }
616 614
617 615 TAVOR_TNF_EXIT(tavor_agent_unregister_all);
618 616 return (DDI_SUCCESS);
619 617 }
620 618
621 619
622 620 /*
623 621 * tavor_agent_mad_resp_handling()
624 622 * Context: Called with priority of taskQ thread
625 623 */
626 624 /* ARGSUSED */
627 625 static void
628 626 tavor_agent_mad_resp_handling(tavor_state_t *state, ibmf_msg_t *msgp,
629 627 uint_t port)
630 628 {
631 629 ib_mad_hdr_t *rmadhdrp = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
632 630 ib_mad_hdr_t *smadhdrp = msgp->im_msgbufs_send.im_bufs_mad_hdr;
633 631 uint_t hop_count, hop_point;
634 632 uchar_t *resp, *ret_path;
635 633
636 634 resp = (uchar_t *)msgp->im_msgbufs_send.im_bufs_cl_data;
↓ open down ↓ |
333 lines elided |
↑ open up ↑ |
637 635
638 636 /*
639 637 * Handle directed route MADs as a special case. Tavor firmware
640 638 * does not update the "direction" bit, "hop pointer", "Return
641 639 * Path" or, in fact, any of the "directed route" parameters. So
642 640 * the responsibility falls on Tavor driver software to inspect the
643 641 * MADs and update those fields as appropriate (see section 14.2.2
644 642 * of the IBA specification, rev 1.1)
645 643 */
646 644 if (TAVOR_MAD_IS_DR(rmadhdrp)) {
647 -
648 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)rmadhdrp)))
649 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)smadhdrp)))
650 -
651 645 /*
652 646 * Set the "Direction" bit to one. This indicates that this
653 647 * is now directed route response
654 648 */
655 649 TAVOR_DRMAD_SET_DIRECTION(rmadhdrp);
656 650
657 651 /* Extract the "hop pointer" and "hop count" from the MAD */
658 652 hop_count = TAVOR_DRMAD_GET_HOPCOUNT(rmadhdrp);
659 653 hop_point = TAVOR_DRMAD_GET_HOPPOINTER(rmadhdrp);
660 654
661 655 /* Append the port we came in on to the "Return Path" */
662 656 if ((hop_count != 0) && ((hop_point == hop_count) ||
663 657 (hop_point == hop_count + 1))) {
664 658 ret_path = &resp[TAVOR_DRMAD_RETURN_PATH_OFFSET];
665 659 ret_path[hop_point] = port;
666 660 }
667 661
668 662 /* Then increment the "hop pointer" in the MAD */
669 663 hop_point++;
670 664 TAVOR_DRMAD_SET_HOPPOINTER(smadhdrp, hop_point);
671 665 }
672 666 }
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX