10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*12787SLida.Horn@Oracle.COM * Common Development and Distribution License (the "License").
6*12787SLida.Horn@Oracle.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*12787SLida.Horn@Oracle.COM
220Sstevel@tonic-gate /*
23*12787SLida.Horn@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This file implements the timer setup and timeout handling functions.
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <sys/ib/mgt/ibmf/ibmf_impl.h>
310Sstevel@tonic-gate
320Sstevel@tonic-gate extern int ibmf_trace_level;
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * ibmf_i_set_timer():
360Sstevel@tonic-gate * Set the timer to the response or transaction time interval
370Sstevel@tonic-gate */
380Sstevel@tonic-gate void
ibmf_i_set_timer(void (* func)(void *),ibmf_msg_impl_t * msgimplp,ibmf_timer_t type)390Sstevel@tonic-gate ibmf_i_set_timer(void (*func)(void *), ibmf_msg_impl_t *msgimplp,
400Sstevel@tonic-gate ibmf_timer_t type)
410Sstevel@tonic-gate {
420Sstevel@tonic-gate clock_t interval;
430Sstevel@tonic-gate ibmf_rmpp_ctx_t *rmpp_ctx;
440Sstevel@tonic-gate
450Sstevel@tonic-gate ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
460Sstevel@tonic-gate
470Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_set_timer_start,
480Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_set_timer: msgp = %p, "
490Sstevel@tonic-gate "timer_type = 0x%x, func_cb = 0x%p\n",
500Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp, tnf_opaque, timer_type, type,
510Sstevel@tonic-gate tnf_opaque, func_cb, func);
520Sstevel@tonic-gate
530Sstevel@tonic-gate if (type == IBMF_RESP_TIMER) {
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * The response timer interval is the sum of the IBA
570Sstevel@tonic-gate * defined RespTimeValue (Vol. 1, Section 13.4.6.2.2),
580Sstevel@tonic-gate * and the round trip time value. Both values are determined
590Sstevel@tonic-gate * by the IBMF client and passed in the retrans_rtv and
600Sstevel@tonic-gate * retrans_rttv fields respectively, when calling
610Sstevel@tonic-gate * ibmf_msg_transport()
620Sstevel@tonic-gate */
630Sstevel@tonic-gate ASSERT(msgimplp->im_rp_timeout_id == 0);
640Sstevel@tonic-gate interval = msgimplp->im_retrans.retrans_rtv +
650Sstevel@tonic-gate msgimplp->im_retrans.retrans_rttv;
660Sstevel@tonic-gate
670Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_set_timer,
680Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_set_timer: %s, interval = %ld "
690Sstevel@tonic-gate "resp_time %x round trip time %x\n",
700Sstevel@tonic-gate tnf_string, msg, "setting response timer",
710Sstevel@tonic-gate tnf_long, interval, interval,
720Sstevel@tonic-gate tnf_uint, resp_time, msgimplp->im_retrans.retrans_rtv,
730Sstevel@tonic-gate tnf_uint, interval, msgimplp->im_retrans.retrans_rttv);
740Sstevel@tonic-gate
750Sstevel@tonic-gate msgimplp->im_rp_timeout_id = timeout(func,
760Sstevel@tonic-gate (void *)msgimplp, drv_usectohz(interval));
770Sstevel@tonic-gate } else if (type == IBMF_TRANS_TIMER) {
780Sstevel@tonic-gate rmpp_ctx = &msgimplp->im_rmpp_ctx;
790Sstevel@tonic-gate
800Sstevel@tonic-gate ASSERT(msgimplp->im_tr_timeout_id == 0);
810Sstevel@tonic-gate if (rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) {
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate * if payload was not specified use IB spec default
840Sstevel@tonic-gate * of 40 seconds
850Sstevel@tonic-gate */
860Sstevel@tonic-gate interval = IBMF_RETRANS_DEF_TRANS_TO;
870Sstevel@tonic-gate
880Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
890Sstevel@tonic-gate ibmf_i_set_timer, IBMF_TNF_TRACE, "",
900Sstevel@tonic-gate "ibmf_i_set_timer: %s, interval = %ld\n",
910Sstevel@tonic-gate tnf_string, msg,
920Sstevel@tonic-gate "payload size unknown. Using default trans_to",
930Sstevel@tonic-gate tnf_long, interval, interval);
940Sstevel@tonic-gate } else {
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * if payload was specified, use a variation of IB
970Sstevel@tonic-gate * spec equation (13.6.3.2) that accounts for average
980Sstevel@tonic-gate * window size
990Sstevel@tonic-gate */
1000Sstevel@tonic-gate interval = (msgimplp->im_retrans.retrans_rtv +
1010Sstevel@tonic-gate msgimplp->im_retrans.retrans_rttv) /
1020Sstevel@tonic-gate IBMF_RMPP_DEFAULT_WIN_SZ * 4 *
1030Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_num_pkts;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3,
1060Sstevel@tonic-gate ibmf_i_set_timer, IBMF_TNF_TRACE, "",
1070Sstevel@tonic-gate "ibmf_i_set_timer: %s, num_pkts = %d, rttv ="
1080Sstevel@tonic-gate " %x, window_size = %d, interval = %ld\n",
1090Sstevel@tonic-gate tnf_string, msg, "setting trans timer",
1100Sstevel@tonic-gate tnf_uint, num_pkts,
1110Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_num_pkts, tnf_uint, rtv,
1120Sstevel@tonic-gate msgimplp->im_retrans.retrans_rttv,
1130Sstevel@tonic-gate tnf_uint, window_size, IBMF_RMPP_DEFAULT_WIN_SZ,
1140Sstevel@tonic-gate tnf_long, interval, interval);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * Use the client specified transaction timeout value if
1190Sstevel@tonic-gate * smaller than the calculated value
1200Sstevel@tonic-gate */
1210Sstevel@tonic-gate if ((msgimplp->im_retrans.retrans_trans_to != 0) &&
1220Sstevel@tonic-gate (msgimplp->im_retrans.retrans_trans_to < interval)) {
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate interval = msgimplp->im_retrans.retrans_trans_to;
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
1270Sstevel@tonic-gate ibmf_i_set_timer, IBMF_TNF_TRACE, "",
1280Sstevel@tonic-gate "ibmf_i_set_timer: %s, new_interval = %ld\n",
1290Sstevel@tonic-gate tnf_string, msg, "user trans_to is smaller",
1300Sstevel@tonic-gate tnf_long, new_interval, interval);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_set_timer,
1340Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_set_timer: %s, interval = %ld"
1350Sstevel@tonic-gate "\n", tnf_string, msg, "setting transaction timer",
1360Sstevel@tonic-gate tnf_long, interval, interval);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate msgimplp->im_tr_timeout_id = timeout(func,
1390Sstevel@tonic-gate (void *)msgimplp, drv_usectohz(interval));
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_set_timer_end,
1430Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_set_timer() exit\n");
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate * ibmf_i_unset_timer():
1480Sstevel@tonic-gate * Unset the timer
1490Sstevel@tonic-gate */
1500Sstevel@tonic-gate void
ibmf_i_unset_timer(ibmf_msg_impl_t * msgimplp,ibmf_timer_t type)1510Sstevel@tonic-gate ibmf_i_unset_timer(ibmf_msg_impl_t *msgimplp, ibmf_timer_t type)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_unset_timer_start,
1540Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_unset_timer(): msgp = %p, \n",
1550Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate if (type == IBMF_RESP_TIMER) {
1600Sstevel@tonic-gate if (msgimplp->im_rp_timeout_id != 0) {
1610Sstevel@tonic-gate msgimplp->im_rp_unset_timeout_id =
1620Sstevel@tonic-gate msgimplp->im_rp_timeout_id;
1630Sstevel@tonic-gate msgimplp->im_rp_timeout_id = 0;
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate } else if (type == IBMF_TRANS_TIMER) {
1660Sstevel@tonic-gate if (msgimplp->im_tr_timeout_id != 0) {
1670Sstevel@tonic-gate msgimplp->im_tr_unset_timeout_id =
1680Sstevel@tonic-gate msgimplp->im_tr_timeout_id;
1690Sstevel@tonic-gate msgimplp->im_tr_timeout_id = 0;
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_unset_timer_end,
1740Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_unset_timer() exit\n");
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /*
1780Sstevel@tonic-gate * ibmf_i_recv_timeout:
1790Sstevel@tonic-gate *
1800Sstevel@tonic-gate * Perform "receive" timeout processing for the message.
1810Sstevel@tonic-gate * This timeout handler is only used in RMPP processing.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate void
ibmf_i_recv_timeout(void * argp)1840Sstevel@tonic-gate ibmf_i_recv_timeout(void *argp)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp = (ibmf_msg_impl_t *)argp;
1870Sstevel@tonic-gate ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
1880Sstevel@tonic-gate ibmf_rmpp_ctx_t *rmpp_ctx;
1890Sstevel@tonic-gate int msg_flags;
1900Sstevel@tonic-gate uint_t ref_cnt;
1910Sstevel@tonic-gate int status;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
1940Sstevel@tonic-gate ibmf_i_recv_timeout_start, IBMF_TNF_TRACE, "",
1950Sstevel@tonic-gate "ibmf_i_recv_timeout(): msgp = 0x%p\n", tnf_opaque, msg, msgimplp);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
2000Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
2010Sstevel@tonic-gate "ibmf_i_recv_timeout(): resetting id time %llx\n",
2020Sstevel@tonic-gate tnf_opaque, time, gethrtime());
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * If the message has been marked unitialized or done
2060Sstevel@tonic-gate * release the message mutex and return
2070Sstevel@tonic-gate */
2080Sstevel@tonic-gate if ((msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_UNINIT) ||
2090Sstevel@tonic-gate (msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE)) {
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
2140Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
2150Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s, msgp = 0x%p\n", tnf_string, msg,
2160Sstevel@tonic-gate "Message marked for removal, return without processing "
2170Sstevel@tonic-gate "recv timeout",
2180Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate return;
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate /*
2240Sstevel@tonic-gate * Unset the response and trans timers if they haven't fired (unlikely)
2250Sstevel@tonic-gate */
2260Sstevel@tonic-gate ibmf_i_unset_timer(msgimplp, IBMF_RESP_TIMER);
2270Sstevel@tonic-gate ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate rmpp_ctx = &msgimplp->im_rmpp_ctx;
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /* Perform timeout processing for the RMPP transaction */
2320Sstevel@tonic-gate if (rmpp_ctx->rmpp_state == IBMF_RMPP_STATE_RECEVR_ACTIVE) {
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
2350Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
2360Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s\n", tnf_string, msg,
2370Sstevel@tonic-gate "RMPP context is Receiver Active, sending ABORT T2L");
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
2400Sstevel@tonic-gate IBMF_RMPP_STATUS_T2L, 0, 0, IBMF_NO_BLOCK);
2410Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
2420Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
2430Sstevel@tonic-gate ibmf_i_recv_timeout_err, IBMF_TNF_ERROR, "",
2440Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s\n", tnf_string, msg,
2450Sstevel@tonic-gate "RMPP ABORT send failed");
2460Sstevel@tonic-gate msgimplp->im_trans_state_flags |=
2470Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_SEND_DONE;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
2510Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
2520Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
2570Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_ERROR, "",
2580Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s\n", tnf_string, msg,
2590Sstevel@tonic-gate "RMPP context is Receiver Active, terminating transaction");
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate ibmf_i_terminate_transaction(msgimplp->im_client,
2620Sstevel@tonic-gate msgimplp, IBMF_TRANS_TIMEOUT);
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate } else if (rmpp_ctx->rmpp_state == IBMF_RMPP_STATE_RECEVR_TERMINATE) {
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
2670Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
2680Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s\n", tnf_string, msg,
2690Sstevel@tonic-gate "RMPP context is Receiver Terminate, "
2700Sstevel@tonic-gate "terminating transaction");
2710Sstevel@tonic-gate rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
2720Sstevel@tonic-gate ibmf_i_terminate_transaction(msgimplp->im_client, msgimplp,
2730Sstevel@tonic-gate IBMF_SUCCESS);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * Save the transaction state flags and the timeout IDs
2780Sstevel@tonic-gate * before releasing the mutex as they may be changed after that.
2790Sstevel@tonic-gate */
2800Sstevel@tonic-gate msg_flags = msgimplp->im_trans_state_flags;
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
2850Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
2860Sstevel@tonic-gate "ibmf_i_recv_timeout(): %s, msgp = 0x%p, refcnt = %d\n", tnf_string,
2870Sstevel@tonic-gate msg, "recv timeout done. Dec ref count", tnf_opaque, msgimplp,
2880Sstevel@tonic-gate msgimplp, tnf_uint, flags, msg_flags);
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate /*
2910Sstevel@tonic-gate * If the transaction flags indicate a completed transaction,
2920Sstevel@tonic-gate * notify the client
2930Sstevel@tonic-gate */
2940Sstevel@tonic-gate if (msg_flags & IBMF_TRANS_STATE_FLAG_DONE) {
2950Sstevel@tonic-gate /* Remove the message from the client's message list */
2960Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &ref_cnt);
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate * Notify the client if the message reference count is zero.
3000Sstevel@tonic-gate * At this point, we know that the transaction is done and
3010Sstevel@tonic-gate * the message has been removed from the client's message list.
3020Sstevel@tonic-gate * So, we only need to make sure the reference count is zero
3030Sstevel@tonic-gate * before notifying the client.
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate if (ref_cnt == 0) {
3060Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
3070Sstevel@tonic-gate if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) {
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate * If the message is a termination message,
3110Sstevel@tonic-gate * free it at this time.
3120Sstevel@tonic-gate */
3130Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
3140Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
3150Sstevel@tonic-gate "ibmf_i_recv_timeout(): freeing terminate "
3160Sstevel@tonic-gate "message %p\n", tnf_opaque, msgp, msgimplp);
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* free up the UD destination resource */
3190Sstevel@tonic-gate if (msgimplp->im_ibmf_ud_dest != NULL) {
3200Sstevel@tonic-gate ibmf_i_free_ud_dest(clientp, msgimplp);
3210Sstevel@tonic-gate ibmf_i_clean_ud_dest_list(
3220Sstevel@tonic-gate clientp->ic_myci, B_FALSE);
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate /* Free the receive buffer */
3260Sstevel@tonic-gate kmem_free(
3270Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
3280Sstevel@tonic-gate IBMF_MAD_SIZE);
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate /* destroy the message mutex */
3310Sstevel@tonic-gate mutex_destroy(&msgimplp->im_mutex);
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /* Free the termination message context */
3340Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate * Decrease the "messages allocated" count
3380Sstevel@tonic-gate * so that an ibmf_unregister() can succeed
3390Sstevel@tonic-gate * for this client.
3400Sstevel@tonic-gate */
3410Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
3420Sstevel@tonic-gate clientp->ic_msgs_alloced--;
3430Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate } else {
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
3480Sstevel@tonic-gate ibmf_i_recv_timeout, IBMF_TNF_TRACE, "",
3490Sstevel@tonic-gate "ibmf_i_recv_timeout(): calling "
3500Sstevel@tonic-gate "notify %p\n", tnf_opaque, msgp, msgimplp);
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate ibmf_i_notify_client(msgimplp);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3580Sstevel@tonic-gate ibmf_i_recv_timeout_end, IBMF_TNF_TRACE, "",
3590Sstevel@tonic-gate "ibmf_i_recv_timeout() exit\n");
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate /*
3630Sstevel@tonic-gate * ibmf_i_send_timeout:
3640Sstevel@tonic-gate *
3650Sstevel@tonic-gate * Perform "send" timeout processing for the message.
3660Sstevel@tonic-gate * This timeout handler is used in non-RMPP and RMPP processing.
3670Sstevel@tonic-gate */
3680Sstevel@tonic-gate void
ibmf_i_send_timeout(void * argp)3690Sstevel@tonic-gate ibmf_i_send_timeout(void *argp)
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp = (ibmf_msg_impl_t *)argp;
3720Sstevel@tonic-gate ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
3730Sstevel@tonic-gate ibmf_rmpp_ctx_t *rmpp_ctx;
3740Sstevel@tonic-gate int msg_flags;
3750Sstevel@tonic-gate uint_t ref_cnt;
3760Sstevel@tonic-gate int status;
3770Sstevel@tonic-gate
378*12787SLida.Horn@Oracle.COM IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4,
3790Sstevel@tonic-gate ibmf_i_send_timeout_start, IBMF_TNF_TRACE, "",
380*12787SLida.Horn@Oracle.COM "ibmf_i_send_timeout_client(): msgp = 0x%p mgt_class = 0x%x "
381*12787SLida.Horn@Oracle.COM "local lid 0x%x remote lid 0x%x remote q# 0x%x\n",
382*12787SLida.Horn@Oracle.COM tnf_opaque, msg, msgimplp,
383*12787SLida.Horn@Oracle.COM tnf_uint, mgt_class, msgimplp->im_mgt_class,
384*12787SLida.Horn@Oracle.COM tnf_uint, local_lid, msgimplp->im_local_addr.ia_local_lid,
385*12787SLida.Horn@Oracle.COM tnf_uint, remote_lid, msgimplp->im_local_addr.ia_remote_lid,
386*12787SLida.Horn@Oracle.COM tnf_uint, qno, msgimplp->im_local_addr.ia_remote_qno);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * If the message has been marked uninitialized or done, release the
3920Sstevel@tonic-gate * message mutex and return
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate if ((msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_UNINIT) ||
3950Sstevel@tonic-gate (msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE)) {
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
4000Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
4010Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n", tnf_string, msg,
4020Sstevel@tonic-gate "Message is done, return without processing send timeout",
4030Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate return;
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_timeout,
4090Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_send_timeout(): resetting id %d\n",
4100Sstevel@tonic-gate tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate /*
4130Sstevel@tonic-gate * If the timer fired, but the corresponding MAD was received before
4140Sstevel@tonic-gate * we got to this point in the timeout code, then do nothing in the
4150Sstevel@tonic-gate * timeout handler and return
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate if ((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) &&
4180Sstevel@tonic-gate (msgimplp->im_rp_timeout_id == 0)) {
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
4230Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
4240Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n", tnf_string, msg,
4250Sstevel@tonic-gate "Message not in undefined state, return without processing "
4260Sstevel@tonic-gate "send timeout",
4270Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate return;
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate /* Clear the response timer */
4330Sstevel@tonic-gate if (msgimplp->im_rp_timeout_id != 0)
4340Sstevel@tonic-gate ibmf_i_unset_timer(msgimplp, IBMF_RESP_TIMER);
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate rmpp_ctx = &msgimplp->im_rmpp_ctx;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate /*
4390Sstevel@tonic-gate * Non-RMPP send transaction timeout processing
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate if ((msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate /*
4440Sstevel@tonic-gate * We use the RMPP context to store the retry count even if
4450Sstevel@tonic-gate * the response does not use RMPP
4460Sstevel@tonic-gate */
4470Sstevel@tonic-gate if (rmpp_ctx->rmpp_retry_cnt <
4480Sstevel@tonic-gate msgimplp->im_retrans.retrans_retries) {
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3,
4510Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
4520Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p, "
4530Sstevel@tonic-gate "retry_cnt = %d, max_retries = %d\n",
4540Sstevel@tonic-gate tnf_string, msg, "Non-RMPP send timed out",
4550Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp,
4560Sstevel@tonic-gate tnf_uint, retry_cnt, rmpp_ctx->rmpp_retry_cnt,
4570Sstevel@tonic-gate tnf_uint, max_retries,
4580Sstevel@tonic-gate msgimplp->im_retrans.retrans_retries);
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate rmpp_ctx->rmpp_retry_cnt++;
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate status = ibmf_i_send_single_pkt(msgimplp->im_client,
4630Sstevel@tonic-gate msgimplp->im_qp_hdl, msgimplp, IBMF_NO_BLOCK);
4640Sstevel@tonic-gate if (status == IBMF_SUCCESS) {
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
4690Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
4700Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n",
4710Sstevel@tonic-gate tnf_string, msg, "Resent send",
4720Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate return;
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1,
4780Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_ERROR, "",
4790Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p, "
4800Sstevel@tonic-gate "status = %d\n", tnf_string, msg,
4810Sstevel@tonic-gate "Retry send failed; terminating transaction",
4820Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp,
4830Sstevel@tonic-gate tnf_opaque, status, status);
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate } else {
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
4880Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_ERROR, "",
4890Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
4900Sstevel@tonic-gate "Not RMPP SEND, terminate transaction with "
4910Sstevel@tonic-gate "IBMF_TRANS_TIMEOUT");
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate /*
4950Sstevel@tonic-gate * If we are in receive RMPP mode, then an ABORT should
4960Sstevel@tonic-gate * be sent after the required number of retries.
4970Sstevel@tonic-gate */
4980Sstevel@tonic-gate if (msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) {
4990Sstevel@tonic-gate status = ibmf_i_send_rmpp(msgimplp,
5000Sstevel@tonic-gate IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_TMR, 0, 0,
5010Sstevel@tonic-gate IBMF_NO_BLOCK);
5020Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
5030Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
5040Sstevel@tonic-gate ibmf_i_send_timeout_err, IBMF_TNF_ERROR, "",
5050Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string,
5060Sstevel@tonic-gate msg, "RMPP ABORT send failed");
5070Sstevel@tonic-gate msgimplp->im_trans_state_flags |=
5080Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_SEND_DONE;
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate ibmf_i_terminate_transaction(msgimplp->im_client,
5140Sstevel@tonic-gate msgimplp, IBMF_TRANS_TIMEOUT);
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate msg_flags = msgimplp->im_trans_state_flags;
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate /* Notify the client if the transaction is done */
5210Sstevel@tonic-gate if (msg_flags & IBMF_TRANS_STATE_FLAG_DONE) {
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
5240Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
5250Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n",
5260Sstevel@tonic-gate tnf_string, msg, "calling notify",
5270Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
5280Sstevel@tonic-gate /* Remove the message from the client's message list */
5290Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &ref_cnt);
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * Notify the client if the message reference count is
5320Sstevel@tonic-gate * zero. At this point, we know that the transaction is
5330Sstevel@tonic-gate * done and the message has been removed from the
5340Sstevel@tonic-gate * client's message list. So, we need to be sure the
5350Sstevel@tonic-gate * reference count is zero before notifying the client.
5360Sstevel@tonic-gate */
5370Sstevel@tonic-gate if (ref_cnt == 0) {
5380Sstevel@tonic-gate ibmf_i_notify_client(msgimplp);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_timeout,
5430Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_send_timeout() exit\n");
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate return;
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3,
5490Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
5500Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p, retry_cnt = %d, "
5510Sstevel@tonic-gate "max_retries = %d\n", tnf_string, msg, "RMPP send timed out",
5520Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp,
5530Sstevel@tonic-gate tnf_uint, retry_cnt, rmpp_ctx->rmpp_retry_cnt,
5540Sstevel@tonic-gate tnf_uint, max_retries, msgimplp->im_retrans.retrans_retries);
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate /* RMPP send transaction timeout processing */
5570Sstevel@tonic-gate if (rmpp_ctx->rmpp_retry_cnt == msgimplp->im_retrans.retrans_retries) {
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
5600Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
5610Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
5620Sstevel@tonic-gate "Maximum retries done, sending ABORT TMR");
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
5650Sstevel@tonic-gate IBMF_RMPP_STATUS_TMR, 0, 0, IBMF_NO_BLOCK);
5660Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
5670Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
5680Sstevel@tonic-gate ibmf_i_send_timeout_err, IBMF_TNF_ERROR, "",
5690Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
5700Sstevel@tonic-gate "RMPP ABORT send failed");
5710Sstevel@tonic-gate msgimplp->im_trans_state_flags |=
5720Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_SEND_DONE;
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
5780Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
5790Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
5820Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_ERROR, "",
5830Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
5840Sstevel@tonic-gate "Maximum retries done, terminate transaction with "
5850Sstevel@tonic-gate "IBMF_TRANS_TIMEOUT");
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate ibmf_i_terminate_transaction(msgimplp->im_client,
5880Sstevel@tonic-gate msgimplp, IBMF_TRANS_TIMEOUT);
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate } else {
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate if (rmpp_ctx->rmpp_state == IBMF_RMPP_STATE_SENDER_ACTIVE) {
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
5950Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
5960Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
5970Sstevel@tonic-gate "RMPP context is Sender Active, Resending window");
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate /*
6000Sstevel@tonic-gate * resend the window
6010Sstevel@tonic-gate */
6020Sstevel@tonic-gate rmpp_ctx->rmpp_ns = rmpp_ctx->rmpp_wf;
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
6050Sstevel@tonic-gate } else if (rmpp_ctx->rmpp_state ==
6060Sstevel@tonic-gate IBMF_RMPP_STATE_SENDER_SWITCH) {
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
6090Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
6100Sstevel@tonic-gate "ibmf_i_send_timeout(): %s\n", tnf_string, msg,
6110Sstevel@tonic-gate "RMPP context is Sender Terminate, sending ACK");
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate /* send ACK */
6140Sstevel@tonic-gate (void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
6150Sstevel@tonic-gate IBMF_RMPP_STATUS_NORMAL, 0, 1, IBMF_NO_BLOCK);
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
6180Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
6190Sstevel@tonic-gate "ibmf_i_send_timeout(): setting timer %d %p\n",
6200Sstevel@tonic-gate tnf_opaque, msgp, msgimplp, tnf_opaque,
6210Sstevel@tonic-gate timeout_id, msgimplp->im_rp_timeout_id);
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /* set response timer */
6240Sstevel@tonic-gate ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
6250Sstevel@tonic-gate IBMF_RESP_TIMER);
6260Sstevel@tonic-gate }
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate rmpp_ctx->rmpp_retry_cnt++;
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate msg_flags = msgimplp->im_trans_state_flags;
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate clientp = (ibmf_client_t *)msgimplp->im_client;
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
6390Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
6400Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n", tnf_string, msg,
6410Sstevel@tonic-gate "Send timeout done", tnf_opaque, msgimplp, msgimplp);
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate if (msg_flags & IBMF_TRANS_STATE_FLAG_DONE) {
6440Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
6450Sstevel@tonic-gate ibmf_i_send_timeout, IBMF_TNF_TRACE, "",
6460Sstevel@tonic-gate "ibmf_i_send_timeout(): %s, msgp = 0x%p\n", tnf_string, msg,
6470Sstevel@tonic-gate "calling notify", tnf_opaque, msgimplp, msgimplp);
6480Sstevel@tonic-gate /* Remove the message from the client's message list */
6490Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &ref_cnt);
6500Sstevel@tonic-gate /*
6510Sstevel@tonic-gate * Notify the client if the message reference count is zero.
6520Sstevel@tonic-gate * At this point, we know that the transaction is done and
6530Sstevel@tonic-gate * the message has been removed from the client's message list.
6540Sstevel@tonic-gate * So, we only need to make sure the reference count is zero
6550Sstevel@tonic-gate * before notifying the client.
6560Sstevel@tonic-gate */
6570Sstevel@tonic-gate if (ref_cnt == 0) {
6580Sstevel@tonic-gate ibmf_i_notify_client(msgimplp);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_timeout_end,
6630Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_send_timeout() exit\n");
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate void
ibmf_i_err_terminate_timeout(void * argp)6670Sstevel@tonic-gate ibmf_i_err_terminate_timeout(void *argp)
6680Sstevel@tonic-gate {
6690Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp = (ibmf_msg_impl_t *)argp;
6700Sstevel@tonic-gate ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
6710Sstevel@tonic-gate int msg_flags;
6720Sstevel@tonic-gate uint_t ref_cnt;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
6750Sstevel@tonic-gate ibmf_i_err_terminate_timeout_start, IBMF_TNF_TRACE, "",
6760Sstevel@tonic-gate "ibmf_i_err_terminate_timeout_client(): msgp = 0x%p\n",
6770Sstevel@tonic-gate tnf_opaque, msg, msgimplp);
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate /*
6820Sstevel@tonic-gate * If the message has been marked uninitialized or done, release the
6830Sstevel@tonic-gate * message mutex and return
6840Sstevel@tonic-gate */
6850Sstevel@tonic-gate if ((msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_UNINIT) ||
6860Sstevel@tonic-gate (msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE)) {
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
6910Sstevel@tonic-gate ibmf_i_err_terminate_timeout, IBMF_TNF_TRACE, "",
6920Sstevel@tonic-gate "ibmf_i_err_terminate_timeout(): %s, msgp = 0x%p\n",
6930Sstevel@tonic-gate tnf_string, msg, "Message is done, return without "
6940Sstevel@tonic-gate "processing error terminate timeout",
6950Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate return;
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_err_terminate_timeout,
7010Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_err_terminate_timeout(): resetting "
7020Sstevel@tonic-gate "id %d\n", tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate /* Clear the response timer */
7050Sstevel@tonic-gate if (msgimplp->im_rp_timeout_id != 0)
7060Sstevel@tonic-gate msgimplp->im_rp_timeout_id = 0;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate /* Mark the transaction as terminated */
7090Sstevel@tonic-gate ibmf_i_terminate_transaction(msgimplp->im_client, msgimplp,
7100Sstevel@tonic-gate IBMF_TRANS_FAILURE);
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate msg_flags = msgimplp->im_trans_state_flags;
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate clientp = (ibmf_client_t *)msgimplp->im_client;
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_err_terminate_timeout,
7190Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_err_terminate_timeout(): %s, "
7200Sstevel@tonic-gate "msgp = 0x%p\n", tnf_string, msg,
7210Sstevel@tonic-gate "Error terminate timeout done", tnf_opaque, msgimplp, msgimplp);
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate if (msg_flags & IBMF_TRANS_STATE_FLAG_DONE) {
7240Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
7250Sstevel@tonic-gate ibmf_i_err_terminate_timeout, IBMF_TNF_TRACE, "",
7260Sstevel@tonic-gate "ibmf_i_err_terminate_timeout(): %s, msgp = 0x%p\n",
7270Sstevel@tonic-gate tnf_string, msg,
7280Sstevel@tonic-gate "calling notify", tnf_opaque, msgimplp, msgimplp);
7290Sstevel@tonic-gate /* Remove the message from the client's message list */
7300Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &ref_cnt);
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate * Notify the client if the message reference count is zero.
7330Sstevel@tonic-gate * At this point, we know that the transaction is done and
7340Sstevel@tonic-gate * the message has been removed from the client's message list.
7350Sstevel@tonic-gate * So, we only need to make sure the reference count is zero
7360Sstevel@tonic-gate * before notifying the client.
7370Sstevel@tonic-gate */
7380Sstevel@tonic-gate if (ref_cnt == 0) {
7390Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
7400Sstevel@tonic-gate if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) {
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate /*
7430Sstevel@tonic-gate * If the message is a termination message,
7440Sstevel@tonic-gate * free it at this time.
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
7480Sstevel@tonic-gate ibmf_i_err_terminate_timeout,
7490Sstevel@tonic-gate IBMF_TNF_TRACE, "",
7500Sstevel@tonic-gate "ibmf_i_recv_timeout(): freeing terminate "
7510Sstevel@tonic-gate "message %p\n", tnf_opaque, msgp, msgimplp);
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate /* free up the UD destination resource */
7540Sstevel@tonic-gate if (msgimplp->im_ibmf_ud_dest != NULL) {
7550Sstevel@tonic-gate ibmf_i_free_ud_dest(clientp, msgimplp);
7560Sstevel@tonic-gate ibmf_i_clean_ud_dest_list(
7570Sstevel@tonic-gate clientp->ic_myci, B_FALSE);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate /* Free the receive buffer */
7610Sstevel@tonic-gate kmem_free(
7620Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
7630Sstevel@tonic-gate IBMF_MAD_SIZE);
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate /* destroy the message mutex */
7660Sstevel@tonic-gate mutex_destroy(&msgimplp->im_mutex);
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate /* Free the termination message context */
7690Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
7700Sstevel@tonic-gate
7710Sstevel@tonic-gate /*
7720Sstevel@tonic-gate * Decrease the "messages allocated" count
7730Sstevel@tonic-gate * so that an ibmf_unregister() can succeed
7740Sstevel@tonic-gate * for this client.
7750Sstevel@tonic-gate */
7760Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
7770Sstevel@tonic-gate clientp->ic_msgs_alloced--;
7780Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate } else {
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
7830Sstevel@tonic-gate ibmf_i_err_terminate_timeout,
7840Sstevel@tonic-gate IBMF_TNF_TRACE, "",
7850Sstevel@tonic-gate "ibmf_i_recv_timeout(): calling "
7860Sstevel@tonic-gate "notify %p\n", tnf_opaque, msgp, msgimplp);
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate ibmf_i_notify_client(msgimplp);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
7940Sstevel@tonic-gate ibmf_i_err_terminate_timeout_end, IBMF_TNF_TRACE, "",
7950Sstevel@tonic-gate "ibmf_i_err_terminate_timeout() exit\n");
7960Sstevel@tonic-gate }
797