xref: /NextBSD/contrib/ofed/management/opensm/libvendor/osm_vendor_umadt.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*
2  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35 
36 /*
37  * Abstract:
38  *    Implementation of osm_req_t.
39  * This object represents the generic attribute requester.
40  * This object is part of the opensm family of objects.
41  *
42  */
43 
44 /*
45   Next available error code: 0x300
46 */
47 
48 #if HAVE_CONFIG_H
49 #  include <config.h>
50 #endif				/* HAVE_CONFIG_H */
51 
52 #ifdef OSM_VENDOR_INTF_UMADT
53 
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <dlfcn.h>
57 #include <string.h>
58 
59 #include <complib/cl_qlist.h>
60 #include <complib/cl_thread.h>
61 #include <complib/cl_timer.h>
62 #include <iba/ib_types.h>
63 #include <opensm/osm_madw.h>
64 #include <opensm/osm_log.h>
65 #include <opensm/osm_mad_pool.h>
66 
67 #include <vendor/osm_vendor_umadt.h>
68 #include <vendor/osm_umadt.h>
69 
70 /*  GEN1 includes */
71 #include "umadt_so.h"
72 #include "ibt.h"
73 #include "statustext.h"
74 
75 /* //////////////////////////////////////////////////////////////////////// */
76 /* //////////////////////////////////////////////////////////////////////// */
77 /* //////////////////////////////////////////////////////////////////////// */
78 /* //////////////////////////////////////////////////////////////////////// */
79 /* //////////////////////////////////////////////////////////////////////// */
80 /*  */
81 /*      VENDOR_MAD_INTF */
82 /*  */
83 /* //////////////////////////////////////////////////////////////////////// */
84 /* //////////////////////////////////////////////////////////////////////// */
85 /* //////////////////////////////////////////////////////////////////////// */
86 /* //////////////////////////////////////////////////////////////////////// */
87 /* //////////////////////////////////////////////////////////////////////// */
88 
89 /* //////////////////// */
90 /*  Globals        // */
91 /* //////////////////// */
92 typedef struct _ib_sa_mad_vM3 {
93 	uint8_t base_ver;
94 	uint8_t mgmt_class;
95 	uint8_t class_ver;
96 	uint8_t method;
97 	ib_net16_t status;
98 	ib_net16_t resv;
99 	ib_net64_t trans_id;
100 	ib_net16_t attr_id;
101 	ib_net16_t resv1;
102 	ib_net32_t attr_mod;
103 	ib_net64_t resv2;
104 	ib_net64_t sm_key;
105 
106 	ib_net32_t seg_num;
107 	ib_net32_t payload_len;
108 	uint8_t frag_flag;
109 	uint8_t edit_mod;
110 	ib_net16_t window;
111 	ib_net16_t attr_offset;
112 	ib_net16_t resv3;
113 
114 	ib_net64_t comp_mask;
115 
116 	uint8_t data[IB_SA_DATA_SIZE];
117 } ib_sa_mad_t_vM3;
118 #define  DEFAULT_TIMER_INTERVAL_MSEC   500	/*  500msec timer interval */
119 
120 void __mad_recv_processor(void *context);
121 
122 boolean_t __valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info);
123 
124 cl_status_t
125 __match_tid_context(const cl_list_item_t * const p_list_item, void *context);
126 void __osm_vendor_timer_callback(IN void *context);
127 
osm_vendor_new(IN osm_log_t * const p_log,IN const uint32_t timeout)128 osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
129 			     IN const uint32_t timeout)
130 {
131 	ib_api_status_t status;
132 	umadt_obj_t *p_umadt_obj;
133 
134 	OSM_LOG_ENTER(p_log);
135 
136 	p_umadt_obj = malloc(sizeof(umadt_obj_t));
137 	if (p_umadt_obj) {
138 		memset(p_umadt_obj, 0, sizeof(umadt_obj_t));
139 
140 		status = osm_vendor_init((osm_vendor_t *) p_umadt_obj, p_log,
141 					 timeout);
142 		if (status != IB_SUCCESS) {
143 			osm_vendor_delete((osm_vendor_t **) & p_umadt_obj);
144 		}
145 	} else {
146 		printf
147 		    ("osm_vendor_construct: ERROR! Unable to create Umadt object!\n");
148 	}
149 
150 	OSM_LOG_EXIT(p_log);
151 
152 	return ((osm_vendor_t *) p_umadt_obj);
153 }
154 
osm_vendor_delete(IN osm_vendor_t ** const pp_vend)155 void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
156 {
157 	umadt_obj_t *p_umadt_obj = (umadt_obj_t *) * pp_vend;
158 	cl_list_item_t *p_list_item;
159 	uint32_t count, i;
160 	mad_bind_info_t *p_mad_bind_info;
161 
162 	OSM_LOG_ENTER(p_umadt_obj->p_log);
163 
164 	cl_spinlock_acquire(&p_umadt_obj->register_lock);
165 	p_mad_bind_info =
166 	    (mad_bind_info_t *) cl_qlist_head(&p_umadt_obj->register_list);
167 	count = cl_qlist_count(&p_umadt_obj->register_list);
168 	cl_spinlock_release(&p_umadt_obj->register_lock);
169 	for (i = 0; i < count; i++) {
170 		cl_spinlock_acquire(&p_umadt_obj->register_lock);
171 		p_list_item = cl_qlist_next(&p_mad_bind_info->list_item);
172 		cl_spinlock_release(&p_umadt_obj->register_lock);
173 		/*  Unbind this handle */
174 		/*  osm_vendor_ubind also removesd the item from the list */
175 		/*  osm_vendor_unbind takes the list lock so release it here */
176 		osm_vendor_unbind((osm_bind_handle_t) p_mad_bind_info);
177 		p_mad_bind_info = (mad_bind_info_t *) p_list_item;
178 	}
179 	dlclose(p_umadt_obj->umadt_handle);
180 	free(p_umadt_obj);
181 	*pp_vend = NULL;
182 
183 	OSM_LOG_EXIT(p_umadt_obj->p_log);
184 }
185 
186 /* //////////////////////////////////////////////////////////////////////// */
187 /*  See VendorAbstractMadIntf.h for info */
188 /* //////////////////////////////////////////////////////////////////////// */
189 /*  */
190 ib_api_status_t
osm_vendor_init(IN osm_vendor_t * const p_vend,IN osm_log_t * const p_log,IN const uint32_t timeout)191 osm_vendor_init(IN osm_vendor_t * const p_vend,
192 		IN osm_log_t * const p_log, IN const uint32_t timeout)
193 {
194 	FSTATUS Status;
195 	PUMADT_GET_INTERFACE uMadtGetInterface;
196 	char *error;
197 	umadt_obj_t *p_umadt_obj = (umadt_obj_t *) p_vend;
198 
199 	OSM_LOG_ENTER(p_log);
200 
201 	p_umadt_obj->p_log = p_log;
202 	p_umadt_obj->timeout = timeout;
203 
204 	p_umadt_obj->umadt_handle = dlopen("libibt.so", RTLD_NOW);
205 
206 	if (!p_umadt_obj->umadt_handle) {
207 		printf("Could not load libibt.so <%s>\n", dlerror());
208 		return IB_ERROR;
209 	}
210 	uMadtGetInterface =
211 	    dlsym(p_umadt_obj->umadt_handle, "uMadtGetInterface");
212 	if ((error = dlerror()) != NULL) {
213 		printf("Could not resolve symbol uMadtGetInterface ERROR<%s>\n",
214 		       error);
215 		return IB_ERROR;
216 	}
217 
218 	Status = (*uMadtGetInterface) (&p_umadt_obj->uMadtInterface);
219 	if (Status != FSUCCESS) {
220 		printf(" Error in getting uMADT interface ERROR<%d>\n", Status);
221 		return IB_ERROR;
222 	}
223 
224 	/*  Initialize the register list and register list lock */
225 	cl_qlist_init(&p_umadt_obj->register_list);
226 
227 	cl_spinlock_construct(&p_umadt_obj->register_lock);
228 	CL_ASSERT(cl_spinlock_init(&p_umadt_obj->register_lock) == CL_SUCCESS);
229 	p_umadt_obj->init_done = TRUE;
230 	printf("*****SUCCESS*****\n");
231 
232 	OSM_LOG_EXIT(p_log);
233 	return IB_SUCCESS;
234 
235 }
236 
237 /* //////////////////////////////////////////////////////////////////////// */
238 /*  See VendorAbstractMadIntf.h for info */
239 /* //////////////////////////////////////////////////////////////////////// */
240 ib_api_status_t
osm_vendor_get_ports(IN osm_vendor_t * const p_vend,IN ib_net64_t * const p_guids,IN uint32_t * const p_num_guids)241 osm_vendor_get_ports(IN osm_vendor_t * const p_vend,
242 		     IN ib_net64_t * const p_guids,
243 		     IN uint32_t * const p_num_guids)
244 {
245 	char *error = NULL;
246 	PIBT_GET_INTERFACE pfnIbtGetInterface;
247 	PIBT_INIT pfnIbtInitFunc;
248 
249 	FSTATUS Status;
250 	uint32_t caCount, caGuidCount;
251 	IB_CA_ATTRIBUTES caAttributes;
252 	IB_HANDLE caHandle;
253 	uint32_t i;
254 	IB_PORT_ATTRIBUTES *pPortAttributesList;
255 	EUI64 CaGuidArray[8];
256 	void *context;
257 	uint64_t *p_port_guid;
258 	uint32_t free_guids;
259 
260 	umadt_obj_t *p_umadt_obj = (umadt_obj_t *) p_vend;
261 
262 	OSM_LOG_ENTER(p_umadt_obj->p_log);
263 
264 	CL_ASSERT(p_guids);
265 	CL_ASSERT(p_num_guids);
266 
267 	pfnIbtInitFunc =
268 	    (PIBT_INIT) dlsym(p_umadt_obj->umadt_handle, "IbtInit");
269 
270 	if (!pfnIbtInitFunc) {
271 		printf("Error getting IbtInit function address.\n");
272 		return IB_ERROR;
273 	}
274 
275 	(*pfnIbtInitFunc) ();
276 
277 	pfnIbtGetInterface =
278 	    (PIBT_GET_INTERFACE) dlsym(p_umadt_obj->umadt_handle,
279 				       "IbtGetInterface");
280 
281 	if (!pfnIbtGetInterface || (error = dlerror()) != NULL) {
282 		printf("Error getting IbtGetInterface function address.<%s>\n",
283 		       error);
284 		return FALSE;
285 	}
286 	(*pfnIbtGetInterface) (&p_umadt_obj->IbtInterface);
287 
288 	caGuidCount = 8;
289 	Status =
290 	    p_umadt_obj->IbtInterface.GetCaGuidArray(&caGuidCount,
291 						     &CaGuidArray[0]);
292 
293 	if ((Status != FSUCCESS) || (caGuidCount == 0)) {
294 		return FALSE;
295 	}
296 
297 	free_guids = *p_num_guids;
298 	p_port_guid = p_guids;
299 
300 	/* query each ca & copy its info into callers buffer */
301 	for (caCount = 0; caCount < caGuidCount; caCount++) {
302 		memset(&caAttributes, 0, sizeof(IB_CA_ATTRIBUTES));
303 
304 		/* Open the CA */
305 		Status = p_umadt_obj->IbtInterface.Vpi.OpenCA(CaGuidArray[caCount], NULL,	/*  CACompletionCallback */
306 							      NULL,	/*  AsyncEventCallback */
307 							      NULL, &caHandle);
308 		if (Status != FSUCCESS) {
309 			return IB_ERROR;
310 		}
311 
312 		Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
313 							       &caAttributes,
314 							       &context);
315 
316 		if (Status != FSUCCESS) {
317 			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
318 			return IB_ERROR;
319 		}
320 
321 		if (caAttributes.Ports > free_guids) {
322 			*p_num_guids = 0;
323 			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
324 			return IB_INSUFFICIENT_MEMORY;
325 		}
326 
327 		pPortAttributesList =
328 		    (IB_PORT_ATTRIBUTES *) malloc(caAttributes.
329 						  PortAttributesListSize);
330 
331 		if (pPortAttributesList == NULL) {
332 			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
333 			*p_num_guids = 0;
334 			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
335 			return IB_INSUFFICIENT_MEMORY;
336 		}
337 
338 		memset(pPortAttributesList, 0,
339 		       caAttributes.PortAttributesListSize);
340 
341 		caAttributes.PortAttributesList = pPortAttributesList;
342 
343 		Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
344 							       &caAttributes,
345 							       &context);
346 
347 		if (Status != FSUCCESS) {
348 			p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
349 			*p_num_guids = 0;
350 			memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
351 			return IB_ERROR;
352 		}
353 
354 		pPortAttributesList = caAttributes.PortAttributesList;
355 
356 		for (i = 0; i < caAttributes.Ports; i++) {
357 			*(p_port_guid) =
358 			    cl_hton64((uint64_t) pPortAttributesList->GUID);
359 			pPortAttributesList = pPortAttributesList->Next;
360 			p_port_guid++;
361 		}
362 		free(caAttributes.PortAttributesList);
363 		p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
364 
365 		free_guids = free_guids - caAttributes.Ports;
366 
367 	}
368 	*p_num_guids = *p_num_guids - free_guids;
369 	return IB_SUCCESS;
370 }
371 
372 /* //////////////////////////////////////////////////////////////////////// */
373 /*  See VendorAbstractMadIntf.h for info */
374 /* //////////////////////////////////////////////////////////////////////// */
osm_vendor_get(IN osm_bind_handle_t h_bind,IN const uint32_t mad_size,IN osm_vend_wrap_t * p_vend_wrap)375 ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
376 			 IN const uint32_t mad_size,
377 			 IN osm_vend_wrap_t * p_vend_wrap)
378 {
379 	/* FSTATUS Status; */
380 	/* uint32_t mad_count = 0; */
381 	/* MadtStruct *p_madt_struct; */
382 	mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) h_bind;
383 	umadt_obj_t *p_umadt_obj = p_mad_bind_info->p_umadt_obj;
384 	ib_mad_t *p_mad;
385 	OSM_LOG_ENTER(p_umadt_obj->p_log);
386 
387 	CL_ASSERT(h_bind);
388 
389 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
390 
391 	/*  Sanity check */
392 	CL_ASSERT(p_umadt_obj->init_done);
393 	CL_ASSERT(p_vend_wrap);
394 	CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
395 
396 #if 0
397 	mad_count = 1;
398 	Status =
399 	    p_umadt_obj->uMadtInterface.uMadtGetSendMad(p_mad_bind_info->
400 							umadt_handle,
401 							&mad_count,
402 							&p_madt_struct);
403 
404 	if (Status != FSUCCESS || p_madt_struct == NULL) {
405 		p_vend_wrap->p_madt_struct = NULL;
406 		return NULL;
407 	}
408 	p_vend_wrap->p_madt_struct = p_madt_struct;
409 	p_vend_wrap->direction = SEND;
410 	return ((ib_mad_t *) & p_madt_struct->IBMad);
411 #endif				/*  0 */
412 	p_mad = (ib_mad_t *) malloc(mad_size);
413 	if (!p_mad) {
414 		p_vend_wrap->p_madt_struct = NULL;
415 		return NULL;
416 	}
417 
418 	memset(p_mad, 0, mad_size);
419 
420 	p_vend_wrap->p_madt_struct = NULL;
421 	p_vend_wrap->direction = SEND;
422 	p_vend_wrap->size = mad_size;
423 	return (p_mad);
424 
425 }
426 
427 /* //////////////////////////////////////////////////////////////////////// */
428 /*  See VendorAbstractMadIntf.h for info */
429 /* //////////////////////////////////////////////////////////////////////// */
430 void
osm_vendor_put(IN osm_bind_handle_t h_bind,IN osm_vend_wrap_t * const p_vend_wrap,IN ib_mad_t * const p_mad)431 osm_vendor_put(IN osm_bind_handle_t h_bind,
432 	       IN osm_vend_wrap_t * const p_vend_wrap,
433 	       IN ib_mad_t * const p_mad)
434 {
435 
436 	FSTATUS Status;
437 
438 	mad_bind_info_t *p_mad_bind_info;
439 	umadt_obj_t *p_umadt_obj;
440 
441 	/*  */
442 	/*  Validate the vendor mad transport handle */
443 	/*  */
444 	CL_ASSERT(h_bind);
445 	p_mad_bind_info = (mad_bind_info_t *) h_bind;
446 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
447 
448 	/*  sanity check */
449 	CL_ASSERT(p_umadt_obj->init_done);
450 	CL_ASSERT(h_bind);
451 	CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
452 	CL_ASSERT(p_vend_wrap);
453 	/* CL_ASSERT( (ib_mad_t*)&p_vend_wrap->p_madt_struct->IBMad == p_mad ); */
454 
455 	/*  Release the MAD based on the direction of the MAD */
456 	if (p_vend_wrap->direction == SEND) {
457 		/*  */
458 		/* For a send the PostSend released the MAD with Umadt. Simply dealloacte the */
459 		/* local memory that was allocated on the osm_vendor_get() call. */
460 		/*  */
461 		free(p_mad);
462 #if 0
463 		Status =
464 		    p_umadt_obj->uMadtInterface.
465 		    uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
466 					p_vend_wrap->p_madt_struct);
467 		if (Status != FSUCCESS) {
468 			/* printf("uMadtReleaseSendMad: Status  = <%d>\n", Status); */
469 			return;
470 		}
471 #endif
472 	} else if (p_vend_wrap->direction == RECEIVE) {
473 		CL_ASSERT((ib_mad_t *) & p_vend_wrap->p_madt_struct->IBMad ==
474 			  p_mad);
475 		Status =
476 		    p_umadt_obj->uMadtInterface.
477 		    uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle,
478 					p_vend_wrap->p_madt_struct);
479 		if (Status != FSUCCESS) {
480 			/* printf("uMadtReleaseRecvMad Status=<%d>\n", Status); */
481 			return;
482 		}
483 	} else {
484 		return;
485 	}
486 	return;
487 }
488 
489 /* //////////////////////////////////////////////////////////////////////// */
490 /*  See VendorAbstractMadIntf.h for info */
491 /* //////////////////////////////////////////////////////////////////////// */
492 ib_api_status_t
osm_vendor_send(IN osm_bind_handle_t h_bind,IN osm_vend_wrap_t * const p_vend_wrap,IN osm_mad_addr_t * const p_mad_addr,IN ib_mad_t * const p_mad,IN void * transaction_context,IN boolean_t const resp_expected)493 osm_vendor_send(IN osm_bind_handle_t h_bind,
494 		IN osm_vend_wrap_t * const p_vend_wrap,
495 		IN osm_mad_addr_t * const p_mad_addr,
496 		IN ib_mad_t * const p_mad,
497 		IN void *transaction_context, IN boolean_t const resp_expected)
498 {
499 	FSTATUS Status;
500 
501 	MadAddrStruct destAddr = { 0 };
502 
503 	mad_bind_info_t *p_mad_bind_info;
504 	trans_context_t *p_trans_context;
505 
506 	umadt_obj_t *p_umadt_obj = NULL;
507 
508 	uint32_t mad_count = 0;
509 	MadtStruct *p_madt_struct = NULL;
510 	uint32_t i;
511 	uint32_t num_mads = 0;
512 	uint32_t seg_num = 0;
513 	uint8_t *p_frag_data = NULL;
514 	ib_sa_mad_t_vM3 *p_sa_mad = NULL;
515 
516 	CL_ASSERT(h_bind);
517 	p_mad_bind_info = (mad_bind_info_t *) h_bind;
518 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
519 
520 	/*  sanity check */
521 	CL_ASSERT(p_umadt_obj);
522 	CL_ASSERT(p_umadt_obj->init_done);
523 	CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
524 	CL_ASSERT(p_vend_wrap);
525 	CL_ASSERT(p_mad_addr);
526 	CL_ASSERT(p_mad);
527 	/* CL_ASSERT( (ib_mad_t*)&p_vend_wrap->p_madt_struct->IBMad == p_mad ); */
528 
529 	/*  */
530 	/*  based on the class, fill out the address info */
531 	/*  */
532 	destAddr.DestLid = p_mad_addr->dest_lid;
533 	destAddr.PathBits = p_mad_addr->path_bits;
534 	destAddr.StaticRate = p_mad_addr->static_rate;
535 
536 	if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
537 	    p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
538 		CL_ASSERT(p_mad_addr->addr_type.smi.source_lid);
539 		destAddr.AddrType.Smi.SourceLid =
540 		    p_mad_addr->addr_type.smi.source_lid;
541 	} else {
542 		destAddr.AddrType.Gsi.RemoteQpNumber =
543 		    p_mad_addr->addr_type.gsi.remote_qp;
544 		destAddr.AddrType.Gsi.RemoteQkey =
545 		    p_mad_addr->addr_type.gsi.remote_qkey;
546 		destAddr.AddrType.Gsi.PKey = OSM_DEFAULT_PKEY;
547 		destAddr.AddrType.Gsi.ServiceLevel =
548 		    p_mad_addr->addr_type.gsi.service_level;
549 		destAddr.AddrType.Gsi.GlobalRoute =
550 		    p_mad_addr->addr_type.gsi.global_route;
551 		/* destAddr.AddrType.Gsi.GRHInfo = p_mad_addr->addr_type.gsi.grh_info; */
552 	}
553 	p_mad->trans_id = cl_ntoh64(p_mad->trans_id) << 24;
554 
555 	/*  */
556 	/*  Create a transaction context for this send and save the TID and client context. */
557 	/*  */
558 
559 	if (resp_expected) {
560 		p_trans_context = malloc(sizeof(trans_context_t));
561 		CL_ASSERT(p_trans_context);
562 
563 		memset(p_trans_context, 0, sizeof(trans_context_t));
564 		p_trans_context->trans_id = p_mad->trans_id;
565 		p_trans_context->context = transaction_context;
566 		p_trans_context->sent_time = cl_get_time_stamp();
567 
568 		cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
569 		cl_qlist_insert_tail(&p_mad_bind_info->trans_ctxt_list,
570 				     &p_trans_context->list_item);
571 		cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
572 	}
573 
574 	if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
575 	    p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
576 		/*  Get one mad from uMadt */
577 		mad_count = 1;
578 		Status =
579 		    p_umadt_obj->uMadtInterface.
580 		    uMadtGetSendMad(p_mad_bind_info->umadt_handle, &mad_count,
581 				    &p_madt_struct);
582 
583 		if (Status != FSUCCESS || p_madt_struct == NULL) {
584 			return IB_ERROR;
585 		}
586 
587 		/*  No Segmentation required */
588 		memcpy(&p_madt_struct->IBMad, p_mad, MAD_BLOCK_SIZE);
589 
590 		/*  Post the MAD */
591 
592 		Status =
593 		    p_umadt_obj->uMadtInterface.uMadtPostSend(p_mad_bind_info->
594 							      umadt_handle,
595 							      p_madt_struct,
596 							      &destAddr);
597 		if (Status != FSUCCESS) {
598 			printf("uMadtPostSendMad: Status  = <%d>\n", Status);
599 			return IB_ERROR;
600 		}
601 
602 		/*  Release send MAD */
603 		Status =
604 		    p_umadt_obj->uMadtInterface.
605 		    uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
606 					p_madt_struct);
607 		if (Status != FSUCCESS) {
608 			printf("uMadtReleaseSendMad: Status  = <%d>\n", Status);
609 			return IB_ERROR;
610 		}
611 	} else {
612 
613 		/*  */
614 		/*  Segment the MAD, get the required send mads from uMadt and post the MADs. */
615 		/*  */
616 		uint32_t payload_len;
617 
618 		payload_len =
619 		    cl_ntoh32(((ib_sa_mad_t_vM3 *) p_mad)->payload_len);
620 		num_mads = payload_len / IB_SA_DATA_SIZE;
621 		if (payload_len % IB_SA_DATA_SIZE != 0) {
622 			num_mads++;	/*  Get one additional mad for the remainder */
623 		}
624 		for (i = 0; i < num_mads; i++) {
625 			/*  Get one mad from uMadt */
626 			mad_count = 1;
627 			Status =
628 			    p_umadt_obj->uMadtInterface.
629 			    uMadtGetSendMad(p_mad_bind_info->umadt_handle,
630 					    &mad_count, &p_madt_struct);
631 
632 			if (Status != FSUCCESS || p_madt_struct == NULL) {
633 				return IB_ERROR;
634 			}
635 			/*  Copy client MAD into uMadt's MAD. */
636 			if (i == 0) {	/*  First Packet */
637 				/*  Since this is the first MAD, copy the entire MAD_SIZE */
638 				memcpy(&p_madt_struct->IBMad, p_mad,
639 				       MAD_BLOCK_SIZE);
640 
641 				p_frag_data =
642 				    (uint8_t *) p_mad + MAD_BLOCK_SIZE;
643 
644 				p_sa_mad =
645 				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
646 				if (num_mads == 1) {	/*  Only one Packet */
647 					p_sa_mad->seg_num = 0;
648 					p_sa_mad->frag_flag = 5;	/*  Set bit 0 for first pkt and b4 for last pkt */
649 					/*  the payload length gets copied with the mad header above */
650 				} else {	/*  More than one packet in this response */
651 
652 					seg_num = 1;
653 					p_sa_mad->seg_num =
654 					    cl_ntoh32(seg_num++);
655 					p_sa_mad->frag_flag = 1;	/*  Set bit 0 for first pkt */
656 					/*  the payload length gets copied with the mad header above */
657 				}
658 
659 			} else if (i < num_mads - 1) {	/*  Not last packet */
660 				/*  First copy only the header */
661 				memcpy(&p_madt_struct->IBMad, p_mad,
662 				       IB_SA_MAD_HDR_SIZE);
663 				/*  Set the relevant fields in the SA_MAD_HEADER */
664 				p_sa_mad =
665 				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
666 				p_sa_mad->payload_len =
667 				    cl_ntoh32(IB_SA_DATA_SIZE);
668 				p_sa_mad->seg_num = cl_ntoh32(seg_num++);
669 				p_sa_mad->frag_flag = 0;
670 				/*  Now copy the fragmented data */
671 				memcpy(((uint8_t *) & p_madt_struct->IBMad) +
672 				       IB_SA_MAD_HDR_SIZE, p_frag_data,
673 				       IB_SA_DATA_SIZE);
674 				p_frag_data = p_frag_data + IB_SA_DATA_SIZE;
675 
676 			} else if (i == num_mads - 1) {	/*  Last packet */
677 				/*  First copy only the header */
678 				memcpy(&p_madt_struct->IBMad, p_mad,
679 				       IB_SA_MAD_HDR_SIZE);
680 				/*  Set the relevant fields in the SA_MAD_HEADER */
681 				p_sa_mad =
682 				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
683 				p_sa_mad->seg_num = cl_ntoh32(seg_num++);
684 				p_sa_mad->frag_flag = 4;	/*  Set Bit 2 for last pkt */
685 				p_sa_mad->payload_len =
686 				    cl_ntoh32(cl_ntoh32
687 					      (((ib_sa_mad_t_vM3 *) p_mad)->
688 					       payload_len) % IB_SA_DATA_SIZE);
689 				/*  Now copy the fragmented data */
690 				memcpy((((uint8_t *) & p_madt_struct->IBMad)) +
691 				       IB_SA_MAD_HDR_SIZE, p_frag_data,
692 				       cl_ntoh32(p_sa_mad->payload_len));
693 				p_frag_data = p_frag_data + IB_SA_DATA_SIZE;
694 
695 			}
696 			/*  Post the MAD */
697 			Status =
698 			    p_umadt_obj->uMadtInterface.
699 			    uMadtPostSend(p_mad_bind_info->umadt_handle,
700 					  p_madt_struct, &destAddr);
701 			if (Status != FSUCCESS) {
702 				printf("uMadtPostSendMad: Status  = <%d>\n",
703 				       Status);
704 				return IB_ERROR;
705 			}
706 
707 			/*  Release send MAD */
708 			Status =
709 			    p_umadt_obj->uMadtInterface.
710 			    uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
711 						p_madt_struct);
712 			if (Status != FSUCCESS) {
713 				printf("uMadtReleaseSendMad: Status  = <%d>\n",
714 				       Status);
715 				return IB_ERROR;
716 			}
717 		}
718 	}
719 	return (IB_SUCCESS);
720 }
721 
722 /* //////////////////////////////////////////////////////////////////////// */
723 /*  See VendorAbstractMadIntf.h for info */
724 /* //////////////////////////////////////////////////////////////////////// */
725 
726 osm_bind_handle_t
osm_vendor_bind(IN osm_vendor_t * const p_vend,IN osm_bind_info_t * const p_osm_bind_info,IN osm_mad_pool_t * const p_mad_pool,IN osm_vend_mad_recv_callback_t mad_recv_callback,IN void * context)727 osm_vendor_bind(IN osm_vendor_t * const p_vend,
728 		IN osm_bind_info_t * const p_osm_bind_info,
729 		IN osm_mad_pool_t * const p_mad_pool,
730 		IN osm_vend_mad_recv_callback_t mad_recv_callback,
731 		IN void *context)
732 {
733 	cl_status_t cl_status;
734 	FSTATUS Status;		/*  GEN1 Status for Umadt */
735 
736 	mad_bind_info_t *p_mad_bind_info;
737 	RegisterClassStruct *p_umadt_reg_class;
738 
739 	umadt_obj_t *p_umadt_obj;
740 	OSM_LOG_ENTER(((umadt_obj_t *) p_vend)->p_log);
741 
742 	CL_ASSERT(p_vend);
743 
744 	p_umadt_obj = (umadt_obj_t *) p_vend;
745 
746 	/*  Sanity check */
747 	CL_ASSERT(p_umadt_obj->init_done);
748 	CL_ASSERT(p_osm_bind_info);
749 	CL_ASSERT(p_mad_pool);
750 	CL_ASSERT(mad_recv_callback);
751 
752 	/*  Allocate memory for registering the handle. */
753 	p_mad_bind_info = (mad_bind_info_t *) malloc(sizeof(*p_mad_bind_info));
754 	if (p_mad_bind_info) {
755 		memset(p_mad_bind_info, 0, sizeof(*p_mad_bind_info));
756 		p_umadt_reg_class = &p_mad_bind_info->umadt_reg_class;
757 	}
758 	p_umadt_reg_class->PortGuid = cl_ntoh64(p_osm_bind_info->port_guid);
759 	p_umadt_reg_class->ClassId = p_osm_bind_info->mad_class;
760 	p_umadt_reg_class->ClassVersion = p_osm_bind_info->class_version;
761 	p_umadt_reg_class->isResponder = p_osm_bind_info->is_responder;
762 	p_umadt_reg_class->isTrapProcessor = p_osm_bind_info->is_trap_processor;
763 	p_umadt_reg_class->isReportProcessor =
764 	    p_osm_bind_info->is_report_processor;
765 	p_umadt_reg_class->SendQueueSize = p_osm_bind_info->send_q_size;
766 	p_umadt_reg_class->RecvQueueSize = p_osm_bind_info->recv_q_size;
767 	p_umadt_reg_class->NotifySendCompletion = TRUE;
768 
769 	p_mad_bind_info->p_umadt_obj = p_umadt_obj;
770 	p_mad_bind_info->p_mad_pool = p_mad_pool;
771 	p_mad_bind_info->mad_recv_callback = mad_recv_callback;
772 	p_mad_bind_info->client_context = context;
773 
774 	/*  register with Umadt for MAD interface */
775 	Status = p_umadt_obj->uMadtInterface.uMadtRegister(p_umadt_reg_class,
776 							   &p_mad_bind_info->
777 							   umadt_handle);
778 	if (Status != FSUCCESS) {
779 		free(p_mad_bind_info);
780 		OSM_LOG_EXIT(p_umadt_obj->p_log);
781 		return (OSM_BIND_INVALID_HANDLE);
782 	}
783 	CL_ASSERT(p_mad_bind_info->umadt_handle);
784 	/*  */
785 	/*  Start a worker thread to process receives. */
786 	/*  */
787 	cl_thread_construct(&p_mad_bind_info->recv_processor_thread);
788 	cl_status = cl_thread_init(&p_mad_bind_info->recv_processor_thread,
789 				   __mad_recv_processor,
790 				   (void *)p_mad_bind_info, "mad_recv_worker");
791 	CL_ASSERT(cl_status == CL_SUCCESS);
792 
793 	cl_qlist_init(&p_mad_bind_info->trans_ctxt_list);
794 	cl_spinlock_construct(&p_mad_bind_info->trans_ctxt_lock);
795 	cl_spinlock_init(&p_mad_bind_info->trans_ctxt_lock);
796 	cl_spinlock_construct(&p_mad_bind_info->timeout_list_lock);
797 	cl_spinlock_init(&p_mad_bind_info->timeout_list_lock);
798 
799 	cl_status = cl_timer_init(&p_mad_bind_info->timeout_timer,
800 				  __osm_vendor_timer_callback,
801 				  (void *)p_mad_bind_info);
802 	CL_ASSERT(cl_status == CL_SUCCESS);
803 	cl_qlist_init(&p_mad_bind_info->timeout_list);
804 	/*  */
805 	/*  Insert the mad_reg_struct in list and return pointer to it as the handle */
806 	/*  */
807 	cl_spinlock_acquire(&p_umadt_obj->register_lock);
808 
809 	cl_qlist_insert_head(&p_umadt_obj->register_list,
810 			     &p_mad_bind_info->list_item);
811 
812 	cl_spinlock_release(&p_umadt_obj->register_lock);
813 
814 	/*
815 	   A timeout value of 0 means disable timeouts.
816 	 */
817 	if (p_umadt_obj->timeout) {
818 		cl_timer_start(&p_mad_bind_info->timeout_timer,
819 			       DEFAULT_TIMER_INTERVAL_MSEC);
820 	}
821 
822 	OSM_LOG_EXIT(p_umadt_obj->p_log);
823 	return ((osm_bind_handle_t) p_mad_bind_info);
824 }
825 
826 /**********************************************************************
827  **********************************************************************/
osm_vendor_unbind(IN osm_bind_handle_t h_bind)828 void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
829 {
830 	mad_bind_info_t *p_mad_bind_info;
831 	umadt_obj_t *p_umadt_obj;
832 	cl_list_item_t *p_list_item, *p_next_list_item;
833 
834 	CL_ASSERT(h_bind);
835 	p_mad_bind_info = (mad_bind_info_t *) h_bind;
836 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
837 
838 	/*  sanity check */
839 	CL_ASSERT(p_umadt_obj);
840 	CL_ASSERT(p_umadt_obj->init_done);
841 	CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
842 
843 	p_umadt_obj->uMadtInterface.uMadtDestroy(&p_mad_bind_info->
844 						 umadt_handle);
845 	cl_timer_destroy(&p_mad_bind_info->timeout_timer);
846 	cl_thread_destroy(&p_mad_bind_info->recv_processor_thread);
847 
848 	cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
849 	p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list);
850 	while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
851 		p_next_list_item = cl_qlist_next(p_list_item);
852 		cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
853 				     p_list_item);
854 		free(p_list_item);
855 		p_list_item = p_next_list_item;
856 	}
857 	cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
858 
859 	cl_spinlock_acquire(&p_mad_bind_info->timeout_list_lock);
860 	p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list);
861 	while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) {
862 		p_next_list_item = cl_qlist_next(p_list_item);
863 		cl_qlist_remove_item(&p_mad_bind_info->timeout_list,
864 				     p_list_item);
865 		free(p_list_item);
866 		p_list_item = p_next_list_item;
867 	}
868 	cl_spinlock_release(&p_mad_bind_info->timeout_list_lock);
869 
870 	free(p_mad_bind_info);
871 }
872 
873 /**********************************************************************
874  **********************************************************************/
__mad_recv_processor(IN void * context)875 void __mad_recv_processor(IN void *context)
876 {
877 	mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) context;
878 	umadt_obj_t *p_umadt_obj;
879 	osm_madw_t *p_osm_madw = NULL;
880 	osm_vend_wrap_t *p_vend_wrap = NULL;
881 	osm_mad_addr_t osm_mad_addr = { 0 };
882 	cl_list_item_t *p_list_item;
883 	void *transaction_context;
884 
885 	FSTATUS Status;
886 	MadtStruct *pRecvMad = NULL;
887 	MadWorkCompletion *pRecvCmp = NULL;
888 
889 	CL_ASSERT(context);
890 
891 	p_mad_bind_info = (mad_bind_info_t *) context;
892 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
893 	/*  PollFor a completion */
894 	/*  if FNOTFOND, then wait for a completion then again poll and return the MAD */
895 	while (1) {
896 		Status =
897 		    p_umadt_obj->uMadtInterface.
898 		    uMadtPollForRecvCompletion(p_mad_bind_info->umadt_handle,
899 					       &pRecvMad, &pRecvCmp);
900 		if (Status != FSUCCESS) {
901 			if (Status == FNOT_FOUND) {
902 				/* Wait for a completion */
903 				Status = p_umadt_obj->uMadtInterface.uMadtWaitForAnyCompletion(p_mad_bind_info->umadt_handle, RECV_COMPLETION, 0x5000);	/* 5 sec timeout */
904 
905 				if (Status == FTIMEOUT) {
906 					continue;
907 				}
908 				CL_ASSERT(Status == FSUCCESS);
909 
910 				Status =
911 				    p_umadt_obj->uMadtInterface.
912 				    uMadtPollForRecvCompletion(p_mad_bind_info->
913 							       umadt_handle,
914 							       &pRecvMad,
915 							       &pRecvCmp);
916 				if (Status != FSUCCESS) {
917 					printf
918 					    (" mad_recv_worker: Error in PollForRecv returning <%x>\n",
919 					     Status);
920 					CL_ASSERT(0);
921 				}
922 			} else {
923 				printf
924 				    ("uMadtPollForRecvCompletion Status=<%x>\n",
925 				     Status);
926 				CL_ASSERT(0);
927 			}
928 		}
929 		CL_ASSERT(pRecvMad);
930 		CL_ASSERT(pRecvCmp);
931 
932 		if (((ib_sa_mad_t_vM3 *) (&pRecvMad->IBMad))->frag_flag & 0x20) {
933 			/*  Ignore the ACK packet */
934 			Status =
935 			    p_umadt_obj->uMadtInterface.
936 			    uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle,
937 						pRecvMad);
938 			continue;
939 		}
940 		/*  */
941 		/*  Extract the return address to pass it on to the client */
942 		/*  */
943 		osm_mad_addr.dest_lid = pRecvCmp->AddressInfo.DestLid;
944 		osm_mad_addr.path_bits = pRecvCmp->AddressInfo.PathBits;
945 		osm_mad_addr.static_rate = pRecvCmp->AddressInfo.StaticRate;
946 
947 		if (p_mad_bind_info->umadt_reg_class.ClassId ==
948 		    IB_MCLASS_SUBN_LID
949 		    || p_mad_bind_info->umadt_reg_class.ClassId ==
950 		    IB_MCLASS_SUBN_DIR) {
951 			osm_mad_addr.addr_type.smi.source_lid =
952 			    pRecvCmp->AddressInfo.AddrType.Smi.SourceLid;
953 			/* osm_mad_addr.addr_type.smi.port_num = pRecvCmp->AddressInfo.AddrType.Smi.PortNumber; */
954 		} else {
955 			osm_mad_addr.addr_type.gsi.remote_qp =
956 			    pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQpNumber;
957 			osm_mad_addr.addr_type.gsi.remote_qkey =
958 			    pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQkey;
959 			osm_mad_addr.addr_type.gsi.pkey_ix = 0;
960 			osm_mad_addr.addr_type.gsi.service_level =
961 			    pRecvCmp->AddressInfo.AddrType.Gsi.ServiceLevel;
962 			osm_mad_addr.addr_type.gsi.global_route =
963 			    pRecvCmp->AddressInfo.AddrType.Gsi.GlobalRoute;
964 			/* osm_mad_addr.addr_type.gsi.grh_info = pRecvCmp->AddressInfo.AddrType.Gsi.GRHInfo; */
965 		}
966 		p_osm_madw =
967 		    osm_mad_pool_get_wrapper(p_mad_bind_info->p_mad_pool,
968 					     p_mad_bind_info, MAD_BLOCK_SIZE,
969 					     (ib_mad_t *) & pRecvMad->IBMad,
970 					     &osm_mad_addr);
971 		CL_ASSERT(p_osm_madw);
972 		p_vend_wrap = osm_madw_get_vend_ptr(p_osm_madw);
973 		CL_ASSERT(p_vend_wrap);
974 		p_vend_wrap->p_madt_struct = pRecvMad;
975 		p_vend_wrap->direction = RECEIVE;
976 
977 		osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
978 			"__mad_recv_processor: "
979 			"Received data p_osm_madw[0x%p].\n", p_osm_madw);
980 
981 		/*  */
982 		/*  Do TID Processing. */
983 		/*  */
984 		/*  If R bit is set swap the TID */
985 
986 		cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
987 		p_list_item =
988 		    cl_qlist_find_from_head(&p_mad_bind_info->trans_ctxt_list,
989 					    __match_tid_context,
990 					    &p_osm_madw->p_mad->trans_id);
991 
992 		if (p_list_item ==
993 		    cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
994 			transaction_context = NULL;
995 		} else {
996 			transaction_context =
997 			    ((trans_context_t *) p_list_item)->context;
998 			cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
999 					     p_list_item);
1000 			free(p_list_item);
1001 		}
1002 		cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
1003 		((ib_mad_t *) p_osm_madw->p_mad)->trans_id =
1004 		    cl_ntoh64(p_osm_madw->p_mad->trans_id >> 24);
1005 		osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
1006 			"__mad_recv_processor: "
1007 			"Received data p_osm_madw [0x%p]" "\n\t\t\t\tTID[0x%"
1008 			PRIx64 ", context[%p]. \n", p_osm_madw,
1009 			((ib_mad_t *) p_osm_madw->p_mad)->trans_id,
1010 			transaction_context);
1011 
1012 		(*(p_mad_bind_info->mad_recv_callback)) (p_osm_madw,
1013 							 p_mad_bind_info->
1014 							 client_context,
1015 							 transaction_context);
1016 
1017 	}
1018 }
1019 
1020 /**********************************************************************
1021  **********************************************************************/
1022 
1023 cl_status_t
__match_tid_context(const cl_list_item_t * const p_list_item,void * context)1024 __match_tid_context(const cl_list_item_t * const p_list_item, void *context)
1025 {
1026 	if (((trans_context_t *) p_list_item)->trans_id ==
1027 	    *((uint64_t *) context))
1028 		return CL_SUCCESS;
1029 	return CL_NOT_FOUND;
1030 }
1031 
1032 /**********************************************************************
1033  **********************************************************************/
1034 
__valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info)1035 boolean_t __valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info)
1036 {
1037 
1038 	umadt_obj_t *p_umadt_obj;
1039 
1040 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
1041 
1042 	cl_spinlock_acquire(&p_umadt_obj->register_lock);
1043 	if (!cl_is_item_in_qlist(&p_umadt_obj->register_list,
1044 				 &p_mad_bind_info->list_item)) {
1045 		cl_spinlock_release(&p_umadt_obj->register_lock);
1046 		return FALSE;
1047 	}
1048 	cl_spinlock_release(&p_umadt_obj->register_lock);
1049 	return TRUE;
1050 }
1051 
__osm_vendor_timer_callback(IN void * context)1052 void __osm_vendor_timer_callback(IN void *context)
1053 {
1054 	uint64_t current_time;
1055 	mad_bind_info_t *p_mad_bind_info;
1056 	umadt_obj_t *p_umadt_obj;
1057 	uint32_t timeout;
1058 
1059 	cl_list_item_t *p_list_item, *p_next_list_item;
1060 
1061 	CL_ASSERT(context);
1062 
1063 	p_mad_bind_info = (mad_bind_info_t *) context;
1064 	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
1065 	timeout = p_umadt_obj->timeout * 1000;
1066 
1067 	current_time = cl_get_time_stamp();
1068 
1069 	cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
1070 
1071 	p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list);
1072 	while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
1073 
1074 		p_next_list_item = cl_qlist_next(p_list_item);
1075 
1076 		/*  DEFAULT_PKT_TIMEOUT is in milli seconds */
1077 		if (current_time - ((trans_context_t *) p_list_item)->sent_time
1078 		    > timeout) {
1079 			/*  Add this transaction to the timeout_list */
1080 			cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
1081 					     p_list_item);
1082 			cl_qlist_insert_tail(&p_mad_bind_info->timeout_list,
1083 					     p_list_item);
1084 		}
1085 
1086 		p_list_item = p_next_list_item;
1087 	}
1088 
1089 	cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
1090 
1091 	p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list);
1092 	while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) {
1093 		osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
1094 			"__osm_vendor_timer_callback: "
1095 			"Timing out transaction context [0x%p].\n",
1096 			((trans_context_t *) p_list_item)->context);
1097 
1098 		(*(p_mad_bind_info->mad_recv_callback)) (NULL,
1099 							 p_mad_bind_info->
1100 							 client_context,
1101 							 ((trans_context_t *)
1102 							  p_list_item)->
1103 							 context);
1104 
1105 		p_next_list_item = cl_qlist_next(p_list_item);
1106 		cl_qlist_remove_item(&p_mad_bind_info->timeout_list,
1107 				     p_list_item);
1108 		free(p_list_item);
1109 		p_list_item = p_next_list_item;
1110 	}
1111 
1112 	cl_timer_start(&p_mad_bind_info->timeout_timer,
1113 		       DEFAULT_TIMER_INTERVAL_MSEC);
1114 
1115 }
1116 
1117 #endif				/* OSM_VENDOR_INTF_UMADT */
1118