2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005,2009 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #endif /* HAVE_CONFIG_H */
42 #include <vendor/osm_vendor_mlx.h>
43 #include <vendor/osm_vendor_mlx_defs.h>
44 #include <vendor/osm_vendor_mlx_txn.h>
45 #include <vendor/osm_vendor_mlx_svc.h>
46 #include <vendor/osm_vendor_mlx_sender.h>
48 static ib_api_status_t
49 __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
50 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
52 static ib_api_status_t
53 __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
54 IN osmv_txn_ctx_t * p_txn, IN uint64_t key);
56 static ib_api_status_t
57 __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
58 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
60 static void __osmv_txn_all_done(osm_bind_handle_t h_bind);
63 __osmv_txn_timeout_cb(IN uint64_t key,
64 IN uint32_t num_regs, IN void *cb_context);
67 osmv_txn_init(IN osm_bind_handle_t h_bind,
68 IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
71 osmv_txn_ctx_t *p_txn;
72 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
74 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
76 CL_ASSERT(NULL != h_bind && NULL != pp_txn);
78 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
79 "Starting transaction 0x%016" PRIx64
80 " (key=0x%016" PRIx64 ")\n", tid, key);
82 p_txn = malloc(sizeof(osmv_txn_ctx_t));
84 return IB_INSUFFICIENT_MEMORY;
87 memset(p_txn, 0, sizeof(osmv_txn_ctx_t));
88 p_txn->p_log = p_bo->txn_mgr.p_log;
92 p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_NONE;
94 /* insert into transaction manager DB */
95 st = __osmv_txnmgr_insert_txn(&p_bo->txn_mgr, p_txn, key);
96 if (IB_SUCCESS != st) {
97 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
98 "osmv_txn_init: ERR 6703: "
99 "Failed to insert to transaction 0x%016" PRIx64
100 " (key=0x%016" PRIx64 ") to manager DB\n",
102 goto insert_txn_failed;
106 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
112 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
117 osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,
118 IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw)
124 /* Double-Sided RMPP Direction Switch */
125 osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));
127 p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER;
128 p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t));
130 if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) {
131 return IB_INSUFFICIENT_MEMORY;
134 memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0,
135 sizeof(osmv_rmpp_send_ctx_t));
137 st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx,
138 (void *)p_madw->p_mad,
139 p_madw->mad_size, p_txn->p_log);
144 osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,
145 IN osmv_txn_ctx_t * p_txn,
146 IN boolean_t is_init_by_peer)
149 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
150 uint64_t key = osmv_txn_get_key(p_txn);
154 /* Double-Sided RMPP Direction Switch */
155 osmv_txn_remove_timeout_ev(h_bind, key);
157 /* Set the Transaction Timeout value */
158 st = osmv_txn_set_timeout_ev(h_bind, key,
159 p_bo->p_vendor->ttime_timeout);
160 if (IB_SUCCESS != st) {
165 p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER;
166 p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer;
168 p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t));
170 if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) {
172 osmv_txn_remove_timeout_ev(h_bind, key);
173 return IB_INSUFFICIENT_MEMORY;
176 memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0,
177 sizeof(osmv_rmpp_recv_ctx_t));
179 st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx,
187 * osmv_txn_set_timeout_ev
195 osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind,
196 IN uint64_t key, IN uint64_t msec)
198 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
199 cl_event_wheel_t *p_event_wheel = p_bo->txn_mgr.p_event_wheel;
202 status = cl_event_wheel_reg(p_event_wheel, key, cl_get_time_stamp() + 1000 * msec, /* TTL */
203 __osmv_txn_timeout_cb,
204 p_bo /* The context */ );
206 return (ib_api_status_t) status;
211 * osmv_txn_remove_timeout_ev
218 void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key)
220 cl_event_wheel_t *p_event_wheel =
221 ((osmv_bind_obj_t *) h_bind)->txn_mgr.p_event_wheel;
222 cl_event_wheel_unreg(p_event_wheel, key);
226 osmv_txn_done(IN osm_bind_handle_t h_bind,
227 IN uint64_t key, IN boolean_t is_in_cb)
229 osmv_txn_ctx_t *p_ctx;
230 osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind;
232 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
236 /* Cancel the (single) timeout possibly outstanding for this txn
237 * Don't do this if you are in the callback context, for 2 reasons:
238 * (1) The event wheel will remove the context itself.
239 * (2) If we try to, there is a deadlock in the event wheel
241 if (FALSE == is_in_cb) {
242 osmv_txn_remove_timeout_ev(h_bind, key);
247 __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) {
251 /* Destroy the transaction's RMPP contexts
252 * (can be more than one in the case of double sided transfer)
255 if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) {
256 osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx);
259 if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) {
260 osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx);
265 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
269 osmv_txn_lookup(IN osm_bind_handle_t h_bind,
270 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
272 return __osmv_txnmgr_lookup(&(((osmv_bind_obj_t *) h_bind)->txn_mgr),
276 void osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind)
278 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
279 cl_map_item_t *p_item;
281 osmv_txn_ctx_t *p_txn;
282 osmv_rmpp_send_ctx_t *p_send_ctx;
283 cl_qmap_t *p_map = p_bo->txn_mgr.p_txn_map;
285 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
287 while (FALSE == cl_is_qmap_empty(p_map)) {
289 p_item = cl_qmap_head(p_map);
290 p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
291 p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
292 p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
294 if (NULL != p_send_ctx) {
296 p_send_ctx->status = IB_INTERRUPTED;
298 /* Wake up the sender thread to let it break out */
299 cl_event_signal(&p_send_ctx->event);
302 cl_qmap_remove_item(p_map, p_item);
305 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
309 osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr,
310 IN osm_log_t * p_log, IN cl_spinlock_t * p_lock)
312 cl_status_t cl_st = CL_SUCCESS;
314 p_tx_mgr->p_event_wheel = malloc(sizeof(cl_event_wheel_t));
315 if (!p_tx_mgr->p_event_wheel) {
316 return IB_INSUFFICIENT_MEMORY;
319 memset(p_tx_mgr->p_event_wheel, 0, sizeof(cl_event_wheel_t));
321 cl_event_wheel_construct(p_tx_mgr->p_event_wheel);
323 /* NOTE! We are using an extended constructor.
324 * We tell the Event Wheel run in a non-protected manner in the reg/unreg calls,
325 * and acquire an external lock in the asynchronous callback.
327 cl_st = cl_event_wheel_init_ex(p_tx_mgr->p_event_wheel, p_lock);
328 if (cl_st != CL_SUCCESS) {
329 free(p_tx_mgr->p_event_wheel);
330 return (ib_api_status_t) cl_st;
333 p_tx_mgr->p_txn_map = malloc(sizeof(cl_qmap_t));
334 if (!p_tx_mgr->p_txn_map) {
335 cl_event_wheel_destroy(p_tx_mgr->p_event_wheel);
336 free(p_tx_mgr->p_event_wheel);
337 return IB_INSUFFICIENT_MEMORY;
340 memset(p_tx_mgr->p_txn_map, 0, sizeof(cl_qmap_t));
342 cl_qmap_init(p_tx_mgr->p_txn_map);
343 p_tx_mgr->p_log = p_log;
348 void osmv_txnmgr_done(IN osm_bind_handle_t h_bind)
350 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
352 __osmv_txn_all_done(h_bind);
353 free(p_bo->txn_mgr.p_txn_map);
355 cl_event_wheel_destroy(p_bo->txn_mgr.p_event_wheel);
356 free(p_bo->txn_mgr.p_event_wheel);
360 __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
361 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
363 ib_api_status_t status = IB_SUCCESS;
364 cl_map_item_t *p_item;
369 OSM_LOG_ENTER(p_tx_mgr->p_log);
374 osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
375 "__osmv_txnmgr_lookup: "
376 "Looking for key: 0x%016" PRIx64 " in map ptr:%p\n", key,
377 p_tx_mgr->p_txn_map);
379 p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
380 while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
381 tmp_key = cl_qmap_key(p_item);
382 osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
383 "__osmv_txnmgr_lookup: "
384 "Found key 0x%016" PRIx64 "\n", tmp_key);
385 p_item = cl_qmap_next(p_item);
388 p_item = cl_qmap_get(p_tx_mgr->p_txn_map, key);
389 if (cl_qmap_end(p_tx_mgr->p_txn_map) == p_item) {
390 status = IB_NOT_FOUND;
392 p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
393 *pp_txn = cl_qmap_obj(p_obj);
396 OSM_LOG_EXIT(p_tx_mgr->p_log);
401 __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
402 IN osmv_txn_ctx_t * p_txn, IN uint64_t key)
404 cl_map_obj_t *p_obj = NULL;
405 cl_map_item_t *p_item;
411 key = osmv_txn_get_key(p_txn);
412 p_obj = malloc(sizeof(cl_map_obj_t));
414 return IB_INSUFFICIENT_MEMORY;
416 osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
417 "__osmv_txnmgr_insert_txn: "
418 "Inserting key: 0x%016" PRIx64 " to map ptr:%p\n", key,
419 p_tx_mgr->p_txn_map);
421 memset(p_obj, 0, sizeof(cl_map_obj_t));
423 cl_qmap_set_obj(p_obj, p_txn);
424 /* assuming lookup with this key was made and the result was IB_NOT_FOUND */
425 cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item);
427 p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
428 while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
429 tmp_key = cl_qmap_key(p_item);
430 osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
431 "__osmv_txnmgr_insert_txn: "
432 "Found key 0x%016" PRIx64 "\n", tmp_key);
433 p_item = cl_qmap_next(p_item);
440 __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
441 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
444 cl_map_item_t *p_item;
446 OSM_LOG_ENTER(p_tx_mgr->p_log);
451 p_item = cl_qmap_remove(p_tx_mgr->p_txn_map, key);
453 if (p_item == cl_qmap_end(p_tx_mgr->p_txn_map)) {
455 osm_log(p_tx_mgr->p_log, OSM_LOG_ERROR,
456 "__osmv_txnmgr_remove_txn: ERR 6701: "
457 "Could not remove the transaction 0x%016" PRIx64 " - "
458 "something is really wrong!\n", key);
459 OSM_LOG_EXIT(p_tx_mgr->p_log);
463 p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
464 *pp_txn = cl_qmap_obj(p_obj);
468 OSM_LOG_EXIT(p_tx_mgr->p_log);
472 void __osmv_txn_all_done(osm_bind_handle_t h_bind)
474 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
475 cl_map_item_t *p_item;
477 osmv_txn_ctx_t *p_txn;
479 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
481 p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
482 while (p_item != cl_qmap_end(p_bo->txn_mgr.p_txn_map)) {
484 p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
485 p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
486 osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
488 /* assuming osmv_txn_done has removed the txn from the map */
489 p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
492 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
495 /******************************************************************************/
497 void osmv_txn_lock(IN osm_bind_handle_t h_bind)
499 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
501 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
502 "--> Acquiring lock %p on bind handle %p\n", &p_bo->lock, p_bo);
504 cl_spinlock_acquire(&p_bo->lock);
506 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
507 "--> Acquired lock %p on bind handle %p\n", &p_bo->lock, p_bo);
510 void osmv_txn_unlock(IN osm_bind_handle_t h_bind)
512 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
513 cl_spinlock_t *p_lock = &p_bo->lock;
514 osm_log_t *p_log = p_bo->p_vendor->p_log;
516 osm_log(p_log, OSM_LOG_DEBUG,
517 "<-- Releasing lock %p on bind handle %p\n", p_lock, p_bo);
519 cl_spinlock_release(&p_bo->lock);
521 /* We'll use the saved ptrs, since now the p_bo can be destroyed already */
522 osm_log(p_log, OSM_LOG_DEBUG,
523 "<-- Released lock %p on bind handle %p\n", p_lock, p_bo);
528 __osmv_txn_timeout_cb(IN uint64_t key,
529 IN uint32_t num_regs, IN void *cb_context)
531 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) cb_context;
533 osmv_txn_ctx_t *p_txn;
534 osmv_rmpp_send_ctx_t *p_send_ctx;
535 osm_madw_t *p_madw = NULL;
537 osm_mad_addr_t *p_mad_addr;
538 boolean_t invoke_err_cb = FALSE;
540 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
542 /* Don't try to acquire a lock on the Bind Object -
543 * it's taken by the mechanism that drives the timeout based events!
544 * (Recall the special constructor that the Event Wheel is applied with)
546 if (p_bo->is_closing) {
550 ret = osmv_txn_lookup(p_bo, key, &p_txn);
551 if (IB_NOT_FOUND == ret) {
552 /* Prevent a race - the transaction is already destroyed */
556 p_madw = p_txn->p_madw;
558 switch (osmv_txn_get_rmpp_state(p_txn)) {
560 case OSMV_TXN_RMPP_NONE:
561 if (num_regs <= OSM_DEFAULT_RETRY_COUNT) {
562 /* We still did not exceed the limit of retransmissions.
563 * Set the next timeout's value.
565 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
566 "__osmv_txn_timeout_cb: "
567 "The transaction request (tid=0x%016" PRIx64 ")"
568 " timed out %d times. Retrying the send.\n",
569 osmv_txn_get_tid(p_txn), num_regs);
571 /* resend this mad */
572 ret = osmv_simple_send_madw((osm_bind_handle_t *) p_bo,
573 p_madw, p_txn, TRUE);
574 if (ret != IB_SUCCESS) {
575 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
576 "__osmv_txn_timeout_cb: "
577 "Fail to send retry for transaction"
578 "request (tid=0x%016" PRIx64 ").\n",
579 osmv_txn_get_tid(p_txn));
581 osmv_txn_done((osm_bind_handle_t) p_bo, key,
582 TRUE /*in timeout callback */ );
584 /* This is a requester. Always apply the callback */
585 invoke_err_cb = TRUE;
587 uint64_t next_timeout_ms;
589 p_bo->p_vendor->resp_timeout * (num_regs +
592 /* when do we need to timeout again */
594 cl_get_time_stamp() +
595 (uint64_t) (1000 * next_timeout_ms);
597 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
598 "__osmv_txn_timeout_cb: "
599 "Retry request timout in : %lu [msec].\n",
603 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
604 "__osmv_txn_timeout_cb: ERR 6702: "
605 "The transaction request (0x%016" PRIx64 ") "
606 "timed out (after %d retries). "
607 "Invoking the error callback.\n",
608 osmv_txn_get_tid(p_txn), num_regs);
610 osmv_txn_done((osm_bind_handle_t) p_bo, key,
611 TRUE /*in timeout callback */ );
613 /* This is a requester. Always apply the callback */
614 invoke_err_cb = TRUE;
618 case OSMV_TXN_RMPP_SENDER:
619 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
620 "RMPP sender (tid=0x%016" PRIx64 ") did not receive ACK "
621 "on every segment in the current send window.\n",
622 osmv_txn_get_tid(p_txn));
624 p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
625 if (num_regs <= OSM_DEFAULT_RETRY_COUNT) {
626 /* We still did not exceed the limit of retransmissions.
627 * Set the next timeout's value.
630 cl_get_time_stamp() +
631 1000 * p_bo->p_vendor->resp_timeout;
633 p_send_ctx->status = IB_TIMEOUT;
635 p_mad = osm_madw_get_mad_ptr(p_madw);
636 p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
638 /* Send an ABORT to the other side */
639 osmv_rmpp_send_nak((osm_bind_handle_t) p_bo, p_mad,
640 p_mad_addr, IB_RMPP_TYPE_ABORT,
644 /* Wake the RMPP sender thread up */
645 cl_event_signal(&p_send_ctx->event);
648 case OSMV_TXN_RMPP_RECEIVER:
649 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
650 "Transaction timeout on an RMPP receiver "
651 "(tid=0x%016" PRIx64 "). Dropping the transaction.\n",
652 osmv_txn_get_tid(p_txn));
654 osmv_txn_done((osm_bind_handle_t) p_bo, key,
655 TRUE /*in timeout callback */ );
657 if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) {
658 /* This is a requester, still waiting for the reply. Apply the callback */
659 invoke_err_cb = TRUE;
668 if (TRUE == invoke_err_cb) {
669 CL_ASSERT(NULL != p_madw);
670 /* update the status in the p_madw */
671 p_madw->status = IB_TIMEOUT;
672 p_bo->send_err_cb(p_bo->cb_context, p_madw);
673 /* no re-registration */
678 OSM_LOG_EXIT(p_bo->p_vendor->p_log);