]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/libvendor/osm_vendor_mlx_anafa.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_anafa.c
1 /*
2  * Copyright (c) 2004-2006 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 #if HAVE_CONFIG_H
37 #  include <config.h>
38 #endif                          /* HAVE_CONFIG_H */
39
40 #include <sys/ioctl.h>
41 #include <stdlib.h>
42 #include <stddef.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <errno.h>
47
48 #include <vendor/osm_vendor_mlx.h>
49 #include <vendor/osm_vendor_mlx_transport.h>
50 #include <vendor/osm_vendor_mlx_transport_anafa.h>
51 #include <vendor/osm_vendor_mlx_svc.h>
52 #include <vendor/osm_vendor_mlx_sender.h>
53 #include <vendor/osm_pkt_randomizer.h>
54 #include <vendor/osm_ts_useraccess.h>
55
56 /**
57  *      FORWARD REFERENCES
58  */
59 static ib_api_status_t
60 __osmv_get_send_txn(IN osm_bind_handle_t h_bind,
61                     IN osm_madw_t * const p_madw,
62                     IN boolean_t is_rmpp,
63                     IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn);
64
65 static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind);
66
67 /*
68  *  NAME            osm_vendor_new
69  *
70  *  DESCRIPTION     Create and Initialize the osm_vendor_t Object
71  */
72
73 osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
74                              IN const uint32_t timeout)
75 {
76         ib_api_status_t status;
77         osm_vendor_t *p_vend;
78
79         OSM_LOG_ENTER(p_log);
80
81         CL_ASSERT(p_log);
82
83         p_vend = malloc(sizeof(*p_vend));
84         if (p_vend != NULL) {
85                 memset(p_vend, 0, sizeof(*p_vend));
86                 status = osm_vendor_init(p_vend, p_log, timeout);
87                 if (status != IB_SUCCESS) {
88                         osm_vendor_delete(&p_vend);
89                 }
90         } else {
91                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
92                         "osm_vendor_new: ERR 7401: "
93                         "Fail to allocate vendor object.\n");
94         }
95
96         OSM_LOG_EXIT(p_log);
97         return (p_vend);
98 }
99
100 /*
101  *  NAME            osm_vendor_delete
102  *
103  *  DESCRIPTION     Delete all the binds behind the vendor + free the vendor object
104  */
105
106 void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
107 {
108         cl_list_item_t *p_item;
109         cl_list_obj_t *p_obj;
110         osm_bind_handle_t bind_h;
111         osm_log_t *p_log;
112
113         OSM_LOG_ENTER((*pp_vend)->p_log);
114         p_log = (*pp_vend)->p_log;
115
116         /* go over the bind handles , unbind them and remove from list */
117         /* Note that if we reached here due to problem in the init, then
118            the bind_handles list is not initialized yet */
119         if ((*pp_vend)->bind_handles.state == CL_INITIALIZED) {
120                 p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles));
121                 while (p_item != cl_qlist_end(&((*pp_vend)->bind_handles))) {
122
123                         p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
124                         bind_h = (osm_bind_handle_t *) cl_qlist_obj(p_obj);
125                         osm_log(p_log, OSM_LOG_DEBUG,
126                                 "osm_vendor_delete: unbinding bind_h:%p \n",
127                                 bind_h);
128
129                         __osm_vendor_internal_unbind(bind_h);
130
131                         free(p_obj);
132                         /* removing from list */
133                         p_item =
134                             cl_qlist_remove_head(&((*pp_vend)->bind_handles));
135                 }
136         }
137
138         if (NULL != ((*pp_vend)->p_transport_info)) {
139                 free((*pp_vend)->p_transport_info);
140                 (*pp_vend)->p_transport_info = NULL;
141         }
142
143         /* remove the packet randomizer object */
144         if ((*pp_vend)->run_randomizer == TRUE)
145                 osm_pkt_randomizer_destroy(&((*pp_vend)->p_pkt_randomizer),
146                                            p_log);
147
148         free(*pp_vend);
149         *pp_vend = NULL;
150
151         OSM_LOG_EXIT(p_log);
152 }
153
154 /*
155  *  NAME            osm_vendor_init
156  *
157  *  DESCRIPTION     Initialize the vendor object
158  */
159
160 ib_api_status_t
161 osm_vendor_init(IN osm_vendor_t * const p_vend,
162                 IN osm_log_t * const p_log, IN const uint32_t timeout)
163 {
164         ib_api_status_t status = IB_SUCCESS;
165         char device_file[16];
166         int device_fd;
167
168         OSM_LOG_ENTER(p_log);
169
170         p_vend->p_log = p_log;
171         p_vend->resp_timeout = timeout;
172         p_vend->ttime_timeout = timeout * OSMV_TXN_TIMEOUT_FACTOR;
173
174         p_vend->p_transport_info = (osmv_TOPSPIN_ANAFA_transport_info_t *)
175             malloc(sizeof(osmv_TOPSPIN_ANAFA_transport_info_t));
176         if (!p_vend->p_transport_info) {
177                 return IB_ERROR;
178         }
179
180         memset(p_vend->p_transport_info, 0,
181                sizeof(osmv_TOPSPIN_ANAFA_transport_info_t));
182
183         /* update the run_randomizer flag */
184         if (getenv("OSM_PKT_DROP_RATE") != NULL
185             && atol(getenv("OSM_PKT_DROP_RATE")) != 0) {
186                 /* if the OSM_PKT_DROP_RATE global variable is defined
187                    to a non-zero value -
188                    then the randomizer should be called.
189                    Need to create the packet randomizer object */
190                 p_vend->run_randomizer = TRUE;
191                 status =
192                     osm_pkt_randomizer_init(&(p_vend->p_pkt_randomizer), p_log);
193                 if (status != IB_SUCCESS)
194                         return status;
195         } else {
196                 p_vend->run_randomizer = FALSE;
197                 p_vend->p_pkt_randomizer = NULL;
198         }
199
200         /* open TopSpin file device */
201         sprintf(device_file, "/dev/ts_ua0");
202         device_fd = open("/dev/ts_ua0", O_RDWR);
203         if (device_fd < 0) {
204                 fprintf(stderr, "Fatal: Fail to open the file:%s(%d)\n",
205                         device_file, errno);
206                 return IB_ERROR;
207         }
208
209         ((osmv_TOPSPIN_ANAFA_transport_info_t *) p_vend->p_transport_info)->
210             device_fd = device_fd;
211
212         cl_qlist_init(&p_vend->bind_handles);
213
214         OSM_LOG_EXIT(p_log);
215         return (IB_SUCCESS);
216 }
217
218 /*
219  *  NAME            osm_vendor_bind
220  *
221  *  DESCRIPTION     Create a new bind object under the vendor object
222  */
223
224 osm_bind_handle_t
225 osm_vendor_bind(IN osm_vendor_t * const p_vend,
226                 IN osm_bind_info_t * const p_bind_info,
227                 IN osm_mad_pool_t * const p_mad_pool,
228                 IN osm_vend_mad_recv_callback_t mad_recv_callback,
229                 IN osm_vend_mad_send_err_callback_t send_err_callback,
230                 IN void *context)
231 {
232         osmv_bind_obj_t *p_bo;
233         cl_status_t cl_st;
234         cl_list_obj_t *p_obj;
235         uint8_t hca_idx = 0;
236
237         if (NULL == p_vend || NULL == p_bind_info || NULL == p_mad_pool
238             || NULL == mad_recv_callback || NULL == send_err_callback) {
239                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
240                         "osm_vendor_bind: ERR 7402: "
241                         "NULL parameter passed in: p_vend=%p p_bind_info=%p p_mad_pool=%p recv_cb=%p send_err_cb=%p\n",
242                         p_vend, p_bind_info, p_mad_pool, mad_recv_callback,
243                         send_err_callback);
244
245                 return OSM_BIND_INVALID_HANDLE;
246         }
247
248         p_bo = malloc(sizeof(osmv_bind_obj_t));
249         if (NULL == p_bo) {
250                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
251                         "osm_vendor_bind: ERR 7403: "
252                         "could not allocate the bind object\n");
253                 return OSM_BIND_INVALID_HANDLE;
254         }
255
256         memset(p_bo, 0, sizeof(osmv_bind_obj_t));
257         p_bo->p_vendor = p_vend;
258         p_bo->recv_cb = mad_recv_callback;
259         p_bo->send_err_cb = send_err_callback;
260         p_bo->cb_context = context;
261         p_bo->p_osm_pool = p_mad_pool;
262         p_bo->port_num = 1;     /* anafa2 has one port */
263         p_bo->hca_hndl = 0;     /* only one ca on anafa system */
264
265         /* obtain the hca name and port num from the guid */
266         osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
267                 "osm_vendor_bind: "
268                 "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n",
269                 cl_ntoh64(p_bind_info->port_guid));
270
271         p_bo->is_closing = FALSE;
272         cl_spinlock_construct(&(p_bo->lock));
273         cl_st = cl_spinlock_init(&(p_bo->lock));
274         if (cl_st != CL_SUCCESS) {
275                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
276                         "osm_vendor_bind: ERR 7405: "
277                         "could not initialize the spinlock ...\n");
278                 free(p_bo);
279                 return OSM_BIND_INVALID_HANDLE;
280         }
281
282         osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
283                 "osm_vendor_bind: osmv_txnmgr_init ... \n");
284         if (osmv_txnmgr_init(&p_bo->txn_mgr, p_vend->p_log, &(p_bo->lock)) !=
285             IB_SUCCESS) {
286                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
287                         "osm_vendor_bind: ERR 7406: "
288                         "osmv_txnmgr_init failed \n");
289                 cl_spinlock_destroy(&p_bo->lock);
290                 free(p_bo);
291                 return OSM_BIND_INVALID_HANDLE;
292         }
293
294         /* Do the real job! (Transport-dependent) */
295         if (IB_SUCCESS !=
296             osmv_transport_init(p_bind_info, OSMV_ANAFA_ID, hca_idx, p_bo)) {
297                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
298                         "osm_vendor_bind: ERR 7407: "
299                         "osmv_transport_init failed \n");
300                 osmv_txnmgr_done((osm_bind_handle_t) p_bo);
301                 cl_spinlock_destroy(&p_bo->lock);
302                 free(p_bo);
303                 return OSM_BIND_INVALID_HANDLE;
304         }
305
306         /* insert bind handle into db */
307         p_obj = malloc(sizeof(cl_list_obj_t));
308         if (NULL == p_obj) {
309
310                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
311                         "osm_vendor_bind: ERR 7408: "
312                         "osm_vendor_bind: could not allocate the list object\n");
313
314                 osmv_transport_done(p_bo->p_transp_mgr);
315                 osmv_txnmgr_done((osm_bind_handle_t) p_bo);
316                 cl_spinlock_destroy(&p_bo->lock);
317                 free(p_bo);
318                 return OSM_BIND_INVALID_HANDLE;
319         }
320         if (p_obj)
321                 memset(p_obj, 0, sizeof(cl_list_obj_t));
322         cl_qlist_set_obj(p_obj, p_bo);
323
324         cl_qlist_insert_head(&p_vend->bind_handles, &p_obj->list_item);
325
326         return (osm_bind_handle_t) p_bo;
327 }
328
329 /*
330  *  NAME            osm_vendor_unbind
331  *
332  *  DESCRIPTION     Destroy the bind object and remove it from the vendor's list
333  */
334
335 void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
336 {
337         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
338         osm_log_t *p_log = p_bo->p_vendor->p_log;
339         cl_list_obj_t *p_obj;
340         cl_list_item_t *p_item, *p_item_tmp;
341         cl_qlist_t *const p_bh_list =
342             (cl_qlist_t * const)&p_bo->p_vendor->bind_handles;
343
344         OSM_LOG_ENTER(p_log);
345
346         /* go over all the items in the list and remove the specific item */
347         p_item = cl_qlist_head(&p_bo->p_vendor->bind_handles);
348         while (p_item != cl_qlist_end(&p_bo->p_vendor->bind_handles)) {
349                 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
350                 if (cl_qlist_obj(p_obj) == h_bind) {
351                         break;
352                 }
353                 p_item_tmp = cl_qlist_next(p_item);
354                 p_item = p_item_tmp;
355         }
356
357         CL_ASSERT(p_item != cl_qlist_end(p_bh_list));
358
359         cl_qlist_remove_item(p_bh_list, p_item);
360         free(p_obj);
361
362         __osm_vendor_internal_unbind(h_bind);
363
364         OSM_LOG_EXIT(p_bo->p_vendor->p_log);
365 }
366
367 /*
368  *  NAME            osm_vendor_get
369  *
370  *  DESCRIPTION     Allocate the space for a new MAD
371  */
372
373 ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
374                          IN const uint32_t mad_size,
375                          IN osm_vend_wrap_t * const p_vw)
376 {
377         ib_mad_t *p_mad;
378         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
379         osm_vendor_t const *p_vend = p_bo->p_vendor;
380         uint32_t act_mad_size;
381
382         OSM_LOG_ENTER(p_vend->p_log);
383
384         CL_ASSERT(p_vw);
385
386         if (mad_size < MAD_BLOCK_SIZE) {
387                 /* Stupid, but the applications want that! */
388                 act_mad_size = MAD_BLOCK_SIZE;
389         } else {
390                 act_mad_size = mad_size;
391         }
392
393         /* allocate it */
394         p_mad = (ib_mad_t *) malloc(act_mad_size);
395         if (p_mad == NULL) {
396                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
397                         "osm_vendor_get: ERR 7409: "
398                         "Error Obtaining MAD buffer.\n");
399                 goto Exit;
400         }
401
402         memset(p_mad, 0, act_mad_size);
403
404         if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
405                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
406                         "osm_vendor_get: "
407                         "Allocated MAD %p, size = %u.\n", p_mad, act_mad_size);
408         }
409         p_vw->p_mad = p_mad;
410
411 Exit:
412         OSM_LOG_EXIT(p_vend->p_log);
413         return (p_mad);
414 }
415
416 /*
417  *  NAME            osm_vendor_send
418  *
419  *  DESCRIPTION     Send a MAD buffer (RMPP or simple send).
420  *
421  *                  Semantics:
422  *                   (1) The RMPP send completes when every segment
423  *                       is acknowledged (synchronous)
424  *                   (2) The simple send completes when the send completion
425  *                       is received (asynchronous)
426  */
427
428 ib_api_status_t
429 osm_vendor_send(IN osm_bind_handle_t h_bind,
430                 IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
431 {
432         ib_api_status_t ret = IB_SUCCESS;
433         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
434         boolean_t is_rmpp = FALSE, is_rmpp_ds = FALSE;
435         osmv_txn_ctx_t *p_txn = NULL;
436         ib_mad_t *p_mad;
437
438         OSM_LOG_ENTER(p_bo->p_vendor->p_log);
439
440         if (NULL == h_bind || NULL == p_madw ||
441             NULL == (p_mad = osm_madw_get_mad_ptr(p_madw)) ||
442             NULL == osm_madw_get_mad_addr_ptr(p_madw)) {
443
444                 return IB_INVALID_PARAMETER;
445         }
446
447         is_rmpp = (p_madw->mad_size > MAD_BLOCK_SIZE
448                    || osmv_mad_is_rmpp(p_mad));
449         is_rmpp_ds = (TRUE == is_rmpp && TRUE == resp_expected);
450
451         /* Make our operations with the send context atomic */
452         osmv_txn_lock(p_bo);
453
454         if (TRUE == p_bo->is_closing) {
455                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
456                         "osm_vendor_send: ERR 7410: "
457                         "The handle %p is being unbound, cannot send.\n",
458                         h_bind);
459                 ret = IB_INTERRUPTED;
460                 goto send_done;
461         }
462
463         if (TRUE == resp_expected || TRUE == is_rmpp) {
464
465                 /* We must run under a transaction framework.
466                  * Get the transaction object (old or new) */
467                 ret = __osmv_get_send_txn(h_bind, p_madw, is_rmpp,
468                                           resp_expected, &p_txn);
469                 if (IB_SUCCESS != ret) {
470                         goto send_done;
471                 }
472         }
473
474         if (TRUE == is_rmpp) {
475                 /* Do the job - RMPP!
476                  * The call returns as all the packets are ACK'ed/upon error
477                  * The txn lock will be released each time the function sleeps
478                  * and re-acquired when it wakes up
479                  */
480                 ret = osmv_rmpp_send_madw(h_bind, p_madw, p_txn, is_rmpp_ds);
481         } else {
482
483                 /* Do the job - single MAD!
484                  * The call returns as soon as the MAD is put on the wire
485                  */
486                 ret = osmv_simple_send_madw(h_bind, p_madw, p_txn, FALSE);      /* anafa2 */
487         }
488
489         if (IB_SUCCESS == ret) {
490
491                 if ((TRUE == is_rmpp) && (FALSE == is_rmpp_ds)) {
492                         /* For double-sided sends, the txn continues to live */
493                         osmv_txn_done(h_bind, osmv_txn_get_key(p_txn),
494                                       FALSE /*not in callback */ );
495                 }
496
497                 if (FALSE == resp_expected) {
498                         osm_mad_pool_put(p_bo->p_osm_pool, p_madw);
499                 }
500         } else {
501                 if (NULL != p_txn) {
502                         osmv_txn_done(h_bind, osmv_txn_get_key(p_txn),
503                                       FALSE /*not in callback */ );
504                 }
505
506                 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
507                         "osm_vendor_send: ERR 7411: failed to send MADW %p\n",
508                         p_madw);
509
510                 if (TRUE == resp_expected) {
511                         /* Change the status on the p_madw */
512                         p_madw->status = ret;
513                         /* Only the requester expects the error callback */
514                         p_bo->send_err_cb(p_bo->cb_context, p_madw);
515                 } else {
516                         /* put back the mad - it is useless ... */
517                         osm_mad_pool_put(p_bo->p_osm_pool, p_madw);
518                 }
519         }
520
521 send_done:
522
523         osmv_txn_unlock(p_bo);
524
525         OSM_LOG_EXIT(p_bo->p_vendor->p_log);
526         return ret;
527 }
528
529 /*
530  *  NAME            osm_vendor_put
531  *
532  *  DESCRIPTION     Free the MAD's memory
533  */
534
535 void
536 osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
537 {
538
539         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
540         osm_vendor_t const *p_vend = p_bo->p_vendor;
541
542         OSM_LOG_ENTER(p_vend->p_log);
543
544         CL_ASSERT(p_vw);
545         CL_ASSERT(p_vw->p_mad);
546
547         if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
548                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
549                         "osm_vendor_put: " "Retiring MAD %p.\n", p_vw->p_mad);
550         }
551
552         free(p_vw->p_mad);
553         p_vw->p_mad = NULL;
554
555         OSM_LOG_EXIT(p_vend->p_log);
556 }
557
558 /*
559  *  NAME            osm_vendor_local_lid_change
560  *
561  *  DESCRIPTION     Notifies the vendor transport layer that the local address
562  *                  has changed.  This allows the vendor layer to perform
563  *                  housekeeping functions such as address vector updates.
564  */
565
566 ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
567 {
568         osm_vendor_t const *p_vend = ((osmv_bind_obj_t *) h_bind)->p_vendor;
569         OSM_LOG_ENTER(p_vend->p_log);
570
571         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
572                 "osm_vendor_local_lid_change: " "Change of LID.\n");
573
574         OSM_LOG_EXIT(p_vend->p_log);
575
576         return (IB_SUCCESS);
577
578 }
579
580 /*
581  *  NAME            osm_vendor_set_sm
582  *
583  *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit.
584  */
585
586 void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
587 {
588         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
589         osm_vendor_t const *p_vend = p_bo->p_vendor;
590         osmv_TOPSPIN_ANAFA_transport_mgr_t *p_mgr;
591         int ioctl_ret;
592         osm_ts_set_port_info_ioctl port_info;
593
594         OSM_LOG_ENTER(p_vend->p_log);
595
596         port_info.port = 0;     /* anafa has only 1 port */
597         port_info.port_info.valid_fields = IB_PORT_IS_SM;
598         port_info.port_info.is_sm = is_sm_val;
599
600         p_mgr = (osmv_TOPSPIN_ANAFA_transport_mgr_t *) p_bo->p_transp_mgr;
601         ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCSPORTINFO, &port_info);
602
603         if (ioctl_ret < 0) {
604                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
605                         "osm_vendor_set_sm: ERR 7412: "
606                         "Unable set 'IS_SM' bit to:%u in port attributes (%d). errno=%d\n",
607                         is_sm_val, ioctl_ret, errno);
608         }
609
610         OSM_LOG_EXIT(p_vend->p_log);
611 }
612
613 /*
614  *  NAME            __osm_vendor_internal_unbind
615  *
616  *  DESCRIPTION     Destroying a bind:
617  *                    (1) Wait for the completion of the sends in flight
618  *                    (2) Destroy the associated data structures
619  */
620
621 static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind)
622 {
623         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
624         osm_log_t *p_log = p_bo->p_vendor->p_log;
625
626         OSM_LOG_ENTER(p_log);
627
628         /* "notifying" all that from now on no new sends can be done */
629         p_bo->txn_mgr.p_event_wheel->closing = TRUE;
630
631         osmv_txn_lock(p_bo);
632         p_bo->is_closing = TRUE;
633
634         /* notifying all sleeping rmpp sends to exit */
635         osmv_txn_abort_rmpp_txns(h_bind);
636
637         /*  frees all data in bind handle   */
638         osm_log(p_log, OSM_LOG_DEBUG,
639                 "__osm_vendor_internal_unbind: destroying transport mgr.. \n");
640         osmv_txn_unlock(p_bo);
641
642         osmv_transport_done(h_bind);
643         osm_log(p_log, OSM_LOG_DEBUG,
644                 "__osm_vendor_internal_unbind: destroying txn mgr.. \n");
645         osmv_txn_lock(p_bo);
646         osmv_txnmgr_done(h_bind);
647         osm_log(p_log, OSM_LOG_DEBUG,
648                 "__osm_vendor_internal_unbind: destroying bind lock.. \n");
649
650         osmv_txn_unlock(p_bo);
651         /*
652            we intentionally let the p_bo and its lock leak -
653            as we did not implement a way to track active bind handles provided to
654            the client - and the client might use them
655
656            cl_spinlock_destroy(&p_bo->lock);
657            free(p_bo);
658          */
659
660         OSM_LOG_EXIT(p_log);
661 }
662
663 /*
664  *  NAME            __osmv_get_send_txn
665  *
666  *  DESCRIPTION     Return a transaction object that corresponds to this MAD.
667  *                  Optionally, create it, if the new request (query) is sent or received.
668  */
669
670 static ib_api_status_t
671 __osmv_get_send_txn(IN osm_bind_handle_t h_bind,
672                     IN osm_madw_t * const p_madw,
673                     IN boolean_t is_rmpp,
674                     IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn)
675 {
676         ib_api_status_t ret;
677         uint64_t tid, key;
678         osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
679         ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw);
680
681         OSM_LOG_ENTER(p_bo->p_vendor->p_log);
682         CL_ASSERT(NULL != pp_txn);
683
684         key = tid = cl_ntoh64(p_mad->trans_id);
685         if (TRUE == resp_expected) {
686                 /* Create a unique identifier at the requester side */
687                 key = osmv_txn_uniq_key(tid);
688         }
689
690         /* We must run under a transaction framework */
691         ret = osmv_txn_lookup(h_bind, key, pp_txn);
692         if (IB_NOT_FOUND == ret) {
693                 /* Generally, we start a new transaction */
694                 ret = osmv_txn_init(h_bind, tid, key, pp_txn);
695                 if (IB_SUCCESS != ret) {
696                         goto get_send_txn_done;
697                 }
698         } else {
699                 CL_ASSERT(NULL != *pp_txn);
700                 /* The transaction context exists.
701                  * This is legal only if I am going to return an
702                  * (RMPP?) reply to an RMPP request sent by the other part
703                  * (double-sided RMPP transfer)
704                  */
705                 if (FALSE == is_rmpp
706                     || FALSE == osmv_txn_is_rmpp_init_by_peer(*pp_txn)) {
707                         osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
708                                 "__osmv_get_send_txn: ERR 7413: "
709                                 "The transaction id=0x%llX is not unique. Send failed.\n",
710                                 tid);
711
712                         ret = IB_INVALID_SETTING;
713                         goto get_send_txn_done;
714                 }
715
716                 if (TRUE == resp_expected) {
717                         osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
718                                 "__osmv_get_send_txn: ERR 7414: "
719                                 "The transaction id=%llX can\'t expect a response. Send failed.\n",
720                                 tid);
721
722                         ret = IB_INVALID_PARAMETER;
723                         goto get_send_txn_done;
724                 }
725         }
726
727         if (TRUE == is_rmpp) {
728                 ret = osmv_txn_init_rmpp_sender(h_bind, *pp_txn, p_madw);
729                 if (IB_SUCCESS != ret) {
730                         osmv_txn_done(h_bind, tid, FALSE);
731                         goto get_send_txn_done;
732                 }
733         }
734
735         /* Save a reference to the MAD in the txn context
736          * We'll need to match it in two cases:
737          *  (1) When the response is returned, if I am the requester
738          *  (2) In RMPP retransmissions
739          */
740         osmv_txn_set_madw(*pp_txn, p_madw);
741
742 get_send_txn_done:
743         OSM_LOG_EXIT(p_bo->p_vendor->p_log);
744
745         return ret;
746 }
747
748 /**********************************************************************
749  **********************************************************************/
750 void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
751 {
752
753 }