1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff#if HAVE_CONFIG_H
37219820Sjeff#  include <config.h>
38219820Sjeff#endif				/* HAVE_CONFIG_H */
39219820Sjeff
40219820Sjeff#include <math.h>
41219820Sjeff#include <stdlib.h>
42219820Sjeff#include <opensm/osm_helper.h>
43219820Sjeff#include <opensm/osm_log.h>
44219820Sjeff#include <vendor/osm_vendor.h>
45219820Sjeff#include <vendor/osm_vendor_api.h>
46219820Sjeff#include <opensm/osm_mad_pool.h>
47219820Sjeff
48219820Sjeff#if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS)
49219820Sjeff
50219820Sjeff#include <vendor/osm_vendor_mtl_transaction_mgr.h>
51219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
52219820Sjeff#include <vendor/osm_mtl_bind.h>
53219820Sjeff#endif
54219820Sjeff
55219820Sjeff/* this is the callback function of the timer */
56219820Sjeffvoid __osm_transaction_mgr_callback(IN void *context)
57219820Sjeff{
58219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
59219820Sjeff	osm_vendor_t *p_vend = (osm_vendor_t *) context;
60219820Sjeff	cl_list_item_t *p_list_item;
61219820Sjeff	cl_list_item_t *p_list_next_item;
62219820Sjeff	osm_madw_req_t *osm_madw_req_p;
63219820Sjeff	uint64_t current_time;	/*  [usec] */
64219820Sjeff	uint32_t new_timeout;	/*  [msec] */
65219820Sjeff	cl_status_t cl_status;
66219820Sjeff	ib_mad_t *p_mad;
67219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
68219820Sjeff	osm_mtl_bind_info_t *p_bind;
69219820Sjeff#else
70219820Sjeff	osm_ts_bind_info_t *p_bind;
71219820Sjeff#endif
72219820Sjeff	cl_list_t tmp_madw_p_list;	/*  this list will include all the madw_p that should be removed. */
73219820Sjeff	cl_list_t retry_madw_p_list;	/*  this list will include all the madw_p that were retried and need to be removed. */
74219820Sjeff	osm_madw_t *madw_p;
75219820Sjeff
76219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
77219820Sjeff
78219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
79219820Sjeff
80219820Sjeff	/*  initialize the tmp_madw_p_list */
81219820Sjeff	cl_list_construct(&tmp_madw_p_list);
82219820Sjeff	cl_status = cl_list_init(&tmp_madw_p_list, 50);
83219820Sjeff	if (cl_status != CL_SUCCESS) {
84219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
85219820Sjeff			"__osm_transaction_mgr_callback : ERROR 1000: "
86219820Sjeff			"Failed to create tmp_madw_p_list\n");
87219820Sjeff	}
88219820Sjeff
89219820Sjeff	cl_list_construct(&retry_madw_p_list);
90219820Sjeff	cl_status = cl_list_init(&retry_madw_p_list, 50);
91219820Sjeff	if (cl_status != CL_SUCCESS) {
92219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
93219820Sjeff			"__osm_transaction_mgr_callback : ERROR 1000: "
94219820Sjeff			"Failed to create retry_madw_p_list\n");
95219820Sjeff	}
96219820Sjeff
97219820Sjeff	current_time = cl_get_time_stamp();
98219820Sjeff	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
99219820Sjeff	p_list_item = cl_qlist_head(trans_mgr_p->madw_reqs_list_p);
100219820Sjeff	if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
101219820Sjeff		/*  the list is empty - nothing to do */
102219820Sjeff		cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
103219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
104219820Sjeff			"__osm_transaction_mgr_callback : Nothing to do\n");
105219820Sjeff		goto Exit;
106219820Sjeff	}
107219820Sjeff
108219820Sjeff	/*  non empty list: */
109219820Sjeff
110219820Sjeff	/*  get the osm_madw_req_p  */
111219820Sjeff	osm_madw_req_p = PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
112219820Sjeff
113219820Sjeff	while (osm_madw_req_p->waking_time <= current_time) {
114219820Sjeff		/*  this object was supposed to have gotten a response */
115219820Sjeff		/*  we need to decide if we need to retry or done with it. */
116219820Sjeff		if (osm_madw_req_p->retry_cnt > 0) {
117219820Sjeff			/*  add to the list of the retrys : */
118219820Sjeff			cl_list_insert_tail(&retry_madw_p_list, osm_madw_req_p);
119219820Sjeff
120219820Sjeff			/*  update wakeup time and retry count */
121219820Sjeff			osm_madw_req_p->waking_time =
122219820Sjeff			    p_vend->timeout * 1000 + cl_get_time_stamp();
123219820Sjeff			osm_madw_req_p->retry_cnt--;
124219820Sjeff
125219820Sjeff			/*  make sure we will get some timer call if not earlier */
126219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
127219820Sjeff				"__osm_transaction_mgr_callback : Timer restart:%u\n",
128219820Sjeff				p_vend->timeout);
129219820Sjeff
130219820Sjeff			cl_status =
131219820Sjeff			    cl_timer_start(&trans_mgr_p->madw_list_timer,
132219820Sjeff					   p_vend->timeout);
133219820Sjeff
134219820Sjeff			/*  go to the next object and check if it also needs to be removed - didn't receive response */
135219820Sjeff			/*  we need to do it before we move current item to the end of the list */
136219820Sjeff			p_list_next_item = cl_qlist_next(p_list_item);
137219820Sjeff
138219820Sjeff			/*  remove from the head */
139219820Sjeff			cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
140219820Sjeff					     &(osm_madw_req_p->list_item));
141219820Sjeff
142219820Sjeff			/*  insert the object to the qlist and the qmap */
143219820Sjeff			cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p,
144219820Sjeff					     &(osm_madw_req_p->list_item));
145219820Sjeff
146219820Sjeff		} else {
147219820Sjeff			/*  go to the next object and check if it also needs to be removed - didn't receive response */
148219820Sjeff			p_list_next_item = cl_qlist_next(p_list_item);
149219820Sjeff
150219820Sjeff			/*  remove from the head */
151219820Sjeff			cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
152219820Sjeff					     &(osm_madw_req_p->list_item));
153219820Sjeff
154219820Sjeff			/*  add it to the tmp_madw_p_list to be removed */
155219820Sjeff			cl_list_insert_tail(&tmp_madw_p_list,
156219820Sjeff					    osm_madw_req_p->p_madw);
157219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
158219820Sjeff				"__osm_transaction_mgr_callback : Found failed transaction madw: %p\n",
159219820Sjeff				osm_madw_req_p->p_madw);
160219820Sjeff		}
161219820Sjeff
162219820Sjeff		/*  Advance */
163219820Sjeff		p_list_item = p_list_next_item;
164219820Sjeff		if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
165219820Sjeff			/*  the list is empty - nothing to do */
166219820Sjeff			break;
167219820Sjeff		}
168219820Sjeff
169219820Sjeff		/*  get the osm_madw_req_p  */
170219820Sjeff		osm_madw_req_p =
171219820Sjeff		    PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
172219820Sjeff	}
173219820Sjeff
174219820Sjeff	/*  look at the current p_list_item. If it is not the end item - then we need to  */
175219820Sjeff	/*  re-start the timer */
176219820Sjeff	if (p_list_item != cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
177219820Sjeff		/*  get the osm_madw_req_p  */
178219820Sjeff		osm_madw_req_p =
179219820Sjeff		    PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item);
180219820Sjeff
181219820Sjeff		/*  we have the object that still didn't get response - re-start the timer */
182219820Sjeff		/*  start the timer to the timeout (in miliseconds) */
183219820Sjeff		new_timeout =
184219820Sjeff		    (osm_madw_req_p->waking_time - cl_get_time_stamp()) / 1000 +
185219820Sjeff		    1;
186219820Sjeff		cl_status =
187219820Sjeff		    cl_timer_start(&trans_mgr_p->madw_list_timer, new_timeout);
188219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
189219820Sjeff			"__osm_transaction_mgr_callback : Timer restart:%u\n",
190219820Sjeff			new_timeout);
191219820Sjeff
192219820Sjeff		if (cl_status != CL_SUCCESS) {
193219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
194219820Sjeff				"__osm_transaction_mgr_callback : ERROR 1000: "
195219820Sjeff				"Failed to start timer\n");
196219820Sjeff		}
197219820Sjeff	}
198219820Sjeff	/* if not empty - retry on retry list: */
199219820Sjeff	if (!cl_is_list_empty(&retry_madw_p_list)) {
200219820Sjeff
201219820Sjeff		/*  remove all elements that were retried: */
202219820Sjeff		osm_madw_req_p =
203219820Sjeff		    (osm_madw_req_t
204219820Sjeff		     *) (cl_list_remove_head(&retry_madw_p_list));
205219820Sjeff		while (osm_madw_req_p != NULL) {
206219820Sjeff
207219820Sjeff			/*  resend: */
208219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
209219820Sjeff				"__osm_transaction_mgr_callback : "
210219820Sjeff				"Retry %d of madw %p\n",
211219820Sjeff				OSM_DEFAULT_RETRY_COUNT -
212219820Sjeff				osm_madw_req_p->retry_cnt,
213219820Sjeff				osm_madw_req_p->p_madw);
214219820Sjeff
215219820Sjeff			/*  actually send it */
216219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
217219820Sjeff			osm_mtl_send_mad((osm_mtl_bind_info_t *)
218219820Sjeff					 osm_madw_req_p->p_bind,
219219820Sjeff					 osm_madw_req_p->p_madw);
220219820Sjeff#else
221219820Sjeff			ib_api_status_t
222219820Sjeff			    osm_ts_send_mad(osm_ts_bind_info_t * p_bind,
223219820Sjeff					    osm_madw_t * const p_madw);
224219820Sjeff			osm_ts_send_mad((osm_ts_bind_info_t *) osm_madw_req_p->
225219820Sjeff					p_bind, osm_madw_req_p->p_madw);
226219820Sjeff#endif
227219820Sjeff			/*  next one */
228219820Sjeff			osm_madw_req_p =
229219820Sjeff			    (osm_madw_req_t
230219820Sjeff			     *) (cl_list_remove_head(&retry_madw_p_list));
231219820Sjeff		}
232219820Sjeff	}
233219820Sjeff
234219820Sjeff	/*  if the tmp_madw_p_list has elements - need to call the send_err_callback */
235219820Sjeff	madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list));
236219820Sjeff	while (madw_p != NULL) {
237219820Sjeff		/*  need to remove it from pool */
238219820Sjeff
239219820Sjeff		/* obtain the madw_p stored as the wrid in the send call */
240219820Sjeff		p_mad = osm_madw_get_mad_ptr(madw_p);
241219820Sjeff		p_bind = madw_p->h_bind;
242219820Sjeff		/*
243219820Sjeff		   Return any wrappers to the pool that may have been
244219820Sjeff		   pre-emptively allocated to handle a receive.
245219820Sjeff		 */
246219820Sjeff		if (madw_p->vend_wrap.p_resp_madw) {
247219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
248219820Sjeff			osm_mad_pool_put(p_bind->p_osm_pool,
249219820Sjeff					 madw_p->vend_wrap.p_resp_madw);
250219820Sjeff#else
251219820Sjeff			osm_mad_pool_put(p_bind->p_osm_pool,
252219820Sjeff					 madw_p->vend_wrap.p_resp_madw);
253219820Sjeff#endif
254219820Sjeff			madw_p->vend_wrap.p_resp_madw = NULL;
255219820Sjeff		}
256219820Sjeff
257219820Sjeff		/* invoke the CB */
258219820Sjeff		(*(osm_vend_mad_send_err_callback_t)
259219820Sjeff		 (p_bind->send_err_callback)) (p_bind->client_context, madw_p);
260219820Sjeff		madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list));
261219820Sjeff	}
262219820Sjeff
263219820SjeffExit:
264219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
265219820Sjeff
266219820Sjeff}
267219820Sjeff
268219820Sjeff/*
269219820Sjeff * Construct and Initialize
270219820Sjeff */
271219820Sjeff
272219820Sjeffvoid osm_transaction_mgr_init(IN osm_vendor_t * const p_vend)
273219820Sjeff{
274219820Sjeff	cl_status_t cl_status;
275219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
276219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
277219820Sjeff
278219820Sjeff	CL_ASSERT(p_vend->p_transaction_mgr == NULL);
279219820Sjeff
280219820Sjeff	(osm_transaction_mgr_t *) p_vend->p_transaction_mgr =
281219820Sjeff	    (osm_transaction_mgr_t *) malloc(sizeof(osm_transaction_mgr_t));
282219820Sjeff
283219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
284219820Sjeff
285219820Sjeff	/*  construct lock object  */
286219820Sjeff	cl_spinlock_construct(&(trans_mgr_p->transaction_mgr_lock));
287219820Sjeff	CL_ASSERT(cl_spinlock_init(&(trans_mgr_p->transaction_mgr_lock)) ==
288219820Sjeff		  CL_SUCCESS);
289219820Sjeff
290219820Sjeff	/*  initialize the qlist */
291219820Sjeff	trans_mgr_p->madw_reqs_list_p =
292219820Sjeff	    (cl_qlist_t *) malloc(sizeof(cl_qlist_t));
293219820Sjeff	cl_qlist_init(trans_mgr_p->madw_reqs_list_p);
294219820Sjeff
295219820Sjeff	/*  initialize the qmap */
296219820Sjeff	trans_mgr_p->madw_by_tid_map_p =
297219820Sjeff	    (cl_qmap_t *) malloc(sizeof(cl_qmap_t));
298219820Sjeff	cl_qmap_init(trans_mgr_p->madw_by_tid_map_p);
299219820Sjeff
300219820Sjeff	/*  create the timer used by the madw_req_list */
301219820Sjeff	cl_timer_construct(&(trans_mgr_p->madw_list_timer));
302219820Sjeff
303219820Sjeff	/*  init the timer with timeout. */
304219820Sjeff	cl_status = cl_timer_init(&trans_mgr_p->madw_list_timer,
305219820Sjeff				  __osm_transaction_mgr_callback, p_vend);
306219820Sjeff
307219820Sjeff	if (cl_status != CL_SUCCESS) {
308219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
309219820Sjeff			"osm_transaction_mgr_init : ERROR 1000: "
310219820Sjeff			"Failed to initialize madw_reqs_list timer\n");
311219820Sjeff	}
312219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
313219820Sjeff}
314219820Sjeff
315219820Sjeffvoid osm_transaction_mgr_destroy(IN osm_vendor_t * const p_vend)
316219820Sjeff{
317219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
318219820Sjeff	cl_list_item_t *p_list_item;
319219820Sjeff	cl_map_item_t *p_map_item;
320219820Sjeff	osm_madw_req_t *osm_madw_req_p;
321219820Sjeff
322219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
323219820Sjeff
324219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
325219820Sjeff
326219820Sjeff	if (p_vend->p_transaction_mgr != NULL) {
327219820Sjeff		/* we need to get a lock */
328219820Sjeff		cl_spinlock_acquire(&trans_mgr_p->transaction_mgr_lock);
329219820Sjeff
330219820Sjeff		/* go over all the items in the list and remove them */
331219820Sjeff		p_list_item =
332219820Sjeff		    cl_qlist_remove_head(trans_mgr_p->madw_reqs_list_p);
333219820Sjeff		while (p_list_item !=
334219820Sjeff		       cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) {
335219820Sjeff			osm_madw_req_p = (osm_madw_req_t *) p_list_item;
336219820Sjeff
337219820Sjeff			if (osm_madw_req_p->p_madw->p_mad)
338219820Sjeff				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
339219820Sjeff					"osm_transaction_mgr_destroy: "
340219820Sjeff					"Found outstanding MADW:%p  TID:<0x%"
341219820Sjeff					PRIx64 ">.\n", osm_madw_req_p->p_madw,
342219820Sjeff					osm_madw_req_p->p_madw->p_mad->
343219820Sjeff					trans_id);
344219820Sjeff			else
345219820Sjeff				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
346219820Sjeff					"osm_transaction_mgr_destroy: "
347219820Sjeff					"Found outstanding MADW:%p  TID:UNDEFINED.\n",
348219820Sjeff					osm_madw_req_p->p_madw);
349219820Sjeff
350219820Sjeff			/*  each item - remove it from the map */
351219820Sjeff			p_map_item = &(osm_madw_req_p->map_item);
352219820Sjeff			cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
353219820Sjeff					    p_map_item);
354219820Sjeff			/*  free the item */
355219820Sjeff			free(osm_madw_req_p);
356219820Sjeff			p_list_item =
357219820Sjeff			    cl_qlist_remove_head(trans_mgr_p->madw_reqs_list_p);
358219820Sjeff		}
359219820Sjeff		/*  free the qlist and qmap */
360219820Sjeff		free(trans_mgr_p->madw_reqs_list_p);
361219820Sjeff		free(trans_mgr_p->madw_by_tid_map_p);
362219820Sjeff		/*  reliease and destroy the lock */
363219820Sjeff		cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
364219820Sjeff		cl_spinlock_destroy(&(trans_mgr_p->transaction_mgr_lock));
365219820Sjeff		/*  destroy the timer */
366219820Sjeff		cl_timer_trim(&trans_mgr_p->madw_list_timer, 1);
367219820Sjeff		cl_timer_destroy(&trans_mgr_p->madw_list_timer);
368219820Sjeff		/*  free the transaction_manager object */
369219820Sjeff		free(trans_mgr_p);
370219820Sjeff		trans_mgr_p = NULL;
371219820Sjeff	}
372219820Sjeff
373219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
374219820Sjeff}
375219820Sjeff
376219820Sjeffib_api_status_t
377219820Sjeffosm_transaction_mgr_insert_madw(IN osm_bind_handle_t * const p_bind,
378219820Sjeff				IN osm_madw_t * p_madw)
379219820Sjeff{
380219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
381219820Sjeff	osm_vendor_t *const p_vend = ((osm_mtl_bind_info_t *) p_bind)->p_vend;
382219820Sjeff#else
383219820Sjeff	osm_vendor_t *const p_vend = ((osm_ts_bind_info_t *) p_bind)->p_vend;
384219820Sjeff#endif
385219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
386219820Sjeff	osm_madw_req_t *osm_madw_req_p;
387219820Sjeff	uint64_t timeout;
388219820Sjeff	uint64_t waking_time;
389219820Sjeff	cl_status_t cl_status;
390219820Sjeff	uint64_t key;
391219820Sjeff	const ib_mad_t *mad_p = p_madw->p_mad;
392219820Sjeff
393219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
394219820Sjeff
395219820Sjeff	CL_ASSERT(mad_p);
396219820Sjeff
397219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
398219820Sjeff
399219820Sjeff	timeout = (uint64_t) (p_vend->timeout) * 1000;	/* change the miliseconds value of timeout to microseconds. */
400219820Sjeff	waking_time = timeout + cl_get_time_stamp();
401219820Sjeff
402219820Sjeff	osm_madw_req_p = (osm_madw_req_t *) malloc(sizeof(osm_madw_req_t));
403219820Sjeff
404219820Sjeff	osm_madw_req_p->p_madw = p_madw;
405219820Sjeff	osm_madw_req_p->waking_time = waking_time;
406219820Sjeff	osm_madw_req_p->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
407219820Sjeff	osm_madw_req_p->p_bind = p_bind;
408219820Sjeff
409219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
410219820Sjeff		"osm_transaction_mgr_insert_madw: "
411219820Sjeff		"Inserting MADW:%p with waking_time: <0x%" PRIx64 ">  TID:<0x%"
412219820Sjeff		PRIx64 ">.\n", p_madw, waking_time, p_madw->p_mad->trans_id);
413219820Sjeff
414219820Sjeff	/* Get the lock on the manager */
415219820Sjeff	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
416219820Sjeff	/* If the list is empty - need to start the timer with timer of timeout (in miliseconds) */
417219820Sjeff	if (cl_is_qlist_empty(trans_mgr_p->madw_reqs_list_p)) {
418219820Sjeff		/*  stop the timer if it is running */
419219820Sjeff		cl_timer_stop(&trans_mgr_p->madw_list_timer);
420219820Sjeff
421219820Sjeff		/*  start the timer to the timeout (in miliseconds) */
422219820Sjeff		cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer,
423219820Sjeff					   p_vend->timeout);
424219820Sjeff		if (cl_status != CL_SUCCESS) {
425219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
426219820Sjeff				"osm_transaction_mgr_insert_madw : ERROR 1000: "
427219820Sjeff				"Failed to start timer\n");
428219820Sjeff		}
429219820Sjeff	}
430219820Sjeff
431219820Sjeff	/*  insert the object to the qlist and the qmap */
432219820Sjeff	cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p,
433219820Sjeff			     &(osm_madw_req_p->list_item));
434219820Sjeff	/*  get the key */
435219820Sjeff	key = (uint64_t) mad_p->trans_id;
436219820Sjeff	cl_qmap_insert(trans_mgr_p->madw_by_tid_map_p, key,
437219820Sjeff		       &(osm_madw_req_p->map_item));
438219820Sjeff	cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
439219820Sjeff
440219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
441219820Sjeff
442219820Sjeff	return (IB_SUCCESS);
443219820Sjeff}
444219820Sjeff
445219820Sjeffib_api_status_t
446219820Sjeffosm_transaction_mgr_erase_madw(IN osm_vendor_t * const p_vend,
447219820Sjeff			       IN ib_mad_t * p_mad)
448219820Sjeff{
449219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
450219820Sjeff	osm_madw_req_t *osm_madw_req_p;
451219820Sjeff	uint64_t key;
452219820Sjeff	cl_map_item_t *p_map_item;
453219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
454219820Sjeff
455219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
456219820Sjeff
457219820Sjeff	key = (uint64_t) p_mad->trans_id;
458219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
459219820Sjeff		"osm_transaction_mgr_erase_madw: "
460219820Sjeff		"Removing TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
461219820Sjeff
462219820Sjeff	cl_spinlock_acquire(&trans_mgr_p->transaction_mgr_lock);
463219820Sjeff	p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key);
464219820Sjeff	if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) {
465219820Sjeff		/*  we found such an item.  */
466219820Sjeff		/*  get the osm_madw_req_p  */
467219820Sjeff		osm_madw_req_p =
468219820Sjeff		    PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item);
469219820Sjeff
470219820Sjeff		/*  remove the item from the qlist */
471219820Sjeff		cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
472219820Sjeff				     &(osm_madw_req_p->list_item));
473219820Sjeff		/*  remove the item from the qmap */
474219820Sjeff		cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
475219820Sjeff				    &(osm_madw_req_p->map_item));
476219820Sjeff
477219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
478219820Sjeff			"osm_transaction_mgr_erase_madw: "
479219820Sjeff			"Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
480219820Sjeff
481219820Sjeff		/*  free the item */
482219820Sjeff		free(osm_madw_req_p);
483219820Sjeff	} else {
484219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
485219820Sjeff			"osm_transaction_mgr_erase_madw: "
486219820Sjeff			"osm_transaction_mgr_erase_madw:<0x%" PRIx64
487219820Sjeff			"> NOT FOUND.\n", p_mad->trans_id);
488219820Sjeff	}
489219820Sjeff	cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);
490219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
491219820Sjeff
492219820Sjeff	return (IB_SUCCESS);
493219820Sjeff}
494219820Sjeff
495219820Sjeffib_api_status_t
496219820Sjeffosm_transaction_mgr_get_madw_for_tid(IN osm_vendor_t * const p_vend,
497219820Sjeff				     IN ib_mad_t * const p_mad,
498219820Sjeff				     OUT osm_madw_t ** req_madw_p)
499219820Sjeff{
500219820Sjeff	osm_transaction_mgr_t *trans_mgr_p;
501219820Sjeff	osm_madw_req_t *osm_madw_req_p;
502219820Sjeff	cl_map_item_t *p_map_item;
503219820Sjeff	uint64_t key;
504219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
505219820Sjeff
506219820Sjeff	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;
507219820Sjeff
508219820Sjeff	*req_madw_p = NULL;
509219820Sjeff
510219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
511219820Sjeff		"osm_transaction_mgr_get_madw_for_tid: "
512219820Sjeff		"Looking for TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
513219820Sjeff
514219820Sjeff	key = (uint64_t) p_mad->trans_id;
515219820Sjeff	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
516219820Sjeff	p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key);
517219820Sjeff	if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) {
518219820Sjeff		/*  we found such an item.  */
519219820Sjeff		/*  get the osm_madw_req_p  */
520219820Sjeff		osm_madw_req_p =
521219820Sjeff		    PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item);
522219820Sjeff
523219820Sjeff		/*  Since the Transaction was looked up and provided for */
524219820Sjeff		/*  processing we retire it */
525219820Sjeff		cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p,
526219820Sjeff				     &(osm_madw_req_p->list_item));
527219820Sjeff		/*  remove the item from the qmap */
528219820Sjeff		cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p,
529219820Sjeff				    &(osm_madw_req_p->map_item));
530219820Sjeff
531219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
532219820Sjeff			"osm_transaction_mgr_get_madw_for_tid: "
533219820Sjeff			"Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id);
534219820Sjeff
535219820Sjeff		*req_madw_p = osm_madw_req_p->p_madw;
536219820Sjeff	}
537219820Sjeff
538219820Sjeff	cl_spinlock_release(&(trans_mgr_p->transaction_mgr_lock));
539219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
540219820Sjeff		"osm_transaction_mgr_get_madw_for_tid: "
541219820Sjeff		"Got MADW:%p.\n", *req_madw_p);
542219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
543219820Sjeff	return (IB_SUCCESS);
544219820Sjeff}
545219820Sjeff
546219820Sjeff#endif
547