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 #if HAVE_CONFIG_H
37 #  include <config.h>
38 #endif				/* HAVE_CONFIG_H */
39 
40 #include <math.h>
41 #include <stdlib.h>
42 #include <opensm/osm_helper.h>
43 #include <opensm/osm_log.h>
44 #include <vendor/osm_vendor.h>
45 #include <vendor/osm_vendor_api.h>
46 #include <opensm/osm_mad_pool.h>
47 
48 #if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS)
49 
50 #include <vendor/osm_vendor_mtl_transaction_mgr.h>
51 #ifdef OSM_VENDOR_INTF_MTL
52 #include <vendor/osm_mtl_bind.h>
53 #endif
54 
55 /* this is the callback function of the timer */
56 void __osm_transaction_mgr_callback(IN void *context)
57 {
58 	osm_transaction_mgr_t *trans_mgr_p;
59 	osm_vendor_t *p_vend = (osm_vendor_t *) context;
60 	cl_list_item_t *p_list_item;
61 	cl_list_item_t *p_list_next_item;
62 	osm_madw_req_t *osm_madw_req_p;
63 	uint64_t current_time;	/*  [usec] */
64 	uint32_t new_timeout;	/*  [msec] */
65 	cl_status_t cl_status;
66 	ib_mad_t *p_mad;
67 #ifdef OSM_VENDOR_INTF_MTL
68 	osm_mtl_bind_info_t *p_bind;
69 #else
70 	osm_ts_bind_info_t *p_bind;
71 #endif
72 	cl_list_t tmp_madw_p_list;	/*  this list will include all the madw_p that should be removed. */
73 	cl_list_t retry_madw_p_list;	/*  this list will include all the madw_p that were retried and need to be removed. */
74 	osm_madw_t *madw_p;
75 
76 	OSM_LOG_ENTER(p_vend->p_log);
77 
78 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
79 
80 	/*  initialize the tmp_madw_p_list */
81 	cl_list_construct(&tmp_madw_p_list);
82 	cl_status = cl_list_init(&tmp_madw_p_list, 50);
83 	if (cl_status != CL_SUCCESS) {
84 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
85 			"__osm_transaction_mgr_callback : ERROR 1000: "
86 			"Failed to create tmp_madw_p_list\n");
87 	}
88 
89 	cl_list_construct(&retry_madw_p_list);
90 	cl_status = cl_list_init(&retry_madw_p_list, 50);
91 	if (cl_status != CL_SUCCESS) {
92 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
93 			"__osm_transaction_mgr_callback : ERROR 1000: "
94 			"Failed to create retry_madw_p_list\n");
95 	}
96 
97 	current_time = cl_get_time_stamp();
98 	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
99 	p_list_item = cl_qlist_head(trans_mgr_p->madw_reqs_list_p);
100 	if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
101 		/*  the list is empty - nothing to do */
102 		cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
103 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
104 			"__osm_transaction_mgr_callback : Nothing to do\n");
105 		goto Exit;
106 	}
107 
108 	/*  non empty list: */
109 
110 	/*  get the osm_madw_req_p  */
111 	osm_madw_req_p = PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
112 
113 	while (osm_madw_req_p->waking_time <= current_time) {
114 		/*  this object was supposed to have gotten a response */
115 		/*  we need to decide if we need to retry or done with it. */
116 		if (osm_madw_req_p->retry_cnt > 0) {
117 			/*  add to the list of the retrys : */
118 			cl_list_insert_tail(&retry_madw_p_list, osm_madw_req_p);
119 
120 			/*  update wakeup time and retry count */
121 			osm_madw_req_p->waking_time =
122 			    p_vend->timeout * 1000 + cl_get_time_stamp();
123 			osm_madw_req_p->retry_cnt--;
124 
125 			/*  make sure we will get some timer call if not earlier */
126 			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
127 				"__osm_transaction_mgr_callback : Timer restart:%u\n",
128 				p_vend->timeout);
129 
130 			cl_status =
131 			    cl_timer_start(&trans_mgr_p->madw_list_timer,
132 					   p_vend->timeout);
133 
134 			/*  go to the next object and check if it also needs to be removed - didn't receive response */
135 			/*  we need to do it before we move current item to the end of the list */
136 			p_list_next_item = cl_qlist_next(p_list_item);
137 
138 			/*  remove from the head */
139 			cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
140 					     &(osm_madw_req_p->list_item));
141 
142 			/*  insert the object to the qlist and the qmap */
143 			cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p,
144 					     &(osm_madw_req_p->list_item));
145 
146 		} else {
147 			/*  go to the next object and check if it also needs to be removed - didn't receive response */
148 			p_list_next_item = cl_qlist_next(p_list_item);
149 
150 			/*  remove from the head */
151 			cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
152 					     &(osm_madw_req_p->list_item));
153 
154 			/*  add it to the tmp_madw_p_list to be removed */
155 			cl_list_insert_tail(&tmp_madw_p_list,
156 					    osm_madw_req_p->p_madw);
157 			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
158 				"__osm_transaction_mgr_callback : Found failed transaction madw: %p\n",
159 				osm_madw_req_p->p_madw);
160 		}
161 
162 		/*  Advance */
163 		p_list_item = p_list_next_item;
164 		if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
165 			/*  the list is empty - nothing to do */
166 			break;
167 		}
168 
169 		/*  get the osm_madw_req_p  */
170 		osm_madw_req_p =
171 		    PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
172 	}
173 
174 	/*  look at the current p_list_item. If it is not the end item - then we need to  */
175 	/*  re-start the timer */
176 	if (p_list_item != cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
177 		/*  get the osm_madw_req_p  */
178 		osm_madw_req_p =
179 		    PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
180 
181 		/*  we have the object that still didn't get response - re-start the timer */
182 		/*  start the timer to the timeout (in miliseconds) */
183 		new_timeout =
184 		    (osm_madw_req_p->waking_time - cl_get_time_stamp()) / 1000 +
185 		    1;
186 		cl_status =
187 		    cl_timer_start(&trans_mgr_p->madw_list_timer, new_timeout);
188 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
189 			"__osm_transaction_mgr_callback : Timer restart:%u\n",
190 			new_timeout);
191 
192 		if (cl_status != CL_SUCCESS) {
193 			osm_log(p_vend->p_log, OSM_LOG_ERROR,
194 				"__osm_transaction_mgr_callback : ERROR 1000: "
195 				"Failed to start timer\n");
196 		}
197 	}
198 	/* if not empty - retry on retry list: */
199 	if (!cl_is_list_empty(&retry_madw_p_list)) {
200 
201 		/*  remove all elements that were retried: */
202 		osm_madw_req_p =
203 		    (osm_madw_req_t
204 		     *) (cl_list_remove_head(&retry_madw_p_list));
205 		while (osm_madw_req_p != NULL) {
206 
207 			/*  resend: */
208 			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
209 				"__osm_transaction_mgr_callback : "
210 				"Retry %d of madw %p\n",
211 				OSM_DEFAULT_RETRY_COUNT -
212 				osm_madw_req_p->retry_cnt,
213 				osm_madw_req_p->p_madw);
214 
215 			/*  actually send it */
216 #ifdef OSM_VENDOR_INTF_MTL
217 			osm_mtl_send_mad((osm_mtl_bind_info_t *)
218 					 osm_madw_req_p->p_bind,
219 					 osm_madw_req_p->p_madw);
220 #else
221 			ib_api_status_t
222 			    osm_ts_send_mad(osm_ts_bind_info_t * p_bind,
223 					    osm_madw_t * const p_madw);
224 			osm_ts_send_mad((osm_ts_bind_info_t *) osm_madw_req_p->
225 					p_bind, osm_madw_req_p->p_madw);
226 #endif
227 			/*  next one */
228 			osm_madw_req_p =
229 			    (osm_madw_req_t
230 			     *) (cl_list_remove_head(&retry_madw_p_list));
231 		}
232 	}
233 
234 	/*  if the tmp_madw_p_list has elements - need to call the send_err_callback */
235 	madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list));
236 	while (madw_p != NULL) {
237 		/*  need to remove it from pool */
238 
239 		/* obtain the madw_p stored as the wrid in the send call */
240 		p_mad = osm_madw_get_mad_ptr(madw_p);
241 		p_bind = madw_p->h_bind;
242 		/*
243 		   Return any wrappers to the pool that may have been
244 		   pre-emptively allocated to handle a receive.
245 		 */
246 		if (madw_p->vend_wrap.p_resp_madw) {
247 #ifdef OSM_VENDOR_INTF_MTL
248 			osm_mad_pool_put(p_bind->p_osm_pool,
249 					 madw_p->vend_wrap.p_resp_madw);
250 #else
251 			osm_mad_pool_put(p_bind->p_osm_pool,
252 					 madw_p->vend_wrap.p_resp_madw);
253 #endif
254 			madw_p->vend_wrap.p_resp_madw = NULL;
255 		}
256 
257 		/* invoke the CB */
258 		(*(osm_vend_mad_send_err_callback_t)
259 		 (p_bind->send_err_callback)) (p_bind->client_context, madw_p);
260 		madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list));
261 	}
262 
263 Exit:
264 	OSM_LOG_EXIT(p_vend->p_log);
265 
266 }
267 
268 /*
269  * Construct and Initialize
270  */
271 
272 void osm_transaction_mgr_init(IN osm_vendor_t * const p_vend)
273 {
274 	cl_status_t cl_status;
275 	osm_transaction_mgr_t *trans_mgr_p;
276 	OSM_LOG_ENTER(p_vend->p_log);
277 
278 	CL_ASSERT(p_vend->p_transaction_mgr == NULL);
279 
280 	(osm_transaction_mgr_t *) p_vend->p_transaction_mgr =
281 	    (osm_transaction_mgr_t *) malloc(sizeof(osm_transaction_mgr_t));
282 
283 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
284 
285 	/*  construct lock object  */
286 	cl_spinlock_construct(&(trans_mgr_p->transaction_mgr_lock));
287 	CL_ASSERT(cl_spinlock_init(&(trans_mgr_p->transaction_mgr_lock)) ==
288 		  CL_SUCCESS);
289 
290 	/*  initialize the qlist */
291 	trans_mgr_p->madw_reqs_list_p =
292 	    (cl_qlist_t *) malloc(sizeof(cl_qlist_t));
293 	cl_qlist_init(trans_mgr_p->madw_reqs_list_p);
294 
295 	/*  initialize the qmap */
296 	trans_mgr_p->madw_by_tid_map_p =
297 	    (cl_qmap_t *) malloc(sizeof(cl_qmap_t));
298 	cl_qmap_init(trans_mgr_p->madw_by_tid_map_p);
299 
300 	/*  create the timer used by the madw_req_list */
301 	cl_timer_construct(&(trans_mgr_p->madw_list_timer));
302 
303 	/*  init the timer with timeout. */
304 	cl_status = cl_timer_init(&trans_mgr_p->madw_list_timer,
305 				  __osm_transaction_mgr_callback, p_vend);
306 
307 	if (cl_status != CL_SUCCESS) {
308 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
309 			"osm_transaction_mgr_init : ERROR 1000: "
310 			"Failed to initialize madw_reqs_list timer\n");
311 	}
312 	OSM_LOG_EXIT(p_vend->p_log);
313 }
314 
315 void osm_transaction_mgr_destroy(IN osm_vendor_t * const p_vend)
316 {
317 	osm_transaction_mgr_t *trans_mgr_p;
318 	cl_list_item_t *p_list_item;
319 	cl_map_item_t *p_map_item;
320 	osm_madw_req_t *osm_madw_req_p;
321 
322 	OSM_LOG_ENTER(p_vend->p_log);
323 
324 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
325 
326 	if (p_vend->p_transaction_mgr != NULL) {
327 		/* we need to get a lock */
328 		cl_spinlock_acquire(&trans_mgr_p->transaction_mgr_lock);
329 
330 		/* go over all the items in the list and remove them */
331 		p_list_item =
332 		    cl_qlist_remove_head(trans_mgr_p->madw_reqs_list_p);
333 		while (p_list_item !=
334 		       cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
335 			osm_madw_req_p = (osm_madw_req_t *) p_list_item;
336 
337 			if (osm_madw_req_p->p_madw->p_mad)
338 				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
339 					"osm_transaction_mgr_destroy: "
340 					"Found outstanding MADW:%p  TID:<0x%"
341 					PRIx64 ">.\n", osm_madw_req_p->p_madw,
342 					osm_madw_req_p->p_madw->p_mad->
343 					trans_id);
344 			else
345 				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
346 					"osm_transaction_mgr_destroy: "
347 					"Found outstanding MADW:%p  TID:UNDEFINED.\n",
348 					osm_madw_req_p->p_madw);
349 
350 			/*  each item - remove it from the map */
351 			p_map_item = &(osm_madw_req_p->map_item);
352 			cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
353 					    p_map_item);
354 			/*  free the item */
355 			free(osm_madw_req_p);
356 			p_list_item =
357 			    cl_qlist_remove_head(trans_mgr_p->madw_reqs_list_p);
358 		}
359 		/*  free the qlist and qmap */
360 		free(trans_mgr_p->madw_reqs_list_p);
361 		free(trans_mgr_p->madw_by_tid_map_p);
362 		/*  reliease and destroy the lock */
363 		cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
364 		cl_spinlock_destroy(&(trans_mgr_p->transaction_mgr_lock));
365 		/*  destroy the timer */
366 		cl_timer_trim(&trans_mgr_p->madw_list_timer, 1);
367 		cl_timer_destroy(&trans_mgr_p->madw_list_timer);
368 		/*  free the transaction_manager object */
369 		free(trans_mgr_p);
370 		trans_mgr_p = NULL;
371 	}
372 
373 	OSM_LOG_EXIT(p_vend->p_log);
374 }
375 
376 ib_api_status_t
377 osm_transaction_mgr_insert_madw(IN osm_bind_handle_t * const p_bind,
378 				IN osm_madw_t * p_madw)
379 {
380 #ifdef OSM_VENDOR_INTF_MTL
381 	osm_vendor_t *const p_vend = ((osm_mtl_bind_info_t *) p_bind)->p_vend;
382 #else
383 	osm_vendor_t *const p_vend = ((osm_ts_bind_info_t *) p_bind)->p_vend;
384 #endif
385 	osm_transaction_mgr_t *trans_mgr_p;
386 	osm_madw_req_t *osm_madw_req_p;
387 	uint64_t timeout;
388 	uint64_t waking_time;
389 	cl_status_t cl_status;
390 	uint64_t key;
391 	const ib_mad_t *mad_p = p_madw->p_mad;
392 
393 	OSM_LOG_ENTER(p_vend->p_log);
394 
395 	CL_ASSERT(mad_p);
396 
397 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
398 
399 	timeout = (uint64_t) (p_vend->timeout) * 1000;	/* change the miliseconds value of timeout to microseconds. */
400 	waking_time = timeout + cl_get_time_stamp();
401 
402 	osm_madw_req_p = (osm_madw_req_t *) malloc(sizeof(osm_madw_req_t));
403 
404 	osm_madw_req_p->p_madw = p_madw;
405 	osm_madw_req_p->waking_time = waking_time;
406 	osm_madw_req_p->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
407 	osm_madw_req_p->p_bind = p_bind;
408 
409 	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
410 		"osm_transaction_mgr_insert_madw: "
411 		"Inserting MADW:%p with waking_time: <0x%" PRIx64 ">  TID:<0x%"
412 		PRIx64 ">.\n", p_madw, waking_time, p_madw->p_mad->trans_id);
413 
414 	/* Get the lock on the manager */
415 	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
416 	/* If the list is empty - need to start the timer with timer of timeout (in miliseconds) */
417 	if (cl_is_qlist_empty(trans_mgr_p->madw_reqs_list_p)) {
418 		/*  stop the timer if it is running */
419 		cl_timer_stop(&trans_mgr_p->madw_list_timer);
420 
421 		/*  start the timer to the timeout (in miliseconds) */
422 		cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer,
423 					   p_vend->timeout);
424 		if (cl_status != CL_SUCCESS) {
425 			osm_log(p_vend->p_log, OSM_LOG_ERROR,
426 				"osm_transaction_mgr_insert_madw : ERROR 1000: "
427 				"Failed to start timer\n");
428 		}
429 	}
430 
431 	/*  insert the object to the qlist and the qmap */
432 	cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p,
433 			     &(osm_madw_req_p->list_item));
434 	/*  get the key */
435 	key = (uint64_t) mad_p->trans_id;
436 	cl_qmap_insert(trans_mgr_p->madw_by_tid_map_p, key,
437 		       &(osm_madw_req_p->map_item));
438 	cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
439 
440 	OSM_LOG_EXIT(p_vend->p_log);
441 
442 	return (IB_SUCCESS);
443 }
444 
445 ib_api_status_t
446 osm_transaction_mgr_erase_madw(IN osm_vendor_t * const p_vend,
447 			       IN ib_mad_t * p_mad)
448 {
449 	osm_transaction_mgr_t *trans_mgr_p;
450 	osm_madw_req_t *osm_madw_req_p;
451 	uint64_t key;
452 	cl_map_item_t *p_map_item;
453 	OSM_LOG_ENTER(p_vend->p_log);
454 
455 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
456 
457 	key = (uint64_t) p_mad->trans_id;
458 	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
459 		"osm_transaction_mgr_erase_madw: "
460 		"Removing TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
461 
462 	cl_spinlock_acquire(&trans_mgr_p->transaction_mgr_lock);
463 	p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key);
464 	if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) {
465 		/*  we found such an item.  */
466 		/*  get the osm_madw_req_p  */
467 		osm_madw_req_p =
468 		    PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item);
469 
470 		/*  remove the item from the qlist */
471 		cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
472 				     &(osm_madw_req_p->list_item));
473 		/*  remove the item from the qmap */
474 		cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
475 				    &(osm_madw_req_p->map_item));
476 
477 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
478 			"osm_transaction_mgr_erase_madw: "
479 			"Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
480 
481 		/*  free the item */
482 		free(osm_madw_req_p);
483 	} else {
484 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
485 			"osm_transaction_mgr_erase_madw: "
486 			"osm_transaction_mgr_erase_madw:<0x%" PRIx64
487 			"> NOT FOUND.\n", p_mad->trans_id);
488 	}
489 	cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
490 	OSM_LOG_EXIT(p_vend->p_log);
491 
492 	return (IB_SUCCESS);
493 }
494 
495 ib_api_status_t
496 osm_transaction_mgr_get_madw_for_tid(IN osm_vendor_t * const p_vend,
497 				     IN ib_mad_t * const p_mad,
498 				     OUT osm_madw_t ** req_madw_p)
499 {
500 	osm_transaction_mgr_t *trans_mgr_p;
501 	osm_madw_req_t *osm_madw_req_p;
502 	cl_map_item_t *p_map_item;
503 	uint64_t key;
504 	OSM_LOG_ENTER(p_vend->p_log);
505 
506 	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
507 
508 	*req_madw_p = NULL;
509 
510 	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
511 		"osm_transaction_mgr_get_madw_for_tid: "
512 		"Looking for TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
513 
514 	key = (uint64_t) p_mad->trans_id;
515 	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
516 	p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key);
517 	if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) {
518 		/*  we found such an item.  */
519 		/*  get the osm_madw_req_p  */
520 		osm_madw_req_p =
521 		    PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item);
522 
523 		/*  Since the Transaction was looked up and provided for */
524 		/*  processing we retire it */
525 		cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
526 				     &(osm_madw_req_p->list_item));
527 		/*  remove the item from the qmap */
528 		cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
529 				    &(osm_madw_req_p->map_item));
530 
531 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
532 			"osm_transaction_mgr_get_madw_for_tid: "
533 			"Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
534 
535 		*req_madw_p = osm_madw_req_p->p_madw;
536 	}
537 
538 	cl_spinlock_release(&(trans_mgr_p->transaction_mgr_lock));
539 	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
540 		"osm_transaction_mgr_get_madw_for_tid: "
541 		"Got MADW:%p.\n", *req_madw_p);
542 	OSM_LOG_EXIT(p_vend->p_log);
543 	return (IB_SUCCESS);
544 }
545 
546 #endif
547