xref: /onnv-gate/usr/src/uts/common/io/ib/mgt/ibmf/ibmf_timers.c (revision 12787:45ed97ad3d9f)
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