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 <stdlib.h> 41219820Sjeff 42219820Sjeff#include <vendor/osm_vendor_mlx.h> 43219820Sjeff#include <vendor/osm_vendor_mlx_defs.h> 44219820Sjeff#include <vendor/osm_vendor_mlx_txn.h> 45219820Sjeff#include <vendor/osm_vendor_mlx_svc.h> 46219820Sjeff#include <vendor/osm_vendor_mlx_sender.h> 47219820Sjeff 48219820Sjeffstatic ib_api_status_t 49219820Sjeff__osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr, 50219820Sjeff IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); 51219820Sjeff 52219820Sjeffstatic ib_api_status_t 53219820Sjeff__osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr, 54219820Sjeff IN osmv_txn_ctx_t * p_txn, IN uint64_t key); 55219820Sjeff 56219820Sjeffstatic ib_api_status_t 57219820Sjeff__osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr, 58219820Sjeff IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); 59219820Sjeff 60219820Sjeffstatic void __osmv_txn_all_done(osm_bind_handle_t h_bind); 61219820Sjeff 62219820Sjeffstatic uint64_t 63219820Sjeff__osmv_txn_timeout_cb(IN uint64_t key, 64219820Sjeff IN uint32_t num_regs, IN void *cb_context); 65219820Sjeff 66219820Sjeffib_api_status_t 67219820Sjeffosmv_txn_init(IN osm_bind_handle_t h_bind, 68219820Sjeff IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) 69219820Sjeff{ 70219820Sjeff ib_api_status_t st; 71219820Sjeff osmv_txn_ctx_t *p_txn; 72219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 73219820Sjeff 74219820Sjeff OSM_LOG_ENTER(p_bo->p_vendor->p_log); 75219820Sjeff 76219820Sjeff CL_ASSERT(NULL != h_bind && NULL != pp_txn); 77219820Sjeff 78219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 79219820Sjeff "Starting transaction 0x%llX (key=0x%llX)\n", tid, key); 80219820Sjeff 81219820Sjeff p_txn = malloc(sizeof(osmv_txn_ctx_t)); 82219820Sjeff if (!p_txn) { 83219820Sjeff return IB_INSUFFICIENT_MEMORY; 84219820Sjeff } 85219820Sjeff 86219820Sjeff memset(p_txn, 0, sizeof(osmv_txn_ctx_t)); 87219820Sjeff p_txn->p_log = p_bo->txn_mgr.p_log; 88219820Sjeff p_txn->tid = tid; 89219820Sjeff p_txn->key = key; 90219820Sjeff p_txn->p_madw = NULL; 91219820Sjeff p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_NONE; 92219820Sjeff 93219820Sjeff /* insert into transaction manager DB */ 94219820Sjeff st = __osmv_txnmgr_insert_txn(&p_bo->txn_mgr, p_txn, key); 95219820Sjeff if (IB_SUCCESS != st) { 96219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 97219820Sjeff "osmv_txn_init: ERR 6703: " 98219820Sjeff "Failed to insert to transaction 0x%llX (key=0x%llX) to manager DB\n", 99219820Sjeff tid, key); 100219820Sjeff goto insert_txn_failed; 101219820Sjeff } 102219820Sjeff 103219820Sjeff *pp_txn = p_txn; 104219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 105219820Sjeff return IB_SUCCESS; 106219820Sjeff 107219820Sjeffinsert_txn_failed: 108219820Sjeff free(p_txn); 109219820Sjeff 110219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 111219820Sjeff return st; 112219820Sjeff} 113219820Sjeff 114219820Sjeffib_api_status_t 115219820Sjeffosmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind, 116219820Sjeff IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw) 117219820Sjeff{ 118219820Sjeff ib_api_status_t st; 119219820Sjeff 120219820Sjeff CL_ASSERT(p_txn); 121219820Sjeff 122219820Sjeff /* Double-Sided RMPP Direction Switch */ 123219820Sjeff osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn)); 124219820Sjeff 125219820Sjeff p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER; 126219820Sjeff p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t)); 127219820Sjeff 128219820Sjeff if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) { 129219820Sjeff return IB_INSUFFICIENT_MEMORY; 130219820Sjeff } 131219820Sjeff 132219820Sjeff memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0, 133219820Sjeff sizeof(osmv_rmpp_send_ctx_t)); 134219820Sjeff 135219820Sjeff st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx, 136219820Sjeff (void *)p_madw->p_mad, 137219820Sjeff p_madw->mad_size, p_txn->p_log); 138219820Sjeff return st; 139219820Sjeff} 140219820Sjeff 141219820Sjeffib_api_status_t 142219820Sjeffosmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind, 143219820Sjeff IN osmv_txn_ctx_t * p_txn, 144219820Sjeff IN boolean_t is_init_by_peer) 145219820Sjeff{ 146219820Sjeff ib_api_status_t st; 147219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 148219820Sjeff uint64_t key = osmv_txn_get_key(p_txn); 149219820Sjeff 150219820Sjeff CL_ASSERT(p_txn); 151219820Sjeff 152219820Sjeff /* Double-Sided RMPP Direction Switch */ 153219820Sjeff osmv_txn_remove_timeout_ev(h_bind, key); 154219820Sjeff 155219820Sjeff /* Set the Transaction Timeout value */ 156219820Sjeff st = osmv_txn_set_timeout_ev(h_bind, key, 157219820Sjeff p_bo->p_vendor->ttime_timeout); 158219820Sjeff if (IB_SUCCESS != st) { 159219820Sjeff 160219820Sjeff return st; 161219820Sjeff } 162219820Sjeff 163219820Sjeff p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER; 164219820Sjeff p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer; 165219820Sjeff 166219820Sjeff p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t)); 167219820Sjeff 168219820Sjeff if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) { 169219820Sjeff 170219820Sjeff osmv_txn_remove_timeout_ev(h_bind, key); 171219820Sjeff return IB_INSUFFICIENT_MEMORY; 172219820Sjeff } 173219820Sjeff 174219820Sjeff memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0, 175219820Sjeff sizeof(osmv_rmpp_recv_ctx_t)); 176219820Sjeff 177219820Sjeff st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 178219820Sjeff p_txn->p_log); 179219820Sjeff 180219820Sjeff return st; 181219820Sjeff} 182219820Sjeff 183219820Sjeff/* 184219820Sjeff * NAME 185219820Sjeff * osmv_txn_set_timeout_ev 186219820Sjeff * 187219820Sjeff * DESCRIPTION 188219820Sjeff * 189219820Sjeff * SEE ALSO 190219820Sjeff * 191219820Sjeff */ 192219820Sjeffib_api_status_t 193219820Sjeffosmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind, 194219820Sjeff IN uint64_t key, IN uint64_t msec) 195219820Sjeff{ 196219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 197219820Sjeff cl_event_wheel_t *p_event_wheel = p_bo->txn_mgr.p_event_wheel; 198219820Sjeff cl_status_t status; 199219820Sjeff 200219820Sjeff status = cl_event_wheel_reg(p_event_wheel, key, cl_get_time_stamp() + 1000 * msec, /* TTL */ 201219820Sjeff __osmv_txn_timeout_cb, 202219820Sjeff p_bo /* The context */ ); 203219820Sjeff 204219820Sjeff return (ib_api_status_t) status; 205219820Sjeff} 206219820Sjeff 207219820Sjeff/* 208219820Sjeff * NAME 209219820Sjeff * osmv_txn_remove_timeout_ev 210219820Sjeff * 211219820Sjeff * DESCRIPTION 212219820Sjeff 213219820Sjeff * SEE ALSO 214219820Sjeff * 215219820Sjeff */ 216219820Sjeffvoid osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key) 217219820Sjeff{ 218219820Sjeff cl_event_wheel_t *p_event_wheel = 219219820Sjeff ((osmv_bind_obj_t *) h_bind)->txn_mgr.p_event_wheel; 220219820Sjeff cl_event_wheel_unreg(p_event_wheel, key); 221219820Sjeff} 222219820Sjeff 223219820Sjeffvoid 224219820Sjeffosmv_txn_done(IN osm_bind_handle_t h_bind, 225219820Sjeff IN uint64_t key, IN boolean_t is_in_cb) 226219820Sjeff{ 227219820Sjeff osmv_txn_ctx_t *p_ctx; 228219820Sjeff osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind; 229219820Sjeff 230219820Sjeff OSM_LOG_ENTER(p_bo->p_vendor->p_log); 231219820Sjeff 232219820Sjeff CL_ASSERT(h_bind); 233219820Sjeff 234219820Sjeff /* Cancel the (single) timeout possibly outstanding for this txn 235219820Sjeff * Don't do this if you are in the callback context, for 2 reasons: 236219820Sjeff * (1) The event wheel will remove the context itself. 237219820Sjeff * (2) If we try to, there is a deadlock in the event wheel 238219820Sjeff */ 239219820Sjeff if (FALSE == is_in_cb) { 240219820Sjeff osmv_txn_remove_timeout_ev(h_bind, key); 241219820Sjeff } 242219820Sjeff 243219820Sjeff /* Remove from DB */ 244219820Sjeff if (IB_NOT_FOUND == 245219820Sjeff __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) { 246219820Sjeff return; 247219820Sjeff } 248219820Sjeff 249219820Sjeff /* Destroy the transaction's RMPP contexts 250219820Sjeff * (can be more than one in the case of double sided transfer) 251219820Sjeff */ 252219820Sjeff 253219820Sjeff if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) { 254219820Sjeff osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx); 255219820Sjeff } 256219820Sjeff 257219820Sjeff if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) { 258219820Sjeff osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx); 259219820Sjeff } 260219820Sjeff 261219820Sjeff free(p_ctx); 262219820Sjeff 263219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 264219820Sjeff} 265219820Sjeff 266219820Sjeffib_api_status_t 267219820Sjeffosmv_txn_lookup(IN osm_bind_handle_t h_bind, 268219820Sjeff IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) 269219820Sjeff{ 270219820Sjeff return __osmv_txnmgr_lookup(&(((osmv_bind_obj_t *) h_bind)->txn_mgr), 271219820Sjeff key, pp_txn); 272219820Sjeff} 273219820Sjeff 274219820Sjeffvoid osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind) 275219820Sjeff{ 276219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 277219820Sjeff cl_map_item_t *p_item; 278219820Sjeff cl_map_obj_t *p_obj; 279219820Sjeff osmv_txn_ctx_t *p_txn; 280219820Sjeff osmv_rmpp_send_ctx_t *p_send_ctx; 281219820Sjeff cl_qmap_t *p_map = p_bo->txn_mgr.p_txn_map; 282219820Sjeff 283219820Sjeff OSM_LOG_ENTER(p_bo->p_vendor->p_log); 284219820Sjeff 285219820Sjeff while (FALSE == cl_is_qmap_empty(p_map)) { 286219820Sjeff 287219820Sjeff p_item = cl_qmap_head(p_map); 288219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); 289219820Sjeff p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj); 290219820Sjeff p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); 291219820Sjeff 292219820Sjeff if (NULL != p_send_ctx) { 293219820Sjeff 294219820Sjeff p_send_ctx->status = IB_INTERRUPTED; 295219820Sjeff 296219820Sjeff /* Wake up the sender thread to let it break out */ 297219820Sjeff cl_event_signal(&p_send_ctx->event); 298219820Sjeff } 299219820Sjeff 300219820Sjeff cl_qmap_remove_item(p_map, p_item); 301219820Sjeff } 302219820Sjeff 303219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 304219820Sjeff} 305219820Sjeff 306219820Sjeffib_api_status_t 307219820Sjeffosmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr, 308219820Sjeff IN osm_log_t * p_log, IN cl_spinlock_t * p_lock) 309219820Sjeff{ 310219820Sjeff cl_status_t cl_st = CL_SUCCESS; 311219820Sjeff 312219820Sjeff p_tx_mgr->p_event_wheel = malloc(sizeof(cl_event_wheel_t)); 313219820Sjeff if (!p_tx_mgr->p_event_wheel) { 314219820Sjeff return IB_INSUFFICIENT_MEMORY; 315219820Sjeff } 316219820Sjeff 317219820Sjeff memset(p_tx_mgr->p_event_wheel, 0, sizeof(cl_event_wheel_t)); 318219820Sjeff 319219820Sjeff cl_event_wheel_construct(p_tx_mgr->p_event_wheel); 320219820Sjeff 321219820Sjeff /* NOTE! We are using an extended constructor. 322219820Sjeff * We tell the Event Wheel run in a non-protected manner in the reg/unreg calls, 323219820Sjeff * and acquire an external lock in the asynchronous callback. 324219820Sjeff */ 325219820Sjeff cl_st = cl_event_wheel_init_ex(p_tx_mgr->p_event_wheel, p_lock); 326219820Sjeff if (cl_st != CL_SUCCESS) { 327219820Sjeff free(p_tx_mgr->p_event_wheel); 328219820Sjeff return (ib_api_status_t) cl_st; 329219820Sjeff } 330219820Sjeff 331219820Sjeff p_tx_mgr->p_txn_map = malloc(sizeof(cl_qmap_t)); 332219820Sjeff if (!p_tx_mgr->p_txn_map) { 333219820Sjeff cl_event_wheel_destroy(p_tx_mgr->p_event_wheel); 334219820Sjeff free(p_tx_mgr->p_event_wheel); 335219820Sjeff return IB_INSUFFICIENT_MEMORY; 336219820Sjeff } 337219820Sjeff 338219820Sjeff memset(p_tx_mgr->p_txn_map, 0, sizeof(cl_qmap_t)); 339219820Sjeff 340219820Sjeff cl_qmap_init(p_tx_mgr->p_txn_map); 341219820Sjeff p_tx_mgr->p_log = p_log; 342219820Sjeff 343219820Sjeff return cl_st; 344219820Sjeff} 345219820Sjeff 346219820Sjeffvoid osmv_txnmgr_done(IN osm_bind_handle_t h_bind) 347219820Sjeff{ 348219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 349219820Sjeff 350219820Sjeff __osmv_txn_all_done(h_bind); 351219820Sjeff free(p_bo->txn_mgr.p_txn_map); 352219820Sjeff 353219820Sjeff cl_event_wheel_destroy(p_bo->txn_mgr.p_event_wheel); 354219820Sjeff free(p_bo->txn_mgr.p_event_wheel); 355219820Sjeff} 356219820Sjeff 357219820Sjeffib_api_status_t 358219820Sjeff__osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr, 359219820Sjeff IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) 360219820Sjeff{ 361219820Sjeff ib_api_status_t status = IB_SUCCESS; 362219820Sjeff cl_map_item_t *p_item; 363219820Sjeff cl_map_obj_t *p_obj; 364219820Sjeff 365219820Sjeff uint64_t tmp_key; 366219820Sjeff 367219820Sjeff OSM_LOG_ENTER(p_tx_mgr->p_log); 368219820Sjeff 369219820Sjeff CL_ASSERT(p_tx_mgr); 370219820Sjeff CL_ASSERT(pp_txn); 371219820Sjeff 372219820Sjeff osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, 373219820Sjeff "__osmv_txnmgr_lookup: " 374219820Sjeff "Looking for key: 0x%llX in map ptr:%p\n", key, 375219820Sjeff p_tx_mgr->p_txn_map); 376219820Sjeff 377219820Sjeff p_item = cl_qmap_head(p_tx_mgr->p_txn_map); 378219820Sjeff while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) { 379219820Sjeff tmp_key = cl_qmap_key(p_item); 380219820Sjeff osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, 381219820Sjeff "__osmv_txnmgr_lookup: " 382219820Sjeff "Found key 0x%llX \n", tmp_key); 383219820Sjeff p_item = cl_qmap_next(p_item); 384219820Sjeff } 385219820Sjeff 386219820Sjeff p_item = cl_qmap_get(p_tx_mgr->p_txn_map, key); 387219820Sjeff if (cl_qmap_end(p_tx_mgr->p_txn_map) == p_item) { 388219820Sjeff status = IB_NOT_FOUND; 389219820Sjeff } else { 390219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); 391219820Sjeff *pp_txn = cl_qmap_obj(p_obj); 392219820Sjeff } 393219820Sjeff 394219820Sjeff OSM_LOG_EXIT(p_tx_mgr->p_log); 395219820Sjeff return status; 396219820Sjeff} 397219820Sjeff 398219820Sjeffib_api_status_t 399219820Sjeff__osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr, 400219820Sjeff IN osmv_txn_ctx_t * p_txn, IN uint64_t key) 401219820Sjeff{ 402219820Sjeff cl_map_obj_t *p_obj = NULL; 403219820Sjeff cl_map_item_t *p_item; 404219820Sjeff uint64_t tmp_key; 405219820Sjeff 406219820Sjeff CL_ASSERT(p_tx_mgr); 407219820Sjeff CL_ASSERT(p_txn); 408219820Sjeff 409219820Sjeff key = osmv_txn_get_key(p_txn); 410219820Sjeff p_obj = malloc(sizeof(cl_map_obj_t)); 411219820Sjeff if (NULL == p_obj) 412219820Sjeff return IB_INSUFFICIENT_MEMORY; 413219820Sjeff 414219820Sjeff osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, 415219820Sjeff "__osmv_txnmgr_insert_txn: " 416219820Sjeff "Inserting key: 0x%llX to map ptr:%p\n", key, 417219820Sjeff p_tx_mgr->p_txn_map); 418219820Sjeff 419219820Sjeff memset(p_obj, 0, sizeof(cl_map_obj_t)); 420219820Sjeff 421219820Sjeff cl_qmap_set_obj(p_obj, p_txn); 422219820Sjeff /* assuming lookup with this key was made and the result was IB_NOT_FOUND */ 423219820Sjeff cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item); 424219820Sjeff 425219820Sjeff p_item = cl_qmap_head(p_tx_mgr->p_txn_map); 426219820Sjeff while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) { 427219820Sjeff tmp_key = cl_qmap_key(p_item); 428219820Sjeff osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, 429219820Sjeff "__osmv_txnmgr_insert_txn: " 430219820Sjeff "Found key 0x%llX \n", tmp_key); 431219820Sjeff p_item = cl_qmap_next(p_item); 432219820Sjeff } 433219820Sjeff 434219820Sjeff return IB_SUCCESS; 435219820Sjeff} 436219820Sjeff 437219820Sjeffib_api_status_t 438219820Sjeff__osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr, 439219820Sjeff IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) 440219820Sjeff{ 441219820Sjeff cl_map_obj_t *p_obj; 442219820Sjeff cl_map_item_t *p_item; 443219820Sjeff 444219820Sjeff OSM_LOG_ENTER(p_tx_mgr->p_log); 445219820Sjeff 446219820Sjeff CL_ASSERT(p_tx_mgr); 447219820Sjeff CL_ASSERT(pp_txn); 448219820Sjeff 449219820Sjeff p_item = cl_qmap_remove(p_tx_mgr->p_txn_map, key); 450219820Sjeff 451219820Sjeff if (p_item == cl_qmap_end(p_tx_mgr->p_txn_map)) { 452219820Sjeff 453219820Sjeff osm_log(p_tx_mgr->p_log, OSM_LOG_ERROR, 454219820Sjeff "__osmv_txnmgr_remove_txn: ERR 6701: " 455219820Sjeff "Could not remove the transaction 0x%llX - " 456219820Sjeff "something is really wrong!\n", key); 457219820Sjeff OSM_LOG_EXIT(p_tx_mgr->p_log); 458219820Sjeff return IB_NOT_FOUND; 459219820Sjeff } 460219820Sjeff 461219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); 462219820Sjeff *pp_txn = cl_qmap_obj(p_obj); 463219820Sjeff 464219820Sjeff free(p_obj); 465219820Sjeff 466219820Sjeff OSM_LOG_EXIT(p_tx_mgr->p_log); 467219820Sjeff return IB_SUCCESS; 468219820Sjeff} 469219820Sjeff 470219820Sjeffvoid __osmv_txn_all_done(osm_bind_handle_t h_bind) 471219820Sjeff{ 472219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 473219820Sjeff cl_map_item_t *p_item; 474219820Sjeff cl_map_obj_t *p_obj; 475219820Sjeff osmv_txn_ctx_t *p_txn; 476219820Sjeff 477219820Sjeff OSM_LOG_ENTER(p_bo->p_vendor->p_log); 478219820Sjeff 479219820Sjeff p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map); 480219820Sjeff while (p_item != cl_qmap_end(p_bo->txn_mgr.p_txn_map)) { 481219820Sjeff 482219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); 483219820Sjeff p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj); 484219820Sjeff osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE); 485219820Sjeff free(p_obj); 486219820Sjeff /* assuming osmv_txn_done has removed the txn from the map */ 487219820Sjeff p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map); 488219820Sjeff } 489219820Sjeff 490219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 491219820Sjeff} 492219820Sjeff 493219820Sjeff/******************************************************************************/ 494219820Sjeff 495219820Sjeffvoid osmv_txn_lock(IN osm_bind_handle_t h_bind) 496219820Sjeff{ 497219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 498219820Sjeff 499219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 500219820Sjeff "--> Acquiring lock %p on bind handle %p\n", &p_bo->lock, p_bo); 501219820Sjeff 502219820Sjeff cl_spinlock_acquire(&p_bo->lock); 503219820Sjeff 504219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 505219820Sjeff "--> Acquired lock %p on bind handle %p\n", &p_bo->lock, p_bo); 506219820Sjeff} 507219820Sjeff 508219820Sjeffvoid osmv_txn_unlock(IN osm_bind_handle_t h_bind) 509219820Sjeff{ 510219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 511219820Sjeff cl_spinlock_t *p_lock = &p_bo->lock; 512219820Sjeff osm_log_t *p_log = p_bo->p_vendor->p_log; 513219820Sjeff 514219820Sjeff osm_log(p_log, OSM_LOG_DEBUG, 515219820Sjeff "<-- Releasing lock %p on bind handle %p\n", p_lock, p_bo); 516219820Sjeff 517219820Sjeff cl_spinlock_release(&p_bo->lock); 518219820Sjeff 519219820Sjeff /* We'll use the saved ptrs, since now the p_bo can be destroyed already */ 520219820Sjeff osm_log(p_log, OSM_LOG_DEBUG, 521219820Sjeff "<-- Released lock %p on bind handle %p\n", p_lock, p_bo); 522219820Sjeff 523219820Sjeff} 524219820Sjeff 525219820Sjeffstatic uint64_t 526219820Sjeff__osmv_txn_timeout_cb(IN uint64_t key, 527219820Sjeff IN uint32_t num_regs, IN void *cb_context) 528219820Sjeff{ 529219820Sjeff osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) cb_context; 530219820Sjeff uint64_t ret = 0; 531219820Sjeff osmv_txn_ctx_t *p_txn; 532219820Sjeff osmv_rmpp_send_ctx_t *p_send_ctx; 533219820Sjeff osm_madw_t *p_madw = NULL; 534219820Sjeff ib_mad_t *p_mad; 535219820Sjeff osm_mad_addr_t *p_mad_addr; 536219820Sjeff boolean_t invoke_err_cb = FALSE; 537219820Sjeff 538219820Sjeff OSM_LOG_ENTER(p_bo->p_vendor->p_log); 539219820Sjeff 540219820Sjeff /* Don't try to acquire a lock on the Bind Object - 541219820Sjeff * it's taken by the mechanism that drives the timeout based events! 542219820Sjeff * (Recall the special constructor that the Event Wheel is applied with) 543219820Sjeff */ 544219820Sjeff if (p_bo->is_closing) { 545219820Sjeff goto txn_done; 546219820Sjeff } 547219820Sjeff 548219820Sjeff ret = osmv_txn_lookup(p_bo, key, &p_txn); 549219820Sjeff if (IB_NOT_FOUND == ret) { 550219820Sjeff /* Prevent a race - the transaction is already destroyed */ 551219820Sjeff goto txn_done; 552219820Sjeff } 553219820Sjeff 554219820Sjeff p_madw = p_txn->p_madw; 555219820Sjeff 556219820Sjeff switch (osmv_txn_get_rmpp_state(p_txn)) { 557219820Sjeff 558219820Sjeff case OSMV_TXN_RMPP_NONE: 559219820Sjeff if (num_regs <= OSMV_MAX_RETRANSMIT) { 560219820Sjeff /* We still did not exceed the limit of retransmissions. 561219820Sjeff * Set the next timeout's value. 562219820Sjeff */ 563219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 564219820Sjeff "__osmv_txn_timeout_cb: " 565219820Sjeff "The transaction request (tid=0x%llX) timed out %d times. " 566219820Sjeff "Retrying the send.\n", 567219820Sjeff osmv_txn_get_tid(p_txn), num_regs); 568219820Sjeff 569219820Sjeff /* resend this mad */ 570219820Sjeff ret = osmv_simple_send_madw((osm_bind_handle_t *) p_bo, 571219820Sjeff p_madw, p_txn, TRUE); 572219820Sjeff if (ret != IB_SUCCESS) { 573219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 574219820Sjeff "__osmv_txn_timeout_cb: " 575219820Sjeff "Fail to send retry for transaction request (tid=0x%llX).\n", 576219820Sjeff osmv_txn_get_tid(p_txn)); 577219820Sjeff 578219820Sjeff osmv_txn_done((osm_bind_handle_t) p_bo, key, 579219820Sjeff TRUE /*in timeout callback */ ); 580219820Sjeff 581219820Sjeff /* This is a requester. Always apply the callback */ 582219820Sjeff invoke_err_cb = TRUE; 583219820Sjeff } else { 584219820Sjeff uint64_t next_timeout_ms; 585219820Sjeff next_timeout_ms = 586219820Sjeff p_bo->p_vendor->resp_timeout * (num_regs + 587219820Sjeff 1) * 588219820Sjeff (num_regs + 1); 589219820Sjeff /* when do we need to timeout again */ 590219820Sjeff ret = 591219820Sjeff cl_get_time_stamp() + 592219820Sjeff (uint64_t) (1000 * next_timeout_ms); 593219820Sjeff 594219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 595219820Sjeff "__osmv_txn_timeout_cb: " 596219820Sjeff "Retry request timout in : %lu [msec].\n", 597219820Sjeff next_timeout_ms); 598219820Sjeff } 599219820Sjeff } else { 600219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 601219820Sjeff "__osmv_txn_timeout_cb: ERR 6702: " 602219820Sjeff "The transaction request (tid=0x%llX) timed out (after %d retries). " 603219820Sjeff "Invoking the error callback.\n", 604219820Sjeff osmv_txn_get_tid(p_txn), num_regs); 605219820Sjeff 606219820Sjeff osmv_txn_done((osm_bind_handle_t) p_bo, key, 607219820Sjeff TRUE /*in timeout callback */ ); 608219820Sjeff 609219820Sjeff /* This is a requester. Always apply the callback */ 610219820Sjeff invoke_err_cb = TRUE; 611219820Sjeff } 612219820Sjeff break; 613219820Sjeff 614219820Sjeff case OSMV_TXN_RMPP_SENDER: 615219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 616219820Sjeff "RMPP sender (tid=0x%llX) did not receive ACK " 617219820Sjeff "on every segment in the current send window.\n", 618219820Sjeff osmv_txn_get_tid(p_txn)); 619219820Sjeff 620219820Sjeff p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); 621219820Sjeff if (num_regs <= OSMV_MAX_RETRANSMIT) { 622219820Sjeff /* We still did not exceed the limit of retransmissions. 623219820Sjeff * Set the next timeout's value. 624219820Sjeff */ 625219820Sjeff ret = 626219820Sjeff cl_get_time_stamp() + 627219820Sjeff 1000 * p_bo->p_vendor->resp_timeout; 628219820Sjeff } else { 629219820Sjeff p_send_ctx->status = IB_TIMEOUT; 630219820Sjeff 631219820Sjeff p_mad = osm_madw_get_mad_ptr(p_madw); 632219820Sjeff p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); 633219820Sjeff 634219820Sjeff /* Send an ABORT to the other side */ 635219820Sjeff osmv_rmpp_send_nak((osm_bind_handle_t) p_bo, p_mad, 636219820Sjeff p_mad_addr, IB_RMPP_TYPE_ABORT, 637219820Sjeff IB_RMPP_STATUS_T2L); 638219820Sjeff } 639219820Sjeff 640219820Sjeff /* Wake the RMPP sender thread up */ 641219820Sjeff cl_event_signal(&p_send_ctx->event); 642219820Sjeff break; 643219820Sjeff 644219820Sjeff case OSMV_TXN_RMPP_RECEIVER: 645219820Sjeff osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 646219820Sjeff "Transaction timeout on an RMPP receiver (tid=0x%llX). " 647219820Sjeff "Dropping the transaction.\n", osmv_txn_get_tid(p_txn)); 648219820Sjeff 649219820Sjeff osmv_txn_done((osm_bind_handle_t) p_bo, key, 650219820Sjeff TRUE /*in timeout callback */ ); 651219820Sjeff 652219820Sjeff if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) { 653219820Sjeff /* This is a requester, still waiting for the reply. Apply the callback */ 654219820Sjeff invoke_err_cb = TRUE; 655219820Sjeff } 656219820Sjeff 657219820Sjeff break; 658219820Sjeff 659219820Sjeff default: 660219820Sjeff CL_ASSERT(FALSE); 661219820Sjeff } 662219820Sjeff 663219820Sjeff if (TRUE == invoke_err_cb) { 664219820Sjeff CL_ASSERT(NULL != p_madw); 665219820Sjeff /* update the status in the p_madw */ 666219820Sjeff p_madw->status = IB_TIMEOUT; 667219820Sjeff p_bo->send_err_cb(p_bo->cb_context, p_madw); 668219820Sjeff /* no re-registration */ 669219820Sjeff ret = 0; 670219820Sjeff } 671219820Sjeff 672219820Sjefftxn_done: 673219820Sjeff OSM_LOG_EXIT(p_bo->p_vendor->p_log); 674219820Sjeff return ret; 675219820Sjeff} 676