]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/libvendor/osm_vendor_mlx_ibmgt.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / libvendor / osm_vendor_mlx_ibmgt.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 /*  AUTHOR                 Edward Bortnikov
37  *
38  *  DESCRIPTION
39  *     The lower-level MAD transport interface implementation
40  *     that allows sending a single MAD/receiving a callback
41  *     when a single MAD is received.
42  */
43
44 #if HAVE_CONFIG_H
45 #  include <config.h>
46 #endif                          /* HAVE_CONFIG_H */
47
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ib_mgt.h>
51 #include <complib/cl_event.h>
52 #include <vendor/osm_vendor_mlx_transport.h>
53 #include <vendor/osm_vendor_mlx_dispatcher.h>
54 #include <opensm/osm_log.h>
55
56 typedef struct _osmv_IBMGT_transport_mgr_ {
57         IB_MGT_mad_type_t mad_type;
58         uint8_t mgmt_class;     /* for gsi */
59         /* for communication between send call back and send mad */
60         boolean_t is_send_ok;
61         cl_event_t send_done;
62 } osmv_IBMGT_transport_mgr_t;
63
64 typedef struct _osmv_IBMGT_transport_info_ {
65         IB_MGT_mad_hndl_t smi_h;
66         cl_qlist_t *p_smi_list;
67
68         IB_MGT_mad_hndl_t gsi_h;
69         /* holds bind object list for every binded mgmt class */
70         cl_qlist_t *gsi_mgmt_lists[15];
71 } osmv_IBMGT_transport_info_t;
72
73 static void
74 __osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
75                                   IN uint8_t is_smi,
76                                   OUT osm_mad_addr_t * p_mad_addr);
77
78 static void
79 __osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
80                                     IN uint8_t is_smi, OUT IB_ud_av_t * p_av);
81
82 void
83 __osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
84                      IN u_int64_t wrid,
85                      IN IB_comp_status_t status, IN void *private_ctx_p);
86
87 void
88 __osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
89                     IN void *private_ctx_p,
90                     IN void *payload_p,
91                     IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p);
92
93 /*
94  * NAME
95  *   osmv_transport_init
96  *
97  * DESCRIPTION
98  *   Setup the MAD transport infrastructure (filters, callbacks etc).
99  */
100
101 ib_api_status_t
102 osmv_transport_init(IN osm_bind_info_t * p_info,
103                     IN char hca_id[VENDOR_HCA_MAXNAMES],
104                     IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
105 {
106         ib_api_status_t st = IB_SUCCESS;
107         IB_MGT_ret_t ret;
108         IB_MGT_mad_type_t mad_type;
109         osmv_IBMGT_transport_mgr_t *p_mgr;
110         osmv_IBMGT_transport_info_t *p_tpot_info;
111         cl_list_obj_t *p_obj = NULL;
112         osm_log_t *p_log = p_bo->p_vendor->p_log;
113         int i;
114
115         UNUSED_PARAM(hca_idx);
116
117         /* if first bind, allocate tranport_info at vendor */
118         if (NULL == p_bo->p_vendor->p_transport_info) {
119                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
120                         "osmv_transport_init: first bind() for the vendor\n");
121                 p_bo->p_vendor->p_transport_info
122                     = (osmv_IBMGT_transport_info_t *)
123                     malloc(sizeof(osmv_IBMGT_transport_info_t));
124                 if (NULL == p_bo->p_vendor->p_transport_info) {
125                         return IB_INSUFFICIENT_MEMORY;
126                 }
127                 memset(p_bo->p_vendor->p_transport_info, 0,
128                        sizeof(osmv_IBMGT_transport_info_t));
129                 p_tpot_info =
130                     (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
131                                                      p_transport_info);
132
133                 p_tpot_info->smi_h = 0xffffffff;
134                 p_tpot_info->p_smi_list = NULL;
135
136                 p_tpot_info->gsi_h = 0xffffffff;
137                 for (i = 0; i < 15; i++) {
138
139                         p_tpot_info->gsi_mgmt_lists[i] = NULL;
140                 }
141
142         } else {
143
144                 p_tpot_info =
145                     (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
146                                                      p_transport_info);
147         }
148
149         /* Initialize the magic_ptr to the pointer of the p_bo info.
150            This will be used to signal when the object is being destroyed, so no
151            real action will be done then. */
152         p_bo->magic_ptr = p_bo;
153
154         /* allocate transport mgr */
155         p_mgr = malloc(sizeof(osmv_IBMGT_transport_mgr_t));
156         if (NULL == p_mgr) {
157                 free(p_tpot_info);
158                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
159                         "osmv_transport_init: ERR 7201: " "alloc failed \n");
160                 return IB_INSUFFICIENT_MEMORY;
161         }
162
163         memset(p_mgr, 0, sizeof(osmv_IBMGT_transport_mgr_t));
164
165         p_bo->p_transp_mgr = p_mgr;
166
167         switch (p_info->mad_class) {
168         case IB_MCLASS_SUBN_LID:
169         case IB_MCLASS_SUBN_DIR:
170                 mad_type = IB_MGT_SMI;
171                 break;
172
173         case IB_MCLASS_SUBN_ADM:
174         default:
175                 mad_type = IB_MGT_GSI;
176                 break;
177         }
178
179         /* we only support one class registration per SMI/GSI !!! */
180         switch (mad_type) {
181         case IB_MGT_SMI:
182                 /* we do not need to bind the handle if already available */
183                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
184                         "osmv_transport_init: SMI bind\n");
185
186                 if (p_tpot_info->smi_h == 0xffffffff) {
187                         ret = IB_MGT_get_handle(hca_id,
188                                                 p_bo->port_num,
189                                                 IB_MGT_SMI,
190                                                 &(p_tpot_info->smi_h));
191                         if (IB_MGT_OK != ret) {
192                                 osm_log(p_log, OSM_LOG_ERROR,
193                                         "osmv_transport_init: ERR 7202: "
194                                         "IB_MGT_get_handle for smi failed \n");
195                                 st = IB_ERROR;
196                                 free(p_mgr);
197                                 goto Exit;
198                         }
199
200                         osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
201                                 "osmv_transport_init: got smi handle:%d \n",
202                                 p_tpot_info->smi_h);
203
204                         ret = IB_MGT_bind_sm(p_tpot_info->smi_h);
205                         if (IB_MGT_OK != ret) {
206                                 osm_log(p_log, OSM_LOG_ERROR,
207                                         "osmv_transport_init: ERR 7203: "
208                                         "IB_MGT_bind_sm failed \n");
209                                 st = IB_ERROR;
210                                 free(p_mgr);
211                                 goto Exit;
212                         }
213
214                         /* init smi list */
215                         p_tpot_info->p_smi_list = malloc(sizeof(cl_qlist_t));
216                         if (NULL == p_tpot_info->p_smi_list) {
217                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
218                                         "osmv_transport_init: ERR 7204: "
219                                         "alloc failed \n");
220                                 IB_MGT_unbind_sm(p_tpot_info->smi_h);
221                                 IB_MGT_release_handle(p_tpot_info->smi_h);
222                                 free(p_mgr);
223                                 return IB_INSUFFICIENT_MEMORY;
224                         }
225                         memset(p_tpot_info->p_smi_list, 0, sizeof(cl_qlist_t));
226                         cl_qlist_init(p_tpot_info->p_smi_list);
227
228                         osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
229                                 "osmv_transport_init: before reg_cb\n");
230                         ret = IB_MGT_reg_cb(p_tpot_info->smi_h,
231                                             &__osmv_IBMGT_rcv_cb,
232                                             p_bo,
233                                             &__osmv_IBMGT_send_cb,
234                                             p_tpot_info->p_smi_list,
235                                             IB_MGT_RCV_CB_MASK |
236                                             IB_MGT_SEND_CB_MASK);
237                         if (ret != IB_SUCCESS) {
238                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
239                                         "osmv_transport_init: ERR 7205: "
240                                         "reg_cb failed with return code:%x \n",
241                                         ret);
242                                 IB_MGT_unbind_sm(p_tpot_info->smi_h);
243                                 IB_MGT_release_handle(p_tpot_info->smi_h);
244                                 free(p_tpot_info->p_smi_list);
245                                 free(p_mgr);
246                                 st = IB_ERROR;
247                                 goto Exit;
248                         }
249
250                 }
251                 /* insert to list of smi's - for raising callbacks later on */
252                 p_obj = malloc(sizeof(cl_list_obj_t));
253                 if (p_obj)
254                         memset(p_obj, 0, sizeof(cl_list_obj_t));
255                 cl_qlist_set_obj(p_obj, p_bo);
256                 cl_qlist_insert_tail(p_tpot_info->p_smi_list,
257                                      &p_obj->list_item);
258
259                 break;
260
261         case IB_MGT_GSI:
262                 /* we do not need to bind the handle if already available */
263                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
264                         "osmv_transport_init: ERR 7206: GSI bind\n");
265                 if (p_tpot_info->gsi_h == 0xffffffff) {
266                         ret = IB_MGT_get_handle(hca_id,
267                                                 p_bo->port_num,
268                                                 IB_MGT_GSI,
269                                                 &(p_tpot_info->gsi_h));
270                         if (IB_MGT_OK != ret) {
271                                 osm_log(p_log, OSM_LOG_ERROR,
272                                         "osmv_transport_init: ERR 7207: "
273                                         "IB_MGT_get_handle for gsi failed \n");
274                                 st = IB_ERROR;
275                                 free(p_mgr);
276                                 goto Exit;
277                         }
278                 }
279
280                 /* this mgmt class was not binded yet */
281                 if (p_tpot_info->gsi_mgmt_lists[p_info->mad_class] == NULL) {
282                         ret =
283                             IB_MGT_bind_gsi_class(p_tpot_info->gsi_h,
284                                                   p_info->mad_class);
285                         if (IB_MGT_OK != ret) {
286                                 osm_log(p_log, OSM_LOG_ERROR,
287                                         "osmv_transport_init: ERR 7208: "
288                                         "IB_MGT_bind_gsi_class failed \n");
289                                 st = IB_ERROR;
290                                 free(p_mgr);
291                                 goto Exit;
292                         }
293
294                         p_tpot_info->gsi_mgmt_lists[p_info->mad_class] =
295                             malloc(sizeof(cl_qlist_t));
296                         if (NULL ==
297                             p_tpot_info->gsi_mgmt_lists[p_info->mad_class]) {
298                                 IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
299                                                         p_info->mad_class);
300                                 free(p_mgr);
301                                 return IB_INSUFFICIENT_MEMORY;
302                         }
303                         memset(p_tpot_info->gsi_mgmt_lists[p_info->mad_class],
304                                0, sizeof(cl_qlist_t));
305                         cl_qlist_init(p_tpot_info->
306                                       gsi_mgmt_lists[p_info->mad_class]);
307                 }
308                 /* insert to list of smi's - for raising callbacks later on */
309                 p_obj = malloc(sizeof(cl_list_obj_t));
310                 if (p_obj)
311                         memset(p_obj, 0, sizeof(cl_list_obj_t));
312                 cl_qlist_set_obj(p_obj, p_bo);
313                 cl_qlist_insert_tail(p_tpot_info->
314                                      gsi_mgmt_lists[p_info->mad_class],
315                                      &p_obj->list_item);
316
317                 p_mgr->mgmt_class = p_info->mad_class;
318                 ret = IB_MGT_reg_cb(p_tpot_info->gsi_h,
319                                     &__osmv_IBMGT_rcv_cb,
320                                     p_bo,
321                                     &__osmv_IBMGT_send_cb,
322                                     p_bo,
323                                     IB_MGT_RCV_CB_MASK | IB_MGT_SEND_CB_MASK);
324
325                 if (ret != IB_SUCCESS) {
326                         IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
327                                                 p_mgr->mgmt_class);
328                         free(p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class]);
329                         free(p_mgr);
330                         st = IB_ERROR;
331                         goto Exit;
332                 }
333
334                 break;
335
336         default:
337                 osm_log(p_log, OSM_LOG_ERROR,
338                         "osmv_transport_init: ERR 7209: unrecognized mgmt class \n");
339                 st = IB_ERROR;
340                 free(p_mgr);
341                 goto Exit;
342         }
343
344         osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
345                 "osmv_transport_init: GSI bind\n");
346         cl_event_construct(&p_mgr->send_done);
347         cl_event_init(&p_mgr->send_done, TRUE);
348         p_mgr->is_send_ok = FALSE;
349         p_mgr->mad_type = mad_type;
350
351 Exit:
352         /* OSM_LOG_EXIT(p_log ); */
353         return (ib_api_status_t) st;
354 }
355
356 /*
357  * NAME
358  *   osmv_transport_send_mad
359  *
360  * DESCRIPTION
361  *   Send a single MAD (256 byte)
362  */
363
364 ib_api_status_t
365 osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
366                         IN void *p_ib_mad, IN const osm_mad_addr_t * p_mad_addr)
367 {
368
369         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
370         osmv_IBMGT_transport_info_t *p_tpot_info =
371             (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
372         osm_vendor_t const *p_vend = p_bo->p_vendor;
373         ib_api_status_t status;
374         IB_ud_av_t av;
375         IB_MGT_ret_t ret;
376         ib_mad_t *p_mad = p_ib_mad;
377
378         OSM_LOG_ENTER(p_vend->p_log);
379
380         CL_ASSERT(p_bo->p_vendor->p_transport_info);
381
382         /*
383          * For all sends other than directed route SM MADs,
384          * acquire an address vector for the destination.
385          */
386         if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
387                 __osmv_IBMGT_osm_addr_to_ibmgt_addr(p_mad_addr,
388                                                     p_mad->mgmt_class ==
389                                                     IB_MCLASS_SUBN_LID, &av);
390         } else {
391                 /* is a directed route - we need to construct a permissive address */
392                 memset(&av, 0, sizeof(av));
393                 /* we do not need port number since it is part of the mad_hndl */
394                 av.dlid = IB_LID_PERMISSIVE;
395         }
396
397         /* send it */
398         if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
399             (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
400
401                 /* SMI CASE */
402                 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
403                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
404                                 "osmv_transport_mad_send: "
405                                 "av.dlid:0x%X, "
406                                 "av.static_rate:%d, "
407                                 "av.path_bits:%d.\n",
408                                 cl_ntoh16(av.dlid), av.static_rate,
409                                 av.src_path_bits);
410                 }
411
412                 ret = IB_MGT_send_mad(p_tpot_info->smi_h, p_mad,        /*  actual payload */
413                                       &av,      /*  address vector */
414                                       (u_int64_t) CAST_P2LONG(p_bo),
415                                       IB_MGT_DEFAULT_SEND_TIME);
416         } else {
417                 /* GSI CASE - Support Remote QP */
418                 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
419                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
420                                 "osmv_transport_mad_send: "
421                                 "av.dlid:0x%X, av.static_rate:%d, av.path_bits:%d, remote qp:%d \n",
422                                 cl_ntoh16(av.dlid), av.static_rate,
423                                 av.src_path_bits,
424                                 cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp)
425                             );
426                 }
427
428                 ret = IB_MGT_send_mad_to_qp(p_tpot_info->gsi_h, p_mad,  /*  actual payload */
429                                             &av,        /*  address vector */
430                                             (u_int64_t) CAST_P2LONG(p_bo),
431                                             IB_MGT_DEFAULT_SEND_TIME,
432                                             cl_ntoh32(p_mad_addr->addr_type.gsi.
433                                                       remote_qp));
434
435         }
436
437         status = IB_SUCCESS;
438         if (ret != IB_MGT_OK) {
439                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
440                         "osmv_transport_mad_send: ERR 7210: "
441                         "Error sending mad (%d).\n", ret);
442                 status = IB_ERROR;
443         } else {
444                 osmv_IBMGT_transport_mgr_t *p_mgr =
445                     (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
446
447                 /* Let the others work when I am sleeping ... */
448                 osmv_txn_unlock(p_bo);
449
450                 cl_event_wait_on(&(p_mgr->send_done), 0xffffffff, TRUE);
451
452                 /* Re-acquire the lock */
453                 osmv_txn_lock(p_bo);
454
455                 if (TRUE == p_bo->is_closing) {
456
457                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
458                                 "osmv_transport_mad_send: ERR 7211: "
459                                 "The handle %p is being unbound, cannot send.\n",
460                                 h_bind);
461                         status = IB_ERROR;
462                 }
463
464                 if (p_mgr->is_send_ok == FALSE) {
465                         status = IB_ERROR;
466                 }
467         }
468
469         OSM_LOG_EXIT(p_vend->p_log);
470         return (status);
471 }
472
473 void osmv_transport_done(IN const osm_bind_handle_t h_bind)
474 {
475         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
476         osm_log_t *p_log = p_bo->p_vendor->p_log;
477         osmv_IBMGT_transport_mgr_t *p_mgr;
478         osmv_IBMGT_transport_info_t *p_tpot_info;
479         IB_MGT_ret_t ret;
480         cl_list_obj_t *p_obj = NULL;
481         cl_list_item_t *p_item, *p_item_tmp;
482         int i;
483         cl_qlist_t *p_list = NULL;
484
485         OSM_LOG_ENTER(p_log);
486
487         CL_ASSERT(p_bo);
488
489         /* First of all - zero out the magic_ptr, so if a callback is called -
490            it'll know that we are currently closing down, and will not handle the
491            mad. */
492         p_bo->magic_ptr = 0;
493
494         p_mgr = (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
495         p_tpot_info =
496             (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
497
498         switch (p_mgr->mad_type) {
499         case IB_MGT_SMI:
500                 p_list = p_tpot_info->p_smi_list;
501
502                 /* remove from the bindings list */
503                 p_item = cl_qlist_head(p_list);
504                 while (p_item != cl_qlist_end(p_list)) {
505                         p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
506                         if (cl_qlist_obj(p_obj) == h_bind) {
507                                 break;
508                         }
509                         p_item_tmp = cl_qlist_next(p_item);
510                         p_item = p_item_tmp;
511                 }
512
513                 CL_ASSERT(p_item != cl_qlist_end(p_list));
514                 cl_qlist_remove_item(p_list, p_item);
515                 if (p_obj)
516                         free(p_obj);
517
518                 /* no one is binded to smi anymore - we can free the list, unbind & realease the hndl */
519                 if (cl_is_qlist_empty(p_list) == TRUE) {
520                         free(p_list);
521                         p_list = NULL;
522
523                         ret = IB_MGT_unbind_sm(p_tpot_info->smi_h);
524                         if (ret != IB_MGT_OK) {
525                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
526                                         "osmv_transport_done: ERR 7212: "
527                                         "Failed to unbind sm\n");
528                         }
529
530                         ret = IB_MGT_release_handle(p_tpot_info->smi_h);
531                         if (ret != IB_MGT_OK) {
532                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
533                                         "osmv_transport_done: ERR 7213: "
534                                         "Failed to release smi handle\n");
535                         }
536                         p_tpot_info->smi_h = 0xffffffff;
537                 }
538                 break;
539
540         case IB_MGT_GSI:
541                 p_list = p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class];
542                 /* remove from the bindings list */
543                 p_item = cl_qlist_head(p_list);
544                 while (p_item != cl_qlist_end(p_list)) {
545                         p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
546                         if (cl_qlist_obj(p_obj) == h_bind) {
547                                 break;
548                         }
549                         p_item_tmp = cl_qlist_next(p_item);
550                         p_item = p_item_tmp;
551                 }
552
553                 CL_ASSERT(p_item != cl_qlist_end(p_list));
554                 cl_qlist_remove_item(p_list, p_item);
555                 if (p_obj)
556                         free(p_obj);
557
558                 /* no one is binded to this class anymore - we can free the list and unbind this class */
559                 if (cl_is_qlist_empty(p_list) == TRUE) {
560                         free(p_list);
561                         p_list = NULL;
562
563                         ret =
564                             IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
565                                                     p_mgr->mgmt_class);
566                         if (ret != IB_MGT_OK) {
567                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
568                                         "osmv_transport_done: ERR 7214: "
569                                         "Failed to unbind gsi class\n");
570                         }
571                 }
572
573                 /* all the mgmt classes are unbinded - release gsi handle */
574                 for (i = 0; i < 15; i++) {
575                         if (p_tpot_info->gsi_mgmt_lists[i] != NULL) {
576                                 break;
577                         }
578                 }
579
580                 if (i == 15) {
581                         ret = IB_MGT_release_handle(p_tpot_info->gsi_h);
582                         if (ret != IB_MGT_OK) {
583                                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
584                                         "osmv_transport_done: ERR 7215: "
585                                         "Failed to release gsi handle\n");
586                         }
587                         p_tpot_info->gsi_h = 0xffffffff;
588                 }
589         }                       /* end switch */
590
591         free(p_mgr);
592 }
593
594 /**********************************************************************
595  * IB_MGT Receive callback : invoked after each receive
596  **********************************************************************/
597 void
598 __osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
599                     IN void *private_ctx_p,
600                     IN void *payload_p,
601                     IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p)
602 {
603         osmv_bind_obj_t *p_bo;
604         osm_mad_addr_t mad_addr;
605         cl_list_item_t *p_item;
606         cl_list_obj_t *p_obj;
607         cl_qlist_t *p_list;
608         ib_mad_t *p_mad = (ib_mad_t *) payload_p;
609         osm_vendor_t *p_vendor;
610         osmv_IBMGT_transport_info_t *p_tinfo;
611
612         __osmv_IBMGT_rcv_desc_to_osm_addr(rcv_remote_info_p,
613                                           ((p_mad->mgmt_class ==
614                                             IB_MCLASS_SUBN_LID)
615                                            || (p_mad->mgmt_class ==
616                                                IB_MCLASS_SUBN_DIR)), &mad_addr);
617
618         /* different handling of SMI and GSI */
619         if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
620             (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
621                 /* SMI CASE */
622                 p_bo = (osmv_bind_obj_t *) private_ctx_p;
623                 /* Make sure the p_bo object is still relevant */
624                 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
625                         return;
626
627                 p_vendor = p_bo->p_vendor;
628                 p_tinfo =
629                     (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
630                 p_list = p_tinfo->p_smi_list;
631         } else {
632                 /* GSI CASE */
633                 p_bo = (osmv_bind_obj_t *) private_ctx_p;
634                 /* Make sure the p_bo object is still relevant */
635                 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
636                         return;
637
638                 p_vendor = p_bo->p_vendor;
639                 p_tinfo =
640                     (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
641                 p_list = p_tinfo->gsi_mgmt_lists[p_mad->mgmt_class];
642         }
643
644         /* go over the bindings list and send the mad, one of them will accept it,
645            the others will drope
646          */
647         p_item = cl_qlist_head(p_list);
648         while (p_item != cl_qlist_end(p_list)) {
649                 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
650                 p_bo = cl_qlist_obj(p_obj);
651                 /* give upper layer the mad */
652                 osmv_dispatch_mad((osm_bind_handle_t) p_bo, payload_p,
653                                   &mad_addr);
654                 /* Make sure the p_bo object is still relevant */
655                 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
656                         return;
657
658                 p_item = cl_qlist_next(p_item);
659         }
660 }
661
662 /**********************************************************************
663  * IB_MGT Send callback : invoked after each send
664  **********************************************************************/
665 void
666 __osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
667                      IN u_int64_t wrid,
668                      IN IB_comp_status_t status, IN void *private_ctx_p)
669 {
670         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) CAST_P2LONG(wrid);
671
672         osmv_IBMGT_transport_mgr_t *p_mgr =
673             (osmv_IBMGT_transport_mgr_t *) p_bo->p_transp_mgr;
674
675         /* Make sure the p_bo object is still relevant */
676         if (p_bo->magic_ptr != p_bo)
677                 return;
678
679         /* we assume that each send on a bind object is synchronized, and no paralel sends
680            from diffrent threads with same object can be made */
681         if (status == IB_COMP_SUCCESS) {
682                 p_mgr->is_send_ok = TRUE;
683         } else
684                 p_mgr->is_send_ok = FALSE;
685         cl_event_signal(&p_mgr->send_done);
686
687 }
688
689 /**********************************************************************
690  * IB_MGT to OSM ADDRESS VECTOR
691  **********************************************************************/
692 static void
693 __osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
694                                   IN uint8_t is_smi,
695                                   OUT osm_mad_addr_t * p_mad_addr)
696 {
697         /*  p_mad_addr->dest_lid = p_osm->subn.sm_base_lid; - for resp we use the dest lid ... */
698         p_mad_addr->dest_lid = cl_hton16(p_rcv_desc->remote_lid);
699         p_mad_addr->static_rate = 0;    /*  HACK - we do not  know the rate ! */
700         p_mad_addr->path_bits = p_rcv_desc->local_path_bits;
701         /* Clear the grh any way to avoid unset fields */
702         memset(&p_mad_addr->addr_type.gsi.grh_info, 0,
703                sizeof(p_mad_addr->addr_type.gsi.grh_info));
704
705         if (is_smi) {
706                 /* SMI */
707                 p_mad_addr->addr_type.smi.source_lid =
708                     cl_hton16(p_rcv_desc->remote_lid);
709                 p_mad_addr->addr_type.smi.port_num = 99;        /*  HACK - if used - should fail */
710         } else {
711                 /* GSI */
712                 /* seems to me there is a IBMGT bug reversing the QPN ... */
713                 /* Does IBMGT supposed to provide the QPN is network or HOST ? */
714                 p_mad_addr->addr_type.gsi.remote_qp = cl_hton32(p_rcv_desc->qp);
715
716                 p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
717                 /*  we do have the p_mad_addr->pkey_ix but how to get the PKey by index ? */
718                 /*  the only way seems to be to use VAPI_query_hca_pkey_tbl and obtain */
719                 /*  the full PKey table - than go by the index. */
720                 /*  since this does not seem reasonable to me I simply use the default */
721                 /*  There is a TAVOR limitation that only one P_KEY is supported per  */
722                 /*  QP - so QP1 must use IB_DEFAULT_PKEY */
723                 p_mad_addr->addr_type.gsi.pkey_ix = 0;
724                 p_mad_addr->addr_type.gsi.service_level = p_rcv_desc->sl;
725
726                 p_mad_addr->addr_type.gsi.global_route = p_rcv_desc->grh_flag;
727                 /* copy the GRH data if relevant */
728                 if (p_mad_addr->addr_type.gsi.global_route) {
729                         p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
730                             ib_grh_set_ver_class_flow(p_rcv_desc->grh.
731                                                       IP_version,
732                                                       p_rcv_desc->grh.
733                                                       traffic_class,
734                                                       p_rcv_desc->grh.
735                                                       flow_label);
736                         p_mad_addr->addr_type.gsi.grh_info.hop_limit =
737                             p_rcv_desc->grh.hop_limit;
738                         memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
739                                &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
740                         memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
741                                p_rcv_desc->grh.dgid, sizeof(ib_net64_t));
742                 }
743         }
744 }
745
746 /**********************************************************************
747  * OSM ADDR VECTOR TO IB_MGT
748  **********************************************************************/
749 void
750 __osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
751                                     IN uint8_t is_smi, OUT IB_ud_av_t * p_av)
752 {
753
754         /* For global destination or Multicast address: */
755         u_int8_t ver;
756
757         memset(p_av, 0, sizeof(IB_ud_av_t));
758
759         p_av->src_path_bits = p_mad_addr->path_bits;
760         p_av->static_rate = p_mad_addr->static_rate;
761         p_av->dlid = cl_ntoh16(p_mad_addr->dest_lid);
762
763         if (is_smi) {
764                 p_av->sl = 0;   /*  Just to note we use 0 here. */
765         } else {
766                 p_av->sl = p_mad_addr->addr_type.gsi.service_level;
767                 p_av->grh_flag = p_mad_addr->addr_type.gsi.global_route;
768
769                 if (p_mad_addr->addr_type.gsi.global_route) {
770                         ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.
771                                                   grh_info.ver_class_flow, &ver,
772                                                   &p_av->traffic_class,
773                                                   &p_av->flow_label);
774                         p_av->hop_limit =
775                             p_mad_addr->addr_type.gsi.grh_info.hop_limit;
776                         p_av->sgid_index = 0;   /*  we always use source GID 0 */
777                         memcpy(&p_av->dgid,
778                                &p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
779                                sizeof(ib_net64_t));
780
781                 }
782         }
783 }