]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_sm_mad_ctrl.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / opensm / osm_sm_mad_ctrl.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35
36 /*
37  * Abstract:
38  *    Implementation of osm_sm_mad_ctrl_t.
39  * This object represents the SM MAD request controller object.
40  * This object is part of the opensm family of objects.
41  */
42
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif                          /* HAVE_CONFIG_H */
46
47 #include <string.h>
48 #include <complib/cl_debug.h>
49 #include <iba/ib_types.h>
50 #include <opensm/osm_sm_mad_ctrl.h>
51 #include <vendor/osm_vendor_api.h>
52 #include <opensm/osm_madw.h>
53 #include <opensm/osm_msgdef.h>
54 #include <opensm/osm_helper.h>
55 #include <opensm/osm_opensm.h>
56
57 /****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad
58  * NAME
59  * __osm_sm_mad_ctrl_retire_trans_mad
60  *
61  * DESCRIPTION
62  * This function handles clean-up of MADs associated with the SM's
63  * outstanding transactions on the wire.
64  *
65  * SYNOPSIS
66  */
67
68 static void
69 __osm_sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * const p_ctrl,
70                                    IN osm_madw_t * const p_madw)
71 {
72         uint32_t outstanding;
73
74         OSM_LOG_ENTER(p_ctrl->p_log);
75
76         CL_ASSERT(p_madw);
77         /*
78            Return the MAD & wrapper to the pool.
79          */
80         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
81                 "Retiring MAD with TID 0x%" PRIx64 "\n",
82                 cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id));
83
84         osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
85
86         outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats);
87
88         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n",
89                 p_ctrl->p_stats->qp0_mads_outstanding,
90                 outstanding ? "" : ": wire is clean.");
91
92         OSM_LOG_EXIT(p_ctrl->p_log);
93 }
94
95 /************/
96
97 /****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback
98  * NAME
99  * __osm_sm_mad_ctrl_disp_done_callback
100  *
101  * DESCRIPTION
102  * This function is the Dispatcher callback that indicates
103  * a received MAD has been processed by the recipient.
104  *
105  * SYNOPSIS
106  */
107 static void
108 __osm_sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
109 {
110         osm_sm_mad_ctrl_t *const p_ctrl = (osm_sm_mad_ctrl_t *) context;
111         osm_madw_t *const p_madw = (osm_madw_t *) p_data;
112         ib_smp_t *p_smp;
113
114         OSM_LOG_ENTER(p_ctrl->p_log);
115
116         /*
117            If the MAD that just finished processing was a response,
118            then retire the transaction, since we must have generated
119            the request.
120
121            Otherwise, retire the transaction if a response was expected,
122            as in the case of a send failure. If a response was not expected,
123            just put the MAD back in the pool, because the MAD was a query
124            from some outside agent, e.g. Get(SMInfo) from another SM.
125          */
126         p_smp = osm_madw_get_smp_ptr(p_madw);
127         if (ib_smp_is_response(p_smp)) {
128                 CL_ASSERT(p_madw->resp_expected == FALSE);
129                 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
130         } else if (p_madw->resp_expected == TRUE)
131                 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
132         else
133                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
134
135         OSM_LOG_EXIT(p_ctrl->p_log);
136 }
137
138 /************/
139
140 /****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats
141  * NAME
142  * __osm_sm_mad_ctrl_update_wire_stats
143  *
144  * DESCRIPTION
145  * Updates wire stats for outstanding MADs and calls the VL15 poller.
146  *
147  * SYNOPSIS
148  */
149 static void
150 __osm_sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * const p_ctrl)
151 {
152         uint32_t mads_on_wire;
153
154         OSM_LOG_ENTER(p_ctrl->p_log);
155
156         mads_on_wire =
157             cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire);
158
159         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
160                 "%u SMPs on the wire, %u outstanding\n", mads_on_wire,
161                 p_ctrl->p_stats->qp0_mads_outstanding);
162
163         /*
164            We can signal the VL15 controller to send another MAD
165            if any are waiting for transmission.
166          */
167         osm_vl15_poll(p_ctrl->p_vl15);
168         OSM_LOG_EXIT(p_ctrl->p_log);
169 }
170
171 /****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp
172  * NAME
173  * __osm_sm_mad_ctrl_process_get_resp
174  *
175  * DESCRIPTION
176  * This function handles method GetResp() for received MADs.
177  * This is the most common path for QP0 MADs.
178  *
179  * SYNOPSIS
180  */
181 static void
182 __osm_sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * const p_ctrl,
183                                    IN osm_madw_t * p_madw,
184                                    IN void *transaction_context)
185 {
186         ib_smp_t *p_smp;
187         cl_status_t status;
188         osm_madw_t *p_old_madw;
189         cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
190
191         OSM_LOG_ENTER(p_ctrl->p_log);
192
193         CL_ASSERT(p_madw);
194         CL_ASSERT(transaction_context);
195
196         p_smp = osm_madw_get_smp_ptr(p_madw);
197
198         if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) {
199                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: "
200                         "'D' bit not set in returned SMP\n");
201                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
202         }
203
204         p_old_madw = (osm_madw_t *) transaction_context;
205
206         __osm_sm_mad_ctrl_update_wire_stats(p_ctrl);
207
208         /*
209            Copy the MAD Wrapper context from the requesting MAD
210            to the new MAD.  This mechanism allows the recipient
211            controller to recover its own context regarding this
212            MAD transaction.  Once we've copied the context, we
213            can return the original MAD to the pool.
214          */
215         osm_madw_copy_context(p_madw, p_old_madw);
216         osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw);
217
218         /*
219            Note that attr_id (like the rest of the MAD) is in
220            network byte order.
221          */
222         switch (p_smp->attr_id) {
223         case IB_MAD_ATTR_NODE_DESC:
224                 msg_id = OSM_MSG_MAD_NODE_DESC;
225                 break;
226         case IB_MAD_ATTR_NODE_INFO:
227                 msg_id = OSM_MSG_MAD_NODE_INFO;
228                 break;
229         case IB_MAD_ATTR_SWITCH_INFO:
230                 msg_id = OSM_MSG_MAD_SWITCH_INFO;
231                 break;
232         case IB_MAD_ATTR_PORT_INFO:
233                 msg_id = OSM_MSG_MAD_PORT_INFO;
234                 break;
235         case IB_MAD_ATTR_LIN_FWD_TBL:
236                 msg_id = OSM_MSG_MAD_LFT;
237                 break;
238         case IB_MAD_ATTR_MCAST_FWD_TBL:
239                 msg_id = OSM_MSG_MAD_MFT;
240                 break;
241         case IB_MAD_ATTR_SM_INFO:
242                 msg_id = OSM_MSG_MAD_SM_INFO;
243                 break;
244         case IB_MAD_ATTR_SLVL_TABLE:
245                 msg_id = OSM_MSG_MAD_SLVL;
246                 break;
247         case IB_MAD_ATTR_VL_ARBITRATION:
248                 msg_id = OSM_MSG_MAD_VL_ARB;
249                 break;
250         case IB_MAD_ATTR_P_KEY_TABLE:
251                 msg_id = OSM_MSG_MAD_PKEY;
252                 break;
253
254         case IB_MAD_ATTR_GUID_INFO:
255         case IB_MAD_ATTR_CLASS_PORT_INFO:
256         case IB_MAD_ATTR_NOTICE:
257         case IB_MAD_ATTR_INFORM_INFO:
258         default:
259                 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
260                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: "
261                         "Unsupported attribute = 0x%X\n",
262                         cl_ntoh16(p_smp->attr_id));
263                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
264                 goto Exit;
265         }
266
267         if (msg_id == CL_DISP_MSGID_NONE)
268                 goto Exit;
269
270         /*
271            Post this MAD to the dispatcher for asynchronous
272            processing by the appropriate controller.
273          */
274
275         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
276                 osm_get_disp_msg_str(msg_id));
277
278         status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
279                               __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
280
281         if (status != CL_SUCCESS) {
282                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: "
283                         "Dispatcher post message failed (%s) for attribute = 0x%X\n",
284                         CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id));
285                 goto Exit;
286         }
287
288 Exit:
289         OSM_LOG_EXIT(p_ctrl->p_log);
290 }
291
292 /****f* opensm: SM/__osm_sm_mad_ctrl_process_get
293  * NAME
294  * __osm_sm_mad_ctrl_process_get
295  *
296  * DESCRIPTION
297  * This function handles method Get() for received MADs.
298  *
299  * SYNOPSIS
300  */
301 static void
302 __osm_sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * const p_ctrl,
303                               IN osm_madw_t * p_madw)
304 {
305         ib_smp_t *p_smp;
306         cl_status_t status;
307         cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
308
309         OSM_LOG_ENTER(p_ctrl->p_log);
310
311         p_smp = osm_madw_get_smp_ptr(p_madw);
312
313         /*
314            Note that attr_id (like the rest of the MAD) is in
315            network byte order.
316          */
317         switch (p_smp->attr_id) {
318         case IB_MAD_ATTR_SM_INFO:
319                 msg_id = OSM_MSG_MAD_SM_INFO;
320                 break;
321
322         default:
323                 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
324                 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
325                         "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n",
326                         cl_ntoh16(p_smp->attr_id));
327                 break;
328         }
329
330         if (msg_id == CL_DISP_MSGID_NONE) {
331                 /*
332                    There is an unknown MAD attribute type for which there is
333                    no recipient.  Simply retire the MAD here.
334                  */
335                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
336                 goto Exit;
337         }
338
339         /*
340            Post this MAD to the dispatcher for asynchronous
341            processing by the appropriate controller.
342          */
343
344         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
345                 osm_get_disp_msg_str(msg_id));
346
347         status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
348                               __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
349
350         if (status != CL_SUCCESS) {
351                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: "
352                         "Dispatcher post message failed (%s)\n",
353                         CL_STATUS_MSG(status));
354                 goto Exit;
355         }
356
357 Exit:
358         OSM_LOG_EXIT(p_ctrl->p_log);
359 }
360
361 /*
362  * PARAMETERS
363  *
364  * RETURN VALUES
365  *
366  * NOTES
367  *
368  * SEE ALSO
369  *********/
370
371 /****f* opensm: SM/__osm_sm_mad_ctrl_process_set
372  * NAME
373  * __osm_sm_mad_ctrl_process_set
374  *
375  * DESCRIPTION
376  * This function handles method Set() for received MADs.
377  *
378  * SYNOPSIS
379  */
380 static void
381 __osm_sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * const p_ctrl,
382                               IN osm_madw_t * p_madw)
383 {
384         ib_smp_t *p_smp;
385         cl_status_t status;
386         cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
387
388         OSM_LOG_ENTER(p_ctrl->p_log);
389
390         p_smp = osm_madw_get_smp_ptr(p_madw);
391
392         /*
393            Note that attr_id (like the rest of the MAD) is in
394            network byte order.
395          */
396         switch (p_smp->attr_id) {
397         case IB_MAD_ATTR_SM_INFO:
398                 msg_id = OSM_MSG_MAD_SM_INFO;
399                 break;
400
401         default:
402                 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
403                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: "
404                         "Unsupported attribute = 0x%X\n",
405                         cl_ntoh16(p_smp->attr_id));
406                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
407                 break;
408         }
409
410         if (msg_id == CL_DISP_MSGID_NONE) {
411                 /*
412                    There is an unknown MAD attribute type for which there is
413                    no recipient.  Simply retire the MAD here.
414                  */
415                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
416                 goto Exit;
417         }
418
419         /*
420            Post this MAD to the dispatcher for asynchronous
421            processing by the appropriate controller.
422          */
423
424         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
425                 osm_get_disp_msg_str(msg_id));
426
427         status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
428                               __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
429
430         if (status != CL_SUCCESS) {
431                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: "
432                         "Dispatcher post message failed (%s)\n",
433                         CL_STATUS_MSG(status));
434                 goto Exit;
435         }
436
437 Exit:
438         OSM_LOG_EXIT(p_ctrl->p_log);
439 }
440
441 /*
442  * PARAMETERS
443  *
444  * RETURN VALUES
445  *
446  * NOTES
447  *
448  * SEE ALSO
449  *********/
450
451 /****f* opensm: SM/__osm_sm_mad_ctrl_process_trap
452  * NAME
453  * __osm_sm_mad_ctrl_process_trap
454  *
455  * DESCRIPTION
456  * This function handles method Trap() for received MADs.
457  *
458  * SYNOPSIS
459  */
460 static void
461 __osm_sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * const p_ctrl,
462                                IN osm_madw_t * p_madw)
463 {
464         ib_smp_t *p_smp;
465         cl_status_t status;
466         cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
467
468         OSM_LOG_ENTER(p_ctrl->p_log);
469
470         p_smp = osm_madw_get_smp_ptr(p_madw);
471
472         /* Make sure OpenSM is master. If not - then we should not process the trap */
473         if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
474                 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
475                         "Received trap but OpenSM is not in MASTER state. "
476                         "Dropping mad\n");
477                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
478                 goto Exit;
479         }
480
481         /*
482            Note that attr_id (like the rest of the MAD) is in
483            network byte order.
484          */
485         switch (p_smp->attr_id) {
486         case IB_MAD_ATTR_NOTICE:
487                 msg_id = OSM_MSG_MAD_NOTICE;
488                 break;
489
490         default:
491                 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
492                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: "
493                         "Unsupported attribute = 0x%X\n",
494                         cl_ntoh16(p_smp->attr_id));
495                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
496                 break;
497         }
498
499         if (msg_id == CL_DISP_MSGID_NONE) {
500                 /*
501                    There is an unknown MAD attribute type for which there is
502                    no recipient.  Simply retire the MAD here.
503                  */
504                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
505                 goto Exit;
506         }
507
508         /*
509            Post this MAD to the dispatcher for asynchronous
510            processing by the appropriate controller.
511          */
512
513         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
514                 osm_get_disp_msg_str(msg_id));
515
516         status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
517                               __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
518
519         if (status != CL_SUCCESS) {
520                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: "
521                         "Dispatcher post message failed (%s)\n",
522                         CL_STATUS_MSG(status));
523                 goto Exit;
524         }
525
526 Exit:
527         OSM_LOG_EXIT(p_ctrl->p_log);
528 }
529
530 /*
531  * PARAMETERS
532  *
533  * RETURN VALUES
534  *
535  * NOTES
536  *
537  * SEE ALSO
538  *********/
539
540 /****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback
541  * NAME
542  * __osm_sm_mad_ctrl_rcv_callback
543  *
544  * DESCRIPTION
545  * This is the callback from the transport layer for received MADs.
546  *
547  * SYNOPSIS
548  */
549 static void
550 __osm_sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,
551                                IN void *bind_context,
552                                IN osm_madw_t * p_req_madw)
553 {
554         osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context;
555         ib_smp_t *p_smp;
556         ib_net16_t status;
557
558         OSM_LOG_ENTER(p_ctrl->p_log);
559
560         CL_ASSERT(p_madw);
561
562         /*
563            A MAD was received from the wire, possibly in response to a request.
564          */
565         cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd);
566
567         OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n",
568                 p_ctrl->p_stats->qp0_mads_rcvd);
569
570         p_smp = osm_madw_get_smp_ptr(p_madw);
571
572         /* if we are closing down simply do nothing */
573         if (osm_exit_flag) {
574                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR,
575                         "Ignoring received mad - since we are exiting\n");
576
577                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_DEBUG);
578
579                 /* retire the mad or put it back */
580                 if (ib_smp_is_response(p_smp) ||
581                     (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS)) {
582                         CL_ASSERT(p_madw->resp_expected == FALSE);
583                         __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
584                 } else if (p_madw->resp_expected == TRUE)
585                         __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
586                 else
587                         osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
588
589                 goto Exit;
590         }
591
592         if (osm_log_is_active(p_ctrl->p_log, OSM_LOG_FRAMES))
593                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_FRAMES);
594
595         if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
596                 status = ib_smp_get_status(p_smp);
597         else
598                 status = p_smp->status;
599
600         if (status != 0) {
601                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3111: "
602                         "Error status = 0x%X\n", status);
603                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
604         }
605
606         switch (p_smp->method) {
607         case IB_MAD_METHOD_GET_RESP:
608                 CL_ASSERT(p_req_madw != NULL);
609                 __osm_sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw);
610                 break;
611
612         case IB_MAD_METHOD_GET:
613                 CL_ASSERT(p_req_madw == NULL);
614                 __osm_sm_mad_ctrl_process_get(p_ctrl, p_madw);
615                 break;
616
617         case IB_MAD_METHOD_TRAP:
618                 CL_ASSERT(p_req_madw == NULL);
619                 __osm_sm_mad_ctrl_process_trap(p_ctrl, p_madw);
620                 break;
621
622         case IB_MAD_METHOD_SET:
623                 CL_ASSERT(p_req_madw == NULL);
624                 __osm_sm_mad_ctrl_process_set(p_ctrl, p_madw);
625                 break;
626
627         case IB_MAD_METHOD_SEND:
628         case IB_MAD_METHOD_REPORT:
629         case IB_MAD_METHOD_REPORT_RESP:
630         case IB_MAD_METHOD_TRAP_REPRESS:
631         default:
632                 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
633                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: "
634                         "Unsupported method = 0x%X\n", p_smp->method);
635                 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
636                 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
637                 goto Exit;
638         }
639
640 Exit:
641         OSM_LOG_EXIT(p_ctrl->p_log);
642 }
643
644 /*
645  * PARAMETERS
646  *
647  * RETURN VALUES
648  *
649  * NOTES
650  *
651  * SEE ALSO
652  *********/
653
654 /****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb
655  * NAME
656  * __osm_sm_mad_ctrl_send_err_cb
657  *
658  * DESCRIPTION
659  * This is the callback from the transport layer for send errors
660  * on MADs that were expecting a response.
661  *
662  * SYNOPSIS
663  */
664 static void
665 __osm_sm_mad_ctrl_send_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
666 {
667         osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context;
668         ib_api_status_t status;
669         ib_smp_t *p_smp;
670
671         OSM_LOG_ENTER(p_ctrl->p_log);
672
673         CL_ASSERT(p_madw);
674
675         OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: "
676                 "MAD completed in error (%s)\n",
677                 ib_get_err_str(p_madw->status));
678
679         /*
680            If this was a SubnSet MAD, then this error might indicate a problem
681            in configuring the subnet. In this case - need to mark that there was
682            such a problem. The subnet will not be up, and the next sweep should
683            be a heavy sweep as well.
684          */
685         p_smp = osm_madw_get_smp_ptr(p_madw);
686         if (p_smp->method == IB_MAD_METHOD_SET &&
687             (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
688              p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
689              p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
690              p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL)) {
691                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: "
692                         "Set method failed\n");
693                 p_ctrl->p_subn->subnet_initialization_error = TRUE;
694         }
695
696         /*
697            Since we did not get any response we suspect the DR path
698            used for the target port.
699            Find it and replace it with an alternate path.
700            This is true only if the destination lid is not 0xFFFF, since
701            then we are aiming for a specific path and not specific destination
702            lid.
703          */
704         /* For now - do not add the alternate dr path to the release */
705 #if 0
706         if (p_madw->mad_addr.dest_lid != 0xFFFF) {
707                 osm_physp_t *p_physp =
708                     osm_get_physp_by_mad_addr(p_ctrl->p_log,
709                                               p_ctrl->p_subn,
710                                               &(p_madw->mad_addr));
711                 if (!p_physp) {
712                         OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
713                                 "Failed to find the corresponding phys port\n");
714                 } else {
715                         osm_physp_replace_dr_path_with_alternate_dr_path
716                             (p_ctrl->p_log, p_ctrl->p_subn, p_physp,
717                              p_madw->h_bind);
718                 }
719         }
720 #endif
721
722         /*
723            An error occurred.  No response was received to a request MAD.
724            Retire the original request MAD.
725          */
726
727         osm_dump_dr_smp(p_ctrl->p_log, osm_madw_get_smp_ptr(p_madw),
728                         OSM_LOG_ERROR);
729
730         __osm_sm_mad_ctrl_update_wire_stats(p_ctrl);
731
732         if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
733                 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
734                         "Posting Dispatcher message %s\n",
735                         osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
736
737                 status = cl_disp_post(p_ctrl->h_disp,
738                                       osm_madw_get_err_msg(p_madw),
739                                       p_madw,
740                                       __osm_sm_mad_ctrl_disp_done_callback,
741                                       p_ctrl);
742                 if (status != CL_SUCCESS)
743                         OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: "
744                                 "Dispatcher post message failed (%s)\n",
745                                 CL_STATUS_MSG(status));
746         } else
747                 /*
748                    No error message was provided, just retire the MAD.
749                  */
750                 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
751
752         OSM_LOG_EXIT(p_ctrl->p_log);
753 }
754
755 /*
756  * PARAMETERS
757  *
758  * RETURN VALUES
759  *
760  * NOTES
761  *
762  * SEE ALSO
763  *********/
764
765 /**********************************************************************
766  **********************************************************************/
767 void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * const p_ctrl)
768 {
769         CL_ASSERT(p_ctrl);
770         memset(p_ctrl, 0, sizeof(*p_ctrl));
771         p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
772 }
773
774 /**********************************************************************
775  **********************************************************************/
776 void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * const p_ctrl)
777 {
778         CL_ASSERT(p_ctrl);
779
780         if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE)
781                 osm_vendor_unbind(p_ctrl->h_bind);
782         cl_disp_unregister(p_ctrl->h_disp);
783 }
784
785 /**********************************************************************
786  **********************************************************************/
787 ib_api_status_t
788 osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * const p_ctrl,
789                      IN osm_subn_t * const p_subn,
790                      IN osm_mad_pool_t * const p_mad_pool,
791                      IN osm_vl15_t * const p_vl15,
792                      IN osm_vendor_t * const p_vendor,
793                      IN osm_log_t * const p_log,
794                      IN osm_stats_t * const p_stats,
795                      IN cl_plock_t * const p_lock,
796                      IN cl_dispatcher_t * const p_disp)
797 {
798         ib_api_status_t status = IB_SUCCESS;
799
800         OSM_LOG_ENTER(p_log);
801
802         osm_sm_mad_ctrl_construct(p_ctrl);
803
804         p_ctrl->p_subn = p_subn;
805         p_ctrl->p_log = p_log;
806         p_ctrl->p_disp = p_disp;
807         p_ctrl->p_mad_pool = p_mad_pool;
808         p_ctrl->p_vendor = p_vendor;
809         p_ctrl->p_stats = p_stats;
810         p_ctrl->p_lock = p_lock;
811         p_ctrl->p_vl15 = p_vl15;
812
813         p_ctrl->h_disp = cl_disp_register(p_disp,
814                                           CL_DISP_MSGID_NONE, NULL, NULL);
815
816         if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
817                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: "
818                         "Dispatcher registration failed\n");
819                 status = IB_INSUFFICIENT_RESOURCES;
820                 goto Exit;
821         }
822
823 Exit:
824         OSM_LOG_EXIT(p_log);
825         return (status);
826 }
827
828 /**********************************************************************
829  **********************************************************************/
830 ib_api_status_t
831 osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * const p_ctrl,
832                      IN const ib_net64_t port_guid)
833 {
834         osm_bind_info_t bind_info;
835         ib_api_status_t status = IB_SUCCESS;
836
837         OSM_LOG_ENTER(p_ctrl->p_log);
838
839         if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
840                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: "
841                         "Multiple binds not allowed\n");
842                 status = IB_ERROR;
843                 goto Exit;
844         }
845
846         bind_info.class_version = 1;
847         bind_info.is_report_processor = FALSE;
848         bind_info.is_responder = TRUE;
849         bind_info.is_trap_processor = TRUE;
850         bind_info.mad_class = IB_MCLASS_SUBN_DIR;
851         bind_info.port_guid = port_guid;
852         bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
853         bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
854
855         OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
856                 "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
857
858         p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor,
859                                          &bind_info,
860                                          p_ctrl->p_mad_pool,
861                                          __osm_sm_mad_ctrl_rcv_callback,
862                                          __osm_sm_mad_ctrl_send_err_cb, p_ctrl);
863
864         if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
865                 status = IB_ERROR;
866                 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: "
867                         "Vendor specific bind failed\n");
868                 goto Exit;
869         }
870
871 Exit:
872         OSM_LOG_EXIT(p_ctrl->p_log);
873         return (status);
874 }