Add debug message to help in tracking mads down.
[mirror/winof/.git] / ulp / opensm / user / libvendor / osm_vendor_al.c
1 /*
2  * Copyright (c) 2004, 2005 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 the OpenIB.org BSD license
7  * below:
8  *
9  *     Redistribution and use in source and binary forms, with or
10  *     without modification, are permitted provided that the following
11  *     conditions are met:
12  *
13  *      - Redistributions of source code must retain the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer.
16  *
17  *      - Redistributions in binary form must reproduce the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  *
31  * $Id$
32  */
33
34
35 /*
36  * Abstract:
37  *    Implementation of osm_req_t.
38  * This object represents the generic attribute requester.
39  * This object is part of the opensm family of objects.
40  *
41  * Environment:
42  *    Linux User Mode
43  *
44  * $Revision: 1.8 $
45  */
46
47 /*
48   Next available error code: 0x300
49 */
50 #ifdef __WIN__
51 /* Suppress all warning regarding casting void* to specific pointer object */
52 #pragma warning(disable : 4305)
53 #endif
54
55 #include <vendor/osm_vendor_select.h>
56
57 #ifdef OSM_VENDOR_INTF_AL
58
59 #include <complib/cl_memory.h>
60 #include <complib/cl_qlist.h>
61 #include <complib/cl_thread.h>
62 #include <complib/cl_math.h>
63 #include <complib/cl_debug.h>
64 #include <iba/ib_types.h>
65 #include <opensm/osm_madw.h>
66 #include <opensm/osm_log.h>
67 #include <opensm/osm_mad_pool.h>
68 #include <vendor/osm_vendor_api.h>
69
70 /****s* OpenSM: Vendor AL/osm_al_bind_info_t
71  * NAME
72  *   osm_al_bind_info_t
73  *
74  * DESCRIPTION
75  *    Structure containing bind information.
76  *
77  * SYNOPSIS
78  */
79 typedef struct _osm_al_bind_info
80 {
81   osm_vendor_t                *p_vend;
82   void                        *client_context;
83   ib_qp_handle_t                 h_qp;
84   ib_mad_svc_handle_t               h_svc;
85   uint8_t                        port_num;
86   ib_pool_key_t                  pool_key;
87   osm_vend_mad_recv_callback_t      rcv_callback;
88   osm_vend_mad_send_err_callback_t  send_err_callback;
89   osm_mad_pool_t                 *p_osm_pool;
90   ib_av_handle_t                 h_dr_av;
91
92 } osm_al_bind_info_t;
93 /*
94  * FIELDS
95  * p_vend
96  *    Pointer to the vendor object.
97  *
98  * client_context
99  *    User's context passed during osm_bind
100  *
101  * h_qp
102  *    Handle the QP for this bind.
103  *
104  * h_qp_svc
105  *    Handle the QP mad service for this bind.
106  *
107  * port_num
108  *    Port number (within the HCA) of the bound port.
109  *
110  * pool_key
111  *    Pool key returned by all for this QP.
112  *
113  * h_dr_av
114  *    Address vector handle used for all directed route SMPs.
115  *
116  * SEE ALSO
117  *********/
118
119 /**********************************************************************
120  **********************************************************************/
121 inline static ib_api_status_t
122 __osm_al_convert_wcs(
123   IN ib_wc_status_t        const wc_status )
124 {
125   switch( wc_status )
126   {
127   case IB_WCS_SUCCESS:
128     return( IB_SUCCESS );
129
130   case IB_WCS_TIMEOUT_RETRY_ERR:
131     return( IB_TIMEOUT );
132
133   default:
134     return( IB_ERROR );
135   }
136 }
137
138 /**********************************************************************
139  **********************************************************************/
140 void AL_API
141 __osm_set_vend_wrap( IN  osm_al_bind_info_t* const p_bind,
142                      IN  ib_mad_element_t* const   p_elem,
143                      OUT osm_vend_wrap_t* p_vw)
144 {
145     p_vw->h_bind = p_bind;
146     p_vw->size = p_elem->size;
147     p_vw->p_elem = p_elem;
148     p_vw->h_av = 0;
149     p_vw->p_resp_madw = NULL;
150
151 }
152             
153
154 static void AL_API
155 __osm_al_ca_err_callback(
156   IN ib_async_event_rec_t *p_async_rec )
157 {
158   osm_vendor_t *p_vend = (osm_vendor_t*)p_async_rec->context;
159   OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_err_callback );
160
161   osm_log( p_vend->p_log, OSM_LOG_ERROR,
162            "__osm_al_ca_err_callback: ERR 3B01: "
163            "Event on channel adapter (%s).\n",
164            ib_get_async_event_str( p_async_rec->code ) );
165
166   OSM_LOG_EXIT( p_vend->p_log );
167 }
168
169 /**********************************************************************
170  **********************************************************************/
171 static void AL_API
172 __osm_al_ca_destroy_callback(
173   IN void *context )
174 {
175   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)context;
176   osm_vendor_t *p_vend = p_bind->p_vend;
177   OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_destroy_callback );
178
179   osm_log( p_vend->p_log, OSM_LOG_INFO,
180            "__osm_al_ca_destroy_callback: "
181            "Closing local channel adapter.\n" );
182
183   OSM_LOG_EXIT( p_vend->p_log );
184 }
185
186 /**********************************************************************
187  **********************************************************************/
188
189 static void AL_API
190 __osm_al_err_callback(
191   IN ib_async_event_rec_t *p_async_rec )
192 {
193   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)p_async_rec->context;
194   osm_vendor_t *p_vend = p_bind->p_vend;
195   OSM_LOG_ENTER( p_vend->p_log, __osm_al_err_callback );
196
197   osm_log( p_vend->p_log, OSM_LOG_ERROR,
198            "__osm_al_err_callback: ERR 3B02: "
199            "Error on QP (%s).\n",
200            ib_get_async_event_str( p_async_rec->code ) );
201
202   OSM_LOG_EXIT( p_vend->p_log );
203 }
204
205 /**********************************************************************
206  **********************************************************************/
207 /* 
208     Send_cb will handle  the following cases :
209     Element Status  |  Send Response (no reponse expected)      | Send Request (response expeceted)  
210     ================|===========================================|==========================================
211         ERROR       |   Free : AV , madw(send_err_cb)           | Free : AV , madw , resp_madw 
212         SUCCESS     |   Free : AV , madw                        | Free : AV , madw
213
214     Element Status  |  Receive Response (no reponse expected)    
215     ================|===========================================
216         ERROR       |   Free : AV , madw(send_err_cb) 
217         SUCCESS     |   Free : AV , madw, resp_madw (both through rcv_callback)                        
218    
219 */    
220 static void AL_API
221 __osm_al_send_callback(
222   IN const ib_mad_svc_handle_t h_mad_svc,
223   IN void *mad_svc_context,
224   IN ib_mad_element_t *p_elem )
225 {
226   osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
227   osm_vendor_t* const p_vend = p_bind->p_vend;
228   osm_madw_t* const p_madw = (osm_madw_t*)p_elem->context1;
229   osm_vend_wrap_t* p_vw = osm_madw_get_vend_ptr( p_madw );
230   ib_mad_t *p_mad = ib_get_mad_buf( p_elem );
231   ib_av_attr_t          av_attr;
232   ib_pd_handle_t                h_pd;
233   ib_api_status_t status_elem,status;
234   osm_madw_t *p_new_madw;
235
236   OSM_LOG_ENTER( p_vend->p_log, __osm_al_send_callback );
237   UNUSED_PARAM(h_mad_svc);
238   CL_ASSERT( p_vw );
239   CL_ASSERT( p_vw->h_av );
240   /* since we use context1 , safely , and its the only place that remove the clean 
241     p_elem,p_madw , h_av no checks are required */
242   status_elem = __osm_al_convert_wcs(p_elem->status);
243   osm_log( p_vend->p_log, OSM_LOG_DEBUG,
244            "__osm_al_send_callback: "
245            "Destroying av handle %p.\n", p_elem->h_av );
246   /* Check first if its a direct route handle , in this case skip */
247   if (p_elem->h_av != p_bind->h_dr_av) 
248   {
249       ib_destroy_av( p_elem->h_av );
250   }
251   /* Since the free order is first resp_madw then madw (PARENT) we should check
252    this case first */
253   if (p_elem->resp_expected)
254   {
255       p_madw->status = status_elem;
256       if ( status_elem != IB_SUCCESS )
257       {
258           /*
259               Return any wrappers to the pool that may have been
260               pre-emptively allocated to handle a receive.
261           */
262           osm_log(p_vend->p_log, OSM_LOG_ERROR,
263                   "__osm_al_send_callback: ERR 3333 "
264                   " Mad Completed with WQE Error : %s.\n",ib_get_wc_status_str(p_elem->status));
265           if( p_vw->p_resp_madw )
266           {
267               osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
268               p_vw->p_resp_madw = NULL;
269           }
270
271           p_bind->send_err_callback( p_bind->client_context, p_madw );
272       }
273       else
274       {
275           /* We are in response flow of receive , need to apply the rcv_callback 
276                 The rcv_callback will free the resp_madw , req_madw , p_elem of receive
277                 and request */
278           osm_log(p_vend->p_log, OSM_LOG_DEBUG,
279                   "__osm_al_send_callback: "
280                   "The Mad is a response , thus handeled in __osm_al_send_callback\n");
281           p_new_madw = p_vw->p_resp_madw;
282           p_bind->rcv_callback( p_new_madw, p_bind->client_context,
283                                 p_madw );
284
285       }
286   }
287   else
288   {
289       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
290            "__osm_al_send_callback: "
291            "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
292            cl_ntoh64( p_mad->trans_id ) );
293       osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
294       if ( status_elem != IB_SUCCESS )
295           osm_log( p_vend->p_log, OSM_LOG_ERROR,
296            "__osm_al_send_callback: ERR 3b0b "
297            "request mad had failed.\n");
298       goto Exit;
299   }
300
301
302
303
304
305  Exit:
306   OSM_LOG_EXIT( p_vend->p_log );
307 }
308
309 /**********************************************************************
310  **********************************************************************/
311 /*
312     Receive_cb will be applied in the following cases :
313     Element Status  |  Receive Response (no reponse expected)      | Receive Request (response expeceted)  
314     ================|==============================================|=======================================
315         ERROR       |  NOT APPLIED                                 | NOT_APPLIED
316         SUCCESS     |  Free :  Resp_madw , copy_req_madw           | Allocate new_madw (for response then in send_cb free)
317  */
318  static void AL_API
319 __osm_al_rcv_callback(
320   IN const ib_mad_svc_handle_t h_mad_svc,
321   IN void *mad_svc_context,
322   IN ib_mad_element_t *p_elem )
323 {
324   osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
325   osm_vendor_t* const p_vend = p_bind->p_vend;
326   osm_madw_t *p_old_madw,*p_copy_old_madw;
327   osm_madw_t *p_new_madw;
328   osm_vend_wrap_t* p_old_vw;
329   osm_vend_wrap_t* p_new_vw;
330   ib_mad_t *p_new_mad;
331   osm_mad_addr_t mad_addr;
332
333   OSM_LOG_ENTER( p_vend->p_log, __osm_al_rcv_callback );
334   UNUSED_PARAM(h_mad_svc);
335   CL_ASSERT( p_elem->context1 == NULL );
336   CL_ASSERT( p_elem->context2 == NULL );
337     /*
338   osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
339              "__osm_al_rcv_callback:  "
340              "Handling Transaction : 0x%" PRIx64 " .\n",
341            cl_ntoh64(p_elem->p_mad_buf->trans_id));
342            */
343   p_new_mad = ib_get_mad_buf( p_elem );
344   /*
345     In preperation for initializing the new mad wrapper,
346     Initialize the mad_addr structure for the received wire MAD.
347   */
348   mad_addr.dest_lid = p_elem->remote_lid;
349   mad_addr.path_bits = p_elem->path_bits;
350
351   /* TO DO - figure out which #define to use for the 2.5 Gb rate... */
352   mad_addr.static_rate = 0;
353
354   if( p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
355       p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR )
356   {
357     mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
358   }
359   else
360   {
361     mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
362     mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
363     mad_addr.addr_type.gsi.pkey = p_elem->pkey_index;
364     mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
365     mad_addr.addr_type.gsi.global_route = FALSE;
366   }
367
368   /*
369     If this MAD is a response to a previous request,
370     then grab our pre-allocated MAD wrapper.
371     Otherwise, allocate a new MAD wrapper.
372     context1 - contains the request madw
373   */
374   if( ib_mad_is_response( p_new_mad ) )
375   {
376     /*
377       The acquiring was done in the ib_get_mad_buf function. 
378       If this is a request - then we impllicitly allocate the MAD.
379       In this case - it was allocated in the lower layer. The message
380       is for tracking down messages - locate how/where this mad was
381       allocated.
382     */
383     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
384              "__osm_al_rcv_callback: "
385              "Acquired implicitly MAD %p.\n", p_new_mad );
386
387     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
388                "__osm_al_rcv_callback: "
389                "The Mad is a response , thus handeled in __osm_al_send_callback\n");
390     CL_ASSERT( p_elem->send_context1 != NULL );
391     CL_ASSERT( p_elem->send_context2 == NULL );
392
393     p_old_madw = (osm_madw_t*)p_elem->send_context1;
394     p_old_vw = osm_madw_get_vend_ptr( p_old_madw );
395     p_new_madw = p_old_vw->p_resp_madw;
396
397     CL_ASSERT( p_new_madw );
398     osm_madw_init( p_new_madw, p_bind, p_elem->size,
399                    &mad_addr );
400     osm_madw_set_mad( p_new_madw, p_new_mad );
401     p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
402     __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
403     goto Exit;
404   }
405   else
406   {
407     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
408                  "__osm_al_rcv_callback: "
409                  "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");
410     CL_ASSERT( p_elem->send_context1 == NULL );
411     CL_ASSERT( p_elem->send_context2 == NULL );
412
413     p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,
414                                            p_bind, p_elem->size, p_new_mad, &mad_addr );
415     CL_ASSERT(p_new_madw);
416     p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
417
418     __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
419     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
420              "__osm_al_rcv_callback: "
421              "Calling receive callback function %p.\n",
422              p_bind->rcv_callback );
423
424
425     p_bind->rcv_callback( p_new_madw, p_bind->client_context,
426                           ((osm_madw_t*)p_elem->send_context1) );
427   }
428
429
430   Exit:
431   OSM_LOG_EXIT( p_vend->p_log );
432 }
433
434 /**********************************************************************
435  **********************************************************************/
436 ib_api_status_t
437 osm_vendor_init(
438   IN osm_vendor_t* const p_vend,
439   IN osm_log_t* const p_log,
440   IN const uint32_t timeout )
441 {
442   ib_api_status_t status;
443   OSM_LOG_ENTER( p_log, osm_vendor_init );
444
445   p_vend->p_log = p_log;
446
447   /*
448     Open our instance of AL.
449   */
450   status = ib_open_al( &p_vend->h_al );
451   if( status != IB_SUCCESS )
452   {
453     osm_log( p_vend->p_log, OSM_LOG_ERROR,
454              "osm_vendor_init: ERR 3B03: "
455              "Error opening AL (%s).\n",
456              ib_get_err_str( status ) );
457
458     goto Exit;
459   }
460
461   p_vend->timeout = timeout;
462
463  Exit:
464   OSM_LOG_EXIT( p_log );
465   return( status );
466 }
467
468 /**********************************************************************
469  **********************************************************************/
470 osm_vendor_t*
471 osm_vendor_new(
472   IN osm_log_t* const p_log,
473   IN const uint32_t timeout )
474 {
475   ib_api_status_t    status;
476   osm_vendor_t    *p_vend;
477
478   OSM_LOG_ENTER( p_log, osm_vendor_new );
479
480   p_vend = cl_zalloc( sizeof(*p_vend) );
481   if( p_vend == NULL )
482   {
483     osm_log( p_vend->p_log, OSM_LOG_ERROR,
484              "osm_vendor_new: ERR 3B04: "
485              "Unable to allocate vendor object.\n" );
486     goto Exit;
487   }
488
489   status = osm_vendor_init( p_vend, p_log, timeout );
490   if( status != IB_SUCCESS )
491   {
492     cl_free( p_vend );
493     p_vend = NULL;
494   }
495
496  Exit:
497   OSM_LOG_EXIT( p_log );
498   return( p_vend );
499 }
500
501 /**********************************************************************
502  **********************************************************************/
503 void
504 osm_vendor_delete(
505   IN osm_vendor_t** const pp_vend )
506 {
507   /* TO DO - fill this in */
508   ib_close_al( (*pp_vend)->h_al );
509   cl_free( *pp_vend );
510   *pp_vend = NULL;
511 }
512
513 /**********************************************************************
514  **********************************************************************/
515 static ib_api_status_t
516 __osm_ca_info_init(
517   IN osm_vendor_t*        const p_vend,
518   IN osm_ca_info_t*  const   p_ca_info,
519   IN const ib_net64_t      ca_guid )
520 {
521   ib_api_status_t status;
522
523   OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );
524
525   p_ca_info->guid = ca_guid;
526
527   if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
528   {
529     osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
530              "__osm_ca_info_init: "
531              "Querying CA 0x%" PRIx64 ".\n",
532              cl_ntoh64( ca_guid ) );
533   }
534 /* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */
535   status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,
536                                 &p_ca_info->attr_size );
537   if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
538   {
539     osm_log( p_vend->p_log, OSM_LOG_ERROR,
540              "__osm_ca_info_init: ERR 3B05: "
541              "Unexpected status getting CA attributes (%s).\n",
542              ib_get_err_str( status ) );
543     goto Exit;
544   }
545
546   CL_ASSERT( p_ca_info->attr_size );
547
548   p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );
549   if( p_ca_info->p_attr == NULL )
550   {
551     osm_log( p_vend->p_log, OSM_LOG_ERROR,
552              "__osm_ca_info_init: ERR 3B06: "
553              "Unable to allocate attribute storage.\n" );
554     goto Exit;
555   }
556
557   status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,
558                                 (uint32_t*)&p_ca_info->attr_size );
559
560   if( status != IB_SUCCESS )
561   {
562     osm_log( p_vend->p_log, OSM_LOG_ERROR,
563              "__osm_ca_info_init: ERR 3B07: "
564              "Unexpected status getting CA attributes (%s).\n",
565              ib_get_err_str( status ) );
566     goto Exit;
567   }
568
569  Exit:
570   OSM_LOG_EXIT( p_vend->p_log );
571   return( status );
572 }
573
574
575 /**********************************************************************
576  **********************************************************************/
577 void
578 osm_ca_info_destroy(
579   IN osm_vendor_t*        const p_vend,
580   IN osm_ca_info_t*     const p_ca_info )
581 {
582   OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );
583
584   if( p_ca_info->p_attr )
585     cl_free( p_ca_info->p_attr );
586
587   cl_free( p_ca_info );
588
589   OSM_LOG_EXIT( p_vend->p_log );
590 }
591
592 /**********************************************************************
593  **********************************************************************/
594 osm_ca_info_t*
595 osm_ca_info_new(
596   IN osm_vendor_t*        const p_vend,
597   IN const ib_net64_t      ca_guid )
598 {
599   ib_api_status_t status;
600   osm_ca_info_t *p_ca_info;
601
602   OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );
603
604   CL_ASSERT( ca_guid );
605
606   p_ca_info = cl_zalloc( sizeof(*p_ca_info) );
607   if( p_ca_info == NULL )
608     goto Exit;
609
610   status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );
611   if( status != IB_SUCCESS )
612   {
613     osm_ca_info_destroy( p_vend, p_ca_info );
614     p_ca_info = NULL;
615     goto Exit;
616   }
617
618  Exit:
619   OSM_LOG_EXIT( p_vend->p_log );
620   return( p_ca_info );
621 }
622
623 /**********************************************************************
624  **********************************************************************/
625 static ib_api_status_t
626 __osm_vendor_get_ca_guids(
627   IN osm_vendor_t*        const p_vend,
628   IN ib_net64_t**       const p_guids,
629   IN size_t*           const p_num_guids )
630 {
631   ib_api_status_t status;
632
633   OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );
634
635   CL_ASSERT( p_guids );
636   CL_ASSERT( p_num_guids );
637
638   status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );
639   if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
640   {
641     osm_log( p_vend->p_log, OSM_LOG_ERROR,
642              "__osm_vendor_get_ca_guids: ERR 3B08: "
643              "Unexpected status getting CA GUID array (%s).\n",
644              ib_get_err_str( status ) );
645     goto Exit;
646   }
647
648   if( *p_num_guids == 0 )
649   {
650     osm_log( p_vend->p_log, OSM_LOG_ERROR,
651              "__osm_vendor_get_ca_guids: ERR 3B09: "
652              "No available channel adapters.\n" );
653     status = IB_INSUFFICIENT_RESOURCES;
654     goto Exit;
655   }
656
657   *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );
658   if( *p_guids == NULL )
659   {
660     osm_log( p_vend->p_log, OSM_LOG_ERROR,
661              "__osm_vendor_get_ca_guids: ERR 3B10: "
662              "Unable to allocate CA GUID array.\n" );
663     goto Exit;
664   }
665
666   status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );
667   CL_ASSERT( *p_num_guids );
668
669   if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
670   {
671     osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
672              "__osm_vendor_get_ca_guids: "
673              "Detected %u local channel adapters.\n", *p_num_guids );
674   }
675
676  Exit:
677   OSM_LOG_EXIT( p_vend->p_log );
678   return( status );
679 }
680
681 /****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
682  * NAME
683  * osm_ca_info_get_pi_ptr
684  *
685  * DESCRIPTION
686  * Returns a pointer to the port attribute of the specified port
687  * owned by this CA.
688  *
689  * SYNOPSIS
690  */
691 static ib_port_attr_t*
692 __osm_ca_info_get_port_attr_ptr(
693   IN const osm_ca_info_t* const p_ca_info,
694   IN const uint8_t index )
695 {
696   return( &p_ca_info->p_attr->p_port_attr[index] );
697 }
698 /*
699  * PARAMETERS
700  * p_ca_info
701  *    [in] Pointer to a CA Info object.
702  *
703  * index
704  *    [in] Port "index" for which to retrieve the port attribute.
705  *    The index is the offset into the ca's internal array
706  *    of port attributes.
707  *
708  * RETURN VALUE
709  * Returns a pointer to the port attribute of the specified port
710  * owned by this CA.
711  * Also allocate p_vend->p_ca_info if not allocated and init it .
712  *
713  * NOTES
714  *
715  * SEE ALSO
716  *********/
717
718 /**********************************************************************
719  **********************************************************************/
720 ib_api_status_t
721 osm_vendor_get_all_port_attr(
722   IN osm_vendor_t*        const p_vend,
723   IN ib_port_attr_t*    const p_attr_array,
724   IN uint32_t*       const p_num_ports )
725 {
726   ib_api_status_t status;
727
728   uint32_t ca;
729   size_t ca_count;
730   uint32_t port_count = 0;
731   uint8_t port_num;
732   uint32_t total_ports = 0;
733   ib_net64_t *p_ca_guid = NULL;
734   osm_ca_info_t *p_ca_info;
735
736   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );
737
738   CL_ASSERT( p_vend );
739  
740   /*
741     1) Determine the number of CA's
742     2) If not allready allocated - allocate an array big enough to hold the
743          ca info object , the ca info will be overwrite to contain the new ca info
744     3) Call again to retrieve the guids.
745   */
746   status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );
747
748   if (p_vend->p_ca_info == NULL) 
749   {
750       p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );
751       
752       if( p_vend->p_ca_info == NULL )
753       {
754         osm_log( p_vend->p_log, OSM_LOG_ERROR,
755                  "osm_vendor_get_all_port_attr: ERR 3B11: "
756                  "Unable to allocate CA information array.\n" );
757         goto Exit;
758       }
759   }
760
761   p_vend->ca_count = ca_count;
762
763   /*
764     For each CA, retrieve the port info attributes
765   */
766   for( ca = 0; ca < ca_count; ca++ )
767   {
768     p_ca_info = &p_vend->p_ca_info[ca];
769
770     status = __osm_ca_info_init(
771       p_vend,
772       p_ca_info,
773       p_ca_guid[ca] );
774
775     if( status != IB_SUCCESS )
776     {
777       osm_log( p_vend->p_log, OSM_LOG_ERROR,
778                "osm_vendor_get_all_port_attr: ERR 3B12: "
779                "Unable to initialize CA Info object (%s).\n",
780                ib_get_err_str( status ) );
781     }
782
783     total_ports += osm_ca_info_get_num_ports( p_ca_info );
784   }
785
786   /*
787     If the user supplied enough storage, return the port guids,
788     otherwise, return the appropriate error.
789   */
790   if( *p_num_ports >= total_ports )
791   {
792     for( ca = 0; ca < ca_count; ca++ )
793     {
794       uint32_t num_ports;
795
796       p_ca_info = &p_vend->p_ca_info[ca];
797
798       num_ports = osm_ca_info_get_num_ports( p_ca_info );
799
800       for( port_num = 0; port_num < num_ports; port_num++ )
801       {
802         p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(
803           p_ca_info, port_num );
804         port_count++;
805       }
806     }
807   }
808   else
809   {
810     status = IB_INSUFFICIENT_MEMORY;
811   }
812
813
814   *p_num_ports = total_ports;
815
816
817  Exit:
818   if( p_ca_guid )
819     cl_free( p_ca_guid );
820
821   OSM_LOG_EXIT( p_vend->p_log );
822   return( status );
823 }
824
825 /**********************************************************************
826  **********************************************************************/
827 ib_net64_t
828 osm_vendor_get_ca_guid(
829   IN osm_vendor_t* const p_vend,
830   IN const ib_net64_t port_guid )
831 {
832   uint8_t index;
833   uint8_t num_ports;
834   uint32_t num_guids = 0;
835   osm_ca_info_t *p_ca_info;
836   uint32_t ca;
837
838   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );
839
840   CL_ASSERT( port_guid );
841   /*
842     First, locate the HCA that owns this port.
843   */
844   if( p_vend->p_ca_info == NULL )
845   {
846     /*
847       Initialize the osm_ca_info_t array which allows
848       us to match port GUID to CA.
849     */
850     osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
851   }
852
853   CL_ASSERT( p_vend->p_ca_info );
854   CL_ASSERT( p_vend->ca_count );
855
856   for( ca = 0; ca < p_vend->ca_count; ca++ )
857   {
858     p_ca_info = &p_vend->p_ca_info[ca];
859
860     num_ports = osm_ca_info_get_num_ports( p_ca_info );
861     CL_ASSERT( num_ports );
862
863     for( index = 0; index < num_ports; index++ )
864     {
865       if( port_guid ==
866           osm_ca_info_get_port_guid( p_ca_info, index ) )
867       {
868         OSM_LOG_EXIT( p_vend->p_log );
869         return( osm_ca_info_get_ca_guid( p_ca_info ) );
870       }
871     }
872   }
873
874   /*
875     No local CA owns this guid!
876   */
877   osm_log( p_vend->p_log, OSM_LOG_ERROR,
878            "osm_vendor_get_ca_guid: ERR 3B13: "
879            "Unable to determine CA guid.\n" );
880
881   OSM_LOG_EXIT( p_vend->p_log );
882   return( 0 );
883 }
884
885 /**********************************************************************
886  **********************************************************************/
887 uint8_t
888 osm_vendor_get_port_num(
889   IN osm_vendor_t* const p_vend,
890   IN const ib_net64_t port_guid )
891 {
892   uint8_t index;
893   uint8_t num_ports;
894   uint32_t num_guids = 0;
895   osm_ca_info_t *p_ca_info;
896   uint32_t ca;
897
898   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );
899
900   CL_ASSERT( port_guid );
901   /*
902     First, locate the HCA that owns this port.
903   */
904   if( p_vend->p_ca_info == NULL )
905   {
906     /*
907       Initialize the osm_ca_info_t array which allows
908       us to match port GUID to CA.
909     */
910     osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
911   }
912
913   CL_ASSERT( p_vend->p_ca_info );
914   CL_ASSERT( p_vend->ca_count );
915
916   for( ca = 0; ca < p_vend->ca_count; ca++ )
917   {
918     p_ca_info = &p_vend->p_ca_info[ca];
919
920     num_ports = osm_ca_info_get_num_ports( p_ca_info );
921     CL_ASSERT( num_ports );
922
923     for( index = 0; index < num_ports; index++ )
924     {
925       if( port_guid ==
926           osm_ca_info_get_port_guid( p_ca_info, index ) )
927       {
928         OSM_LOG_EXIT( p_vend->p_log );
929         return( osm_ca_info_get_port_num( p_ca_info, index ) );
930       }
931     }
932   }
933  
934   /*
935     No local CA owns this guid!
936   */
937   osm_log( p_vend->p_log, OSM_LOG_ERROR,
938            "osm_vendor_get_port_num: ERR 3B30: "
939            "Unable to determine CA guid.\n" );
940
941   OSM_LOG_EXIT( p_vend->p_log );
942   return( 0 );
943 }
944
945
946 /**********************************************************************
947  **********************************************************************/
948 static ib_api_status_t
949 __osm_vendor_open_ca(
950   IN osm_vendor_t* const p_vend,
951   IN const ib_net64_t port_guid )
952 {
953   ib_net64_t ca_guid;
954   ib_api_status_t status;
955
956   OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );
957
958   ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );
959   if( ca_guid == 0 )
960   {
961     osm_log( p_vend->p_log, OSM_LOG_ERROR,
962              "__osm_vendor_open_ca: ERR 3B31: "
963              "Bad port GUID value 0x%" PRIx64 ".\n",
964              cl_ntoh64( port_guid ) );
965     status = IB_ERROR;
966     goto Exit;
967   }
968
969   osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
970            "__osm_vendor_open_ca: "
971            "Opening HCA 0x%" PRIx64 ".\n",   cl_ntoh64( ca_guid ) );
972
973   status = ib_open_ca( p_vend->h_al,
974                        ca_guid,
975                        __osm_al_ca_err_callback,
976                        p_vend,
977                        &p_vend->h_ca );
978
979   if( status != IB_SUCCESS )
980   {
981     osm_log( p_vend->p_log, OSM_LOG_ERROR,
982              "__osm_vendor_open_ca: ERR 3B15: "
983              "Unable to open CA (%s).\n",
984              ib_get_err_str( status ) );
985     goto Exit;
986   }
987
988   CL_ASSERT( p_vend->h_ca );
989
990   status = ib_alloc_pd(
991     p_vend->h_ca,
992     IB_PDT_ALIAS,
993     p_vend,
994     &p_vend->h_pd );
995
996   if( status != IB_SUCCESS )
997   {
998     ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback  );
999     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1000              "__osm_vendor_open_ca: ERR 3B16: "
1001              "Unable to allocate protection domain (%s).\n",
1002              ib_get_err_str( status ) );
1003     goto Exit;
1004   }
1005
1006   CL_ASSERT( p_vend->h_pd );
1007
1008  Exit:
1009   OSM_LOG_EXIT( p_vend->p_log );
1010   return( status );
1011 }
1012
1013 /**********************************************************************
1014  **********************************************************************/
1015 static void
1016 __osm_vendor_init_av(
1017   IN const osm_al_bind_info_t* p_bind,
1018   IN ib_av_attr_t* p_av )
1019 {
1020   cl_memclr( p_av, sizeof(*p_av) );
1021   p_av->port_num = p_bind->port_num;
1022   p_av->dlid = IB_LID_PERMISSIVE;
1023 }
1024
1025 /**********************************************************************
1026  **********************************************************************/
1027 osm_bind_handle_t
1028 osm_vendor_bind(
1029   IN osm_vendor_t* const p_vend,
1030   IN osm_bind_info_t* const p_user_bind,
1031   IN osm_mad_pool_t* const p_mad_pool,
1032   IN osm_vend_mad_recv_callback_t mad_recv_callback,
1033   IN osm_vend_mad_send_err_callback_t send_err_callback,
1034   IN void* context )
1035 {
1036   ib_net64_t port_guid;
1037   osm_al_bind_info_t *p_bind = 0;
1038   ib_api_status_t status;
1039   ib_qp_create_t qp_create;
1040   ib_mad_svc_t mad_svc;
1041   ib_av_attr_t av;
1042   DWORD get_last_error;
1043   HANDLE handle;
1044   char mutex_name[100];
1045
1046   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );
1047
1048   CL_ASSERT( p_user_bind );
1049   CL_ASSERT( p_mad_pool );
1050   CL_ASSERT( mad_recv_callback );
1051   CL_ASSERT( send_err_callback );
1052
1053   port_guid = p_user_bind->port_guid;
1054   osm_log( p_vend->p_log, OSM_LOG_INFO,
1055            "osm_vendor_bind: "
1056            "Binding to port 0x%" PRIx64 ".\n",
1057            cl_ntoh64( port_guid ) );
1058
1059   if( p_vend->h_ca == 0 )
1060   {
1061     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1062              "osm_vendor_bind: "
1063              "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));
1064
1065     status = __osm_vendor_open_ca( p_vend, port_guid );
1066     if( status != IB_SUCCESS )
1067     {
1068       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1069                "osm_vendor_bind: ERR 3B17: "
1070                "Unable to Open CA (%s).\n",
1071                ib_get_err_str( status ) );
1072       goto Exit;
1073     }
1074   }
1075
1076   p_bind = cl_zalloc( sizeof(*p_bind) );
1077   if( p_bind == NULL )
1078   {
1079     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1080              "osm_vendor_bind: ERR 3B18: "
1081              "Unable to allocate internal bind object.\n" );
1082     goto Exit;
1083   }
1084
1085   p_bind->p_vend = p_vend;
1086   p_bind->client_context = context;
1087   p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );
1088   p_bind->rcv_callback = mad_recv_callback;
1089   p_bind->send_err_callback = send_err_callback;
1090   p_bind->p_osm_pool = p_mad_pool;
1091
1092   CL_ASSERT( p_bind->port_num );
1093
1094   /* Patch to handle mutiple instances of vendor calls */
1095
1096   switch( p_user_bind->mad_class )
1097   {
1098   case IB_MCLASS_SUBN_LID:
1099   case IB_MCLASS_SUBN_DIR:
1100     sprintf(mutex_name,"Global\\osm_vendor_sm_%d",p_bind->port_num);
1101     break;
1102
1103   case IB_MCLASS_SUBN_ADM:
1104   default:
1105     sprintf(mutex_name,"Global\\osm_vendor_sa_%d",p_bind->port_num);
1106     break;
1107   }
1108
1109   
1110   handle = CreateMutex( NULL, TRUE, mutex_name);
1111
1112   if(handle == NULL) 
1113   {
1114       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1115                "osm_vendor_bind: ERR 3B32: "
1116                "Can't create Mutex\n");
1117       cl_free(p_bind);
1118       p_bind = NULL;
1119       /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
1120       exit(1);
1121   }
1122   get_last_error = GetLastError();
1123
1124   if (get_last_error == ERROR_ALREADY_EXISTS) 
1125   {
1126       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1127                "osm_vendor_bind: ERR 3B35: "
1128                "Current Mutex already exist : %s\n",mutex_name);
1129       printf("ERROR : Port %d already binded.\n",p_bind->port_num);
1130       cl_free(p_bind);
1131       p_bind = NULL;
1132       /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
1133       exit(1);
1134   }
1135   /* End Of Patch */
1136
1137   /*
1138     Get the proper QP.
1139   */
1140   cl_memclr( &qp_create, sizeof(qp_create) );
1141
1142   switch( p_user_bind->mad_class )
1143   {
1144   case IB_MCLASS_SUBN_LID:
1145   case IB_MCLASS_SUBN_DIR:
1146     qp_create.qp_type = IB_QPT_QP0_ALIAS;
1147     break;
1148
1149   case IB_MCLASS_SUBN_ADM:
1150   default:
1151     qp_create.qp_type = IB_QPT_QP1_ALIAS;
1152     break;
1153   }
1154
1155   qp_create.sq_depth = p_user_bind->send_q_size;
1156   qp_create.rq_depth = p_user_bind->recv_q_size;
1157   qp_create.sq_sge = OSM_AL_SQ_SGE;
1158   qp_create.rq_sge = OSM_AL_RQ_SGE;
1159   status = ib_get_spl_qp(
1160     p_vend->h_pd,
1161     port_guid,
1162     &qp_create,
1163     p_bind,
1164     __osm_al_err_callback,
1165     &p_bind->pool_key,
1166     &p_bind->h_qp );
1167
1168   if( status != IB_SUCCESS )
1169   {
1170     cl_free( p_bind );
1171     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1172              "osm_vendor_bind: ERR 3B19: "
1173              "Unable to get QP handle (%s).\n",
1174              ib_get_err_str( status ) );
1175     goto Exit;
1176   }
1177
1178   CL_ASSERT( p_bind->h_qp );
1179   CL_ASSERT( p_bind->pool_key );
1180
1181   cl_memclr( &mad_svc, sizeof(mad_svc) );
1182
1183   mad_svc.mad_svc_context = p_bind;
1184   mad_svc.pfn_mad_send_cb = __osm_al_send_callback; 
1185   mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
1186   mad_svc.mgmt_class = p_user_bind->mad_class;
1187   mad_svc.mgmt_version = p_user_bind->class_version;
1188   mad_svc.support_unsol = p_user_bind->is_responder;
1189   mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
1190   mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
1191   mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
1192   mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
1193   mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
1194
1195
1196   status = ib_reg_mad_svc(
1197     p_bind->h_qp,
1198     &mad_svc,
1199     &p_bind->h_svc );
1200
1201   if( status != IB_SUCCESS )
1202   {
1203     cl_free( p_bind );
1204     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1205              "osm_vendor_bind: ERR 3B21: "
1206              "Unable to register QP0 MAD service (%s).\n",
1207              ib_get_err_str( status ) );
1208     goto Exit;
1209   }
1210
1211   __osm_vendor_init_av( p_bind, &av );
1212
1213   status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );
1214   if( status != IB_SUCCESS )
1215   {
1216     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1217              "osm_vendor_bind: ERR 3B22: "
1218              "Unable to create address vector (%s).\n",
1219              ib_get_err_str( status ) );
1220
1221     goto Exit;
1222   }
1223
1224   if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1225   {
1226     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1227              "osm_vendor_bind: "
1228              "Allocating av handle %p.\n", p_bind->h_dr_av );
1229   }
1230
1231  Exit:
1232   OSM_LOG_EXIT( p_vend->p_log );
1233   return( (osm_bind_handle_t)p_bind );
1234 }
1235
1236 /**********************************************************************
1237  **********************************************************************/
1238 /* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging
1239     The functionality will be added when the Gen2 osm_vendor_unbind
1240     will be implemented.
1241 */    
1242 void
1243 osm_vendor_unbind(
1244   IN osm_bind_handle_t h_bind)
1245 {
1246         osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;
1247         osm_vendor_t *p_vend = p_bind->p_vend;
1248
1249
1250         OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );
1251
1252         OSM_LOG_EXIT( p_vend->p_log);
1253 }
1254
1255 /**********************************************************************
1256  **********************************************************************/
1257 ib_mad_t*
1258 osm_vendor_get(
1259   IN osm_bind_handle_t  h_bind,
1260   IN const uint32_t     mad_size,
1261   IN osm_vend_wrap_t*      const p_vw )
1262 {
1263   ib_mad_t *p_mad;
1264   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1265   osm_vendor_t *p_vend = p_bind->p_vend;
1266   ib_api_status_t status;
1267
1268   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );
1269
1270   CL_ASSERT( p_vw );
1271
1272   p_vw->size = mad_size;
1273   p_vw->h_bind = h_bind;
1274
1275   /*
1276     Retrieve a MAD element from the pool and give the user direct
1277     access to its buffer.
1278   */
1279   status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );
1280   if( status != IB_SUCCESS )
1281   {
1282     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1283              "osm_vendor_get: ERR 3B25: "
1284              "Unable to acquire MAD (%s).\n",
1285              ib_get_err_str( status ) );
1286
1287     p_mad = NULL;
1288     goto Exit;
1289   }
1290
1291   CL_ASSERT( p_vw->p_elem );
1292   p_mad = ib_get_mad_buf( p_vw->p_elem );
1293
1294   if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
1295   {
1296     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1297              "osm_vendor_get: "
1298              "Acquired MAD %p, size = %u.\n", p_mad, mad_size );
1299   }
1300
1301  Exit:
1302   OSM_LOG_EXIT( p_vend->p_log );
1303   return( p_mad );
1304 }
1305
1306 /**********************************************************************
1307  **********************************************************************/
1308 void
1309 osm_vendor_put(
1310   IN osm_bind_handle_t h_bind,
1311   IN osm_vend_wrap_t* const p_vw )
1312 {
1313   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1314   osm_vendor_t *p_vend = p_bind->p_vend;
1315   ib_api_status_t status;
1316
1317   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );
1318
1319   CL_ASSERT( p_vw );
1320   CL_ASSERT( p_vw->p_elem );
1321   CL_ASSERT( p_vw->h_bind == h_bind );
1322
1323   if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
1324   {
1325         
1326     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1327              "osm_vendor_put: "
1328              "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );
1329   //             "Retiring MAD %p.\n", p_mad);
1330   }
1331
1332   status = ib_put_mad( p_vw->p_elem );
1333   if( status != IB_SUCCESS )
1334   {
1335     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1336              "osm_vendor_put: ERR 3B26: "
1337              "Unable to retire MAD (%s).\n",
1338              ib_get_err_str( status ) );
1339   }
1340
1341   OSM_LOG_EXIT( p_vend->p_log );
1342 }
1343
1344 /**********************************************************************
1345  **********************************************************************/
1346 ib_api_status_t
1347 osm_vendor_send(
1348   IN osm_bind_handle_t h_bind,
1349   IN osm_madw_t* const p_madw,
1350   IN boolean_t const resp_expected )
1351 {
1352   osm_al_bind_info_t* const p_bind = h_bind;
1353   osm_vendor_t* const p_vend = p_bind->p_vend;
1354   osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );
1355   osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );
1356   ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );
1357   ib_api_status_t status;
1358   ib_mad_element_t *p_elem;
1359   ib_av_attr_t av;
1360
1361   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );
1362
1363   CL_ASSERT( p_vw->h_bind == h_bind );
1364   CL_ASSERT( p_vw->p_elem );
1365
1366   p_elem = p_vw->p_elem;
1367
1368   /*
1369     If a response is expected to this MAD, then preallocate
1370     a mad wrapper to contain the wire MAD received in the
1371     response.  Allocating a wrapper here allows for easier
1372     failure paths than after we already received the wire mad.
1373     In order to seperate the receive callback and the send callback
1374     dependency , we copy the request madw and send it as context2
1375     Which in time in the receive callback will replace the req_madw 
1376     to allow avoid races with send callback
1377   */
1378   if( resp_expected )
1379   {
1380     p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(
1381       p_bind->p_osm_pool );
1382     if( p_vw->p_resp_madw == NULL  )
1383     {
1384       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1385                "osm_vendor_send: ERR 3B27: "
1386                "Unable to allocate MAD wrapper.\n" );
1387       status = IB_INSUFFICIENT_RESOURCES;
1388       goto Exit;
1389     }
1390     
1391   }
1392   else
1393     p_vw->p_resp_madw = NULL;
1394
1395   /*
1396     For all sends other than directed route SM MADs,
1397     acquire an address vector for the destination.
1398   */
1399   if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )
1400   {
1401     cl_memclr( &av, sizeof(av) );
1402     av.port_num = p_bind->port_num;
1403     av.dlid = p_mad_addr->dest_lid;
1404     av.static_rate = p_mad_addr->static_rate;
1405     av.path_bits = p_mad_addr->path_bits;
1406
1407     if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
1408         (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )
1409     {
1410       av.sl = p_mad_addr->addr_type.gsi.service_level;
1411
1412
1413       if(p_mad_addr->addr_type.gsi.global_route)
1414       {
1415         av.grh_valid = TRUE;
1416         /* ANIL */
1417         /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
1418       }
1419     }
1420
1421     if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1422     {
1423       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1424                "osm_vendor_send: "
1425                "av.port_num 0x%X, "
1426                "av.dlid 0x%X, "
1427                "av.static_rate   %d, "
1428                "av.path_bits %d.\n",
1429                av.port_num, cl_ntoh16(av.dlid),
1430                av.static_rate, av.path_bits);
1431     }
1432
1433     status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );
1434     if( status != IB_SUCCESS )
1435     {
1436       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1437                "osm_vendor_send: ERR 3B28: "
1438                "Unable to create address vector (%s).\n",
1439                ib_get_err_str( status ) );
1440
1441       if( p_vw->p_resp_madw )
1442         osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
1443       /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
1444       if (p_madw) 
1445         osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
1446       goto Exit;
1447     }
1448
1449     if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1450     {
1451       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1452                "osm_vendor_send: "
1453                "Allocating av handle %p.\n", p_vw->h_av );
1454     }
1455   }
1456   else
1457   {
1458     p_vw->h_av = p_bind->h_dr_av;
1459   }
1460
1461   p_elem->h_av = p_vw->h_av;
1462
1463   p_elem->context1 = p_madw;
1464   p_elem->context2 = NULL;
1465
1466   p_elem->immediate_data = 0;
1467   p_elem->p_grh = NULL;
1468   p_elem->resp_expected = resp_expected;
1469   p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
1470
1471   p_elem->send_opt = IB_SEND_OPT_SIGNALED;
1472   p_elem->timeout_ms = p_vend->timeout;
1473
1474   /* Completion information. */
1475   p_elem->status = 0; /* Not trusting AL */
1476
1477
1478   if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
1479       (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )
1480   {
1481     p_elem->remote_qp = 0;
1482     p_elem->remote_qkey = 0;
1483   }
1484   else
1485   {
1486     p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
1487     p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
1488         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1489             "osm_vendor_send: "
1490             "remote qp = 0x%X, remote qkey = 0x%X.\n",
1491             cl_ntoh32(p_elem->remote_qp),
1492             cl_ntoh32(p_elem->remote_qkey) );
1493   }
1494
1495   status = ib_send_mad( p_bind->h_svc, p_elem, NULL );
1496   if( status != IB_SUCCESS )
1497   {
1498     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1499              "osm_vendor_send: ERR 3B29: "
1500              "Send failed , cleaning up (%s).\n",
1501              ib_get_err_str( status ) );
1502     /* When we destroy the av - we should take the pointer from local allocation since
1503         we do not "trust" IBAL to keep track in p_elem */
1504
1505     if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )
1506     {
1507         osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1508                    "__osm_al_send: "
1509                    "Destroying av handle %p.\n", p_vw->h_av );
1510         ib_destroy_av( p_vw->h_av );
1511     }
1512     if( p_vw->p_resp_madw )
1513       osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
1514     /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
1515     if (p_madw) 
1516       osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
1517     goto Exit;
1518   }
1519
1520  Exit:
1521   OSM_LOG_EXIT( p_vend->p_log );
1522   return( status );
1523 }
1524
1525 /**********************************************************************
1526  **********************************************************************/
1527 ib_api_status_t
1528 osm_vendor_local_lid_change(
1529   IN osm_bind_handle_t h_bind )
1530 {
1531   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1532   osm_vendor_t *p_vend = p_bind->p_vend;
1533   ib_av_attr_t av;
1534   ib_api_status_t status;
1535
1536   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );
1537
1538   /*
1539     The only thing we need to do is refresh the directed
1540     route address vector.
1541   */
1542   __osm_vendor_init_av( p_bind, &av );
1543
1544   status = ib_destroy_av( p_bind->h_dr_av );
1545   p_bind->h_dr_av = NULL;
1546   if( status != IB_SUCCESS )
1547   {
1548     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1549              "osm_vendor_local_lid_change: ERR 3B32: "
1550              "Unable to destroy address vector (%s).\n",
1551              ib_get_err_str( status ) );
1552
1553     goto Exit;
1554   }
1555
1556   status = ib_create_av( p_vend->h_pd, &av, &p_bind->h_dr_av );
1557   if( status != IB_SUCCESS )
1558   {
1559     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1560              "osm_vendor_local_lid_change: ERR 3B33: "
1561              "Unable to create address vector (%s).\n",
1562              ib_get_err_str( status ) );
1563
1564     goto Exit;
1565   }
1566
1567  Exit:
1568   OSM_LOG_EXIT( p_vend->p_log );
1569   return( status );
1570 }
1571
1572 /**********************************************************************
1573  **********************************************************************/
1574 void
1575 osm_vendor_set_sm(
1576   IN osm_bind_handle_t h_bind,
1577   IN boolean_t         is_sm_val )
1578 {
1579   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1580   osm_vendor_t *p_vend = p_bind->p_vend;
1581   ib_api_status_t status;
1582   ib_port_attr_mod_t attr_mod;
1583
1584   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );
1585
1586   cl_memclr( &attr_mod, sizeof(attr_mod) );
1587
1588   attr_mod.cap.sm = is_sm_val;
1589
1590   status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,
1591                          IB_CA_MOD_IS_SM, &attr_mod );
1592
1593   if( status != IB_SUCCESS )
1594   {
1595     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1596              "osm_vendor_set_sm: ERR 3B34: "
1597              "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
1598              is_sm_val, ib_get_err_str( status ) );
1599   }
1600
1601   OSM_LOG_EXIT( p_vend->p_log );
1602 }
1603
1604 #endif   /* OSM_VENDOR_INTF_AL */