1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005,2009 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5d6b92ffaSHans Petter Selasky  *
6d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11d6b92ffaSHans Petter Selasky  *
12d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14d6b92ffaSHans Petter Selasky  *     conditions are met:
15d6b92ffaSHans Petter Selasky  *
16d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18d6b92ffaSHans Petter Selasky  *        disclaimer.
19d6b92ffaSHans Petter Selasky  *
20d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24d6b92ffaSHans Petter Selasky  *
25d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32d6b92ffaSHans Petter Selasky  * SOFTWARE.
33d6b92ffaSHans Petter Selasky  *
34d6b92ffaSHans Petter Selasky  */
35d6b92ffaSHans Petter Selasky 
36d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
37d6b92ffaSHans Petter Selasky #  include <config.h>
38d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
39d6b92ffaSHans Petter Selasky 
40d6b92ffaSHans Petter Selasky #include <stdlib.h>
41d6b92ffaSHans Petter Selasky 
42d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx.h>
43d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_defs.h>
44d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_txn.h>
45d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_svc.h>
46d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_sender.h>
47d6b92ffaSHans Petter Selasky 
48d6b92ffaSHans Petter Selasky static ib_api_status_t
49d6b92ffaSHans Petter Selasky __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
50d6b92ffaSHans Petter Selasky 		     IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
51d6b92ffaSHans Petter Selasky 
52d6b92ffaSHans Petter Selasky static ib_api_status_t
53d6b92ffaSHans Petter Selasky __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
54d6b92ffaSHans Petter Selasky 			 IN osmv_txn_ctx_t * p_txn, IN uint64_t key);
55d6b92ffaSHans Petter Selasky 
56d6b92ffaSHans Petter Selasky static ib_api_status_t
57d6b92ffaSHans Petter Selasky __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
58d6b92ffaSHans Petter Selasky 			 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
59d6b92ffaSHans Petter Selasky 
60d6b92ffaSHans Petter Selasky static void __osmv_txn_all_done(osm_bind_handle_t h_bind);
61d6b92ffaSHans Petter Selasky 
62d6b92ffaSHans Petter Selasky static uint64_t
63d6b92ffaSHans Petter Selasky __osmv_txn_timeout_cb(IN uint64_t key,
64d6b92ffaSHans Petter Selasky 		      IN uint32_t num_regs, IN void *cb_context);
65d6b92ffaSHans Petter Selasky 
66d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txn_init(IN osm_bind_handle_t h_bind,IN uint64_t tid,IN uint64_t key,OUT osmv_txn_ctx_t ** pp_txn)67d6b92ffaSHans Petter Selasky osmv_txn_init(IN osm_bind_handle_t h_bind,
68d6b92ffaSHans Petter Selasky 	      IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
69d6b92ffaSHans Petter Selasky {
70d6b92ffaSHans Petter Selasky 	ib_api_status_t st;
71d6b92ffaSHans Petter Selasky 	osmv_txn_ctx_t *p_txn;
72d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
73d6b92ffaSHans Petter Selasky 
74d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
75d6b92ffaSHans Petter Selasky 
76d6b92ffaSHans Petter Selasky 	CL_ASSERT(NULL != h_bind && NULL != pp_txn);
77d6b92ffaSHans Petter Selasky 
78d6b92ffaSHans Petter Selasky 	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
79d6b92ffaSHans Petter Selasky 		"Starting transaction 0x%016" PRIx64
80d6b92ffaSHans Petter Selasky 		" (key=0x%016" PRIx64 ")\n", tid, key);
81d6b92ffaSHans Petter Selasky 
82d6b92ffaSHans Petter Selasky 	p_txn = malloc(sizeof(osmv_txn_ctx_t));
83d6b92ffaSHans Petter Selasky 	if (!p_txn) {
84d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
85d6b92ffaSHans Petter Selasky 	}
86d6b92ffaSHans Petter Selasky 
87d6b92ffaSHans Petter Selasky 	memset(p_txn, 0, sizeof(osmv_txn_ctx_t));
88d6b92ffaSHans Petter Selasky 	p_txn->p_log = p_bo->txn_mgr.p_log;
89d6b92ffaSHans Petter Selasky 	p_txn->tid = tid;
90d6b92ffaSHans Petter Selasky 	p_txn->key = key;
91d6b92ffaSHans Petter Selasky 	p_txn->p_madw = NULL;
92d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_NONE;
93d6b92ffaSHans Petter Selasky 
94d6b92ffaSHans Petter Selasky 	/* insert into transaction manager DB */
95d6b92ffaSHans Petter Selasky 	st = __osmv_txnmgr_insert_txn(&p_bo->txn_mgr, p_txn, key);
96d6b92ffaSHans Petter Selasky 	if (IB_SUCCESS != st) {
97d6b92ffaSHans Petter Selasky 		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
98d6b92ffaSHans Petter Selasky 			"osmv_txn_init: ERR 6703: "
99d6b92ffaSHans Petter Selasky 			"Failed to insert to transaction 0x%016" PRIx64
100d6b92ffaSHans Petter Selasky 			" (key=0x%016" PRIx64 ") to manager DB\n",
101d6b92ffaSHans Petter Selasky 			tid, key);
102d6b92ffaSHans Petter Selasky 		goto insert_txn_failed;
103d6b92ffaSHans Petter Selasky 	}
104d6b92ffaSHans Petter Selasky 
105d6b92ffaSHans Petter Selasky 	*pp_txn = p_txn;
106d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
107d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
108d6b92ffaSHans Petter Selasky 
109d6b92ffaSHans Petter Selasky insert_txn_failed:
110d6b92ffaSHans Petter Selasky 	free(p_txn);
111d6b92ffaSHans Petter Selasky 
112d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
113d6b92ffaSHans Petter Selasky 	return st;
114d6b92ffaSHans Petter Selasky }
115d6b92ffaSHans Petter Selasky 
116d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,IN osmv_txn_ctx_t * p_txn,IN osm_madw_t * p_madw)117d6b92ffaSHans Petter Selasky osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,
118d6b92ffaSHans Petter Selasky 			  IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw)
119d6b92ffaSHans Petter Selasky {
120d6b92ffaSHans Petter Selasky 	ib_api_status_t st;
121d6b92ffaSHans Petter Selasky 
122d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_txn);
123d6b92ffaSHans Petter Selasky 
124d6b92ffaSHans Petter Selasky 	/* Double-Sided RMPP Direction Switch */
125d6b92ffaSHans Petter Selasky 	osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));
126d6b92ffaSHans Petter Selasky 
127d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER;
128d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t));
129d6b92ffaSHans Petter Selasky 
130d6b92ffaSHans Petter Selasky 	if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) {
131d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
132d6b92ffaSHans Petter Selasky 	}
133d6b92ffaSHans Petter Selasky 
134d6b92ffaSHans Petter Selasky 	memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0,
135d6b92ffaSHans Petter Selasky 	       sizeof(osmv_rmpp_send_ctx_t));
136d6b92ffaSHans Petter Selasky 
137d6b92ffaSHans Petter Selasky 	st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx,
138d6b92ffaSHans Petter Selasky 				     (void *)p_madw->p_mad,
139d6b92ffaSHans Petter Selasky 				     p_madw->mad_size, p_txn->p_log);
140d6b92ffaSHans Petter Selasky 	return st;
141d6b92ffaSHans Petter Selasky }
142d6b92ffaSHans Petter Selasky 
143d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,IN osmv_txn_ctx_t * p_txn,IN boolean_t is_init_by_peer)144d6b92ffaSHans Petter Selasky osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,
145d6b92ffaSHans Petter Selasky 			    IN osmv_txn_ctx_t * p_txn,
146d6b92ffaSHans Petter Selasky 			    IN boolean_t is_init_by_peer)
147d6b92ffaSHans Petter Selasky {
148d6b92ffaSHans Petter Selasky 	ib_api_status_t st;
149d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
150d6b92ffaSHans Petter Selasky 	uint64_t key = osmv_txn_get_key(p_txn);
151d6b92ffaSHans Petter Selasky 
152d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_txn);
153d6b92ffaSHans Petter Selasky 
154d6b92ffaSHans Petter Selasky 	/* Double-Sided RMPP Direction Switch */
155d6b92ffaSHans Petter Selasky 	osmv_txn_remove_timeout_ev(h_bind, key);
156d6b92ffaSHans Petter Selasky 
157d6b92ffaSHans Petter Selasky 	/* Set the Transaction Timeout value */
158d6b92ffaSHans Petter Selasky 	st = osmv_txn_set_timeout_ev(h_bind, key,
159d6b92ffaSHans Petter Selasky 				     p_bo->p_vendor->ttime_timeout);
160d6b92ffaSHans Petter Selasky 	if (IB_SUCCESS != st) {
161d6b92ffaSHans Petter Selasky 
162d6b92ffaSHans Petter Selasky 		return st;
163d6b92ffaSHans Petter Selasky 	}
164d6b92ffaSHans Petter Selasky 
165d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER;
166d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer;
167d6b92ffaSHans Petter Selasky 
168d6b92ffaSHans Petter Selasky 	p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t));
169d6b92ffaSHans Petter Selasky 
170d6b92ffaSHans Petter Selasky 	if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) {
171d6b92ffaSHans Petter Selasky 
172d6b92ffaSHans Petter Selasky 		osmv_txn_remove_timeout_ev(h_bind, key);
173d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
174d6b92ffaSHans Petter Selasky 	}
175d6b92ffaSHans Petter Selasky 
176d6b92ffaSHans Petter Selasky 	memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0,
177d6b92ffaSHans Petter Selasky 	       sizeof(osmv_rmpp_recv_ctx_t));
178d6b92ffaSHans Petter Selasky 
179d6b92ffaSHans Petter Selasky 	st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx,
180d6b92ffaSHans Petter Selasky 				     p_txn->p_log);
181d6b92ffaSHans Petter Selasky 
182d6b92ffaSHans Petter Selasky 	return st;
183d6b92ffaSHans Petter Selasky }
184d6b92ffaSHans Petter Selasky 
185d6b92ffaSHans Petter Selasky /*
186d6b92ffaSHans Petter Selasky  * NAME
187d6b92ffaSHans Petter Selasky  *  osmv_txn_set_timeout_ev
188d6b92ffaSHans Petter Selasky  *
189d6b92ffaSHans Petter Selasky  * DESCRIPTION
190d6b92ffaSHans Petter Selasky  *
191d6b92ffaSHans Petter Selasky  * SEE ALSO
192d6b92ffaSHans Petter Selasky  *
193d6b92ffaSHans Petter Selasky  */
194d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind,IN uint64_t key,IN uint64_t msec)195d6b92ffaSHans Petter Selasky osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind,
196d6b92ffaSHans Petter Selasky 			IN uint64_t key, IN uint64_t msec)
197d6b92ffaSHans Petter Selasky {
198d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
199d6b92ffaSHans Petter Selasky 	cl_event_wheel_t *p_event_wheel = p_bo->txn_mgr.p_event_wheel;
200d6b92ffaSHans Petter Selasky 	cl_status_t status;
201d6b92ffaSHans Petter Selasky 
202d6b92ffaSHans Petter Selasky 	status = cl_event_wheel_reg(p_event_wheel, key, cl_get_time_stamp() + 1000 * msec,	/* TTL */
203d6b92ffaSHans Petter Selasky 				    __osmv_txn_timeout_cb,
204d6b92ffaSHans Petter Selasky 				    p_bo /* The context */ );
205d6b92ffaSHans Petter Selasky 
206d6b92ffaSHans Petter Selasky 	return (ib_api_status_t) status;
207d6b92ffaSHans Petter Selasky }
208d6b92ffaSHans Petter Selasky 
209d6b92ffaSHans Petter Selasky /*
210d6b92ffaSHans Petter Selasky  * NAME
211d6b92ffaSHans Petter Selasky  *  osmv_txn_remove_timeout_ev
212d6b92ffaSHans Petter Selasky  *
213d6b92ffaSHans Petter Selasky  * DESCRIPTION
214d6b92ffaSHans Petter Selasky 
215d6b92ffaSHans Petter Selasky  * SEE ALSO
216d6b92ffaSHans Petter Selasky  *
217d6b92ffaSHans Petter Selasky  */
osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind,IN uint64_t key)218d6b92ffaSHans Petter Selasky void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key)
219d6b92ffaSHans Petter Selasky {
220d6b92ffaSHans Petter Selasky 	cl_event_wheel_t *p_event_wheel =
221d6b92ffaSHans Petter Selasky 	    ((osmv_bind_obj_t *) h_bind)->txn_mgr.p_event_wheel;
222d6b92ffaSHans Petter Selasky 	cl_event_wheel_unreg(p_event_wheel, key);
223d6b92ffaSHans Petter Selasky }
224d6b92ffaSHans Petter Selasky 
225d6b92ffaSHans Petter Selasky void
osmv_txn_done(IN osm_bind_handle_t h_bind,IN uint64_t key,IN boolean_t is_in_cb)226d6b92ffaSHans Petter Selasky osmv_txn_done(IN osm_bind_handle_t h_bind,
227d6b92ffaSHans Petter Selasky 	      IN uint64_t key, IN boolean_t is_in_cb)
228d6b92ffaSHans Petter Selasky {
229d6b92ffaSHans Petter Selasky 	osmv_txn_ctx_t *p_ctx;
230d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind;
231d6b92ffaSHans Petter Selasky 
232d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
233d6b92ffaSHans Petter Selasky 
234d6b92ffaSHans Petter Selasky 	CL_ASSERT(h_bind);
235d6b92ffaSHans Petter Selasky 
236d6b92ffaSHans Petter Selasky 	/* Cancel the (single) timeout possibly outstanding for this txn
237d6b92ffaSHans Petter Selasky 	 * Don't do this if you are in the callback context, for 2 reasons:
238d6b92ffaSHans Petter Selasky 	 * (1) The event wheel will remove the context itself.
239d6b92ffaSHans Petter Selasky 	 * (2) If we try to, there is a deadlock in the event wheel
240d6b92ffaSHans Petter Selasky 	 */
241d6b92ffaSHans Petter Selasky 	if (FALSE == is_in_cb) {
242d6b92ffaSHans Petter Selasky 		osmv_txn_remove_timeout_ev(h_bind, key);
243d6b92ffaSHans Petter Selasky 	}
244d6b92ffaSHans Petter Selasky 
245d6b92ffaSHans Petter Selasky 	/* Remove from DB */
246d6b92ffaSHans Petter Selasky 	if (IB_NOT_FOUND ==
247d6b92ffaSHans Petter Selasky 	    __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) {
248d6b92ffaSHans Petter Selasky 		return;
249d6b92ffaSHans Petter Selasky 	}
250d6b92ffaSHans Petter Selasky 
251d6b92ffaSHans Petter Selasky 	/* Destroy the transaction's RMPP contexts
252d6b92ffaSHans Petter Selasky 	 * (can be more than one in the case of double sided transfer)
253d6b92ffaSHans Petter Selasky 	 */
254d6b92ffaSHans Petter Selasky 
255d6b92ffaSHans Petter Selasky 	if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) {
256d6b92ffaSHans Petter Selasky 		osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx);
257d6b92ffaSHans Petter Selasky 	}
258d6b92ffaSHans Petter Selasky 
259d6b92ffaSHans Petter Selasky 	if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) {
260d6b92ffaSHans Petter Selasky 		osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx);
261d6b92ffaSHans Petter Selasky 	}
262d6b92ffaSHans Petter Selasky 
263d6b92ffaSHans Petter Selasky 	free(p_ctx);
264d6b92ffaSHans Petter Selasky 
265d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
266d6b92ffaSHans Petter Selasky }
267d6b92ffaSHans Petter Selasky 
268d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txn_lookup(IN osm_bind_handle_t h_bind,IN uint64_t key,OUT osmv_txn_ctx_t ** pp_txn)269d6b92ffaSHans Petter Selasky osmv_txn_lookup(IN osm_bind_handle_t h_bind,
270d6b92ffaSHans Petter Selasky 		IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
271d6b92ffaSHans Petter Selasky {
272d6b92ffaSHans Petter Selasky 	return __osmv_txnmgr_lookup(&(((osmv_bind_obj_t *) h_bind)->txn_mgr),
273d6b92ffaSHans Petter Selasky 				    key, pp_txn);
274d6b92ffaSHans Petter Selasky }
275d6b92ffaSHans Petter Selasky 
osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind)276d6b92ffaSHans Petter Selasky void osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind)
277d6b92ffaSHans Petter Selasky {
278d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
279d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_item;
280d6b92ffaSHans Petter Selasky 	cl_map_obj_t *p_obj;
281d6b92ffaSHans Petter Selasky 	osmv_txn_ctx_t *p_txn;
282d6b92ffaSHans Petter Selasky 	osmv_rmpp_send_ctx_t *p_send_ctx;
283d6b92ffaSHans Petter Selasky 	cl_qmap_t *p_map = p_bo->txn_mgr.p_txn_map;
284d6b92ffaSHans Petter Selasky 
285d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
286d6b92ffaSHans Petter Selasky 
287d6b92ffaSHans Petter Selasky 	while (FALSE == cl_is_qmap_empty(p_map)) {
288d6b92ffaSHans Petter Selasky 
289d6b92ffaSHans Petter Selasky 		p_item = cl_qmap_head(p_map);
290d6b92ffaSHans Petter Selasky 		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
291d6b92ffaSHans Petter Selasky 		p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
292d6b92ffaSHans Petter Selasky 		p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
293d6b92ffaSHans Petter Selasky 
294d6b92ffaSHans Petter Selasky 		if (NULL != p_send_ctx) {
295d6b92ffaSHans Petter Selasky 
296d6b92ffaSHans Petter Selasky 			p_send_ctx->status = IB_INTERRUPTED;
297d6b92ffaSHans Petter Selasky 
298d6b92ffaSHans Petter Selasky 			/* Wake up the sender thread to let it break out */
299d6b92ffaSHans Petter Selasky 			cl_event_signal(&p_send_ctx->event);
300d6b92ffaSHans Petter Selasky 		}
301d6b92ffaSHans Petter Selasky 
302d6b92ffaSHans Petter Selasky 		cl_qmap_remove_item(p_map, p_item);
303d6b92ffaSHans Petter Selasky 	}
304d6b92ffaSHans Petter Selasky 
305d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
306d6b92ffaSHans Petter Selasky }
307d6b92ffaSHans Petter Selasky 
308d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr,IN osm_log_t * p_log,IN cl_spinlock_t * p_lock)309d6b92ffaSHans Petter Selasky osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr,
310d6b92ffaSHans Petter Selasky 		 IN osm_log_t * p_log, IN cl_spinlock_t * p_lock)
311d6b92ffaSHans Petter Selasky {
312d6b92ffaSHans Petter Selasky 	cl_status_t cl_st = CL_SUCCESS;
313d6b92ffaSHans Petter Selasky 
314d6b92ffaSHans Petter Selasky 	p_tx_mgr->p_event_wheel = malloc(sizeof(cl_event_wheel_t));
315d6b92ffaSHans Petter Selasky 	if (!p_tx_mgr->p_event_wheel) {
316d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
317d6b92ffaSHans Petter Selasky 	}
318d6b92ffaSHans Petter Selasky 
319d6b92ffaSHans Petter Selasky 	memset(p_tx_mgr->p_event_wheel, 0, sizeof(cl_event_wheel_t));
320d6b92ffaSHans Petter Selasky 
321d6b92ffaSHans Petter Selasky 	cl_event_wheel_construct(p_tx_mgr->p_event_wheel);
322d6b92ffaSHans Petter Selasky 
323d6b92ffaSHans Petter Selasky 	/* NOTE! We are using an extended constructor.
324d6b92ffaSHans Petter Selasky 	 * We tell the Event Wheel run in a non-protected manner in the reg/unreg calls,
325d6b92ffaSHans Petter Selasky 	 * and acquire an external lock in the asynchronous callback.
326d6b92ffaSHans Petter Selasky 	 */
327d6b92ffaSHans Petter Selasky 	cl_st = cl_event_wheel_init_ex(p_tx_mgr->p_event_wheel, p_lock);
328d6b92ffaSHans Petter Selasky 	if (cl_st != CL_SUCCESS) {
329d6b92ffaSHans Petter Selasky 		free(p_tx_mgr->p_event_wheel);
330d6b92ffaSHans Petter Selasky 		return (ib_api_status_t) cl_st;
331d6b92ffaSHans Petter Selasky 	}
332d6b92ffaSHans Petter Selasky 
333d6b92ffaSHans Petter Selasky 	p_tx_mgr->p_txn_map = malloc(sizeof(cl_qmap_t));
334d6b92ffaSHans Petter Selasky 	if (!p_tx_mgr->p_txn_map) {
335d6b92ffaSHans Petter Selasky 		cl_event_wheel_destroy(p_tx_mgr->p_event_wheel);
336d6b92ffaSHans Petter Selasky 		free(p_tx_mgr->p_event_wheel);
337d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
338d6b92ffaSHans Petter Selasky 	}
339d6b92ffaSHans Petter Selasky 
340d6b92ffaSHans Petter Selasky 	memset(p_tx_mgr->p_txn_map, 0, sizeof(cl_qmap_t));
341d6b92ffaSHans Petter Selasky 
342d6b92ffaSHans Petter Selasky 	cl_qmap_init(p_tx_mgr->p_txn_map);
343d6b92ffaSHans Petter Selasky 	p_tx_mgr->p_log = p_log;
344d6b92ffaSHans Petter Selasky 
345d6b92ffaSHans Petter Selasky 	return cl_st;
346d6b92ffaSHans Petter Selasky }
347d6b92ffaSHans Petter Selasky 
osmv_txnmgr_done(IN osm_bind_handle_t h_bind)348d6b92ffaSHans Petter Selasky void osmv_txnmgr_done(IN osm_bind_handle_t h_bind)
349d6b92ffaSHans Petter Selasky {
350d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
351d6b92ffaSHans Petter Selasky 
352d6b92ffaSHans Petter Selasky 	__osmv_txn_all_done(h_bind);
353d6b92ffaSHans Petter Selasky 	free(p_bo->txn_mgr.p_txn_map);
354d6b92ffaSHans Petter Selasky 
355d6b92ffaSHans Petter Selasky 	cl_event_wheel_destroy(p_bo->txn_mgr.p_event_wheel);
356d6b92ffaSHans Petter Selasky 	free(p_bo->txn_mgr.p_event_wheel);
357d6b92ffaSHans Petter Selasky }
358d6b92ffaSHans Petter Selasky 
359d6b92ffaSHans Petter Selasky ib_api_status_t
__osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,IN uint64_t key,OUT osmv_txn_ctx_t ** pp_txn)360d6b92ffaSHans Petter Selasky __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
361d6b92ffaSHans Petter Selasky 		     IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
362d6b92ffaSHans Petter Selasky {
363d6b92ffaSHans Petter Selasky 	ib_api_status_t status = IB_SUCCESS;
364d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_item;
365d6b92ffaSHans Petter Selasky 	cl_map_obj_t *p_obj;
366d6b92ffaSHans Petter Selasky 
367d6b92ffaSHans Petter Selasky 	uint64_t tmp_key;
368d6b92ffaSHans Petter Selasky 
369d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_tx_mgr->p_log);
370d6b92ffaSHans Petter Selasky 
371d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_tx_mgr);
372d6b92ffaSHans Petter Selasky 	CL_ASSERT(pp_txn);
373d6b92ffaSHans Petter Selasky 
374d6b92ffaSHans Petter Selasky 	osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
375d6b92ffaSHans Petter Selasky 		"__osmv_txnmgr_lookup: "
376d6b92ffaSHans Petter Selasky 		"Looking for key: 0x%016" PRIx64 " in map ptr:%p\n", key,
377d6b92ffaSHans Petter Selasky 		p_tx_mgr->p_txn_map);
378d6b92ffaSHans Petter Selasky 
379d6b92ffaSHans Petter Selasky 	p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
380d6b92ffaSHans Petter Selasky 	while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
381d6b92ffaSHans Petter Selasky 		tmp_key = cl_qmap_key(p_item);
382d6b92ffaSHans Petter Selasky 		osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
383d6b92ffaSHans Petter Selasky 			"__osmv_txnmgr_lookup: "
384d6b92ffaSHans Petter Selasky 			"Found key 0x%016" PRIx64 "\n", tmp_key);
385d6b92ffaSHans Petter Selasky 		p_item = cl_qmap_next(p_item);
386d6b92ffaSHans Petter Selasky 	}
387d6b92ffaSHans Petter Selasky 
388d6b92ffaSHans Petter Selasky 	p_item = cl_qmap_get(p_tx_mgr->p_txn_map, key);
389d6b92ffaSHans Petter Selasky 	if (cl_qmap_end(p_tx_mgr->p_txn_map) == p_item) {
390d6b92ffaSHans Petter Selasky 		status = IB_NOT_FOUND;
391d6b92ffaSHans Petter Selasky 	} else {
392d6b92ffaSHans Petter Selasky 		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
393d6b92ffaSHans Petter Selasky 		*pp_txn = cl_qmap_obj(p_obj);
394d6b92ffaSHans Petter Selasky 	}
395d6b92ffaSHans Petter Selasky 
396d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_tx_mgr->p_log);
397d6b92ffaSHans Petter Selasky 	return status;
398d6b92ffaSHans Petter Selasky }
399d6b92ffaSHans Petter Selasky 
400d6b92ffaSHans Petter Selasky ib_api_status_t
__osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,IN osmv_txn_ctx_t * p_txn,IN uint64_t key)401d6b92ffaSHans Petter Selasky __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
402d6b92ffaSHans Petter Selasky 			 IN osmv_txn_ctx_t * p_txn, IN uint64_t key)
403d6b92ffaSHans Petter Selasky {
404d6b92ffaSHans Petter Selasky 	cl_map_obj_t *p_obj = NULL;
405d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_item;
406d6b92ffaSHans Petter Selasky 	uint64_t tmp_key;
407d6b92ffaSHans Petter Selasky 
408d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_tx_mgr);
409d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_txn);
410d6b92ffaSHans Petter Selasky 
411d6b92ffaSHans Petter Selasky 	key = osmv_txn_get_key(p_txn);
412d6b92ffaSHans Petter Selasky 	p_obj = malloc(sizeof(cl_map_obj_t));
413d6b92ffaSHans Petter Selasky 	if (NULL == p_obj)
414d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
415d6b92ffaSHans Petter Selasky 
416d6b92ffaSHans Petter Selasky 	osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
417d6b92ffaSHans Petter Selasky 		"__osmv_txnmgr_insert_txn: "
418d6b92ffaSHans Petter Selasky 		"Inserting key: 0x%016" PRIx64 " to map ptr:%p\n", key,
419d6b92ffaSHans Petter Selasky 		p_tx_mgr->p_txn_map);
420d6b92ffaSHans Petter Selasky 
421d6b92ffaSHans Petter Selasky 	memset(p_obj, 0, sizeof(cl_map_obj_t));
422d6b92ffaSHans Petter Selasky 
423d6b92ffaSHans Petter Selasky 	cl_qmap_set_obj(p_obj, p_txn);
424d6b92ffaSHans Petter Selasky 	/* assuming lookup with this key was made and the result was IB_NOT_FOUND */
425d6b92ffaSHans Petter Selasky 	cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item);
426d6b92ffaSHans Petter Selasky 
427d6b92ffaSHans Petter Selasky 	p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
428d6b92ffaSHans Petter Selasky 	while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
429d6b92ffaSHans Petter Selasky 		tmp_key = cl_qmap_key(p_item);
430d6b92ffaSHans Petter Selasky 		osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
431d6b92ffaSHans Petter Selasky 			"__osmv_txnmgr_insert_txn: "
432d6b92ffaSHans Petter Selasky 			"Found key 0x%016" PRIx64 "\n", tmp_key);
433d6b92ffaSHans Petter Selasky 		p_item = cl_qmap_next(p_item);
434d6b92ffaSHans Petter Selasky 	}
435d6b92ffaSHans Petter Selasky 
436d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
437d6b92ffaSHans Petter Selasky }
438d6b92ffaSHans Petter Selasky 
439d6b92ffaSHans Petter Selasky ib_api_status_t
__osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,IN uint64_t key,OUT osmv_txn_ctx_t ** pp_txn)440d6b92ffaSHans Petter Selasky __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
441d6b92ffaSHans Petter Selasky 			 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
442d6b92ffaSHans Petter Selasky {
443d6b92ffaSHans Petter Selasky 	cl_map_obj_t *p_obj;
444d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_item;
445d6b92ffaSHans Petter Selasky 
446d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_tx_mgr->p_log);
447d6b92ffaSHans Petter Selasky 
448d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_tx_mgr);
449d6b92ffaSHans Petter Selasky 	CL_ASSERT(pp_txn);
450d6b92ffaSHans Petter Selasky 
451d6b92ffaSHans Petter Selasky 	p_item = cl_qmap_remove(p_tx_mgr->p_txn_map, key);
452d6b92ffaSHans Petter Selasky 
453d6b92ffaSHans Petter Selasky 	if (p_item == cl_qmap_end(p_tx_mgr->p_txn_map)) {
454d6b92ffaSHans Petter Selasky 
455d6b92ffaSHans Petter Selasky 		osm_log(p_tx_mgr->p_log, OSM_LOG_ERROR,
456d6b92ffaSHans Petter Selasky 			"__osmv_txnmgr_remove_txn: ERR 6701: "
457d6b92ffaSHans Petter Selasky 			"Could not remove the transaction 0x%016" PRIx64 " - "
458d6b92ffaSHans Petter Selasky 			"something is really wrong!\n", key);
459d6b92ffaSHans Petter Selasky 		OSM_LOG_EXIT(p_tx_mgr->p_log);
460d6b92ffaSHans Petter Selasky 		return IB_NOT_FOUND;
461d6b92ffaSHans Petter Selasky 	}
462d6b92ffaSHans Petter Selasky 
463d6b92ffaSHans Petter Selasky 	p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
464d6b92ffaSHans Petter Selasky 	*pp_txn = cl_qmap_obj(p_obj);
465d6b92ffaSHans Petter Selasky 
466d6b92ffaSHans Petter Selasky 	free(p_obj);
467d6b92ffaSHans Petter Selasky 
468d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_tx_mgr->p_log);
469d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
470d6b92ffaSHans Petter Selasky }
471d6b92ffaSHans Petter Selasky 
__osmv_txn_all_done(osm_bind_handle_t h_bind)472d6b92ffaSHans Petter Selasky void __osmv_txn_all_done(osm_bind_handle_t h_bind)
473d6b92ffaSHans Petter Selasky {
474d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
475d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_item;
476d6b92ffaSHans Petter Selasky 	cl_map_obj_t *p_obj;
477d6b92ffaSHans Petter Selasky 	osmv_txn_ctx_t *p_txn;
478d6b92ffaSHans Petter Selasky 
479d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
480d6b92ffaSHans Petter Selasky 
481d6b92ffaSHans Petter Selasky 	p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
482d6b92ffaSHans Petter Selasky 	while (p_item != cl_qmap_end(p_bo->txn_mgr.p_txn_map)) {
483d6b92ffaSHans Petter Selasky 
484d6b92ffaSHans Petter Selasky 		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
485d6b92ffaSHans Petter Selasky 		p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
486d6b92ffaSHans Petter Selasky 		osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
487d6b92ffaSHans Petter Selasky 		free(p_obj);
488d6b92ffaSHans Petter Selasky 		/* assuming osmv_txn_done has removed the txn from the map */
489d6b92ffaSHans Petter Selasky 		p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
490d6b92ffaSHans Petter Selasky 	}
491d6b92ffaSHans Petter Selasky 
492d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
493d6b92ffaSHans Petter Selasky }
494d6b92ffaSHans Petter Selasky 
495d6b92ffaSHans Petter Selasky /******************************************************************************/
496d6b92ffaSHans Petter Selasky 
osmv_txn_lock(IN osm_bind_handle_t h_bind)497d6b92ffaSHans Petter Selasky void osmv_txn_lock(IN osm_bind_handle_t h_bind)
498d6b92ffaSHans Petter Selasky {
499d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
500d6b92ffaSHans Petter Selasky 
501d6b92ffaSHans Petter Selasky 	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
502d6b92ffaSHans Petter Selasky 		"--> Acquiring lock %p on bind handle %p\n", &p_bo->lock, p_bo);
503d6b92ffaSHans Petter Selasky 
504d6b92ffaSHans Petter Selasky 	cl_spinlock_acquire(&p_bo->lock);
505d6b92ffaSHans Petter Selasky 
506d6b92ffaSHans Petter Selasky 	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
507d6b92ffaSHans Petter Selasky 		"--> Acquired lock %p on bind handle %p\n", &p_bo->lock, p_bo);
508d6b92ffaSHans Petter Selasky }
509d6b92ffaSHans Petter Selasky 
osmv_txn_unlock(IN osm_bind_handle_t h_bind)510d6b92ffaSHans Petter Selasky void osmv_txn_unlock(IN osm_bind_handle_t h_bind)
511d6b92ffaSHans Petter Selasky {
512d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
513d6b92ffaSHans Petter Selasky 	cl_spinlock_t *p_lock = &p_bo->lock;
514d6b92ffaSHans Petter Selasky 	osm_log_t *p_log = p_bo->p_vendor->p_log;
515d6b92ffaSHans Petter Selasky 
516d6b92ffaSHans Petter Selasky 	osm_log(p_log, OSM_LOG_DEBUG,
517d6b92ffaSHans Petter Selasky 		"<-- Releasing lock %p on bind handle %p\n", p_lock, p_bo);
518d6b92ffaSHans Petter Selasky 
519d6b92ffaSHans Petter Selasky 	cl_spinlock_release(&p_bo->lock);
520d6b92ffaSHans Petter Selasky 
521d6b92ffaSHans Petter Selasky 	/* We'll use the saved ptrs, since now the p_bo can be destroyed already */
522d6b92ffaSHans Petter Selasky 	osm_log(p_log, OSM_LOG_DEBUG,
523d6b92ffaSHans Petter Selasky 		"<-- Released lock %p on bind handle %p\n", p_lock, p_bo);
524d6b92ffaSHans Petter Selasky 
525d6b92ffaSHans Petter Selasky }
526d6b92ffaSHans Petter Selasky 
527d6b92ffaSHans Petter Selasky static uint64_t
__osmv_txn_timeout_cb(IN uint64_t key,IN uint32_t num_regs,IN void * cb_context)528d6b92ffaSHans Petter Selasky __osmv_txn_timeout_cb(IN uint64_t key,
529d6b92ffaSHans Petter Selasky 		      IN uint32_t num_regs, IN void *cb_context)
530d6b92ffaSHans Petter Selasky {
531d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) cb_context;
532d6b92ffaSHans Petter Selasky 	uint64_t ret = 0;
533d6b92ffaSHans Petter Selasky 	osmv_txn_ctx_t *p_txn;
534d6b92ffaSHans Petter Selasky 	osmv_rmpp_send_ctx_t *p_send_ctx;
535d6b92ffaSHans Petter Selasky 	osm_madw_t *p_madw = NULL;
536d6b92ffaSHans Petter Selasky 	ib_mad_t *p_mad;
537d6b92ffaSHans Petter Selasky 	osm_mad_addr_t *p_mad_addr;
538d6b92ffaSHans Petter Selasky 	boolean_t invoke_err_cb = FALSE;
539d6b92ffaSHans Petter Selasky 
540d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
541d6b92ffaSHans Petter Selasky 
542d6b92ffaSHans Petter Selasky 	/* Don't try to acquire a lock on the Bind Object -
543d6b92ffaSHans Petter Selasky 	 * it's taken by the mechanism that drives the timeout based events!
544d6b92ffaSHans Petter Selasky 	 * (Recall the special constructor that the Event Wheel is applied with)
545d6b92ffaSHans Petter Selasky 	 */
546d6b92ffaSHans Petter Selasky 	if (p_bo->is_closing) {
547d6b92ffaSHans Petter Selasky 		goto txn_done;
548d6b92ffaSHans Petter Selasky 	}
549d6b92ffaSHans Petter Selasky 
550d6b92ffaSHans Petter Selasky 	ret = osmv_txn_lookup(p_bo, key, &p_txn);
551d6b92ffaSHans Petter Selasky 	if (IB_NOT_FOUND == ret) {
552d6b92ffaSHans Petter Selasky 		/* Prevent a race - the transaction is already destroyed */
553d6b92ffaSHans Petter Selasky 		goto txn_done;
554d6b92ffaSHans Petter Selasky 	}
555d6b92ffaSHans Petter Selasky 
556d6b92ffaSHans Petter Selasky 	p_madw = p_txn->p_madw;
557d6b92ffaSHans Petter Selasky 
558d6b92ffaSHans Petter Selasky 	switch (osmv_txn_get_rmpp_state(p_txn)) {
559d6b92ffaSHans Petter Selasky 
560d6b92ffaSHans Petter Selasky 	case OSMV_TXN_RMPP_NONE:
561d6b92ffaSHans Petter Selasky 		if (num_regs <= OSM_DEFAULT_RETRY_COUNT) {
562d6b92ffaSHans Petter Selasky 			/* We still did not exceed the limit of retransmissions.
563d6b92ffaSHans Petter Selasky 			 * Set the next timeout's value.
564d6b92ffaSHans Petter Selasky 			 */
565d6b92ffaSHans Petter Selasky 			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
566d6b92ffaSHans Petter Selasky 				"__osmv_txn_timeout_cb: "
567d6b92ffaSHans Petter Selasky 				"The transaction request (tid=0x%016" PRIx64 ")"
568d6b92ffaSHans Petter Selasky 				" timed out %d times. Retrying the send.\n",
569d6b92ffaSHans Petter Selasky 				osmv_txn_get_tid(p_txn), num_regs);
570d6b92ffaSHans Petter Selasky 
571d6b92ffaSHans Petter Selasky 			/* resend this mad */
572d6b92ffaSHans Petter Selasky 			ret = osmv_simple_send_madw((osm_bind_handle_t *) p_bo,
573d6b92ffaSHans Petter Selasky 						    p_madw, p_txn, TRUE);
574d6b92ffaSHans Petter Selasky 			if (ret != IB_SUCCESS) {
575d6b92ffaSHans Petter Selasky 				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
576d6b92ffaSHans Petter Selasky 					"__osmv_txn_timeout_cb: "
577d6b92ffaSHans Petter Selasky 					"Fail to send retry for transaction"
578d6b92ffaSHans Petter Selasky 					"request (tid=0x%016" PRIx64 ").\n",
579d6b92ffaSHans Petter Selasky 					osmv_txn_get_tid(p_txn));
580d6b92ffaSHans Petter Selasky 
581d6b92ffaSHans Petter Selasky 				osmv_txn_done((osm_bind_handle_t) p_bo, key,
582d6b92ffaSHans Petter Selasky 					      TRUE /*in timeout callback */ );
583d6b92ffaSHans Petter Selasky 
584d6b92ffaSHans Petter Selasky 				/* This is a requester. Always apply the callback */
585d6b92ffaSHans Petter Selasky 				invoke_err_cb = TRUE;
586d6b92ffaSHans Petter Selasky 			} else {
587d6b92ffaSHans Petter Selasky 				uint64_t next_timeout_ms;
588d6b92ffaSHans Petter Selasky 				next_timeout_ms =
589d6b92ffaSHans Petter Selasky 				    p_bo->p_vendor->resp_timeout * (num_regs +
590d6b92ffaSHans Petter Selasky 								    1) *
591d6b92ffaSHans Petter Selasky 				    (num_regs + 1);
592d6b92ffaSHans Petter Selasky 				/* when do we need to timeout again */
593d6b92ffaSHans Petter Selasky 				ret =
594d6b92ffaSHans Petter Selasky 				    cl_get_time_stamp() +
595d6b92ffaSHans Petter Selasky 				    (uint64_t) (1000 * next_timeout_ms);
596d6b92ffaSHans Petter Selasky 
597d6b92ffaSHans Petter Selasky 				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
598d6b92ffaSHans Petter Selasky 					"__osmv_txn_timeout_cb: "
599d6b92ffaSHans Petter Selasky 					"Retry request timout in : %lu [msec].\n",
600d6b92ffaSHans Petter Selasky 					next_timeout_ms);
601d6b92ffaSHans Petter Selasky 			}
602d6b92ffaSHans Petter Selasky 		} else {
603d6b92ffaSHans Petter Selasky 			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
604d6b92ffaSHans Petter Selasky 				"__osmv_txn_timeout_cb: ERR 6702: "
605d6b92ffaSHans Petter Selasky 				"The transaction request (0x%016" PRIx64 ") "
606d6b92ffaSHans Petter Selasky 				"timed out (after %d retries). "
607d6b92ffaSHans Petter Selasky 				"Invoking the error callback.\n",
608d6b92ffaSHans Petter Selasky 				osmv_txn_get_tid(p_txn), num_regs);
609d6b92ffaSHans Petter Selasky 
610d6b92ffaSHans Petter Selasky 			osmv_txn_done((osm_bind_handle_t) p_bo, key,
611d6b92ffaSHans Petter Selasky 				      TRUE /*in timeout callback */ );
612d6b92ffaSHans Petter Selasky 
613d6b92ffaSHans Petter Selasky 			/* This is a requester. Always apply the callback */
614d6b92ffaSHans Petter Selasky 			invoke_err_cb = TRUE;
615d6b92ffaSHans Petter Selasky 		}
616d6b92ffaSHans Petter Selasky 		break;
617d6b92ffaSHans Petter Selasky 
618d6b92ffaSHans Petter Selasky 	case OSMV_TXN_RMPP_SENDER:
619d6b92ffaSHans Petter Selasky 		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
620d6b92ffaSHans Petter Selasky 			"RMPP sender (tid=0x%016" PRIx64 ") did not receive ACK "
621d6b92ffaSHans Petter Selasky 			"on every segment in the current send window.\n",
622d6b92ffaSHans Petter Selasky 			osmv_txn_get_tid(p_txn));
623d6b92ffaSHans Petter Selasky 
624d6b92ffaSHans Petter Selasky 		p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
625d6b92ffaSHans Petter Selasky 		if (num_regs <= OSM_DEFAULT_RETRY_COUNT) {
626d6b92ffaSHans Petter Selasky 			/* We still did not exceed the limit of retransmissions.
627d6b92ffaSHans Petter Selasky 			 * Set the next timeout's value.
628d6b92ffaSHans Petter Selasky 			 */
629d6b92ffaSHans Petter Selasky 			ret =
630d6b92ffaSHans Petter Selasky 			    cl_get_time_stamp() +
631d6b92ffaSHans Petter Selasky 			    1000 * p_bo->p_vendor->resp_timeout;
632d6b92ffaSHans Petter Selasky 		} else {
633d6b92ffaSHans Petter Selasky 			p_send_ctx->status = IB_TIMEOUT;
634d6b92ffaSHans Petter Selasky 
635d6b92ffaSHans Petter Selasky 			p_mad = osm_madw_get_mad_ptr(p_madw);
636d6b92ffaSHans Petter Selasky 			p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
637d6b92ffaSHans Petter Selasky 
638d6b92ffaSHans Petter Selasky 			/* Send an ABORT to the other side */
639d6b92ffaSHans Petter Selasky 			osmv_rmpp_send_nak((osm_bind_handle_t) p_bo, p_mad,
640d6b92ffaSHans Petter Selasky 					   p_mad_addr, IB_RMPP_TYPE_ABORT,
641d6b92ffaSHans Petter Selasky 					   IB_RMPP_STATUS_T2L);
642d6b92ffaSHans Petter Selasky 		}
643d6b92ffaSHans Petter Selasky 
644d6b92ffaSHans Petter Selasky 		/* Wake the RMPP sender thread up */
645d6b92ffaSHans Petter Selasky 		cl_event_signal(&p_send_ctx->event);
646d6b92ffaSHans Petter Selasky 		break;
647d6b92ffaSHans Petter Selasky 
648d6b92ffaSHans Petter Selasky 	case OSMV_TXN_RMPP_RECEIVER:
649d6b92ffaSHans Petter Selasky 		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
650d6b92ffaSHans Petter Selasky 			"Transaction timeout on an RMPP receiver "
651d6b92ffaSHans Petter Selasky 			"(tid=0x%016" PRIx64 "). Dropping the transaction.\n",
652d6b92ffaSHans Petter Selasky 			osmv_txn_get_tid(p_txn));
653d6b92ffaSHans Petter Selasky 
654d6b92ffaSHans Petter Selasky 		osmv_txn_done((osm_bind_handle_t) p_bo, key,
655d6b92ffaSHans Petter Selasky 			      TRUE /*in timeout callback */ );
656d6b92ffaSHans Petter Selasky 
657d6b92ffaSHans Petter Selasky 		if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) {
658d6b92ffaSHans Petter Selasky 			/* This is a requester, still waiting for the reply. Apply the callback */
659d6b92ffaSHans Petter Selasky 			invoke_err_cb = TRUE;
660d6b92ffaSHans Petter Selasky 		}
661d6b92ffaSHans Petter Selasky 
662d6b92ffaSHans Petter Selasky 		break;
663d6b92ffaSHans Petter Selasky 
664d6b92ffaSHans Petter Selasky 	default:
665d6b92ffaSHans Petter Selasky 		CL_ASSERT(FALSE);
666d6b92ffaSHans Petter Selasky 	}
667d6b92ffaSHans Petter Selasky 
668d6b92ffaSHans Petter Selasky 	if (TRUE == invoke_err_cb) {
669d6b92ffaSHans Petter Selasky 		CL_ASSERT(NULL != p_madw);
670d6b92ffaSHans Petter Selasky 		/* update the status in the p_madw */
671d6b92ffaSHans Petter Selasky 		p_madw->status = IB_TIMEOUT;
672d6b92ffaSHans Petter Selasky 		p_bo->send_err_cb(p_bo->cb_context, p_madw);
673d6b92ffaSHans Petter Selasky 		/* no re-registration */
674d6b92ffaSHans Petter Selasky 		ret = 0;
675d6b92ffaSHans Petter Selasky 	}
676d6b92ffaSHans Petter Selasky 
677d6b92ffaSHans Petter Selasky txn_done:
678d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
679d6b92ffaSHans Petter Selasky 	return ret;
680d6b92ffaSHans Petter Selasky }
681