83d703ff2fd1802bb5f6f04ca51c933f5fe243d8
[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     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
377                "__osm_al_rcv_callback: "
378                "The Mad is a response , thus handeled in __osm_al_send_callback\n");
379     CL_ASSERT( p_elem->send_context1 != NULL );
380     CL_ASSERT( p_elem->send_context2 == NULL );
381
382     p_old_madw = (osm_madw_t*)p_elem->send_context1;
383     p_old_vw = osm_madw_get_vend_ptr( p_old_madw );
384     p_new_madw = p_old_vw->p_resp_madw;
385
386     CL_ASSERT( p_new_madw );
387     osm_madw_init( p_new_madw, p_bind, p_elem->size,
388                    &mad_addr );
389     osm_madw_set_mad( p_new_madw, p_new_mad );
390     p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
391     __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
392     goto Exit;
393   }
394   else
395   {
396     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
397                  "__osm_al_rcv_callback: "
398                  "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");
399     CL_ASSERT( p_elem->send_context1 == NULL );
400     CL_ASSERT( p_elem->send_context2 == NULL );
401
402     p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,
403                                            p_bind, p_elem->size, p_new_mad, &mad_addr );
404     CL_ASSERT(p_new_madw);
405     p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
406
407     __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
408     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
409              "__osm_al_rcv_callback: "
410              "Calling receive callback function %p.\n",
411              p_bind->rcv_callback );
412
413
414     p_bind->rcv_callback( p_new_madw, p_bind->client_context,
415                           ((osm_madw_t*)p_elem->send_context1) );
416   }
417
418
419   Exit:
420   OSM_LOG_EXIT( p_vend->p_log );
421 }
422
423 /**********************************************************************
424  **********************************************************************/
425 ib_api_status_t
426 osm_vendor_init(
427   IN osm_vendor_t* const p_vend,
428   IN osm_log_t* const p_log,
429   IN const uint32_t timeout )
430 {
431   ib_api_status_t status;
432   OSM_LOG_ENTER( p_log, osm_vendor_init );
433
434   p_vend->p_log = p_log;
435
436   /*
437     Open our instance of AL.
438   */
439   status = ib_open_al( &p_vend->h_al );
440   if( status != IB_SUCCESS )
441   {
442     osm_log( p_vend->p_log, OSM_LOG_ERROR,
443              "osm_vendor_init: ERR 3B03: "
444              "Error opening AL (%s).\n",
445              ib_get_err_str( status ) );
446
447     goto Exit;
448   }
449
450   p_vend->timeout = timeout;
451
452  Exit:
453   OSM_LOG_EXIT( p_log );
454   return( status );
455 }
456
457 /**********************************************************************
458  **********************************************************************/
459 osm_vendor_t*
460 osm_vendor_new(
461   IN osm_log_t* const p_log,
462   IN const uint32_t timeout )
463 {
464   ib_api_status_t    status;
465   osm_vendor_t    *p_vend;
466
467   OSM_LOG_ENTER( p_log, osm_vendor_new );
468
469   p_vend = cl_zalloc( sizeof(*p_vend) );
470   if( p_vend == NULL )
471   {
472     osm_log( p_vend->p_log, OSM_LOG_ERROR,
473              "osm_vendor_new: ERR 3B04: "
474              "Unable to allocate vendor object.\n" );
475     goto Exit;
476   }
477
478   status = osm_vendor_init( p_vend, p_log, timeout );
479   if( status != IB_SUCCESS )
480   {
481     cl_free( p_vend );
482     p_vend = NULL;
483   }
484
485  Exit:
486   OSM_LOG_EXIT( p_log );
487   return( p_vend );
488 }
489
490 /**********************************************************************
491  **********************************************************************/
492 void
493 osm_vendor_delete(
494   IN osm_vendor_t** const pp_vend )
495 {
496   /* TO DO - fill this in */
497   ib_close_al( (*pp_vend)->h_al );
498   cl_free( *pp_vend );
499   *pp_vend = NULL;
500 }
501
502 /**********************************************************************
503  **********************************************************************/
504 static ib_api_status_t
505 __osm_ca_info_init(
506   IN osm_vendor_t*        const p_vend,
507   IN osm_ca_info_t*  const   p_ca_info,
508   IN const ib_net64_t      ca_guid )
509 {
510   ib_api_status_t status;
511
512   OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );
513
514   p_ca_info->guid = ca_guid;
515
516   if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
517   {
518     osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
519              "__osm_ca_info_init: "
520              "Querying CA 0x%" PRIx64 ".\n",
521              cl_ntoh64( ca_guid ) );
522   }
523 /* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */
524   status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,
525                                 &p_ca_info->attr_size );
526   if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
527   {
528     osm_log( p_vend->p_log, OSM_LOG_ERROR,
529              "__osm_ca_info_init: ERR 3B05: "
530              "Unexpected status getting CA attributes (%s).\n",
531              ib_get_err_str( status ) );
532     goto Exit;
533   }
534
535   CL_ASSERT( p_ca_info->attr_size );
536
537   p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );
538   if( p_ca_info->p_attr == NULL )
539   {
540     osm_log( p_vend->p_log, OSM_LOG_ERROR,
541              "__osm_ca_info_init: ERR 3B06: "
542              "Unable to allocate attribute storage.\n" );
543     goto Exit;
544   }
545
546   status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,
547                                 (uint32_t*)&p_ca_info->attr_size );
548
549   if( status != IB_SUCCESS )
550   {
551     osm_log( p_vend->p_log, OSM_LOG_ERROR,
552              "__osm_ca_info_init: ERR 3B07: "
553              "Unexpected status getting CA attributes (%s).\n",
554              ib_get_err_str( status ) );
555     goto Exit;
556   }
557
558  Exit:
559   OSM_LOG_EXIT( p_vend->p_log );
560   return( status );
561 }
562
563
564 /**********************************************************************
565  **********************************************************************/
566 void
567 osm_ca_info_destroy(
568   IN osm_vendor_t*        const p_vend,
569   IN osm_ca_info_t*     const p_ca_info )
570 {
571   OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );
572
573   if( p_ca_info->p_attr )
574     cl_free( p_ca_info->p_attr );
575
576   cl_free( p_ca_info );
577
578   OSM_LOG_EXIT( p_vend->p_log );
579 }
580
581 /**********************************************************************
582  **********************************************************************/
583 osm_ca_info_t*
584 osm_ca_info_new(
585   IN osm_vendor_t*        const p_vend,
586   IN const ib_net64_t      ca_guid )
587 {
588   ib_api_status_t status;
589   osm_ca_info_t *p_ca_info;
590
591   OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );
592
593   CL_ASSERT( ca_guid );
594
595   p_ca_info = cl_zalloc( sizeof(*p_ca_info) );
596   if( p_ca_info == NULL )
597     goto Exit;
598
599   status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );
600   if( status != IB_SUCCESS )
601   {
602     osm_ca_info_destroy( p_vend, p_ca_info );
603     p_ca_info = NULL;
604     goto Exit;
605   }
606
607  Exit:
608   OSM_LOG_EXIT( p_vend->p_log );
609   return( p_ca_info );
610 }
611
612 /**********************************************************************
613  **********************************************************************/
614 static ib_api_status_t
615 __osm_vendor_get_ca_guids(
616   IN osm_vendor_t*        const p_vend,
617   IN ib_net64_t**       const p_guids,
618   IN size_t*           const p_num_guids )
619 {
620   ib_api_status_t status;
621
622   OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );
623
624   CL_ASSERT( p_guids );
625   CL_ASSERT( p_num_guids );
626
627   status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );
628   if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
629   {
630     osm_log( p_vend->p_log, OSM_LOG_ERROR,
631              "__osm_vendor_get_ca_guids: ERR 3B08: "
632              "Unexpected status getting CA GUID array (%s).\n",
633              ib_get_err_str( status ) );
634     goto Exit;
635   }
636
637   if( *p_num_guids == 0 )
638   {
639     osm_log( p_vend->p_log, OSM_LOG_ERROR,
640              "__osm_vendor_get_ca_guids: ERR 3B09: "
641              "No available channel adapters.\n" );
642     status = IB_INSUFFICIENT_RESOURCES;
643     goto Exit;
644   }
645
646   *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );
647   if( *p_guids == NULL )
648   {
649     osm_log( p_vend->p_log, OSM_LOG_ERROR,
650              "__osm_vendor_get_ca_guids: ERR 3B10: "
651              "Unable to allocate CA GUID array.\n" );
652     goto Exit;
653   }
654
655   status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );
656   CL_ASSERT( *p_num_guids );
657
658   if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
659   {
660     osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
661              "__osm_vendor_get_ca_guids: "
662              "Detected %u local channel adapters.\n", *p_num_guids );
663   }
664
665  Exit:
666   OSM_LOG_EXIT( p_vend->p_log );
667   return( status );
668 }
669
670 /****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
671  * NAME
672  * osm_ca_info_get_pi_ptr
673  *
674  * DESCRIPTION
675  * Returns a pointer to the port attribute of the specified port
676  * owned by this CA.
677  *
678  * SYNOPSIS
679  */
680 static ib_port_attr_t*
681 __osm_ca_info_get_port_attr_ptr(
682   IN const osm_ca_info_t* const p_ca_info,
683   IN const uint8_t index )
684 {
685   return( &p_ca_info->p_attr->p_port_attr[index] );
686 }
687 /*
688  * PARAMETERS
689  * p_ca_info
690  *    [in] Pointer to a CA Info object.
691  *
692  * index
693  *    [in] Port "index" for which to retrieve the port attribute.
694  *    The index is the offset into the ca's internal array
695  *    of port attributes.
696  *
697  * RETURN VALUE
698  * Returns a pointer to the port attribute of the specified port
699  * owned by this CA.
700  * Also allocate p_vend->p_ca_info if not allocated and init it .
701  *
702  * NOTES
703  *
704  * SEE ALSO
705  *********/
706
707 /**********************************************************************
708  **********************************************************************/
709 ib_api_status_t
710 osm_vendor_get_all_port_attr(
711   IN osm_vendor_t*        const p_vend,
712   IN ib_port_attr_t*    const p_attr_array,
713   IN uint32_t*       const p_num_ports )
714 {
715   ib_api_status_t status;
716
717   uint32_t ca;
718   size_t ca_count;
719   uint32_t port_count = 0;
720   uint8_t port_num;
721   uint32_t total_ports = 0;
722   ib_net64_t *p_ca_guid = NULL;
723   osm_ca_info_t *p_ca_info;
724
725   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );
726
727   CL_ASSERT( p_vend );
728  
729   /*
730     1) Determine the number of CA's
731     2) If not allready allocated - allocate an array big enough to hold the
732          ca info object , the ca info will be overwrite to contain the new ca info
733     3) Call again to retrieve the guids.
734   */
735   status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );
736
737   if (p_vend->p_ca_info == NULL) 
738   {
739       p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );
740       
741       if( p_vend->p_ca_info == NULL )
742       {
743         osm_log( p_vend->p_log, OSM_LOG_ERROR,
744                  "osm_vendor_get_all_port_attr: ERR 3B11: "
745                  "Unable to allocate CA information array.\n" );
746         goto Exit;
747       }
748   }
749
750   p_vend->ca_count = ca_count;
751
752   /*
753     For each CA, retrieve the port info attributes
754   */
755   for( ca = 0; ca < ca_count; ca++ )
756   {
757     p_ca_info = &p_vend->p_ca_info[ca];
758
759     status = __osm_ca_info_init(
760       p_vend,
761       p_ca_info,
762       p_ca_guid[ca] );
763
764     if( status != IB_SUCCESS )
765     {
766       osm_log( p_vend->p_log, OSM_LOG_ERROR,
767                "osm_vendor_get_all_port_attr: ERR 3B12: "
768                "Unable to initialize CA Info object (%s).\n",
769                ib_get_err_str( status ) );
770     }
771
772     total_ports += osm_ca_info_get_num_ports( p_ca_info );
773   }
774
775   /*
776     If the user supplied enough storage, return the port guids,
777     otherwise, return the appropriate error.
778   */
779   if( *p_num_ports >= total_ports )
780   {
781     for( ca = 0; ca < ca_count; ca++ )
782     {
783       uint32_t num_ports;
784
785       p_ca_info = &p_vend->p_ca_info[ca];
786
787       num_ports = osm_ca_info_get_num_ports( p_ca_info );
788
789       for( port_num = 0; port_num < num_ports; port_num++ )
790       {
791         p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(
792           p_ca_info, port_num );
793         port_count++;
794       }
795     }
796   }
797   else
798   {
799     status = IB_INSUFFICIENT_MEMORY;
800   }
801
802
803   *p_num_ports = total_ports;
804
805
806  Exit:
807   if( p_ca_guid )
808     cl_free( p_ca_guid );
809
810   OSM_LOG_EXIT( p_vend->p_log );
811   return( status );
812 }
813
814 /**********************************************************************
815  **********************************************************************/
816 ib_net64_t
817 osm_vendor_get_ca_guid(
818   IN osm_vendor_t* const p_vend,
819   IN const ib_net64_t port_guid )
820 {
821   uint8_t index;
822   uint8_t num_ports;
823   uint32_t num_guids = 0;
824   osm_ca_info_t *p_ca_info;
825   uint32_t ca;
826
827   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );
828
829   CL_ASSERT( port_guid );
830   /*
831     First, locate the HCA that owns this port.
832   */
833   if( p_vend->p_ca_info == NULL )
834   {
835     /*
836       Initialize the osm_ca_info_t array which allows
837       us to match port GUID to CA.
838     */
839     osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
840   }
841
842   CL_ASSERT( p_vend->p_ca_info );
843   CL_ASSERT( p_vend->ca_count );
844
845   for( ca = 0; ca < p_vend->ca_count; ca++ )
846   {
847     p_ca_info = &p_vend->p_ca_info[ca];
848
849     num_ports = osm_ca_info_get_num_ports( p_ca_info );
850     CL_ASSERT( num_ports );
851
852     for( index = 0; index < num_ports; index++ )
853     {
854       if( port_guid ==
855           osm_ca_info_get_port_guid( p_ca_info, index ) )
856       {
857         OSM_LOG_EXIT( p_vend->p_log );
858         return( osm_ca_info_get_ca_guid( p_ca_info ) );
859       }
860     }
861   }
862
863   /*
864     No local CA owns this guid!
865   */
866   osm_log( p_vend->p_log, OSM_LOG_ERROR,
867            "osm_vendor_get_ca_guid: ERR 3B13: "
868            "Unable to determine CA guid.\n" );
869
870   OSM_LOG_EXIT( p_vend->p_log );
871   return( 0 );
872 }
873
874 /**********************************************************************
875  **********************************************************************/
876 uint8_t
877 osm_vendor_get_port_num(
878   IN osm_vendor_t* const p_vend,
879   IN const ib_net64_t port_guid )
880 {
881   uint8_t index;
882   uint8_t num_ports;
883   uint32_t num_guids = 0;
884   osm_ca_info_t *p_ca_info;
885   uint32_t ca;
886
887   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );
888
889   CL_ASSERT( port_guid );
890   /*
891     First, locate the HCA that owns this port.
892   */
893   if( p_vend->p_ca_info == NULL )
894   {
895     /*
896       Initialize the osm_ca_info_t array which allows
897       us to match port GUID to CA.
898     */
899     osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
900   }
901
902   CL_ASSERT( p_vend->p_ca_info );
903   CL_ASSERT( p_vend->ca_count );
904
905   for( ca = 0; ca < p_vend->ca_count; ca++ )
906   {
907     p_ca_info = &p_vend->p_ca_info[ca];
908
909     num_ports = osm_ca_info_get_num_ports( p_ca_info );
910     CL_ASSERT( num_ports );
911
912     for( index = 0; index < num_ports; index++ )
913     {
914       if( port_guid ==
915           osm_ca_info_get_port_guid( p_ca_info, index ) )
916       {
917         OSM_LOG_EXIT( p_vend->p_log );
918         return( osm_ca_info_get_port_num( p_ca_info, index ) );
919       }
920     }
921   }
922  
923   /*
924     No local CA owns this guid!
925   */
926   osm_log( p_vend->p_log, OSM_LOG_ERROR,
927            "osm_vendor_get_port_num: ERR 3B30: "
928            "Unable to determine CA guid.\n" );
929
930   OSM_LOG_EXIT( p_vend->p_log );
931   return( 0 );
932 }
933
934
935 /**********************************************************************
936  **********************************************************************/
937 static ib_api_status_t
938 __osm_vendor_open_ca(
939   IN osm_vendor_t* const p_vend,
940   IN const ib_net64_t port_guid )
941 {
942   ib_net64_t ca_guid;
943   ib_api_status_t status;
944
945   OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );
946
947   ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );
948   if( ca_guid == 0 )
949   {
950     osm_log( p_vend->p_log, OSM_LOG_ERROR,
951              "__osm_vendor_open_ca: ERR 3B31: "
952              "Bad port GUID value 0x%" PRIx64 ".\n",
953              cl_ntoh64( port_guid ) );
954     status = IB_ERROR;
955     goto Exit;
956   }
957
958   osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
959            "__osm_vendor_open_ca: "
960            "Opening HCA 0x%" PRIx64 ".\n",   cl_ntoh64( ca_guid ) );
961
962   status = ib_open_ca( p_vend->h_al,
963                        ca_guid,
964                        __osm_al_ca_err_callback,
965                        p_vend,
966                        &p_vend->h_ca );
967
968   if( status != IB_SUCCESS )
969   {
970     osm_log( p_vend->p_log, OSM_LOG_ERROR,
971              "__osm_vendor_open_ca: ERR 3B15: "
972              "Unable to open CA (%s).\n",
973              ib_get_err_str( status ) );
974     goto Exit;
975   }
976
977   CL_ASSERT( p_vend->h_ca );
978
979   status = ib_alloc_pd(
980     p_vend->h_ca,
981     IB_PDT_ALIAS,
982     p_vend,
983     &p_vend->h_pd );
984
985   if( status != IB_SUCCESS )
986   {
987     ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback  );
988     osm_log( p_vend->p_log, OSM_LOG_ERROR,
989              "__osm_vendor_open_ca: ERR 3B16: "
990              "Unable to allocate protection domain (%s).\n",
991              ib_get_err_str( status ) );
992     goto Exit;
993   }
994
995   CL_ASSERT( p_vend->h_pd );
996
997  Exit:
998   OSM_LOG_EXIT( p_vend->p_log );
999   return( status );
1000 }
1001
1002 /**********************************************************************
1003  **********************************************************************/
1004 static void
1005 __osm_vendor_init_av(
1006   IN const osm_al_bind_info_t* p_bind,
1007   IN ib_av_attr_t* p_av )
1008 {
1009   cl_memclr( p_av, sizeof(*p_av) );
1010   p_av->port_num = p_bind->port_num;
1011   p_av->dlid = IB_LID_PERMISSIVE;
1012 }
1013
1014 /**********************************************************************
1015  **********************************************************************/
1016 osm_bind_handle_t
1017 osm_vendor_bind(
1018   IN osm_vendor_t* const p_vend,
1019   IN osm_bind_info_t* const p_user_bind,
1020   IN osm_mad_pool_t* const p_mad_pool,
1021   IN osm_vend_mad_recv_callback_t mad_recv_callback,
1022   IN osm_vend_mad_send_err_callback_t send_err_callback,
1023   IN void* context )
1024 {
1025   ib_net64_t port_guid;
1026   osm_al_bind_info_t *p_bind = 0;
1027   ib_api_status_t status;
1028   ib_qp_create_t qp_create;
1029   ib_mad_svc_t mad_svc;
1030   ib_av_attr_t av;
1031   DWORD get_last_error;
1032   HANDLE handle;
1033   char mutex_name[100];
1034
1035   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );
1036
1037   CL_ASSERT( p_user_bind );
1038   CL_ASSERT( p_mad_pool );
1039   CL_ASSERT( mad_recv_callback );
1040   CL_ASSERT( send_err_callback );
1041
1042   port_guid = p_user_bind->port_guid;
1043   osm_log( p_vend->p_log, OSM_LOG_INFO,
1044            "osm_vendor_bind: "
1045            "Binding to port 0x%" PRIx64 ".\n",
1046            cl_ntoh64( port_guid ) );
1047
1048   if( p_vend->h_ca == 0 )
1049   {
1050     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1051              "osm_vendor_bind: "
1052              "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));
1053
1054     status = __osm_vendor_open_ca( p_vend, port_guid );
1055     if( status != IB_SUCCESS )
1056     {
1057       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1058                "osm_vendor_bind: ERR 3B17: "
1059                "Unable to Open CA (%s).\n",
1060                ib_get_err_str( status ) );
1061       goto Exit;
1062     }
1063   }
1064
1065   p_bind = cl_zalloc( sizeof(*p_bind) );
1066   if( p_bind == NULL )
1067   {
1068     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1069              "osm_vendor_bind: ERR 3B18: "
1070              "Unable to allocate internal bind object.\n" );
1071     goto Exit;
1072   }
1073
1074   p_bind->p_vend = p_vend;
1075   p_bind->client_context = context;
1076   p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );
1077   p_bind->rcv_callback = mad_recv_callback;
1078   p_bind->send_err_callback = send_err_callback;
1079   p_bind->p_osm_pool = p_mad_pool;
1080
1081   CL_ASSERT( p_bind->port_num );
1082
1083   /* Patch to handle mutiple instances of vendor calls */
1084
1085   switch( p_user_bind->mad_class )
1086   {
1087   case IB_MCLASS_SUBN_LID:
1088   case IB_MCLASS_SUBN_DIR:
1089     sprintf(mutex_name,"Global\\osm_vendor_sm_%d",p_bind->port_num);
1090     break;
1091
1092   case IB_MCLASS_SUBN_ADM:
1093   default:
1094     sprintf(mutex_name,"Global\\osm_vendor_sa_%d",p_bind->port_num);
1095     break;
1096   }
1097
1098   
1099   handle = CreateMutex( NULL, TRUE, mutex_name);
1100
1101   if(handle == NULL) 
1102   {
1103       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1104                "osm_vendor_bind: ERR 3B32: "
1105                "Can't create Mutex\n");
1106       cl_free(p_bind);
1107       p_bind = NULL;
1108       /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
1109       exit(1);
1110   }
1111   get_last_error = GetLastError();
1112
1113   if (get_last_error == ERROR_ALREADY_EXISTS) 
1114   {
1115       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1116                "osm_vendor_bind: ERR 3B35: "
1117                "Current Mutex already exist : %s\n",mutex_name);
1118       printf("ERROR : Port %d already binded.\n",p_bind->port_num);
1119       cl_free(p_bind);
1120       p_bind = NULL;
1121       /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
1122       exit(1);
1123   }
1124   /* End Of Patch */
1125
1126   /*
1127     Get the proper QP.
1128   */
1129   cl_memclr( &qp_create, sizeof(qp_create) );
1130
1131   switch( p_user_bind->mad_class )
1132   {
1133   case IB_MCLASS_SUBN_LID:
1134   case IB_MCLASS_SUBN_DIR:
1135     qp_create.qp_type = IB_QPT_QP0_ALIAS;
1136     break;
1137
1138   case IB_MCLASS_SUBN_ADM:
1139   default:
1140     qp_create.qp_type = IB_QPT_QP1_ALIAS;
1141     break;
1142   }
1143
1144   qp_create.sq_depth = p_user_bind->send_q_size;
1145   qp_create.rq_depth = p_user_bind->recv_q_size;
1146   qp_create.sq_sge = OSM_AL_SQ_SGE;
1147   qp_create.rq_sge = OSM_AL_RQ_SGE;
1148   status = ib_get_spl_qp(
1149     p_vend->h_pd,
1150     port_guid,
1151     &qp_create,
1152     p_bind,
1153     __osm_al_err_callback,
1154     &p_bind->pool_key,
1155     &p_bind->h_qp );
1156
1157   if( status != IB_SUCCESS )
1158   {
1159     cl_free( p_bind );
1160     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1161              "osm_vendor_bind: ERR 3B19: "
1162              "Unable to get QP handle (%s).\n",
1163              ib_get_err_str( status ) );
1164     goto Exit;
1165   }
1166
1167   CL_ASSERT( p_bind->h_qp );
1168   CL_ASSERT( p_bind->pool_key );
1169
1170   cl_memclr( &mad_svc, sizeof(mad_svc) );
1171
1172   mad_svc.mad_svc_context = p_bind;
1173   mad_svc.pfn_mad_send_cb = __osm_al_send_callback; 
1174   mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
1175   mad_svc.mgmt_class = p_user_bind->mad_class;
1176   mad_svc.mgmt_version = p_user_bind->class_version;
1177   mad_svc.support_unsol = p_user_bind->is_responder;
1178   mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
1179   mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
1180   mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
1181   mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
1182   mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
1183
1184
1185   status = ib_reg_mad_svc(
1186     p_bind->h_qp,
1187     &mad_svc,
1188     &p_bind->h_svc );
1189
1190   if( status != IB_SUCCESS )
1191   {
1192     cl_free( p_bind );
1193     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1194              "osm_vendor_bind: ERR 3B21: "
1195              "Unable to register QP0 MAD service (%s).\n",
1196              ib_get_err_str( status ) );
1197     goto Exit;
1198   }
1199
1200   __osm_vendor_init_av( p_bind, &av );
1201
1202   status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );
1203   if( status != IB_SUCCESS )
1204   {
1205     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1206              "osm_vendor_bind: ERR 3B22: "
1207              "Unable to create address vector (%s).\n",
1208              ib_get_err_str( status ) );
1209
1210     goto Exit;
1211   }
1212
1213   if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1214   {
1215     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1216              "osm_vendor_bind: "
1217              "Allocating av handle %p.\n", p_bind->h_dr_av );
1218   }
1219
1220  Exit:
1221   OSM_LOG_EXIT( p_vend->p_log );
1222   return( (osm_bind_handle_t)p_bind );
1223 }
1224
1225 /**********************************************************************
1226  **********************************************************************/
1227 /* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging
1228     The functionality will be added when the Gen2 osm_vendor_unbind
1229     will be implemented.
1230 */    
1231 void
1232 osm_vendor_unbind(
1233   IN osm_bind_handle_t h_bind)
1234 {
1235         osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;
1236         osm_vendor_t *p_vend = p_bind->p_vend;
1237
1238
1239         OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );
1240
1241         OSM_LOG_EXIT( p_vend->p_log);
1242 }
1243
1244 /**********************************************************************
1245  **********************************************************************/
1246 ib_mad_t*
1247 osm_vendor_get(
1248   IN osm_bind_handle_t  h_bind,
1249   IN const uint32_t     mad_size,
1250   IN osm_vend_wrap_t*      const p_vw )
1251 {
1252   ib_mad_t *p_mad;
1253   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1254   osm_vendor_t *p_vend = p_bind->p_vend;
1255   ib_api_status_t status;
1256
1257   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );
1258
1259   CL_ASSERT( p_vw );
1260
1261   p_vw->size = mad_size;
1262   p_vw->h_bind = h_bind;
1263
1264   /*
1265     Retrieve a MAD element from the pool and give the user direct
1266     access to its buffer.
1267   */
1268   status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );
1269   if( status != IB_SUCCESS )
1270   {
1271     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1272              "osm_vendor_get: ERR 3B25: "
1273              "Unable to acquire MAD (%s).\n",
1274              ib_get_err_str( status ) );
1275
1276     p_mad = NULL;
1277     goto Exit;
1278   }
1279
1280   CL_ASSERT( p_vw->p_elem );
1281   p_mad = ib_get_mad_buf( p_vw->p_elem );
1282
1283   if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
1284   {
1285     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1286              "osm_vendor_get: "
1287              "Acquired MAD %p, size = %u.\n", p_mad, mad_size );
1288   }
1289
1290  Exit:
1291   OSM_LOG_EXIT( p_vend->p_log );
1292   return( p_mad );
1293 }
1294
1295 /**********************************************************************
1296  **********************************************************************/
1297 void
1298 osm_vendor_put(
1299   IN osm_bind_handle_t h_bind,
1300   IN osm_vend_wrap_t* const p_vw )
1301 {
1302   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1303   osm_vendor_t *p_vend = p_bind->p_vend;
1304   ib_api_status_t status;
1305
1306   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );
1307
1308   CL_ASSERT( p_vw );
1309   CL_ASSERT( p_vw->p_elem );
1310   CL_ASSERT( p_vw->h_bind == h_bind );
1311
1312   if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
1313   {
1314         
1315     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1316              "osm_vendor_put: "
1317              "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );
1318   //             "Retiring MAD %p.\n", p_mad);
1319   }
1320
1321   status = ib_put_mad( p_vw->p_elem );
1322   if( status != IB_SUCCESS )
1323   {
1324     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1325              "osm_vendor_put: ERR 3B26: "
1326              "Unable to retire MAD (%s).\n",
1327              ib_get_err_str( status ) );
1328   }
1329
1330   OSM_LOG_EXIT( p_vend->p_log );
1331 }
1332
1333 /**********************************************************************
1334  **********************************************************************/
1335 ib_api_status_t
1336 osm_vendor_send(
1337   IN osm_bind_handle_t h_bind,
1338   IN osm_madw_t* const p_madw,
1339   IN boolean_t const resp_expected )
1340 {
1341   osm_al_bind_info_t* const p_bind = h_bind;
1342   osm_vendor_t* const p_vend = p_bind->p_vend;
1343   osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );
1344   osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );
1345   ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );
1346   ib_api_status_t status;
1347   ib_mad_element_t *p_elem;
1348   ib_av_attr_t av;
1349
1350   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );
1351
1352   CL_ASSERT( p_vw->h_bind == h_bind );
1353   CL_ASSERT( p_vw->p_elem );
1354
1355   p_elem = p_vw->p_elem;
1356
1357   /*
1358     If a response is expected to this MAD, then preallocate
1359     a mad wrapper to contain the wire MAD received in the
1360     response.  Allocating a wrapper here allows for easier
1361     failure paths than after we already received the wire mad.
1362     In order to seperate the receive callback and the send callback
1363     dependency , we copy the request madw and send it as context2
1364     Which in time in the receive callback will replace the req_madw 
1365     to allow avoid races with send callback
1366   */
1367   if( resp_expected )
1368   {
1369     p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(
1370       p_bind->p_osm_pool );
1371     if( p_vw->p_resp_madw == NULL  )
1372     {
1373       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1374                "osm_vendor_send: ERR 3B27: "
1375                "Unable to allocate MAD wrapper.\n" );
1376       status = IB_INSUFFICIENT_RESOURCES;
1377       goto Exit;
1378     }
1379     
1380   }
1381   else
1382     p_vw->p_resp_madw = NULL;
1383
1384   /*
1385     For all sends other than directed route SM MADs,
1386     acquire an address vector for the destination.
1387   */
1388   if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )
1389   {
1390     cl_memclr( &av, sizeof(av) );
1391     av.port_num = p_bind->port_num;
1392     av.dlid = p_mad_addr->dest_lid;
1393     av.static_rate = p_mad_addr->static_rate;
1394     av.path_bits = p_mad_addr->path_bits;
1395
1396     if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
1397         (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )
1398     {
1399       av.sl = p_mad_addr->addr_type.gsi.service_level;
1400
1401
1402       if(p_mad_addr->addr_type.gsi.global_route)
1403       {
1404         av.grh_valid = TRUE;
1405         /* ANIL */
1406         /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
1407       }
1408     }
1409
1410     if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1411     {
1412       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1413                "osm_vendor_send: "
1414                "av.port_num 0x%X, "
1415                "av.dlid 0x%X, "
1416                "av.static_rate   %d, "
1417                "av.path_bits %d.\n",
1418                av.port_num, cl_ntoh16(av.dlid),
1419                av.static_rate, av.path_bits);
1420     }
1421
1422     status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );
1423     if( status != IB_SUCCESS )
1424     {
1425       osm_log( p_vend->p_log, OSM_LOG_ERROR,
1426                "osm_vendor_send: ERR 3B28: "
1427                "Unable to create address vector (%s).\n",
1428                ib_get_err_str( status ) );
1429
1430       if( p_vw->p_resp_madw )
1431         osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
1432       /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
1433       if (p_madw) 
1434         osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
1435       goto Exit;
1436     }
1437
1438     if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
1439     {
1440       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1441                "osm_vendor_send: "
1442                "Allocating av handle %p.\n", p_vw->h_av );
1443     }
1444   }
1445   else
1446   {
1447     p_vw->h_av = p_bind->h_dr_av;
1448   }
1449
1450   p_elem->h_av = p_vw->h_av;
1451
1452   p_elem->context1 = p_madw;
1453   p_elem->context2 = NULL;
1454
1455   p_elem->immediate_data = 0;
1456   p_elem->p_grh = NULL;
1457   p_elem->resp_expected = resp_expected;
1458   p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
1459
1460   p_elem->send_opt = IB_SEND_OPT_SIGNALED;
1461   p_elem->timeout_ms = p_vend->timeout;
1462
1463   /* Completion information. */
1464   p_elem->status = 0; /* Not trusting AL */
1465
1466
1467   if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
1468       (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )
1469   {
1470     p_elem->remote_qp = 0;
1471     p_elem->remote_qkey = 0;
1472   }
1473   else
1474   {
1475     p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
1476     p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
1477         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1478             "osm_vendor_send: "
1479             "remote qp = 0x%X, remote qkey = 0x%X.\n",
1480             cl_ntoh32(p_elem->remote_qp),
1481             cl_ntoh32(p_elem->remote_qkey) );
1482   }
1483
1484   status = ib_send_mad( p_bind->h_svc, p_elem, NULL );
1485   if( status != IB_SUCCESS )
1486   {
1487     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1488              "osm_vendor_send: ERR 3B29: "
1489              "Send failed , cleaning up (%s).\n",
1490              ib_get_err_str( status ) );
1491     /* When we destroy the av - we should take the pointer from local allocation since
1492         we do not "trust" IBAL to keep track in p_elem */
1493
1494     if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )
1495     {
1496         osm_log( p_vend->p_log, OSM_LOG_DEBUG,
1497                    "__osm_al_send: "
1498                    "Destroying av handle %p.\n", p_vw->h_av );
1499         ib_destroy_av( p_vw->h_av );
1500     }
1501     if( p_vw->p_resp_madw )
1502       osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
1503     /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
1504     if (p_madw) 
1505       osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
1506     goto Exit;
1507   }
1508
1509  Exit:
1510   OSM_LOG_EXIT( p_vend->p_log );
1511   return( status );
1512 }
1513
1514 /**********************************************************************
1515  **********************************************************************/
1516 ib_api_status_t
1517 osm_vendor_local_lid_change(
1518   IN osm_bind_handle_t h_bind )
1519 {
1520   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1521   osm_vendor_t *p_vend = p_bind->p_vend;
1522   ib_av_attr_t av;
1523   ib_api_status_t status;
1524
1525   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );
1526
1527   /*
1528     The only thing we need to do is refresh the directed
1529     route address vector.
1530   */
1531   __osm_vendor_init_av( p_bind, &av );
1532
1533   status = ib_destroy_av( p_bind->h_dr_av );
1534   p_bind->h_dr_av = NULL;
1535   if( status != IB_SUCCESS )
1536   {
1537     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1538              "osm_vendor_local_lid_change: ERR 3B32: "
1539              "Unable to destroy address vector (%s).\n",
1540              ib_get_err_str( status ) );
1541
1542     goto Exit;
1543   }
1544
1545   status = ib_create_av( p_vend->h_pd, &av, &p_bind->h_dr_av );
1546   if( status != IB_SUCCESS )
1547   {
1548     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1549              "osm_vendor_local_lid_change: ERR 3B33: "
1550              "Unable to create address vector (%s).\n",
1551              ib_get_err_str( status ) );
1552
1553     goto Exit;
1554   }
1555
1556  Exit:
1557   OSM_LOG_EXIT( p_vend->p_log );
1558   return( status );
1559 }
1560
1561 /**********************************************************************
1562  **********************************************************************/
1563 void
1564 osm_vendor_set_sm(
1565   IN osm_bind_handle_t h_bind,
1566   IN boolean_t         is_sm_val )
1567 {
1568   osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
1569   osm_vendor_t *p_vend = p_bind->p_vend;
1570   ib_api_status_t status;
1571   ib_port_attr_mod_t attr_mod;
1572
1573   OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );
1574
1575   cl_memclr( &attr_mod, sizeof(attr_mod) );
1576
1577   attr_mod.cap.sm = is_sm_val;
1578
1579   status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,
1580                          IB_CA_MOD_IS_SM, &attr_mod );
1581
1582   if( status != IB_SUCCESS )
1583   {
1584     osm_log( p_vend->p_log, OSM_LOG_ERROR,
1585              "osm_vendor_set_sm: ERR 3B34: "
1586              "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
1587              is_sm_val, ib_get_err_str( status ) );
1588   }
1589
1590   OSM_LOG_EXIT( p_vend->p_log );
1591 }
1592
1593 #endif   /* OSM_VENDOR_INTF_AL */