193c426a1Ske ge - Sun Microsystems - Beijing China /*
293c426a1Ske ge - Sun Microsystems - Beijing China  * CDDL HEADER START
393c426a1Ske ge - Sun Microsystems - Beijing China  *
493c426a1Ske ge - Sun Microsystems - Beijing China  * The contents of this file are subject to the terms of the
593c426a1Ske ge - Sun Microsystems - Beijing China  * Common Development and Distribution License (the "License").
693c426a1Ske ge - Sun Microsystems - Beijing China  * You may not use this file except in compliance with the License.
793c426a1Ske ge - Sun Microsystems - Beijing China  *
893c426a1Ske ge - Sun Microsystems - Beijing China  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
993c426a1Ske ge - Sun Microsystems - Beijing China  * or http://www.opensolaris.org/os/licensing.
1093c426a1Ske ge - Sun Microsystems - Beijing China  * See the License for the specific language governing permissions
1193c426a1Ske ge - Sun Microsystems - Beijing China  * and limitations under the License.
1293c426a1Ske ge - Sun Microsystems - Beijing China  *
1393c426a1Ske ge - Sun Microsystems - Beijing China  * When distributing Covered Code, include this CDDL HEADER in each
1493c426a1Ske ge - Sun Microsystems - Beijing China  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1593c426a1Ske ge - Sun Microsystems - Beijing China  * If applicable, add the following below this CDDL HEADER, with the
1693c426a1Ske ge - Sun Microsystems - Beijing China  * fields enclosed by brackets "[]" replaced with your own identifying
1793c426a1Ske ge - Sun Microsystems - Beijing China  * information: Portions Copyright [yyyy] [name of copyright owner]
1893c426a1Ske ge - Sun Microsystems - Beijing China  *
1993c426a1Ske ge - Sun Microsystems - Beijing China  * CDDL HEADER END
2093c426a1Ske ge - Sun Microsystems - Beijing China  */
2193c426a1Ske ge - Sun Microsystems - Beijing China 
2293c426a1Ske ge - Sun Microsystems - Beijing China /*
231cfa752fSRamaswamy Tummala  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*ec71f88eSPatrick Mooney  * Copyright 2018 Joyent, Inc.
2593c426a1Ske ge - Sun Microsystems - Beijing China  */
2693c426a1Ske ge - Sun Microsystems - Beijing China /* Copyright (c) 1990 Mentat Inc. */
2793c426a1Ske ge - Sun Microsystems - Beijing China 
2893c426a1Ske ge - Sun Microsystems - Beijing China /*
2993c426a1Ske ge - Sun Microsystems - Beijing China  * An implementation of the IPoIB-CM standard based on PSARC 2009/593.
3093c426a1Ske ge - Sun Microsystems - Beijing China  */
3193c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/types.h>
3293c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/conf.h>
3393c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/ddi.h>
3493c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/sunddi.h>
3593c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/modctl.h>
3693c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/stropts.h>
3793c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/stream.h>
3893c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/strsun.h>
3993c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/strsubr.h>
4093c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/dlpi.h>
4193c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/mac_provider.h>
4293c426a1Ske ge - Sun Microsystems - Beijing China 
4393c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/pattr.h>		/* for HCK_FULLCKSUM */
4493c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/atomic.h>		/* for atomic_add*() */
4593c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/ethernet.h>	/* for ETHERTYPE_IP */
4693c426a1Ske ge - Sun Microsystems - Beijing China #include <netinet/in.h>		/* for netinet/ip.h below */
4793c426a1Ske ge - Sun Microsystems - Beijing China #include <netinet/ip.h>		/* for struct ip */
4893c426a1Ske ge - Sun Microsystems - Beijing China #include <inet/common.h>	/* for inet/ip.h below */
4993c426a1Ske ge - Sun Microsystems - Beijing China #include <inet/ip.h>		/* for ipha_t */
5093c426a1Ske ge - Sun Microsystems - Beijing China #include <inet/ip_if.h>		/* for ETHERTYPE_IPV6 */
5193c426a1Ske ge - Sun Microsystems - Beijing China #include <inet/ip6.h>		/* for ip6_t */
5293c426a1Ske ge - Sun Microsystems - Beijing China #include <netinet/icmp6.h>	/* for icmp6_t */
5393c426a1Ske ge - Sun Microsystems - Beijing China 
5493c426a1Ske ge - Sun Microsystems - Beijing China #include <sys/ib/clients/ibd/ibd.h>
5593c426a1Ske ge - Sun Microsystems - Beijing China 
56a567cb71Ske ge - Sun Microsystems - Beijing China extern ibd_global_state_t ibd_gstate;
5703514dd7Ske ge - Sun Microsystems - Beijing China extern int ibd_rc_conn_timeout;
5893c426a1Ske ge - Sun Microsystems - Beijing China uint_t ibd_rc_tx_softintr = 1;
5993c426a1Ske ge - Sun Microsystems - Beijing China /*
6093c426a1Ske ge - Sun Microsystems - Beijing China  * If the number of WRs in receive queue of each RC connection less than
6193c426a1Ske ge - Sun Microsystems - Beijing China  * IBD_RC_RX_WR_THRESHOLD, we will post more receive WRs into it.
6293c426a1Ske ge - Sun Microsystems - Beijing China  */
6393c426a1Ske ge - Sun Microsystems - Beijing China #define	IBD_RC_RX_WR_THRESHOLD		0x20
6493c426a1Ske ge - Sun Microsystems - Beijing China 
6593c426a1Ske ge - Sun Microsystems - Beijing China /*
6693c426a1Ske ge - Sun Microsystems - Beijing China  * If the number of free SWQEs (or large Tx buf) is larger than or equal to
6793c426a1Ske ge - Sun Microsystems - Beijing China  * IBD_RC_TX_FREE_THRESH, we will call mac_tx_update to notify GLD to continue
6893c426a1Ske ge - Sun Microsystems - Beijing China  * transmitting packets.
6993c426a1Ske ge - Sun Microsystems - Beijing China  */
7093c426a1Ske ge - Sun Microsystems - Beijing China #define	IBD_RC_TX_FREE_THRESH		8
7193c426a1Ske ge - Sun Microsystems - Beijing China 
7293c426a1Ske ge - Sun Microsystems - Beijing China #define	IBD_RC_QPN_TO_SID(qpn) \
7393c426a1Ske ge - Sun Microsystems - Beijing China 	((uint64_t)(IBD_RC_SERVICE_ID | ((qpn) & 0xffffff)))
7493c426a1Ske ge - Sun Microsystems - Beijing China 
7593c426a1Ske ge - Sun Microsystems - Beijing China /* For interop with legacy OFED */
7693c426a1Ske ge - Sun Microsystems - Beijing China #define	IBD_RC_QPN_TO_SID_OFED_INTEROP(qpn) \
7793c426a1Ske ge - Sun Microsystems - Beijing China 	((uint64_t)(IBD_RC_SERVICE_ID_OFED_INTEROP | ((qpn) & 0xffffff)))
7893c426a1Ske ge - Sun Microsystems - Beijing China 
7993c426a1Ske ge - Sun Microsystems - Beijing China /* Internet Header + 64 bits of Data Datagram. Refer to RFC 792 */
8093c426a1Ske ge - Sun Microsystems - Beijing China #define	IBD_RC_IP_ICMP_RETURN_DATA_BYTES	64
8193c426a1Ske ge - Sun Microsystems - Beijing China 
8293c426a1Ske ge - Sun Microsystems - Beijing China 
8393c426a1Ske ge - Sun Microsystems - Beijing China /* Functions for Reliable Connected Mode */
8493c426a1Ske ge - Sun Microsystems - Beijing China /* Connection Setup/Close Functions */
8593c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t ibd_rc_dispatch_pass_mad(void *,
8693c426a1Ske ge - Sun Microsystems - Beijing China     ibt_cm_event_t *, ibt_cm_return_args_t *, void *, ibt_priv_data_len_t);
8793c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t ibd_rc_dispatch_actv_mad(void *,
8893c426a1Ske ge - Sun Microsystems - Beijing China     ibt_cm_event_t *, ibt_cm_return_args_t *, void *, ibt_priv_data_len_t);
8903514dd7Ske ge - Sun Microsystems - Beijing China static void ibd_rc_act_close(ibd_rc_chan_t *, boolean_t);
9093c426a1Ske ge - Sun Microsystems - Beijing China 
9193c426a1Ske ge - Sun Microsystems - Beijing China static inline void ibd_rc_add_to_chan_list(ibd_rc_chan_list_t *,
9293c426a1Ske ge - Sun Microsystems - Beijing China     ibd_rc_chan_t *);
9393c426a1Ske ge - Sun Microsystems - Beijing China static inline ibd_rc_chan_t *ibd_rc_rm_header_chan_list(
9493c426a1Ske ge - Sun Microsystems - Beijing China     ibd_rc_chan_list_t *);
9503514dd7Ske ge - Sun Microsystems - Beijing China static inline ibd_rc_chan_t *ibd_rc_rm_from_chan_list(ibd_rc_chan_list_t *,
9693c426a1Ske ge - Sun Microsystems - Beijing China     ibd_rc_chan_t *);
9793c426a1Ske ge - Sun Microsystems - Beijing China 
9893c426a1Ske ge - Sun Microsystems - Beijing China /* CQ handlers */
9993c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_rcq_handler(ibt_cq_hdl_t, void *);
10093c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_scq_handler(ibt_cq_hdl_t, void *);
10193c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_poll_rcq(ibd_rc_chan_t *, ibt_cq_hdl_t);
10293c426a1Ske ge - Sun Microsystems - Beijing China 
10393c426a1Ske ge - Sun Microsystems - Beijing China /* Receive Functions */
10493c426a1Ske ge - Sun Microsystems - Beijing China static int ibd_rc_post_srq(ibd_state_t *, ibd_rwqe_t *);
10593c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_srq_freemsg_cb(char *);
106a567cb71Ske ge - Sun Microsystems - Beijing China static void ibd_rc_srq_free_rwqe(ibd_state_t *, ibd_rwqe_t *);
10793c426a1Ske ge - Sun Microsystems - Beijing China 
10893c426a1Ske ge - Sun Microsystems - Beijing China static int ibd_rc_post_rwqe(ibd_rc_chan_t *, ibd_rwqe_t *);
10993c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_freemsg_cb(char *);
11093c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_process_rx(ibd_rc_chan_t *, ibd_rwqe_t *, ibt_wc_t *);
11193c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_free_rwqe(ibd_rc_chan_t *, ibd_rwqe_t *);
11293c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_fini_rxlist(ibd_rc_chan_t *);
11393c426a1Ske ge - Sun Microsystems - Beijing China 
11493c426a1Ske ge - Sun Microsystems - Beijing China 
11593c426a1Ske ge - Sun Microsystems - Beijing China /* Send Functions */
11693c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_release_swqe(ibd_rc_chan_t *, ibd_swqe_t *);
11793c426a1Ske ge - Sun Microsystems - Beijing China static int ibd_rc_init_txlist(ibd_rc_chan_t *);
11893c426a1Ske ge - Sun Microsystems - Beijing China static void ibd_rc_fini_txlist(ibd_rc_chan_t *);
11993c426a1Ske ge - Sun Microsystems - Beijing China static uint_t ibd_rc_tx_recycle(caddr_t);
12093c426a1Ske ge - Sun Microsystems - Beijing China 
12193c426a1Ske ge - Sun Microsystems - Beijing China 
12293c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_async_rc_close_act_chan(ibd_state_t * state,ibd_req_t * req)12393c426a1Ske ge - Sun Microsystems - Beijing China ibd_async_rc_close_act_chan(ibd_state_t *state, ibd_req_t *req)
12493c426a1Ske ge - Sun Microsystems - Beijing China {
12593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *rc_chan = req->rq_ptr;
12693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace;
12793c426a1Ske ge - Sun Microsystems - Beijing China 
12893c426a1Ske ge - Sun Microsystems - Beijing China 	while (rc_chan != NULL) {
12993c426a1Ske ge - Sun Microsystems - Beijing China 		ace = rc_chan->ace;
13093c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace != NULL);
13193c426a1Ske ge - Sun Microsystems - Beijing China 		/* Close old RC channel */
13203514dd7Ske ge - Sun Microsystems - Beijing China 		ibd_rc_act_close(rc_chan, B_TRUE);
13393c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->id_ac_mutex);
13493c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace->ac_ref != 0);
13593c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&ace->ac_ref);
13693c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_chan = NULL;
13793c426a1Ske ge - Sun Microsystems - Beijing China 		if ((ace->ac_ref == 0) || (ace->ac_ref == CYCLEVAL)) {
13893c426a1Ske ge - Sun Microsystems - Beijing China 			IBD_ACACHE_INSERT_FREE(state, ace);
13993c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_ref = 0;
14093c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
14193c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_ref |= CYCLEVAL;
14293c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_delay_ace_recycle++;
14393c426a1Ske ge - Sun Microsystems - Beijing China 		}
14493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->id_ac_mutex);
14593c426a1Ske ge - Sun Microsystems - Beijing China 		rc_chan = ibd_rc_rm_header_chan_list(
14693c426a1Ske ge - Sun Microsystems - Beijing China 		    &state->rc_obs_act_chan_list);
14793c426a1Ske ge - Sun Microsystems - Beijing China 	}
14893c426a1Ske ge - Sun Microsystems - Beijing China }
14993c426a1Ske ge - Sun Microsystems - Beijing China 
15093c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_async_rc_recycle_ace(ibd_state_t * state,ibd_req_t * req)15193c426a1Ske ge - Sun Microsystems - Beijing China ibd_async_rc_recycle_ace(ibd_state_t *state, ibd_req_t *req)
15293c426a1Ske ge - Sun Microsystems - Beijing China {
15393c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace = req->rq_ptr;
15493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *rc_chan;
15593c426a1Ske ge - Sun Microsystems - Beijing China 
15693c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace != NULL);
15793c426a1Ske ge - Sun Microsystems - Beijing China 	rc_chan = ace->ac_chan;
15893c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(rc_chan != NULL);
15993c426a1Ske ge - Sun Microsystems - Beijing China 	/* Close old RC channel */
16003514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_rc_act_close(rc_chan, B_TRUE);
16193c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->id_ac_mutex);
16293c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace->ac_ref != 0);
16393c426a1Ske ge - Sun Microsystems - Beijing China 	atomic_dec_32(&ace->ac_ref);
16493c426a1Ske ge - Sun Microsystems - Beijing China 	ace->ac_chan = NULL;
16593c426a1Ske ge - Sun Microsystems - Beijing China 	if ((ace->ac_ref == 0) || (ace->ac_ref == CYCLEVAL)) {
16693c426a1Ske ge - Sun Microsystems - Beijing China 		IBD_ACACHE_INSERT_FREE(state, ace);
16793c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_ref = 0;
16893c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
16993c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_ref |= CYCLEVAL;
17093c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_delay_ace_recycle++;
17193c426a1Ske ge - Sun Microsystems - Beijing China 	}
17293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->id_ac_mutex);
17393c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_ace_recycle_lock);
17493c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_ace_recycle = NULL;
17593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_ace_recycle_lock);
17693c426a1Ske ge - Sun Microsystems - Beijing China }
17793c426a1Ske ge - Sun Microsystems - Beijing China 
17893c426a1Ske ge - Sun Microsystems - Beijing China /* Simple ICMP IP Header Template */
17993c426a1Ske ge - Sun Microsystems - Beijing China static const ipha_t icmp_ipha = {
18093c426a1Ske ge - Sun Microsystems - Beijing China 	IP_SIMPLE_HDR_VERSION, 0, 0, 0, 0, 0, IPPROTO_ICMP
18193c426a1Ske ge - Sun Microsystems - Beijing China };
18293c426a1Ske ge - Sun Microsystems - Beijing China 
18393c426a1Ske ge - Sun Microsystems - Beijing China /* Packet is too big. Send ICMP packet to GLD to request a smaller MTU */
18493c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_async_rc_process_too_big(ibd_state_t * state,ibd_req_t * req)18593c426a1Ske ge - Sun Microsystems - Beijing China ibd_async_rc_process_too_big(ibd_state_t *state, ibd_req_t *req)
18693c426a1Ske ge - Sun Microsystems - Beijing China {
18793c426a1Ske ge - Sun Microsystems - Beijing China 	mblk_t *mp = req->rq_ptr;
18893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace = req->rq_ptr2;
18993c426a1Ske ge - Sun Microsystems - Beijing China 	uint16_t mtu = state->id_mtu - IPOIB_HDRSIZE;
19093c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t	len_needed;
19193c426a1Ske ge - Sun Microsystems - Beijing China 	size_t	msg_len;
19293c426a1Ske ge - Sun Microsystems - Beijing China 	mblk_t	*pmtu_mp;
19393c426a1Ske ge - Sun Microsystems - Beijing China 	ushort_t	sap;
19493c426a1Ske ge - Sun Microsystems - Beijing China 	ib_header_info_t *ibha;	/* ib header for pmtu_pkt */
19593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
19693c426a1Ske ge - Sun Microsystems - Beijing China 	 * ipha: IP header for pmtu_pkt
19793c426a1Ske ge - Sun Microsystems - Beijing China 	 * old_ipha: IP header for old packet
19893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
19993c426a1Ske ge - Sun Microsystems - Beijing China 	ipha_t *ipha, *old_ipha;
20093c426a1Ske ge - Sun Microsystems - Beijing China 	icmph_t	*icmph;
20193c426a1Ske ge - Sun Microsystems - Beijing China 
20293c426a1Ske ge - Sun Microsystems - Beijing China 	sap = ntohs(((ipoib_hdr_t *)mp->b_rptr)->ipoib_type);
20393c426a1Ske ge - Sun Microsystems - Beijing China 
20493c426a1Ske ge - Sun Microsystems - Beijing China 	if (!pullupmsg(mp, -1)) {
20593c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_async_rc_process_too_big: pullupmsg fail");
20693c426a1Ske ge - Sun Microsystems - Beijing China 		goto too_big_fail;
20793c426a1Ske ge - Sun Microsystems - Beijing China 	}
20893c426a1Ske ge - Sun Microsystems - Beijing China 	/* move to IP header. */
20993c426a1Ske ge - Sun Microsystems - Beijing China 	mp->b_rptr += IPOIB_HDRSIZE;
21093c426a1Ske ge - Sun Microsystems - Beijing China 	old_ipha = (ipha_t *)mp->b_rptr;
21193c426a1Ske ge - Sun Microsystems - Beijing China 
21293c426a1Ske ge - Sun Microsystems - Beijing China 	len_needed = IPH_HDR_LENGTH(old_ipha);
21393c426a1Ske ge - Sun Microsystems - Beijing China 	if (old_ipha->ipha_protocol == IPPROTO_ENCAP) {
21493c426a1Ske ge - Sun Microsystems - Beijing China 		len_needed += IPH_HDR_LENGTH(((uchar_t *)old_ipha +
21593c426a1Ske ge - Sun Microsystems - Beijing China 		    len_needed));
21693c426a1Ske ge - Sun Microsystems - Beijing China 	} else if (old_ipha->ipha_protocol == IPPROTO_IPV6) {
21793c426a1Ske ge - Sun Microsystems - Beijing China 		ip6_t *ip6h = (ip6_t *)((uchar_t *)old_ipha
21893c426a1Ske ge - Sun Microsystems - Beijing China 		    + len_needed);
21993c426a1Ske ge - Sun Microsystems - Beijing China 		len_needed += ip_hdr_length_v6(mp, ip6h);
22093c426a1Ske ge - Sun Microsystems - Beijing China 	}
22193c426a1Ske ge - Sun Microsystems - Beijing China 	len_needed += IBD_RC_IP_ICMP_RETURN_DATA_BYTES;
22293c426a1Ske ge - Sun Microsystems - Beijing China 	msg_len = msgdsize(mp);
22393c426a1Ske ge - Sun Microsystems - Beijing China 	if (msg_len > len_needed) {
22493c426a1Ske ge - Sun Microsystems - Beijing China 		(void) adjmsg(mp, len_needed - msg_len);
22593c426a1Ske ge - Sun Microsystems - Beijing China 		msg_len = len_needed;
22693c426a1Ske ge - Sun Microsystems - Beijing China 	}
22793c426a1Ske ge - Sun Microsystems - Beijing China 
22893c426a1Ske ge - Sun Microsystems - Beijing China 	if ((pmtu_mp = allocb(sizeof (ib_header_info_t) + sizeof (ipha_t)
22993c426a1Ske ge - Sun Microsystems - Beijing China 	    + sizeof (icmph_t), BPRI_MED)) == NULL) {
23093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_async_rc_process_too_big: allocb fail");
23193c426a1Ske ge - Sun Microsystems - Beijing China 		goto too_big_fail;
23293c426a1Ske ge - Sun Microsystems - Beijing China 	}
23393c426a1Ske ge - Sun Microsystems - Beijing China 	pmtu_mp->b_cont = mp;
23493c426a1Ske ge - Sun Microsystems - Beijing China 	pmtu_mp->b_wptr = pmtu_mp->b_rptr + sizeof (ib_header_info_t)
23593c426a1Ske ge - Sun Microsystems - Beijing China 	    + sizeof (ipha_t) + sizeof (icmph_t);
23693c426a1Ske ge - Sun Microsystems - Beijing China 
23793c426a1Ske ge - Sun Microsystems - Beijing China 	ibha = (ib_header_info_t *)pmtu_mp->b_rptr;
23893c426a1Ske ge - Sun Microsystems - Beijing China 
23993c426a1Ske ge - Sun Microsystems - Beijing China 	/* Fill IB header */
24093c426a1Ske ge - Sun Microsystems - Beijing China 	bcopy(&state->id_macaddr, &ibha->ib_dst, IPOIB_ADDRL);
24193c426a1Ske ge - Sun Microsystems - Beijing China 	/*
24293c426a1Ske ge - Sun Microsystems - Beijing China 	 * If the GRH is not valid, indicate to GLDv3 by setting
24393c426a1Ske ge - Sun Microsystems - Beijing China 	 * the VerTcFlow field to 0.
24493c426a1Ske ge - Sun Microsystems - Beijing China 	 */
24593c426a1Ske ge - Sun Microsystems - Beijing China 	ibha->ib_grh.ipoib_vertcflow = 0;
24693c426a1Ske ge - Sun Microsystems - Beijing China 	ibha->ipib_rhdr.ipoib_type = htons(sap);
24793c426a1Ske ge - Sun Microsystems - Beijing China 	ibha->ipib_rhdr.ipoib_mbz = 0;
24893c426a1Ske ge - Sun Microsystems - Beijing China 
24993c426a1Ske ge - Sun Microsystems - Beijing China 	/* Fill IP header */
25093c426a1Ske ge - Sun Microsystems - Beijing China 	ipha = (ipha_t *)&ibha[1];
25193c426a1Ske ge - Sun Microsystems - Beijing China 	*ipha = icmp_ipha;
25293c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_src = old_ipha->ipha_dst;
25393c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_dst = old_ipha->ipha_src;
25493c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_ttl = old_ipha->ipha_ttl;
25593c426a1Ske ge - Sun Microsystems - Beijing China 	msg_len += sizeof (icmp_ipha) + sizeof (icmph_t);
25693c426a1Ske ge - Sun Microsystems - Beijing China 	if (msg_len > IP_MAXPACKET) {
25793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_process_too_big_pkt: msg_len(%d) "
25893c426a1Ske ge - Sun Microsystems - Beijing China 		    "> IP_MAXPACKET", (uint32_t)msg_len);
25993c426a1Ske ge - Sun Microsystems - Beijing China 		(void) adjmsg(mp, IP_MAXPACKET - msg_len);
26093c426a1Ske ge - Sun Microsystems - Beijing China 		msg_len = IP_MAXPACKET;
26193c426a1Ske ge - Sun Microsystems - Beijing China 	}
26293c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_length = htons((uint16_t)msg_len);
26393c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_hdr_checksum = 0;
26493c426a1Ske ge - Sun Microsystems - Beijing China 	ipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(ipha);
26593c426a1Ske ge - Sun Microsystems - Beijing China 
26693c426a1Ske ge - Sun Microsystems - Beijing China 	/* Fill ICMP body */
26793c426a1Ske ge - Sun Microsystems - Beijing China 	icmph = (icmph_t *)&ipha[1];
26893c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(icmph, sizeof (icmph_t));
26993c426a1Ske ge - Sun Microsystems - Beijing China 	icmph->icmph_type = ICMP_DEST_UNREACHABLE;
27093c426a1Ske ge - Sun Microsystems - Beijing China 	icmph->icmph_code = ICMP_FRAGMENTATION_NEEDED;
27193c426a1Ske ge - Sun Microsystems - Beijing China 	icmph->icmph_du_mtu = htons(mtu);
27293c426a1Ske ge - Sun Microsystems - Beijing China 	icmph->icmph_checksum = 0;
27393c426a1Ske ge - Sun Microsystems - Beijing China 	icmph->icmph_checksum = IP_CSUM(pmtu_mp,
27493c426a1Ske ge - Sun Microsystems - Beijing China 	    (int32_t)sizeof (ib_header_info_t) + (int32_t)sizeof (ipha_t), 0);
27593c426a1Ske ge - Sun Microsystems - Beijing China 
276*ec71f88eSPatrick Mooney 	mac_hcksum_set(pmtu_mp, 0, 0, 0, 0, HCK_FULLCKSUM | HCK_FULLCKSUM_OK);
27793c426a1Ske ge - Sun Microsystems - Beijing China 
27893c426a1Ske ge - Sun Microsystems - Beijing China 	DPRINT(30, "ibd_async_rc_process_too_big: sap=0x%x, ip_src=0x%x, "
27993c426a1Ske ge - Sun Microsystems - Beijing China 	    "ip_dst=0x%x, ttl=%d, len_needed=%d, msg_len=%d",
28093c426a1Ske ge - Sun Microsystems - Beijing China 	    sap, ipha->ipha_src, ipha->ipha_dst, ipha->ipha_ttl,
28193c426a1Ske ge - Sun Microsystems - Beijing China 	    len_needed, (uint32_t)msg_len);
28293c426a1Ske ge - Sun Microsystems - Beijing China 
28393c426a1Ske ge - Sun Microsystems - Beijing China 	mac_rx(state->id_mh, state->id_rh, pmtu_mp);
28493c426a1Ske ge - Sun Microsystems - Beijing China 
28593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&ace->tx_too_big_mutex);
28693c426a1Ske ge - Sun Microsystems - Beijing China 	ace->tx_too_big_ongoing = B_FALSE;
28793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&ace->tx_too_big_mutex);
28893c426a1Ske ge - Sun Microsystems - Beijing China 	return;
28993c426a1Ske ge - Sun Microsystems - Beijing China 
29093c426a1Ske ge - Sun Microsystems - Beijing China too_big_fail:
29193c426a1Ske ge - Sun Microsystems - Beijing China 	/* Drop packet */
29293c426a1Ske ge - Sun Microsystems - Beijing China 	freemsg(mp);
29393c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&ace->tx_too_big_mutex);
29493c426a1Ske ge - Sun Microsystems - Beijing China 	ace->tx_too_big_ongoing = B_FALSE;
29593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&ace->tx_too_big_mutex);
29693c426a1Ske ge - Sun Microsystems - Beijing China }
29793c426a1Ske ge - Sun Microsystems - Beijing China 
29803514dd7Ske ge - Sun Microsystems - Beijing China /*
29903514dd7Ske ge - Sun Microsystems - Beijing China  * Check all active/passive channels. If any ative/passive
30003514dd7Ske ge - Sun Microsystems - Beijing China  * channel has not been used for a long time, close it.
30103514dd7Ske ge - Sun Microsystems - Beijing China  */
30203514dd7Ske ge - Sun Microsystems - Beijing China void
ibd_rc_conn_timeout_call(void * carg)30303514dd7Ske ge - Sun Microsystems - Beijing China ibd_rc_conn_timeout_call(void *carg)
30403514dd7Ske ge - Sun Microsystems - Beijing China {
30503514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = carg;
30603514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace, *pre_ace;
30703514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan, *pre_chan, *next_chan;
30803514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_req_t *req;
30903514dd7Ske ge - Sun Microsystems - Beijing China 
31003514dd7Ske ge - Sun Microsystems - Beijing China 	/* Check all active channels. If chan->is_used == B_FALSE, close it */
31103514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->id_ac_mutex);
31203514dd7Ske ge - Sun Microsystems - Beijing China 	ace = list_head(&state->id_ah_active);
31303514dd7Ske ge - Sun Microsystems - Beijing China 	while ((pre_ace = ace) != NULL) {
31403514dd7Ske ge - Sun Microsystems - Beijing China 		ace = list_next(&state->id_ah_active, ace);
31503514dd7Ske ge - Sun Microsystems - Beijing China 		if (pre_ace->ac_chan != NULL) {
31603514dd7Ske ge - Sun Microsystems - Beijing China 			chan = pre_ace->ac_chan;
31703514dd7Ske ge - Sun Microsystems - Beijing China 			ASSERT(state->id_enable_rc == B_TRUE);
31803514dd7Ske ge - Sun Microsystems - Beijing China 			if (chan->chan_state == IBD_RC_STATE_ACT_ESTAB) {
31903514dd7Ske ge - Sun Microsystems - Beijing China 				if (chan->is_used == B_FALSE) {
32003514dd7Ske ge - Sun Microsystems - Beijing China 					state->rc_timeout_act++;
32103514dd7Ske ge - Sun Microsystems - Beijing China 					INC_REF(pre_ace, 1);
32203514dd7Ske ge - Sun Microsystems - Beijing China 					IBD_ACACHE_PULLOUT_ACTIVE(state,
32303514dd7Ske ge - Sun Microsystems - Beijing China 					    pre_ace);
32403514dd7Ske ge - Sun Microsystems - Beijing China 					chan->chan_state =
32503514dd7Ske ge - Sun Microsystems - Beijing China 					    IBD_RC_STATE_ACT_CLOSING;
32603514dd7Ske ge - Sun Microsystems - Beijing China 					ibd_rc_signal_act_close(state, pre_ace);
32703514dd7Ske ge - Sun Microsystems - Beijing China 				} else {
32803514dd7Ske ge - Sun Microsystems - Beijing China 					chan->is_used = B_FALSE;
32903514dd7Ske ge - Sun Microsystems - Beijing China 				}
33003514dd7Ske ge - Sun Microsystems - Beijing China 			}
33103514dd7Ske ge - Sun Microsystems - Beijing China 		}
33203514dd7Ske ge - Sun Microsystems - Beijing China 	}
33303514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->id_ac_mutex);
33403514dd7Ske ge - Sun Microsystems - Beijing China 
33503514dd7Ske ge - Sun Microsystems - Beijing China 	/* Check all passive channels. If chan->is_used == B_FALSE, close it */
33603514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_pass_chan_list.chan_list_mutex);
33703514dd7Ske ge - Sun Microsystems - Beijing China 	next_chan = state->rc_pass_chan_list.chan_list;
33803514dd7Ske ge - Sun Microsystems - Beijing China 	pre_chan = NULL;
33903514dd7Ske ge - Sun Microsystems - Beijing China 	while ((chan = next_chan) != NULL) {
34003514dd7Ske ge - Sun Microsystems - Beijing China 		next_chan = chan->next;
34103514dd7Ske ge - Sun Microsystems - Beijing China 		if (chan->is_used == B_FALSE) {
34203514dd7Ske ge - Sun Microsystems - Beijing China 			req = kmem_cache_alloc(state->id_req_kmc, KM_NOSLEEP);
34303514dd7Ske ge - Sun Microsystems - Beijing China 			if (req != NULL) {
34403514dd7Ske ge - Sun Microsystems - Beijing China 				/* remove it */
34503514dd7Ske ge - Sun Microsystems - Beijing China 				state->rc_timeout_pas++;
34603514dd7Ske ge - Sun Microsystems - Beijing China 				req->rq_ptr = chan;
34703514dd7Ske ge - Sun Microsystems - Beijing China 				ibd_queue_work_slot(state, req,
34803514dd7Ske ge - Sun Microsystems - Beijing China 				    IBD_ASYNC_RC_CLOSE_PAS_CHAN);
34903514dd7Ske ge - Sun Microsystems - Beijing China 			} else {
35003514dd7Ske ge - Sun Microsystems - Beijing China 				ibd_print_warn(state, "ibd_rc_conn_timeout: "
35103514dd7Ske ge - Sun Microsystems - Beijing China 				    "alloc ibd_req_t fail");
35203514dd7Ske ge - Sun Microsystems - Beijing China 				if (pre_chan == NULL) {
35303514dd7Ske ge - Sun Microsystems - Beijing China 					state->rc_pass_chan_list.chan_list =
35403514dd7Ske ge - Sun Microsystems - Beijing China 					    chan;
35503514dd7Ske ge - Sun Microsystems - Beijing China 				} else {
35603514dd7Ske ge - Sun Microsystems - Beijing China 					pre_chan->next = chan;
35703514dd7Ske ge - Sun Microsystems - Beijing China 				}
35803514dd7Ske ge - Sun Microsystems - Beijing China 				pre_chan = chan;
35903514dd7Ske ge - Sun Microsystems - Beijing China 			}
36003514dd7Ske ge - Sun Microsystems - Beijing China 		} else {
36103514dd7Ske ge - Sun Microsystems - Beijing China 			if (pre_chan == NULL) {
36203514dd7Ske ge - Sun Microsystems - Beijing China 				state->rc_pass_chan_list.chan_list = chan;
36303514dd7Ske ge - Sun Microsystems - Beijing China 			} else {
36403514dd7Ske ge - Sun Microsystems - Beijing China 				pre_chan->next = chan;
36503514dd7Ske ge - Sun Microsystems - Beijing China 			}
36603514dd7Ske ge - Sun Microsystems - Beijing China 			pre_chan = chan;
36703514dd7Ske ge - Sun Microsystems - Beijing China 			chan->is_used = B_FALSE;
36803514dd7Ske ge - Sun Microsystems - Beijing China 		}
36903514dd7Ske ge - Sun Microsystems - Beijing China 	}
37003514dd7Ske ge - Sun Microsystems - Beijing China 	if (pre_chan != NULL) {
37103514dd7Ske ge - Sun Microsystems - Beijing China 		pre_chan->next = NULL;
37203514dd7Ske ge - Sun Microsystems - Beijing China 	} else {
37303514dd7Ske ge - Sun Microsystems - Beijing China 		state->rc_pass_chan_list.chan_list = NULL;
37403514dd7Ske ge - Sun Microsystems - Beijing China 	}
37503514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_pass_chan_list.chan_list_mutex);
37603514dd7Ske ge - Sun Microsystems - Beijing China 
37703514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_timeout_lock);
37803514dd7Ske ge - Sun Microsystems - Beijing China 	if (state->rc_timeout_start == B_TRUE) {
37903514dd7Ske ge - Sun Microsystems - Beijing China 		state->rc_timeout = timeout(ibd_rc_conn_timeout_call, state,
38003514dd7Ske ge - Sun Microsystems - Beijing China 		    SEC_TO_TICK(ibd_rc_conn_timeout));
38103514dd7Ske ge - Sun Microsystems - Beijing China 	}
38203514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_timeout_lock);
38303514dd7Ske ge - Sun Microsystems - Beijing China }
38403514dd7Ske ge - Sun Microsystems - Beijing China 
38593c426a1Ske ge - Sun Microsystems - Beijing China #ifdef DEBUG
38693c426a1Ske ge - Sun Microsystems - Beijing China /*
38793c426a1Ske ge - Sun Microsystems - Beijing China  * ibd_rc_update_stats - update driver private kstat counters
38893c426a1Ske ge - Sun Microsystems - Beijing China  *
38993c426a1Ske ge - Sun Microsystems - Beijing China  * This routine will dump the internal statistics counters for ibd's
39093c426a1Ske ge - Sun Microsystems - Beijing China  * Reliable Connected Mode. The current stats dump values will
39193c426a1Ske ge - Sun Microsystems - Beijing China  * be sent to the kernel status area.
39293c426a1Ske ge - Sun Microsystems - Beijing China  */
39393c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_update_stats(kstat_t * ksp,int rw)39493c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_update_stats(kstat_t *ksp, int rw)
39593c426a1Ske ge - Sun Microsystems - Beijing China {
39693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state;
39793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_stat_t *ibd_rc_ksp;
39893c426a1Ske ge - Sun Microsystems - Beijing China 
39993c426a1Ske ge - Sun Microsystems - Beijing China 	if (rw == KSTAT_WRITE)
40093c426a1Ske ge - Sun Microsystems - Beijing China 		return (EACCES);
40193c426a1Ske ge - Sun Microsystems - Beijing China 
40293c426a1Ske ge - Sun Microsystems - Beijing China 	state = (ibd_state_t *)ksp->ks_private;
40393c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state != NULL);
40493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp = (ibd_rc_stat_t *)ksp->ks_data;
40593c426a1Ske ge - Sun Microsystems - Beijing China 
40693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcv_trans_byte.value.ul = state->rc_rcv_trans_byte;
40793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcv_trans_pkt.value.ul = state->rc_rcv_trans_pkt;
40893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcv_copy_byte.value.ul = state->rc_rcv_copy_byte;
40993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcv_copy_pkt.value.ul = state->rc_rcv_copy_pkt;
41093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcv_alloc_fail.value.ul = state->rc_rcv_alloc_fail;
41193c426a1Ske ge - Sun Microsystems - Beijing China 
41293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rcq_err.value.ul = state->rc_rcq_err;
41393c426a1Ske ge - Sun Microsystems - Beijing China 
41493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_rwqe_short.value.ul = state->rc_rwqe_short;
41593c426a1Ske ge - Sun Microsystems - Beijing China 
41693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_bytes.value.ul = state->rc_xmt_bytes;
41793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_small_pkt.value.ul = state->rc_xmt_small_pkt;
41893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_fragmented_pkt.value.ul =
41993c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_xmt_fragmented_pkt;
42093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_map_fail_pkt.value.ul = state->rc_xmt_map_fail_pkt;
42193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_map_succ_pkt.value.ul = state->rc_xmt_map_succ_pkt;
42293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_ace_not_found.value.ul = state->rc_ace_not_found;
42393c426a1Ske ge - Sun Microsystems - Beijing China 
42493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_scq_no_swqe.value.ul = state->rc_scq_no_swqe;
42593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_scq_no_largebuf.value.ul = state->rc_scq_no_largebuf;
42693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_swqe_short.value.ul = state->rc_swqe_short;
42793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_swqe_mac_update.value.ul = state->rc_swqe_mac_update;
42893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_buf_short.value.ul = state->rc_xmt_buf_short;
42993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_xmt_buf_mac_update.value.ul =
43093c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_xmt_buf_mac_update;
43193c426a1Ske ge - Sun Microsystems - Beijing China 
43293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_conn_succ.value.ul = state->rc_conn_succ;
43393c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_conn_fail.value.ul = state->rc_conn_fail;
43493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_null_conn.value.ul = state->rc_null_conn;
43593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_no_estab_conn.value.ul = state->rc_no_estab_conn;
43693c426a1Ske ge - Sun Microsystems - Beijing China 
43793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_act_close.value.ul = state->rc_act_close;
43893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_pas_close.value.ul = state->rc_pas_close;
43993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_delay_ace_recycle.value.ul = state->rc_delay_ace_recycle;
44093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_act_close_simultaneous.value.ul =
44193c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_act_close_simultaneous;
44293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_reset_cnt.value.ul = state->rc_reset_cnt;
44303514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_timeout_act.value.ul = state->rc_timeout_act;
44403514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp->rc_timeout_pas.value.ul = state->rc_timeout_pas;
44593c426a1Ske ge - Sun Microsystems - Beijing China 
44693c426a1Ske ge - Sun Microsystems - Beijing China 	return (0);
44793c426a1Ske ge - Sun Microsystems - Beijing China }
44893c426a1Ske ge - Sun Microsystems - Beijing China 
44993c426a1Ske ge - Sun Microsystems - Beijing China 
45093c426a1Ske ge - Sun Microsystems - Beijing China /*
45193c426a1Ske ge - Sun Microsystems - Beijing China  * ibd_rc_init_stats - initialize kstat data structures
45293c426a1Ske ge - Sun Microsystems - Beijing China  *
45393c426a1Ske ge - Sun Microsystems - Beijing China  * This routine will create and initialize the driver private
45493c426a1Ske ge - Sun Microsystems - Beijing China  * statistics counters.
45593c426a1Ske ge - Sun Microsystems - Beijing China  */
45693c426a1Ske ge - Sun Microsystems - Beijing China int
ibd_rc_init_stats(ibd_state_t * state)45793c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_init_stats(ibd_state_t *state)
45893c426a1Ske ge - Sun Microsystems - Beijing China {
45993c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_t *ksp;
46093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_stat_t *ibd_rc_ksp;
46103514dd7Ske ge - Sun Microsystems - Beijing China 	char stat_name[KSTAT_STRLEN];
4621cfa752fSRamaswamy Tummala 	int inst;
46393c426a1Ske ge - Sun Microsystems - Beijing China 
46493c426a1Ske ge - Sun Microsystems - Beijing China 	/*
46593c426a1Ske ge - Sun Microsystems - Beijing China 	 * Create and init kstat
46693c426a1Ske ge - Sun Microsystems - Beijing China 	 */
4671cfa752fSRamaswamy Tummala 	inst = ddi_get_instance(state->id_dip);
468fcfc878bSPavan Chandrashekar 	(void) snprintf(stat_name, KSTAT_STRLEN, "statistics%d_%x_%u", inst,
469fcfc878bSPavan Chandrashekar 	    state->id_pkey, state->id_plinkid);
4701cfa752fSRamaswamy Tummala 	ksp = kstat_create("ibd", 0, stat_name, "net", KSTAT_TYPE_NAMED,
47193c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ibd_rc_stat_t) / sizeof (kstat_named_t), 0);
47293c426a1Ske ge - Sun Microsystems - Beijing China 
47393c426a1Ske ge - Sun Microsystems - Beijing China 	if (ksp == NULL) {
47493c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_init_stats: Could not create "
47593c426a1Ske ge - Sun Microsystems - Beijing China 		    "kernel statistics");
47693c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
47793c426a1Ske ge - Sun Microsystems - Beijing China 	}
47893c426a1Ske ge - Sun Microsystems - Beijing China 
47993c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_ksp = ksp;	/* Fill in the ksp of ibd over RC mode */
48093c426a1Ske ge - Sun Microsystems - Beijing China 
48193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_ksp = (ibd_rc_stat_t *)ksp->ks_data;
48293c426a1Ske ge - Sun Microsystems - Beijing China 
48393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
48493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Initialize all the statistics
48593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
48693c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcv_trans_byte, "RC: Rx Bytes, "
48793c426a1Ske ge - Sun Microsystems - Beijing China 	    "transfer mode", KSTAT_DATA_ULONG);
48893c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcv_trans_pkt, "RC: Rx Pkts, "
48993c426a1Ske ge - Sun Microsystems - Beijing China 	    "transfer mode", KSTAT_DATA_ULONG);
49093c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcv_copy_byte, "RC: Rx Bytes, "
49193c426a1Ske ge - Sun Microsystems - Beijing China 	    "copy mode", KSTAT_DATA_ULONG);
49293c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcv_copy_pkt, "RC: Rx Pkts, "
49393c426a1Ske ge - Sun Microsystems - Beijing China 	    "copy mode", KSTAT_DATA_ULONG);
49493c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcv_alloc_fail, "RC: Rx alloc fail",
49593c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
49693c426a1Ske ge - Sun Microsystems - Beijing China 
49793c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rcq_err, "RC: fail in Recv CQ handler",
49893c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
49993c426a1Ske ge - Sun Microsystems - Beijing China 
50093c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_rwqe_short, "RC: Short rwqe",
50193c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
50293c426a1Ske ge - Sun Microsystems - Beijing China 
50393c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_bytes, "RC: Sent Bytes",
50493c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
50593c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_small_pkt,
50693c426a1Ske ge - Sun Microsystems - Beijing China 	    "RC: Tx pkt small size", KSTAT_DATA_ULONG);
50793c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_fragmented_pkt,
50893c426a1Ske ge - Sun Microsystems - Beijing China 	    "RC: Tx pkt fragmentary", KSTAT_DATA_ULONG);
50993c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_map_fail_pkt,
51093c426a1Ske ge - Sun Microsystems - Beijing China 	    "RC: Tx pkt fail ibt_map_mem_iov()", KSTAT_DATA_ULONG);
51193c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_map_succ_pkt,
51293c426a1Ske ge - Sun Microsystems - Beijing China 	    "RC: Tx pkt succ ibt_map_mem_iov()", KSTAT_DATA_ULONG);
51393c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_ace_not_found, "RC: ace not found",
51493c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
51593c426a1Ske ge - Sun Microsystems - Beijing China 
51693c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_scq_no_swqe, "RC: No swqe after "
51793c426a1Ske ge - Sun Microsystems - Beijing China 	    "recycle", KSTAT_DATA_ULONG);
51893c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_scq_no_largebuf, "RC: No large tx buf "
51993c426a1Ske ge - Sun Microsystems - Beijing China 	    "after recycle", KSTAT_DATA_ULONG);
52093c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_swqe_short, "RC: No swqe in ibd_send",
52193c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
52293c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_swqe_mac_update, "RC: mac_tx_update "
52393c426a1Ske ge - Sun Microsystems - Beijing China 	    "#, swqe available", KSTAT_DATA_ULONG);
52493c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_buf_short, "RC: No buf in "
52593c426a1Ske ge - Sun Microsystems - Beijing China 	    "ibd_send", KSTAT_DATA_ULONG);
52693c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_xmt_buf_mac_update, "RC: "
52793c426a1Ske ge - Sun Microsystems - Beijing China 	    "mac_tx_update #, buf available", KSTAT_DATA_ULONG);
52893c426a1Ske ge - Sun Microsystems - Beijing China 
52993c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_conn_succ, "RC: succ connected",
53093c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
53193c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_conn_fail, "RC: fail connect",
53293c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
53393c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_null_conn, "RC: null conn for unicast "
53493c426a1Ske ge - Sun Microsystems - Beijing China 	    "pkt", KSTAT_DATA_ULONG);
53593c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_no_estab_conn, "RC: not in act estab "
53693c426a1Ske ge - Sun Microsystems - Beijing China 	    "state", KSTAT_DATA_ULONG);
53793c426a1Ske ge - Sun Microsystems - Beijing China 
53893c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_act_close, "RC: call ibd_rc_act_close",
53993c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
54093c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_pas_close, "RC: call ibd_rc_pas_close",
54193c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
54293c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_delay_ace_recycle, "RC: delay ace "
54393c426a1Ske ge - Sun Microsystems - Beijing China 	    "recycle", KSTAT_DATA_ULONG);
54493c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_act_close_simultaneous, "RC: "
54593c426a1Ske ge - Sun Microsystems - Beijing China 	    "simultaneous ibd_rc_act_close", KSTAT_DATA_ULONG);
54693c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_reset_cnt, "RC: Reset RC channel",
54793c426a1Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
54803514dd7Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_act_close, "RC: timeout act side",
54903514dd7Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
55003514dd7Ske ge - Sun Microsystems - Beijing China 	kstat_named_init(&ibd_rc_ksp->rc_pas_close, "RC: timeout pas side",
55103514dd7Ske ge - Sun Microsystems - Beijing China 	    KSTAT_DATA_ULONG);
55293c426a1Ske ge - Sun Microsystems - Beijing China 
55393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
55493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Function to provide kernel stat update on demand
55593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
55693c426a1Ske ge - Sun Microsystems - Beijing China 	ksp->ks_update = ibd_rc_update_stats;
55793c426a1Ske ge - Sun Microsystems - Beijing China 
55893c426a1Ske ge - Sun Microsystems - Beijing China 	/*
55993c426a1Ske ge - Sun Microsystems - Beijing China 	 * Pointer into provider's raw statistics
56093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
56193c426a1Ske ge - Sun Microsystems - Beijing China 	ksp->ks_private = (void *)state;
56293c426a1Ske ge - Sun Microsystems - Beijing China 
56393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
56493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Add kstat to systems kstat chain
56593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
56693c426a1Ske ge - Sun Microsystems - Beijing China 	kstat_install(ksp);
56793c426a1Ske ge - Sun Microsystems - Beijing China 
56893c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
56993c426a1Ske ge - Sun Microsystems - Beijing China }
57093c426a1Ske ge - Sun Microsystems - Beijing China #endif
57193c426a1Ske ge - Sun Microsystems - Beijing China 
57293c426a1Ske ge - Sun Microsystems - Beijing China static ibt_status_t
ibd_rc_alloc_chan(ibd_rc_chan_t ** ret_chan,ibd_state_t * state,boolean_t is_tx_chan)57393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_alloc_chan(ibd_rc_chan_t **ret_chan, ibd_state_t *state,
57493c426a1Ske ge - Sun Microsystems - Beijing China     boolean_t is_tx_chan)
57593c426a1Ske ge - Sun Microsystems - Beijing China {
57693c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t result;
57793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan;
57893c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_rc_chan_alloc_args_t alloc_args;
57993c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_chan_alloc_flags_t alloc_flags;
58093c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_chan_sizes_t sizes;
58193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_cq_attr_t cq_atts;
58293c426a1Ske ge - Sun Microsystems - Beijing China 	int rv;
58393c426a1Ske ge - Sun Microsystems - Beijing China 
58493c426a1Ske ge - Sun Microsystems - Beijing China 	chan = kmem_zalloc(sizeof (ibd_rc_chan_t), KM_SLEEP);
58593c426a1Ske ge - Sun Microsystems - Beijing China 
58693c426a1Ske ge - Sun Microsystems - Beijing China 	chan->state = state;
58793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->rx_wqe_list.dl_mutex, NULL, MUTEX_DRIVER, NULL);
58893c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->rx_free_list.dl_mutex, NULL, MUTEX_DRIVER, NULL);
58993c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->tx_wqe_list.dl_mutex, NULL, MUTEX_DRIVER, NULL);
59093c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->tx_rel_list.dl_mutex, NULL, MUTEX_DRIVER, NULL);
59193c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->tx_post_lock, NULL, MUTEX_DRIVER, NULL);
59293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_init(&chan->tx_poll_lock, NULL, MUTEX_DRIVER, NULL);
59393c426a1Ske ge - Sun Microsystems - Beijing China 
59493c426a1Ske ge - Sun Microsystems - Beijing China 	/* Allocate IB structures for a new RC channel. */
59593c426a1Ske ge - Sun Microsystems - Beijing China 	if (is_tx_chan) {
5961cfa752fSRamaswamy Tummala 		chan->scq_size = state->id_rc_num_swqe;
59793c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rcq_size = IBD_RC_MIN_CQ_SIZE;
59893c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
59993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->scq_size = IBD_RC_MIN_CQ_SIZE;
6001cfa752fSRamaswamy Tummala 		chan->rcq_size = state->id_rc_num_rwqe;
60193c426a1Ske ge - Sun Microsystems - Beijing China 	}
60293c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_size = chan->scq_size;
60393c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_sched = NULL;
60493c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_flags = IBT_CQ_NO_FLAGS;
60593c426a1Ske ge - Sun Microsystems - Beijing China 	result = ibt_alloc_cq(state->id_hca_hdl, &cq_atts, &chan->scq_hdl,
60693c426a1Ske ge - Sun Microsystems - Beijing China 	    &chan->scq_size);
60793c426a1Ske ge - Sun Microsystems - Beijing China 	if (result != IBT_SUCCESS) {
60893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_alloc_chan: error <%d>"
60993c426a1Ske ge - Sun Microsystems - Beijing China 		    "create scq completion queue (size <%d>)",
61093c426a1Ske ge - Sun Microsystems - Beijing China 		    result, chan->scq_size);
61193c426a1Ske ge - Sun Microsystems - Beijing China 		goto alloc_scq_err;
61293c426a1Ske ge - Sun Microsystems - Beijing China 	}	/* if failure to alloc cq */
61393c426a1Ske ge - Sun Microsystems - Beijing China 
6141cfa752fSRamaswamy Tummala 	if (ibt_modify_cq(chan->scq_hdl, state->id_rc_tx_comp_count,
6151cfa752fSRamaswamy Tummala 	    state->id_rc_tx_comp_usec, 0) != IBT_SUCCESS) {
61603514dd7Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_alloc_chan: Send CQ "
6171cfa752fSRamaswamy Tummala 		    "interrupt moderation failed");
61893c426a1Ske ge - Sun Microsystems - Beijing China 	}
61993c426a1Ske ge - Sun Microsystems - Beijing China 
62093c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_cq_private(chan->scq_hdl, (void *) (uintptr_t)chan);
62193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_cq_handler(chan->scq_hdl, ibd_rc_scq_handler,
62293c426a1Ske ge - Sun Microsystems - Beijing China 	    (void *) (uintptr_t)chan);
62393c426a1Ske ge - Sun Microsystems - Beijing China 
62493c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_size = chan->rcq_size;
62593c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_sched = NULL;
62693c426a1Ske ge - Sun Microsystems - Beijing China 	cq_atts.cq_flags = IBT_CQ_NO_FLAGS;
62793c426a1Ske ge - Sun Microsystems - Beijing China 	result = ibt_alloc_cq(state->id_hca_hdl, &cq_atts, &chan->rcq_hdl,
62893c426a1Ske ge - Sun Microsystems - Beijing China 	    &chan->rcq_size);
62993c426a1Ske ge - Sun Microsystems - Beijing China 	if (result != IBT_SUCCESS) {
63093c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_alloc_chan: error <%d> creating "
63193c426a1Ske ge - Sun Microsystems - Beijing China 		    "rx completion queue (size <%d>)", result, chan->rcq_size);
63293c426a1Ske ge - Sun Microsystems - Beijing China 		goto alloc_rcq_err;
63393c426a1Ske ge - Sun Microsystems - Beijing China 	}	/* if failure to alloc cq */
63493c426a1Ske ge - Sun Microsystems - Beijing China 
6351cfa752fSRamaswamy Tummala 	if (ibt_modify_cq(chan->rcq_hdl, state->id_rc_rx_comp_count,
6361cfa752fSRamaswamy Tummala 	    state->id_rc_rx_comp_usec, 0) != IBT_SUCCESS) {
63703514dd7Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_alloc_chan: Receive CQ "
6381cfa752fSRamaswamy Tummala 		    "interrupt moderation failed");
63993c426a1Ske ge - Sun Microsystems - Beijing China 	}
6401cfa752fSRamaswamy Tummala 
64193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_cq_private(chan->rcq_hdl, (void *) (uintptr_t)chan);
64293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_cq_handler(chan->rcq_hdl, ibd_rc_rcq_handler,
64393c426a1Ske ge - Sun Microsystems - Beijing China 	    (void *)(uintptr_t)chan);
64493c426a1Ske ge - Sun Microsystems - Beijing China 
64593c426a1Ske ge - Sun Microsystems - Beijing China 	if (is_tx_chan) {
64693c426a1Ske ge - Sun Microsystems - Beijing China 		chan->is_tx_chan = B_TRUE;
64793c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibd_rc_init_txlist(chan) != DDI_SUCCESS) {
64893c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_print_warn(state, "ibd_rc_alloc_chan: "
64993c426a1Ske ge - Sun Microsystems - Beijing China 			    "ibd_rc_init_txlist failed");
65093c426a1Ske ge - Sun Microsystems - Beijing China 			goto init_txlist_err;
65193c426a1Ske ge - Sun Microsystems - Beijing China 		}
65293c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibd_rc_tx_softintr == 1) {
65393c426a1Ske ge - Sun Microsystems - Beijing China 			if ((rv = ddi_add_softintr(state->id_dip,
65493c426a1Ske ge - Sun Microsystems - Beijing China 			    DDI_SOFTINT_LOW, &chan->scq_softintr, NULL, NULL,
65593c426a1Ske ge - Sun Microsystems - Beijing China 			    ibd_rc_tx_recycle, (caddr_t)chan)) !=
65693c426a1Ske ge - Sun Microsystems - Beijing China 			    DDI_SUCCESS) {
65793c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(10, "ibd_rc_alloc_chan: failed in "
65893c426a1Ske ge - Sun Microsystems - Beijing China 				    "ddi_add_softintr(scq_softintr), ret=%d",
65993c426a1Ske ge - Sun Microsystems - Beijing China 				    rv);
66093c426a1Ske ge - Sun Microsystems - Beijing China 				goto alloc_softintr_err;
66193c426a1Ske ge - Sun Microsystems - Beijing China 			}
66293c426a1Ske ge - Sun Microsystems - Beijing China 		}
66393c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
66493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->is_tx_chan = B_FALSE;
66593c426a1Ske ge - Sun Microsystems - Beijing China 	}
66693c426a1Ske ge - Sun Microsystems - Beijing China 
66793c426a1Ske ge - Sun Microsystems - Beijing China 	/*
66893c426a1Ske ge - Sun Microsystems - Beijing China 	 * enable completions
66993c426a1Ske ge - Sun Microsystems - Beijing China 	 */
67093c426a1Ske ge - Sun Microsystems - Beijing China 	result = ibt_enable_cq_notify(chan->scq_hdl, IBT_NEXT_COMPLETION);
67193c426a1Ske ge - Sun Microsystems - Beijing China 	if (result != IBT_SUCCESS) {
67293c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_alloc_chan: ibt_enable_cq_notify"
67393c426a1Ske ge - Sun Microsystems - Beijing China 		    "(scq) failed: status %d\n", result);
67493c426a1Ske ge - Sun Microsystems - Beijing China 		goto alloc_scq_enable_err;
67593c426a1Ske ge - Sun Microsystems - Beijing China 	}
67693c426a1Ske ge - Sun Microsystems - Beijing China 
67793c426a1Ske ge - Sun Microsystems - Beijing China 	/* We will enable chan->rcq_hdl later. */
67893c426a1Ske ge - Sun Microsystems - Beijing China 
67993c426a1Ske ge - Sun Microsystems - Beijing China 	/* alloc a RC channel */
68093c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&alloc_args, sizeof (ibt_rc_chan_alloc_args_t));
68193c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&sizes, sizeof (ibt_chan_sizes_t));
68293c426a1Ske ge - Sun Microsystems - Beijing China 
68393c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_flags = IBT_WR_SIGNALED;
68493c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_control = IBT_CEP_NO_FLAGS;
68593c426a1Ske ge - Sun Microsystems - Beijing China 
68693c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_scq = chan->scq_hdl;
68793c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_rcq = chan->rcq_hdl;
68893c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_pd = state->id_pd_hdl;
68993c426a1Ske ge - Sun Microsystems - Beijing China 
69093c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_hca_port_num = state->id_port;
69193c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_clone_chan = NULL;
69293c426a1Ske ge - Sun Microsystems - Beijing China 
69393c426a1Ske ge - Sun Microsystems - Beijing China 	/* scatter/gather */
69493c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_sizes.cs_sq_sgl = state->rc_tx_max_sqseg;
69593c426a1Ske ge - Sun Microsystems - Beijing China 
69693c426a1Ske ge - Sun Microsystems - Beijing China 	/*
69793c426a1Ske ge - Sun Microsystems - Beijing China 	 * For the number of SGL elements in receive side, I think it
69893c426a1Ske ge - Sun Microsystems - Beijing China 	 * should be 1. Because ibd driver allocates a whole block memory
69993c426a1Ske ge - Sun Microsystems - Beijing China 	 * for each ibt_post_recv().
70093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
70193c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_sizes.cs_rq_sgl = 1;
70293c426a1Ske ge - Sun Microsystems - Beijing China 
70393c426a1Ske ge - Sun Microsystems - Beijing China 	/* The send queue size and the receive queue size */
70493c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_sizes.cs_sq = chan->scq_size;
70593c426a1Ske ge - Sun Microsystems - Beijing China 	alloc_args.rc_sizes.cs_rq = chan->rcq_size;
70693c426a1Ske ge - Sun Microsystems - Beijing China 
70793c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->id_hca_res_lkey_capab) {
70893c426a1Ske ge - Sun Microsystems - Beijing China 		alloc_args.rc_flags = IBT_FAST_REG_RES_LKEY;
70993c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
71093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_alloc_chan: not support reserved lkey");
71193c426a1Ske ge - Sun Microsystems - Beijing China 	}
71293c426a1Ske ge - Sun Microsystems - Beijing China 
71393c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_enable_srq) {
71493c426a1Ske ge - Sun Microsystems - Beijing China 		alloc_flags = IBT_ACHAN_USES_SRQ;
71593c426a1Ske ge - Sun Microsystems - Beijing China 		alloc_args.rc_srq = state->rc_srq_hdl;
71693c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
71793c426a1Ske ge - Sun Microsystems - Beijing China 		alloc_flags = IBT_ACHAN_NO_FLAGS;
71893c426a1Ske ge - Sun Microsystems - Beijing China 	}
71993c426a1Ske ge - Sun Microsystems - Beijing China 
72093c426a1Ske ge - Sun Microsystems - Beijing China 	result = ibt_alloc_rc_channel(state->id_hca_hdl,
72193c426a1Ske ge - Sun Microsystems - Beijing China 	    alloc_flags, &alloc_args, &chan->chan_hdl, &sizes);
72293c426a1Ske ge - Sun Microsystems - Beijing China 	if (result != IBT_SUCCESS) {
72393c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_alloc_chan: ibd_rc_open_channel"
72493c426a1Ske ge - Sun Microsystems - Beijing China 		    " fail:<%d>", result);
72593c426a1Ske ge - Sun Microsystems - Beijing China 		goto alloc_scq_enable_err;
72693c426a1Ske ge - Sun Microsystems - Beijing China 	}
72793c426a1Ske ge - Sun Microsystems - Beijing China 
72803514dd7Ske ge - Sun Microsystems - Beijing China 	if (is_tx_chan)
72903514dd7Ske ge - Sun Microsystems - Beijing China 		atomic_inc_32(&state->rc_num_tx_chan);
73003514dd7Ske ge - Sun Microsystems - Beijing China 	else
73103514dd7Ske ge - Sun Microsystems - Beijing China 		atomic_inc_32(&state->rc_num_rx_chan);
73203514dd7Ske ge - Sun Microsystems - Beijing China 
73303514dd7Ske ge - Sun Microsystems - Beijing China 	/* For the connection reaper routine ibd_rc_conn_timeout_call() */
73403514dd7Ske ge - Sun Microsystems - Beijing China 	chan->is_used = B_TRUE;
73503514dd7Ske ge - Sun Microsystems - Beijing China 
73693c426a1Ske ge - Sun Microsystems - Beijing China 	*ret_chan = chan;
73793c426a1Ske ge - Sun Microsystems - Beijing China 	return (IBT_SUCCESS);
73893c426a1Ske ge - Sun Microsystems - Beijing China 
73993c426a1Ske ge - Sun Microsystems - Beijing China alloc_scq_enable_err:
74093c426a1Ske ge - Sun Microsystems - Beijing China 	if (is_tx_chan) {
74193c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibd_rc_tx_softintr == 1) {
74293c426a1Ske ge - Sun Microsystems - Beijing China 			ddi_remove_softintr(chan->scq_softintr);
74393c426a1Ske ge - Sun Microsystems - Beijing China 		}
74493c426a1Ske ge - Sun Microsystems - Beijing China 	}
74593c426a1Ske ge - Sun Microsystems - Beijing China alloc_softintr_err:
74693c426a1Ske ge - Sun Microsystems - Beijing China 	if (is_tx_chan) {
74793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_fini_txlist(chan);
74893c426a1Ske ge - Sun Microsystems - Beijing China 	}
74993c426a1Ske ge - Sun Microsystems - Beijing China init_txlist_err:
75093c426a1Ske ge - Sun Microsystems - Beijing China 	(void) ibt_free_cq(chan->rcq_hdl);
75193c426a1Ske ge - Sun Microsystems - Beijing China alloc_rcq_err:
75293c426a1Ske ge - Sun Microsystems - Beijing China 	(void) ibt_free_cq(chan->scq_hdl);
75393c426a1Ske ge - Sun Microsystems - Beijing China alloc_scq_err:
75493c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_poll_lock);
75593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_post_lock);
75693c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_rel_list.dl_mutex);
75793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_wqe_list.dl_mutex);
75893c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->rx_free_list.dl_mutex);
75993c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->rx_wqe_list.dl_mutex);
76093c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(chan, sizeof (ibd_rc_chan_t));
76193c426a1Ske ge - Sun Microsystems - Beijing China 	return (result);
76293c426a1Ske ge - Sun Microsystems - Beijing China }
76393c426a1Ske ge - Sun Microsystems - Beijing China 
76493c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_free_chan(ibd_rc_chan_t * chan)76593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_free_chan(ibd_rc_chan_t *chan)
76693c426a1Ske ge - Sun Microsystems - Beijing China {
76793c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t ret;
76893c426a1Ske ge - Sun Microsystems - Beijing China 
76993c426a1Ske ge - Sun Microsystems - Beijing China 	/* DPRINT(30, "ibd_rc_free_chan: chan=%p", chan); */
77093c426a1Ske ge - Sun Microsystems - Beijing China 
77193c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->chan_hdl != NULL) {
77293c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_free_channel(chan->chan_hdl);
77393c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != IBT_SUCCESS) {
77493c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ib_rc_free_chan: ibt_free_channel failed, "
77593c426a1Ske ge - Sun Microsystems - Beijing China 			    "chan=%p, returned: %d", chan, ret);
77693c426a1Ske ge - Sun Microsystems - Beijing China 			return;
77793c426a1Ske ge - Sun Microsystems - Beijing China 		}
77893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->chan_hdl = NULL;
77993c426a1Ske ge - Sun Microsystems - Beijing China 	}
78093c426a1Ske ge - Sun Microsystems - Beijing China 
78193c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->rcq_hdl != NULL) {
78293c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_free_cq(chan->rcq_hdl);
78393c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != IBT_SUCCESS) {
78493c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ib_rc_free_chan: ibt_free_cq(rcq) failed, "
78593c426a1Ske ge - Sun Microsystems - Beijing China 			    "chan=%p, returned: %d", chan, ret);
78693c426a1Ske ge - Sun Microsystems - Beijing China 			return;
78793c426a1Ske ge - Sun Microsystems - Beijing China 		}
78893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rcq_hdl = NULL;
78993c426a1Ske ge - Sun Microsystems - Beijing China 	}
79093c426a1Ske ge - Sun Microsystems - Beijing China 
79193c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->scq_hdl != NULL) {
79293c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_free_cq(chan->scq_hdl);
79393c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != IBT_SUCCESS) {
79493c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ib_rc_free_chan: ibt_free_cq(scq) failed, "
79593c426a1Ske ge - Sun Microsystems - Beijing China 			    "chan=%p, returned: %d", chan, ret);
79693c426a1Ske ge - Sun Microsystems - Beijing China 			return;
79793c426a1Ske ge - Sun Microsystems - Beijing China 		}
79893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->scq_hdl = NULL;
79993c426a1Ske ge - Sun Microsystems - Beijing China 	}
80093c426a1Ske ge - Sun Microsystems - Beijing China 
80193c426a1Ske ge - Sun Microsystems - Beijing China 	/* Free buffers */
80293c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->is_tx_chan) {
80393c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_fini_txlist(chan);
80493c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibd_rc_tx_softintr == 1) {
80593c426a1Ske ge - Sun Microsystems - Beijing China 			ddi_remove_softintr(chan->scq_softintr);
80693c426a1Ske ge - Sun Microsystems - Beijing China 		}
80703514dd7Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&chan->state->rc_num_tx_chan);
80893c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
80993c426a1Ske ge - Sun Microsystems - Beijing China 		if (!chan->state->rc_enable_srq) {
81093c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_fini_rxlist(chan);
81193c426a1Ske ge - Sun Microsystems - Beijing China 		}
81203514dd7Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&chan->state->rc_num_rx_chan);
81393c426a1Ske ge - Sun Microsystems - Beijing China 	}
81493c426a1Ske ge - Sun Microsystems - Beijing China 
81593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_poll_lock);
81693c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_post_lock);
81793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_rel_list.dl_mutex);
81893c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->tx_wqe_list.dl_mutex);
81993c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->rx_free_list.dl_mutex);
82093c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_destroy(&chan->rx_wqe_list.dl_mutex);
82193c426a1Ske ge - Sun Microsystems - Beijing China 
82293c426a1Ske ge - Sun Microsystems - Beijing China 	/*
82393c426a1Ske ge - Sun Microsystems - Beijing China 	 * If it is a passive channel, must make sure it has been removed
82493c426a1Ske ge - Sun Microsystems - Beijing China 	 * from chan->state->rc_pass_chan_list
82593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
82693c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(chan, sizeof (ibd_rc_chan_t));
82793c426a1Ske ge - Sun Microsystems - Beijing China }
82893c426a1Ske ge - Sun Microsystems - Beijing China 
82993c426a1Ske ge - Sun Microsystems - Beijing China /* Add a RC channel */
83093c426a1Ske ge - Sun Microsystems - Beijing China static inline void
ibd_rc_add_to_chan_list(ibd_rc_chan_list_t * list,ibd_rc_chan_t * chan)83193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_add_to_chan_list(ibd_rc_chan_list_t *list, ibd_rc_chan_t *chan)
83293c426a1Ske ge - Sun Microsystems - Beijing China {
83393c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&list->chan_list_mutex);
83493c426a1Ske ge - Sun Microsystems - Beijing China 	if (list->chan_list == NULL) {
83593c426a1Ske ge - Sun Microsystems - Beijing China 		list->chan_list = chan;
83603514dd7Ske ge - Sun Microsystems - Beijing China 		chan->next = NULL;
83793c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
83893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->next = list->chan_list;
83993c426a1Ske ge - Sun Microsystems - Beijing China 		list->chan_list = chan;
84093c426a1Ske ge - Sun Microsystems - Beijing China 	}
84193c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&list->chan_list_mutex);
84293c426a1Ske ge - Sun Microsystems - Beijing China }
84393c426a1Ske ge - Sun Microsystems - Beijing China 
84403514dd7Ske ge - Sun Microsystems - Beijing China static boolean_t
ibd_rc_re_add_to_pas_chan_list(ibd_rc_chan_t * chan)84503514dd7Ske ge - Sun Microsystems - Beijing China ibd_rc_re_add_to_pas_chan_list(ibd_rc_chan_t *chan)
84603514dd7Ske ge - Sun Microsystems - Beijing China {
84703514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
84803514dd7Ske ge - Sun Microsystems - Beijing China 
84903514dd7Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_pass_chan_list.chan_list_mutex);
85003514dd7Ske ge - Sun Microsystems - Beijing China 	if ((state->id_mac_state & IBD_DRV_STARTED) == 0) {
85103514dd7Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_pass_chan_list.chan_list_mutex);
85203514dd7Ske ge - Sun Microsystems - Beijing China 		return (B_FALSE);
85303514dd7Ske ge - Sun Microsystems - Beijing China 	} else {
85403514dd7Ske ge - Sun Microsystems - Beijing China 		if (state->rc_pass_chan_list.chan_list == NULL) {
85503514dd7Ske ge - Sun Microsystems - Beijing China 			state->rc_pass_chan_list.chan_list = chan;
85603514dd7Ske ge - Sun Microsystems - Beijing China 			chan->next = NULL;
85703514dd7Ske ge - Sun Microsystems - Beijing China 		} else {
85803514dd7Ske ge - Sun Microsystems - Beijing China 			chan->next = state->rc_pass_chan_list.chan_list;
85903514dd7Ske ge - Sun Microsystems - Beijing China 			state->rc_pass_chan_list.chan_list = chan;
86003514dd7Ske ge - Sun Microsystems - Beijing China 		}
86103514dd7Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_pass_chan_list.chan_list_mutex);
86203514dd7Ske ge - Sun Microsystems - Beijing China 		return (B_TRUE);
86303514dd7Ske ge - Sun Microsystems - Beijing China 	}
86403514dd7Ske ge - Sun Microsystems - Beijing China }
86503514dd7Ske ge - Sun Microsystems - Beijing China 
86693c426a1Ske ge - Sun Microsystems - Beijing China /* Remove a RC channel */
86703514dd7Ske ge - Sun Microsystems - Beijing China static inline ibd_rc_chan_t *
ibd_rc_rm_from_chan_list(ibd_rc_chan_list_t * list,ibd_rc_chan_t * chan)86893c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_rm_from_chan_list(ibd_rc_chan_list_t *list, ibd_rc_chan_t *chan)
86993c426a1Ske ge - Sun Microsystems - Beijing China {
87093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *pre_chan;
87193c426a1Ske ge - Sun Microsystems - Beijing China 
87293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&list->chan_list_mutex);
87393c426a1Ske ge - Sun Microsystems - Beijing China 	if (list->chan_list == chan) {
87493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_rm_from_chan_list(first): found chan(%p)"
87593c426a1Ske ge - Sun Microsystems - Beijing China 		    " in chan_list", chan);
87693c426a1Ske ge - Sun Microsystems - Beijing China 		list->chan_list = chan->next;
87793c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
87893c426a1Ske ge - Sun Microsystems - Beijing China 		pre_chan = list->chan_list;
87993c426a1Ske ge - Sun Microsystems - Beijing China 		while (pre_chan != NULL) {
88093c426a1Ske ge - Sun Microsystems - Beijing China 			if (pre_chan->next == chan) {
88193c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(30, "ibd_rc_rm_from_chan_list"
88203514dd7Ske ge - Sun Microsystems - Beijing China 				    "(middle): found chan(%p)", chan);
88393c426a1Ske ge - Sun Microsystems - Beijing China 				pre_chan->next = chan->next;
88493c426a1Ske ge - Sun Microsystems - Beijing China 				break;
88593c426a1Ske ge - Sun Microsystems - Beijing China 			}
88693c426a1Ske ge - Sun Microsystems - Beijing China 			pre_chan = pre_chan->next;
88793c426a1Ske ge - Sun Microsystems - Beijing China 		}
88803514dd7Ske ge - Sun Microsystems - Beijing China 		if (pre_chan == NULL)
88903514dd7Ske ge - Sun Microsystems - Beijing China 			chan = NULL;
89093c426a1Ske ge - Sun Microsystems - Beijing China 	}
89193c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&list->chan_list_mutex);
89203514dd7Ske ge - Sun Microsystems - Beijing China 	return (chan);
89393c426a1Ske ge - Sun Microsystems - Beijing China }
89493c426a1Ske ge - Sun Microsystems - Beijing China 
89593c426a1Ske ge - Sun Microsystems - Beijing China static inline ibd_rc_chan_t *
ibd_rc_rm_header_chan_list(ibd_rc_chan_list_t * list)89693c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_rm_header_chan_list(ibd_rc_chan_list_t *list)
89793c426a1Ske ge - Sun Microsystems - Beijing China {
89893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *rc_chan;
89993c426a1Ske ge - Sun Microsystems - Beijing China 
90093c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&list->chan_list_mutex);
90193c426a1Ske ge - Sun Microsystems - Beijing China 	rc_chan = list->chan_list;
90293c426a1Ske ge - Sun Microsystems - Beijing China 	if (rc_chan != NULL) {
90393c426a1Ske ge - Sun Microsystems - Beijing China 		list->chan_list = rc_chan->next;
90493c426a1Ske ge - Sun Microsystems - Beijing China 	}
90593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&list->chan_list_mutex);
90693c426a1Ske ge - Sun Microsystems - Beijing China 	return (rc_chan);
90793c426a1Ske ge - Sun Microsystems - Beijing China }
90893c426a1Ske ge - Sun Microsystems - Beijing China 
90993c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_alloc_srq_copybufs(ibd_state_t * state)91093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_alloc_srq_copybufs(ibd_state_t *state)
91193c426a1Ske ge - Sun Microsystems - Beijing China {
91293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_mr_attr_t mem_attr;
91393c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t rc_rx_bufs_sz;
91493c426a1Ske ge - Sun Microsystems - Beijing China 
91593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
91693c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate one big chunk for all regular rx copy bufs
91793c426a1Ske ge - Sun Microsystems - Beijing China 	 */
91893c426a1Ske ge - Sun Microsystems - Beijing China 	rc_rx_bufs_sz =  (state->rc_mtu + IPOIB_GRH_SIZE) * state->rc_srq_size;
91993c426a1Ske ge - Sun Microsystems - Beijing China 
92093c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rx_bufs = kmem_zalloc(rc_rx_bufs_sz, KM_SLEEP);
92193c426a1Ske ge - Sun Microsystems - Beijing China 
92293c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rwqes = kmem_zalloc(state->rc_srq_size *
92393c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ibd_rwqe_t), KM_SLEEP);
92493c426a1Ske ge - Sun Microsystems - Beijing China 
92593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
92693c426a1Ske ge - Sun Microsystems - Beijing China 	 * Do one memory registration on the entire rxbuf area
92793c426a1Ske ge - Sun Microsystems - Beijing China 	 */
92893c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_vaddr = (uint64_t)(uintptr_t)state->rc_srq_rx_bufs;
92993c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_len = rc_rx_bufs_sz;
93093c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_as = NULL;
93193c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
93293c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_register_mr(state->id_hca_hdl, state->id_pd_hdl, &mem_attr,
93393c426a1Ske ge - Sun Microsystems - Beijing China 	    &state->rc_srq_rx_mr_hdl, &state->rc_srq_rx_mr_desc)
93493c426a1Ske ge - Sun Microsystems - Beijing China 	    != IBT_SUCCESS) {
93593c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_alloc_srq_copybufs: ibt_register_mr() "
93693c426a1Ske ge - Sun Microsystems - Beijing China 		    "failed");
93793c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(state->rc_srq_rwqes,
93893c426a1Ske ge - Sun Microsystems - Beijing China 		    state->rc_srq_size * sizeof (ibd_rwqe_t));
93993c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(state->rc_srq_rx_bufs, rc_rx_bufs_sz);
94093c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_srq_rx_bufs = NULL;
94193c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_srq_rwqes = NULL;
94293c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
94393c426a1Ske ge - Sun Microsystems - Beijing China 	}
94493c426a1Ske ge - Sun Microsystems - Beijing China 
94593c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
94693c426a1Ske ge - Sun Microsystems - Beijing China }
94793c426a1Ske ge - Sun Microsystems - Beijing China 
94893c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_free_srq_copybufs(ibd_state_t * state)94993c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_free_srq_copybufs(ibd_state_t *state)
95093c426a1Ske ge - Sun Microsystems - Beijing China {
95193c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t rc_rx_buf_sz;
95293c426a1Ske ge - Sun Microsystems - Beijing China 
95393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
95493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Don't change the value of state->rc_mtu at the period from call
95593c426a1Ske ge - Sun Microsystems - Beijing China 	 * ibd_rc_alloc_srq_copybufs() to call ibd_rc_free_srq_copybufs().
95693c426a1Ske ge - Sun Microsystems - Beijing China 	 */
95793c426a1Ske ge - Sun Microsystems - Beijing China 	rc_rx_buf_sz = state->rc_mtu + IPOIB_GRH_SIZE;
95893c426a1Ske ge - Sun Microsystems - Beijing China 
95993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
96093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Unregister rxbuf mr
96193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
96293c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_deregister_mr(state->id_hca_hdl,
96393c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_srq_rx_mr_hdl) != IBT_SUCCESS) {
96493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_free_srq_copybufs: ibt_deregister_mr()"
96593c426a1Ske ge - Sun Microsystems - Beijing China 		    " failed");
96693c426a1Ske ge - Sun Microsystems - Beijing China 	}
96793c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rx_mr_hdl = NULL;
96893c426a1Ske ge - Sun Microsystems - Beijing China 
96993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
97093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Free rxbuf memory
97193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
97293c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(state->rc_srq_rwqes,
97393c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_srq_size * sizeof (ibd_rwqe_t));
97493c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(state->rc_srq_rx_bufs, state->rc_srq_size * rc_rx_buf_sz);
97593c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rwqes = NULL;
97693c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rx_bufs = NULL;
97793c426a1Ske ge - Sun Microsystems - Beijing China }
97893c426a1Ske ge - Sun Microsystems - Beijing China 
97993c426a1Ske ge - Sun Microsystems - Beijing China /*
98093c426a1Ske ge - Sun Microsystems - Beijing China  * Allocate and post a certain number of SRQ receive buffers and WRs.
98193c426a1Ske ge - Sun Microsystems - Beijing China  */
98293c426a1Ske ge - Sun Microsystems - Beijing China int
ibd_rc_init_srq_list(ibd_state_t * state)98393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_init_srq_list(ibd_state_t *state)
98493c426a1Ske ge - Sun Microsystems - Beijing China {
98593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe;
98693c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_lkey_t lkey;
98793c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
98893c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t len;
98993c426a1Ske ge - Sun Microsystems - Beijing China 	uint8_t *bufaddr;
99093c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_srq_sizes_t srq_sizes;
99193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_srq_sizes_t	 srq_real_sizes;
99293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t ret;
99393c426a1Ske ge - Sun Microsystems - Beijing China 
99493c426a1Ske ge - Sun Microsystems - Beijing China 	srq_sizes.srq_sgl_sz = 1;
9951cfa752fSRamaswamy Tummala 	srq_sizes.srq_wr_sz = state->id_rc_num_srq;
99693c426a1Ske ge - Sun Microsystems - Beijing China 	ret = ibt_alloc_srq(state->id_hca_hdl, IBT_SRQ_NO_FLAGS,
99793c426a1Ske ge - Sun Microsystems - Beijing China 	    state->id_pd_hdl, &srq_sizes, &state->rc_srq_hdl, &srq_real_sizes);
99893c426a1Ske ge - Sun Microsystems - Beijing China 	if (ret != IBT_SUCCESS) {
99903514dd7Ske ge - Sun Microsystems - Beijing China 		/*
100003514dd7Ske ge - Sun Microsystems - Beijing China 		 * The following code is for CR 6932460 (can't configure ibd
100103514dd7Ske ge - Sun Microsystems - Beijing China 		 * interface on 32 bits x86 systems). 32 bits x86 system has
100203514dd7Ske ge - Sun Microsystems - Beijing China 		 * less memory resource than 64 bits x86 system. If current
100303514dd7Ske ge - Sun Microsystems - Beijing China 		 * resource request can't be satisfied, we request less
100403514dd7Ske ge - Sun Microsystems - Beijing China 		 * resource here.
100503514dd7Ske ge - Sun Microsystems - Beijing China 		 */
100603514dd7Ske ge - Sun Microsystems - Beijing China 		len = state->id_rc_num_srq;
100703514dd7Ske ge - Sun Microsystems - Beijing China 		while ((ret == IBT_HCA_WR_EXCEEDED) &&
100803514dd7Ske ge - Sun Microsystems - Beijing China 		    (len >= 2 * IBD_RC_MIN_CQ_SIZE)) {
100903514dd7Ske ge - Sun Microsystems - Beijing China 			len = len/2;
101003514dd7Ske ge - Sun Microsystems - Beijing China 			srq_sizes.srq_sgl_sz = 1;
101103514dd7Ske ge - Sun Microsystems - Beijing China 			srq_sizes.srq_wr_sz = len;
101203514dd7Ske ge - Sun Microsystems - Beijing China 			ret = ibt_alloc_srq(state->id_hca_hdl,
101303514dd7Ske ge - Sun Microsystems - Beijing China 			    IBT_SRQ_NO_FLAGS, state->id_pd_hdl, &srq_sizes,
101403514dd7Ske ge - Sun Microsystems - Beijing China 			    &state->rc_srq_hdl, &srq_real_sizes);
101503514dd7Ske ge - Sun Microsystems - Beijing China 		}
101603514dd7Ske ge - Sun Microsystems - Beijing China 		if (ret != IBT_SUCCESS) {
101703514dd7Ske ge - Sun Microsystems - Beijing China 			DPRINT(10, "ibd_rc_init_srq_list: ibt_alloc_srq failed."
101803514dd7Ske ge - Sun Microsystems - Beijing China 			    "req_sgl_sz=%d, req_wr_sz=0x%x, final_req_wr_sz="
101903514dd7Ske ge - Sun Microsystems - Beijing China 			    "0x%x, ret=%d", srq_sizes.srq_sgl_sz,
102003514dd7Ske ge - Sun Microsystems - Beijing China 			    srq_sizes.srq_wr_sz, len, ret);
102103514dd7Ske ge - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
102203514dd7Ske ge - Sun Microsystems - Beijing China 		}
102303514dd7Ske ge - Sun Microsystems - Beijing China 		state->id_rc_num_srq = len;
102403514dd7Ske ge - Sun Microsystems - Beijing China 		state->id_rc_num_rwqe = state->id_rc_num_srq + 1;
102593c426a1Ske ge - Sun Microsystems - Beijing China 	}
102693c426a1Ske ge - Sun Microsystems - Beijing China 
102793c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_size = srq_real_sizes.srq_wr_sz;
102893c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_alloc_srq_copybufs(state) != DDI_SUCCESS) {
102993c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_free_srq(state->rc_srq_hdl);
103093c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != IBT_SUCCESS) {
103193c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_print_warn(state, "ibd_rc_init_srq_list: "
103293c426a1Ske ge - Sun Microsystems - Beijing China 			    "ibt_free_srq fail, ret=%d", ret);
103393c426a1Ske ge - Sun Microsystems - Beijing China 		}
103493c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
103593c426a1Ske ge - Sun Microsystems - Beijing China 	}
103693c426a1Ske ge - Sun Microsystems - Beijing China 
103793c426a1Ske ge - Sun Microsystems - Beijing China 	/*
103893c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate and setup the rwqe list
103993c426a1Ske ge - Sun Microsystems - Beijing China 	 */
104093c426a1Ske ge - Sun Microsystems - Beijing China 	lkey = state->rc_srq_rx_mr_desc.md_lkey;
104193c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe = state->rc_srq_rwqes;
104293c426a1Ske ge - Sun Microsystems - Beijing China 	bufaddr = state->rc_srq_rx_bufs;
104393c426a1Ske ge - Sun Microsystems - Beijing China 	len = state->rc_mtu + IPOIB_GRH_SIZE;
104493c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rwqe_list.dl_cnt = 0;
104593c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_rwqe_list.dl_bufs_outstanding = 0;
104693c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < state->rc_srq_size; i++, rwqe++, bufaddr += len) {
104793c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_state = state;
104893c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freeing_wqe = B_FALSE;
104993c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freemsg_cb.free_func = ibd_rc_srq_freemsg_cb;
105093c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freemsg_cb.free_arg = (char *)rwqe;
105193c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_bufaddr = bufaddr;
105293c426a1Ske ge - Sun Microsystems - Beijing China 
105393c426a1Ske ge - Sun Microsystems - Beijing China 		if ((rwqe->rwqe_im_mblk = desballoc(bufaddr, len, 0,
105493c426a1Ske ge - Sun Microsystems - Beijing China 		    &rwqe->w_freemsg_cb)) == NULL) {
105593c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_init_srq_list : desballoc() failed");
105693c426a1Ske ge - Sun Microsystems - Beijing China 			rwqe->rwqe_copybuf.ic_bufaddr = NULL;
1057a567cb71Ske ge - Sun Microsystems - Beijing China 			if (atomic_dec_32_nv(&state->id_running) != 0) {
1058a567cb71Ske ge - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "ibd_rc_init_srq_list: "
1059a567cb71Ske ge - Sun Microsystems - Beijing China 				    "id_running was not 1\n");
1060a567cb71Ske ge - Sun Microsystems - Beijing China 			}
106193c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_fini_srq_list(state);
1062a567cb71Ske ge - Sun Microsystems - Beijing China 			atomic_inc_32(&state->id_running);
106393c426a1Ske ge - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
106493c426a1Ske ge - Sun Microsystems - Beijing China 		}
106593c426a1Ske ge - Sun Microsystems - Beijing China 
106693c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_key = lkey;
106793c426a1Ske ge - Sun Microsystems - Beijing China 		/* Leave IPOIB_GRH_SIZE space */
106893c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_va =
106993c426a1Ske ge - Sun Microsystems - Beijing China 		    (ib_vaddr_t)(uintptr_t)(bufaddr + IPOIB_GRH_SIZE);
107093c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_len = state->rc_mtu;
107193c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_id = (ibt_wrid_t)(uintptr_t)rwqe;
107293c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_nds = 1;
107393c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_sgl = &rwqe->rwqe_copybuf.ic_sgl;
107493c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibd_rc_post_srq(state, rwqe);
107593c426a1Ske ge - Sun Microsystems - Beijing China 	}
107693c426a1Ske ge - Sun Microsystems - Beijing China 
1077a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_srq_free_list.dl_mutex);
1078a567cb71Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_free_list.dl_head = NULL;
1079a567cb71Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_free_list.dl_cnt = 0;
1080a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_srq_free_list.dl_mutex);
1081a567cb71Ske ge - Sun Microsystems - Beijing China 
108293c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
108393c426a1Ske ge - Sun Microsystems - Beijing China }
108493c426a1Ske ge - Sun Microsystems - Beijing China 
108593c426a1Ske ge - Sun Microsystems - Beijing China /*
108693c426a1Ske ge - Sun Microsystems - Beijing China  * Free the statically allocated Rx buffer list for SRQ.
108793c426a1Ske ge - Sun Microsystems - Beijing China  */
108893c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_fini_srq_list(ibd_state_t * state)108993c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_fini_srq_list(ibd_state_t *state)
109093c426a1Ske ge - Sun Microsystems - Beijing China {
109193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe;
109293c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
109393c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t ret;
109493c426a1Ske ge - Sun Microsystems - Beijing China 
1095a567cb71Ske ge - Sun Microsystems - Beijing China 	ASSERT(state->id_running == 0);
109693c426a1Ske ge - Sun Microsystems - Beijing China 	ret = ibt_free_srq(state->rc_srq_hdl);
109793c426a1Ske ge - Sun Microsystems - Beijing China 	if (ret != IBT_SUCCESS) {
109893c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_fini_srq_list: "
109993c426a1Ske ge - Sun Microsystems - Beijing China 		    "ibt_free_srq fail, ret=%d", ret);
110093c426a1Ske ge - Sun Microsystems - Beijing China 	}
110193c426a1Ske ge - Sun Microsystems - Beijing China 
110293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_srq_rwqe_list.dl_mutex);
110393c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe = state->rc_srq_rwqes;
110493c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < state->rc_srq_size; i++, rwqe++) {
110593c426a1Ske ge - Sun Microsystems - Beijing China 		if (rwqe->rwqe_im_mblk != NULL) {
110693c426a1Ske ge - Sun Microsystems - Beijing China 			rwqe->w_freeing_wqe = B_TRUE;
110793c426a1Ske ge - Sun Microsystems - Beijing China 			freemsg(rwqe->rwqe_im_mblk);
110893c426a1Ske ge - Sun Microsystems - Beijing China 		}
110993c426a1Ske ge - Sun Microsystems - Beijing China 	}
111093c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_srq_rwqe_list.dl_mutex);
111193c426a1Ske ge - Sun Microsystems - Beijing China 
111293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_free_srq_copybufs(state);
111393c426a1Ske ge - Sun Microsystems - Beijing China }
111493c426a1Ske ge - Sun Microsystems - Beijing China 
1115a567cb71Ske ge - Sun Microsystems - Beijing China /* Repost the elements in state->ib_rc_free_list */
1116a567cb71Ske ge - Sun Microsystems - Beijing China int
ibd_rc_repost_srq_free_list(ibd_state_t * state)1117a567cb71Ske ge - Sun Microsystems - Beijing China ibd_rc_repost_srq_free_list(ibd_state_t *state)
1118a567cb71Ske ge - Sun Microsystems - Beijing China {
1119a567cb71Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe;
1120a567cb71Ske ge - Sun Microsystems - Beijing China 	ibd_wqe_t *list;
1121a567cb71Ske ge - Sun Microsystems - Beijing China 	uint_t len;
1122a567cb71Ske ge - Sun Microsystems - Beijing China 
1123a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_srq_free_list.dl_mutex);
1124a567cb71Ske ge - Sun Microsystems - Beijing China 	if (state->rc_srq_free_list.dl_head != NULL) {
1125a567cb71Ske ge - Sun Microsystems - Beijing China 		/* repost them */
1126a567cb71Ske ge - Sun Microsystems - Beijing China 		len = state->rc_mtu + IPOIB_GRH_SIZE;
1127a567cb71Ske ge - Sun Microsystems - Beijing China 		list = state->rc_srq_free_list.dl_head;
1128a567cb71Ske ge - Sun Microsystems - Beijing China 		state->rc_srq_free_list.dl_head = NULL;
1129a567cb71Ske ge - Sun Microsystems - Beijing China 		state->rc_srq_free_list.dl_cnt = 0;
1130a567cb71Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_srq_free_list.dl_mutex);
1131a567cb71Ske ge - Sun Microsystems - Beijing China 		while (list != NULL) {
1132a567cb71Ske ge - Sun Microsystems - Beijing China 			rwqe = WQE_TO_RWQE(list);
1133a567cb71Ske ge - Sun Microsystems - Beijing China 			if ((rwqe->rwqe_im_mblk == NULL) &&
1134a567cb71Ske ge - Sun Microsystems - Beijing China 			    ((rwqe->rwqe_im_mblk = desballoc(
1135a567cb71Ske ge - Sun Microsystems - Beijing China 			    rwqe->rwqe_copybuf.ic_bufaddr, len, 0,
1136a567cb71Ske ge - Sun Microsystems - Beijing China 			    &rwqe->w_freemsg_cb)) == NULL)) {
1137a567cb71Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_repost_srq_free_list: "
1138a567cb71Ske ge - Sun Microsystems - Beijing China 				    "failed in desballoc()");
1139a567cb71Ske ge - Sun Microsystems - Beijing China 				do {
1140a567cb71Ske ge - Sun Microsystems - Beijing China 					ibd_rc_srq_free_rwqe(state, rwqe);
1141a567cb71Ske ge - Sun Microsystems - Beijing China 					list = list->w_next;
1142a567cb71Ske ge - Sun Microsystems - Beijing China 					rwqe = WQE_TO_RWQE(list);
1143a567cb71Ske ge - Sun Microsystems - Beijing China 				} while (list != NULL);
1144a567cb71Ske ge - Sun Microsystems - Beijing China 				return (DDI_FAILURE);
1145a567cb71Ske ge - Sun Microsystems - Beijing China 			}
1146a567cb71Ske ge - Sun Microsystems - Beijing China 			if (ibd_rc_post_srq(state, rwqe) == DDI_FAILURE) {
1147a567cb71Ske ge - Sun Microsystems - Beijing China 				ibd_rc_srq_free_rwqe(state, rwqe);
1148a567cb71Ske ge - Sun Microsystems - Beijing China 			}
1149a567cb71Ske ge - Sun Microsystems - Beijing China 			list = list->w_next;
1150a567cb71Ske ge - Sun Microsystems - Beijing China 		}
1151a567cb71Ske ge - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1152a567cb71Ske ge - Sun Microsystems - Beijing China 	}
1153a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_srq_free_list.dl_mutex);
1154a567cb71Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1155a567cb71Ske ge - Sun Microsystems - Beijing China }
1156a567cb71Ske ge - Sun Microsystems - Beijing China 
115793c426a1Ske ge - Sun Microsystems - Beijing China /*
115893c426a1Ske ge - Sun Microsystems - Beijing China  * Free an allocated recv wqe.
115993c426a1Ske ge - Sun Microsystems - Beijing China  */
1160a567cb71Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_srq_free_rwqe(ibd_state_t * state,ibd_rwqe_t * rwqe)116193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_srq_free_rwqe(ibd_state_t *state, ibd_rwqe_t *rwqe)
116293c426a1Ske ge - Sun Microsystems - Beijing China {
116393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
116493c426a1Ske ge - Sun Microsystems - Beijing China 	 * desballoc() failed (no memory) or the posting of rwqe failed.
116593c426a1Ske ge - Sun Microsystems - Beijing China 	 *
116693c426a1Ske ge - Sun Microsystems - Beijing China 	 * This rwqe is placed on a free list so that it
116793c426a1Ske ge - Sun Microsystems - Beijing China 	 * can be reinstated in future.
116893c426a1Ske ge - Sun Microsystems - Beijing China 	 *
116993c426a1Ske ge - Sun Microsystems - Beijing China 	 * NOTE: no code currently exists to reinstate
117093c426a1Ske ge - Sun Microsystems - Beijing China 	 * these "lost" rwqes.
117193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
117293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_srq_free_list.dl_mutex);
117393c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_free_list.dl_cnt++;
117493c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe->rwqe_next = state->rc_srq_free_list.dl_head;
117593c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_srq_free_list.dl_head = RWQE_TO_WQE(rwqe);
117693c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_srq_free_list.dl_mutex);
117793c426a1Ske ge - Sun Microsystems - Beijing China }
117893c426a1Ske ge - Sun Microsystems - Beijing China 
117993c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_srq_freemsg_cb(char * arg)118093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_srq_freemsg_cb(char *arg)
118193c426a1Ske ge - Sun Microsystems - Beijing China {
118293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe = (ibd_rwqe_t *)arg;
118393c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = rwqe->w_state;
118493c426a1Ske ge - Sun Microsystems - Beijing China 
118593c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state->rc_enable_srq);
118693c426a1Ske ge - Sun Microsystems - Beijing China 
118793c426a1Ske ge - Sun Microsystems - Beijing China 	/*
1188a567cb71Ske ge - Sun Microsystems - Beijing China 	 * If the driver is stopped, just free the rwqe.
118993c426a1Ske ge - Sun Microsystems - Beijing China 	 */
1190a567cb71Ske ge - Sun Microsystems - Beijing China 	if (atomic_add_32_nv(&state->id_running, 0) == 0) {
1191a567cb71Ske ge - Sun Microsystems - Beijing China 		if (!rwqe->w_freeing_wqe) {
1192a567cb71Ske ge - Sun Microsystems - Beijing China 			atomic_dec_32(
1193a567cb71Ske ge - Sun Microsystems - Beijing China 			    &state->rc_srq_rwqe_list.dl_bufs_outstanding);
1194a567cb71Ske ge - Sun Microsystems - Beijing China 			DPRINT(6, "ibd_rc_srq_freemsg_cb: wqe being freed");
1195a567cb71Ske ge - Sun Microsystems - Beijing China 			rwqe->rwqe_im_mblk = NULL;
1196a567cb71Ske ge - Sun Microsystems - Beijing China 			ibd_rc_srq_free_rwqe(state, rwqe);
1197a567cb71Ske ge - Sun Microsystems - Beijing China 		}
119893c426a1Ske ge - Sun Microsystems - Beijing China 		return;
119993c426a1Ske ge - Sun Microsystems - Beijing China 	}
120093c426a1Ske ge - Sun Microsystems - Beijing China 
1201a567cb71Ske ge - Sun Microsystems - Beijing China 	atomic_dec_32(&state->rc_srq_rwqe_list.dl_bufs_outstanding);
1202a567cb71Ske ge - Sun Microsystems - Beijing China 
120393c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state->rc_srq_rwqe_list.dl_cnt < state->rc_srq_size);
1204a567cb71Ske ge - Sun Microsystems - Beijing China 	ASSERT(!rwqe->w_freeing_wqe);
120593c426a1Ske ge - Sun Microsystems - Beijing China 
120693c426a1Ske ge - Sun Microsystems - Beijing China 	/*
120793c426a1Ske ge - Sun Microsystems - Beijing China 	 * Upper layer has released held mblk, so we have
120893c426a1Ske ge - Sun Microsystems - Beijing China 	 * no more use for keeping the old pointer in
120993c426a1Ske ge - Sun Microsystems - Beijing China 	 * our rwqe.
121093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
121193c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe->rwqe_im_mblk = desballoc(rwqe->rwqe_copybuf.ic_bufaddr,
121293c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_mtu + IPOIB_GRH_SIZE, 0, &rwqe->w_freemsg_cb);
121393c426a1Ske ge - Sun Microsystems - Beijing China 	if (rwqe->rwqe_im_mblk == NULL) {
121493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_srq_freemsg_cb: desballoc failed");
121593c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_srq_free_rwqe(state, rwqe);
121693c426a1Ske ge - Sun Microsystems - Beijing China 		return;
121793c426a1Ske ge - Sun Microsystems - Beijing China 	}
121893c426a1Ske ge - Sun Microsystems - Beijing China 
121993c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_post_srq(state, rwqe) == DDI_FAILURE) {
1220a567cb71Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_srq_freemsg_cb: ibd_rc_post_srq"
1221a567cb71Ske ge - Sun Microsystems - Beijing China 		    " failed");
122293c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_srq_free_rwqe(state, rwqe);
122393c426a1Ske ge - Sun Microsystems - Beijing China 		return;
122493c426a1Ske ge - Sun Microsystems - Beijing China 	}
122593c426a1Ske ge - Sun Microsystems - Beijing China }
122693c426a1Ske ge - Sun Microsystems - Beijing China 
122793c426a1Ske ge - Sun Microsystems - Beijing China /*
122893c426a1Ske ge - Sun Microsystems - Beijing China  * Post a rwqe to the hardware and add it to the Rx list.
122993c426a1Ske ge - Sun Microsystems - Beijing China  */
123093c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_post_srq(ibd_state_t * state,ibd_rwqe_t * rwqe)123193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_post_srq(ibd_state_t *state, ibd_rwqe_t *rwqe)
123293c426a1Ske ge - Sun Microsystems - Beijing China {
123393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
123493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Here we should add dl_cnt before post recv, because
123593c426a1Ske ge - Sun Microsystems - Beijing China 	 * we would have to make sure dl_cnt is updated before
123693c426a1Ske ge - Sun Microsystems - Beijing China 	 * the corresponding ibd_rc_process_rx() is called.
123793c426a1Ske ge - Sun Microsystems - Beijing China 	 */
123893c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state->rc_srq_rwqe_list.dl_cnt < state->rc_srq_size);
12391a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&state->rc_srq_rwqe_list.dl_cnt);
124093c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_post_srq(state->rc_srq_hdl, &rwqe->w_rwr, 1, NULL) !=
124193c426a1Ske ge - Sun Microsystems - Beijing China 	    IBT_SUCCESS) {
124293c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&state->rc_srq_rwqe_list.dl_cnt);
124393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_post_srq : ibt_post_srq() failed");
124493c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
124593c426a1Ske ge - Sun Microsystems - Beijing China 	}
124693c426a1Ske ge - Sun Microsystems - Beijing China 
124793c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
124893c426a1Ske ge - Sun Microsystems - Beijing China }
124993c426a1Ske ge - Sun Microsystems - Beijing China 
125093c426a1Ske ge - Sun Microsystems - Beijing China /*
125193c426a1Ske ge - Sun Microsystems - Beijing China  * Post a rwqe to the hardware and add it to the Rx list.
125293c426a1Ske ge - Sun Microsystems - Beijing China  */
125393c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_post_rwqe(ibd_rc_chan_t * chan,ibd_rwqe_t * rwqe)125493c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_post_rwqe(ibd_rc_chan_t *chan, ibd_rwqe_t *rwqe)
125593c426a1Ske ge - Sun Microsystems - Beijing China {
125693c426a1Ske ge - Sun Microsystems - Beijing China 	/*
125793c426a1Ske ge - Sun Microsystems - Beijing China 	 * Here we should add dl_cnt before post recv, because we would
125893c426a1Ske ge - Sun Microsystems - Beijing China 	 * have to make sure dl_cnt has already updated before
125993c426a1Ske ge - Sun Microsystems - Beijing China 	 * corresponding ibd_rc_process_rx() is called.
126093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
12611a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&chan->rx_wqe_list.dl_cnt);
126293c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_post_recv(chan->chan_hdl, &rwqe->w_rwr, 1, NULL) !=
126393c426a1Ske ge - Sun Microsystems - Beijing China 	    IBT_SUCCESS) {
126493c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&chan->rx_wqe_list.dl_cnt);
126593c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_post_rwqe : failed in ibt_post_recv()");
126693c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
126793c426a1Ske ge - Sun Microsystems - Beijing China 	}
126893c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
126993c426a1Ske ge - Sun Microsystems - Beijing China }
127093c426a1Ske ge - Sun Microsystems - Beijing China 
127193c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_alloc_rx_copybufs(ibd_rc_chan_t * chan)127293c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_alloc_rx_copybufs(ibd_rc_chan_t *chan)
127393c426a1Ske ge - Sun Microsystems - Beijing China {
127493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
127593c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_mr_attr_t mem_attr;
127693c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t rc_rx_bufs_sz;
127793c426a1Ske ge - Sun Microsystems - Beijing China 
127893c426a1Ske ge - Sun Microsystems - Beijing China 	/*
127993c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate one big chunk for all regular rx copy bufs
128093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
128193c426a1Ske ge - Sun Microsystems - Beijing China 	rc_rx_bufs_sz = (state->rc_mtu + IPOIB_GRH_SIZE) * chan->rcq_size;
128293c426a1Ske ge - Sun Microsystems - Beijing China 
128393c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_bufs = kmem_zalloc(rc_rx_bufs_sz, KM_SLEEP);
128493c426a1Ske ge - Sun Microsystems - Beijing China 
128593c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_rwqes = kmem_zalloc(chan->rcq_size *
128693c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ibd_rwqe_t), KM_SLEEP);
128793c426a1Ske ge - Sun Microsystems - Beijing China 
128893c426a1Ske ge - Sun Microsystems - Beijing China 	/*
128993c426a1Ske ge - Sun Microsystems - Beijing China 	 * Do one memory registration on the entire rxbuf area
129093c426a1Ske ge - Sun Microsystems - Beijing China 	 */
129193c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_vaddr = (uint64_t)(uintptr_t)chan->rx_bufs;
129293c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_len = rc_rx_bufs_sz;
129393c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_as = NULL;
129493c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
129593c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_register_mr(state->id_hca_hdl, state->id_pd_hdl, &mem_attr,
129693c426a1Ske ge - Sun Microsystems - Beijing China 	    &chan->rx_mr_hdl, &chan->rx_mr_desc) != IBT_SUCCESS) {
129793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_alloc_srq_copybufs: ibt_register_mr failed");
129893c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(chan->rx_rwqes, chan->rcq_size * sizeof (ibd_rwqe_t));
129993c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(chan->rx_bufs, rc_rx_bufs_sz);
130093c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rx_bufs = NULL;
130193c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rx_rwqes = NULL;
130293c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
130393c426a1Ske ge - Sun Microsystems - Beijing China 	}
130493c426a1Ske ge - Sun Microsystems - Beijing China 
130593c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
130693c426a1Ske ge - Sun Microsystems - Beijing China }
130793c426a1Ske ge - Sun Microsystems - Beijing China 
130893c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_free_rx_copybufs(ibd_rc_chan_t * chan)130993c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_free_rx_copybufs(ibd_rc_chan_t *chan)
131093c426a1Ske ge - Sun Microsystems - Beijing China {
131193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
131293c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t rc_rx_buf_sz;
131393c426a1Ske ge - Sun Microsystems - Beijing China 
131493c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(!state->rc_enable_srq);
131593c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan->rx_rwqes != NULL);
131693c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan->rx_bufs != NULL);
131793c426a1Ske ge - Sun Microsystems - Beijing China 
131893c426a1Ske ge - Sun Microsystems - Beijing China 	/*
131993c426a1Ske ge - Sun Microsystems - Beijing China 	 * Don't change the value of state->rc_mtu at the period from call
132093c426a1Ske ge - Sun Microsystems - Beijing China 	 * ibd_rc_alloc_rx_copybufs() to call ibd_rc_free_rx_copybufs().
132193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
132293c426a1Ske ge - Sun Microsystems - Beijing China 	rc_rx_buf_sz = state->rc_mtu + IPOIB_GRH_SIZE;
132393c426a1Ske ge - Sun Microsystems - Beijing China 
132493c426a1Ske ge - Sun Microsystems - Beijing China 	/*
132593c426a1Ske ge - Sun Microsystems - Beijing China 	 * Unregister rxbuf mr
132693c426a1Ske ge - Sun Microsystems - Beijing China 	 */
132793c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_deregister_mr(state->id_hca_hdl,
132893c426a1Ske ge - Sun Microsystems - Beijing China 	    chan->rx_mr_hdl) != IBT_SUCCESS) {
132993c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_free_rx_copybufs: ibt_deregister_mr failed");
133093c426a1Ske ge - Sun Microsystems - Beijing China 	}
133193c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_mr_hdl = NULL;
133293c426a1Ske ge - Sun Microsystems - Beijing China 
133393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
133493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Free rxbuf memory
133593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
133693c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(chan->rx_rwqes, chan->rcq_size * sizeof (ibd_rwqe_t));
133793c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_rwqes = NULL;
133893c426a1Ske ge - Sun Microsystems - Beijing China 
133993c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(chan->rx_bufs, chan->rcq_size * rc_rx_buf_sz);
134093c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_bufs = NULL;
134193c426a1Ske ge - Sun Microsystems - Beijing China }
134293c426a1Ske ge - Sun Microsystems - Beijing China 
134393c426a1Ske ge - Sun Microsystems - Beijing China /*
134493c426a1Ske ge - Sun Microsystems - Beijing China  * Post a certain number of receive buffers and WRs on a RC channel.
134593c426a1Ske ge - Sun Microsystems - Beijing China  */
134693c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_init_rxlist(ibd_rc_chan_t * chan)134793c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_init_rxlist(ibd_rc_chan_t *chan)
134893c426a1Ske ge - Sun Microsystems - Beijing China {
134993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
135093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe;
135193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_lkey_t lkey;
135293c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
135393c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t len;
135493c426a1Ske ge - Sun Microsystems - Beijing China 	uint8_t *bufaddr;
135593c426a1Ske ge - Sun Microsystems - Beijing China 
135693c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(!state->rc_enable_srq);
135793c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_alloc_rx_copybufs(chan) != DDI_SUCCESS)
135893c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
135993c426a1Ske ge - Sun Microsystems - Beijing China 
136093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
136193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate and setup the rwqe list
136293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
136393c426a1Ske ge - Sun Microsystems - Beijing China 	lkey = chan->rx_mr_desc.md_lkey;
136493c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe = chan->rx_rwqes;
136593c426a1Ske ge - Sun Microsystems - Beijing China 	bufaddr = chan->rx_bufs;
136693c426a1Ske ge - Sun Microsystems - Beijing China 	len = state->rc_mtu + IPOIB_GRH_SIZE;
136793c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < chan->rcq_size; i++, rwqe++, bufaddr += len) {
136893c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_state = state;
136993c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_chan = chan;
137093c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freeing_wqe = B_FALSE;
137193c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freemsg_cb.free_func = ibd_rc_freemsg_cb;
137293c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_freemsg_cb.free_arg = (char *)rwqe;
137393c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_bufaddr = bufaddr;
137493c426a1Ske ge - Sun Microsystems - Beijing China 
137593c426a1Ske ge - Sun Microsystems - Beijing China 		if ((rwqe->rwqe_im_mblk = desballoc(bufaddr, len, 0,
137693c426a1Ske ge - Sun Microsystems - Beijing China 		    &rwqe->w_freemsg_cb)) == NULL) {
137793c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_init_srq_list: desballoc() failed");
137893c426a1Ske ge - Sun Microsystems - Beijing China 			rwqe->rwqe_copybuf.ic_bufaddr = NULL;
137993c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_fini_rxlist(chan);
138093c426a1Ske ge - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
138193c426a1Ske ge - Sun Microsystems - Beijing China 		}
138293c426a1Ske ge - Sun Microsystems - Beijing China 
138393c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_key = lkey;
138493c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_va =
138593c426a1Ske ge - Sun Microsystems - Beijing China 		    (ib_vaddr_t)(uintptr_t)(bufaddr + IPOIB_GRH_SIZE);
138693c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->rwqe_copybuf.ic_sgl.ds_len = state->rc_mtu;
138793c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_id = (ibt_wrid_t)(uintptr_t)rwqe;
138893c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_nds = 1;
138993c426a1Ske ge - Sun Microsystems - Beijing China 		rwqe->w_rwr.wr_sgl = &rwqe->rwqe_copybuf.ic_sgl;
139093c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibd_rc_post_rwqe(chan, rwqe);
139193c426a1Ske ge - Sun Microsystems - Beijing China 	}
139293c426a1Ske ge - Sun Microsystems - Beijing China 
139393c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
139493c426a1Ske ge - Sun Microsystems - Beijing China }
139593c426a1Ske ge - Sun Microsystems - Beijing China 
139693c426a1Ske ge - Sun Microsystems - Beijing China /*
139793c426a1Ske ge - Sun Microsystems - Beijing China  * Free the statically allocated Rx buffer list for SRQ.
139893c426a1Ske ge - Sun Microsystems - Beijing China  */
139993c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_fini_rxlist(ibd_rc_chan_t * chan)140093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_fini_rxlist(ibd_rc_chan_t *chan)
140193c426a1Ske ge - Sun Microsystems - Beijing China {
140293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe;
140393c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
140493c426a1Ske ge - Sun Microsystems - Beijing China 
140593c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->rx_bufs == NULL) {
140693c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_fini_rxlist: empty chan->rx_bufs, quit");
140793c426a1Ske ge - Sun Microsystems - Beijing China 		return;
140893c426a1Ske ge - Sun Microsystems - Beijing China 	}
140993c426a1Ske ge - Sun Microsystems - Beijing China 
141093c426a1Ske ge - Sun Microsystems - Beijing China 	/* bufs_outstanding must be 0 */
141193c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT((chan->rx_wqe_list.dl_head == NULL) ||
141293c426a1Ske ge - Sun Microsystems - Beijing China 	    (chan->rx_wqe_list.dl_bufs_outstanding == 0));
141393c426a1Ske ge - Sun Microsystems - Beijing China 
141493c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&chan->rx_wqe_list.dl_mutex);
141593c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe = chan->rx_rwqes;
141693c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < chan->rcq_size; i++, rwqe++) {
141793c426a1Ske ge - Sun Microsystems - Beijing China 		if (rwqe->rwqe_im_mblk != NULL) {
141893c426a1Ske ge - Sun Microsystems - Beijing China 			rwqe->w_freeing_wqe = B_TRUE;
141993c426a1Ske ge - Sun Microsystems - Beijing China 			freemsg(rwqe->rwqe_im_mblk);
142093c426a1Ske ge - Sun Microsystems - Beijing China 		}
142193c426a1Ske ge - Sun Microsystems - Beijing China 	}
142293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&chan->rx_wqe_list.dl_mutex);
142393c426a1Ske ge - Sun Microsystems - Beijing China 
142493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_free_rx_copybufs(chan);
142593c426a1Ske ge - Sun Microsystems - Beijing China }
142693c426a1Ske ge - Sun Microsystems - Beijing China 
142793c426a1Ske ge - Sun Microsystems - Beijing China /*
142893c426a1Ske ge - Sun Microsystems - Beijing China  * Free an allocated recv wqe.
142993c426a1Ske ge - Sun Microsystems - Beijing China  */
143093c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_free_rwqe(ibd_rc_chan_t * chan,ibd_rwqe_t * rwqe)143193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_free_rwqe(ibd_rc_chan_t *chan, ibd_rwqe_t *rwqe)
143293c426a1Ske ge - Sun Microsystems - Beijing China {
143393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
143493c426a1Ske ge - Sun Microsystems - Beijing China 	 * desballoc() failed (no memory) or the posting of rwqe failed.
143593c426a1Ske ge - Sun Microsystems - Beijing China 	 *
143693c426a1Ske ge - Sun Microsystems - Beijing China 	 * This rwqe is placed on a free list so that it
143793c426a1Ske ge - Sun Microsystems - Beijing China 	 * can be reinstated in future.
143893c426a1Ske ge - Sun Microsystems - Beijing China 	 *
143993c426a1Ske ge - Sun Microsystems - Beijing China 	 * NOTE: no code currently exists to reinstate
144093c426a1Ske ge - Sun Microsystems - Beijing China 	 * these "lost" rwqes.
144193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
144293c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&chan->rx_free_list.dl_mutex);
144393c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_free_list.dl_cnt++;
144493c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe->rwqe_next = chan->rx_free_list.dl_head;
144593c426a1Ske ge - Sun Microsystems - Beijing China 	chan->rx_free_list.dl_head = RWQE_TO_WQE(rwqe);
144693c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&chan->rx_free_list.dl_mutex);
144793c426a1Ske ge - Sun Microsystems - Beijing China }
144893c426a1Ske ge - Sun Microsystems - Beijing China 
144993c426a1Ske ge - Sun Microsystems - Beijing China /*
145093c426a1Ske ge - Sun Microsystems - Beijing China  * Processing to be done after receipt of a packet; hand off to GLD
145193c426a1Ske ge - Sun Microsystems - Beijing China  * in the format expected by GLD.
145293c426a1Ske ge - Sun Microsystems - Beijing China  */
145393c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_process_rx(ibd_rc_chan_t * chan,ibd_rwqe_t * rwqe,ibt_wc_t * wc)145493c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_process_rx(ibd_rc_chan_t *chan, ibd_rwqe_t *rwqe, ibt_wc_t *wc)
145593c426a1Ske ge - Sun Microsystems - Beijing China {
145693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
145793c426a1Ske ge - Sun Microsystems - Beijing China 	ib_header_info_t *phdr;
145893c426a1Ske ge - Sun Microsystems - Beijing China 	ipoib_hdr_t *ipibp;
145993c426a1Ske ge - Sun Microsystems - Beijing China 	mblk_t *mp;
146093c426a1Ske ge - Sun Microsystems - Beijing China 	mblk_t *mpc;
146193c426a1Ske ge - Sun Microsystems - Beijing China 	int rxcnt;
146293c426a1Ske ge - Sun Microsystems - Beijing China 	ip6_t *ip6h;
146393c426a1Ske ge - Sun Microsystems - Beijing China 	int len;
146493c426a1Ske ge - Sun Microsystems - Beijing China 
146593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
146693c426a1Ske ge - Sun Microsystems - Beijing China 	 * Track number handed to upper layer, and number still
146793c426a1Ske ge - Sun Microsystems - Beijing China 	 * available to receive packets.
146893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
146993c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_enable_srq) {
147093c426a1Ske ge - Sun Microsystems - Beijing China 		rxcnt = atomic_dec_32_nv(&state->rc_srq_rwqe_list.dl_cnt);
147193c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
147293c426a1Ske ge - Sun Microsystems - Beijing China 		rxcnt = atomic_dec_32_nv(&chan->rx_wqe_list.dl_cnt);
147393c426a1Ske ge - Sun Microsystems - Beijing China 	}
147493c426a1Ske ge - Sun Microsystems - Beijing China 
147593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
147693c426a1Ske ge - Sun Microsystems - Beijing China 	 * It can not be a IBA multicast packet.
147793c426a1Ske ge - Sun Microsystems - Beijing China 	 */
147893c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(!wc->wc_flags & IBT_WC_GRH_PRESENT);
147993c426a1Ske ge - Sun Microsystems - Beijing China 
148003514dd7Ske ge - Sun Microsystems - Beijing China 	/* For the connection reaper routine ibd_rc_conn_timeout_call() */
148103514dd7Ske ge - Sun Microsystems - Beijing China 	chan->is_used = B_TRUE;
148293c426a1Ske ge - Sun Microsystems - Beijing China 
148393c426a1Ske ge - Sun Microsystems - Beijing China #ifdef DEBUG
14841cfa752fSRamaswamy Tummala 	if (rxcnt < state->id_rc_rx_rwqe_thresh) {
148593c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_rwqe_short++;
148693c426a1Ske ge - Sun Microsystems - Beijing China 	}
148793c426a1Ske ge - Sun Microsystems - Beijing China #endif
148893c426a1Ske ge - Sun Microsystems - Beijing China 
148993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
149093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Possibly replenish the Rx pool if needed.
149193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
14921cfa752fSRamaswamy Tummala 	if ((rxcnt >= state->id_rc_rx_rwqe_thresh) &&
14931cfa752fSRamaswamy Tummala 	    (wc->wc_bytes_xfer > state->id_rc_rx_copy_thresh)) {
149493c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_add_64(&state->rc_rcv_trans_byte, wc->wc_bytes_xfer);
149593c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_inc_64(&state->rc_rcv_trans_pkt);
149693c426a1Ske ge - Sun Microsystems - Beijing China 
149793c426a1Ske ge - Sun Microsystems - Beijing China 		/*
149893c426a1Ske ge - Sun Microsystems - Beijing China 		 * Record how many rwqe has been occupied by upper
149993c426a1Ske ge - Sun Microsystems - Beijing China 		 * network layer
150093c426a1Ske ge - Sun Microsystems - Beijing China 		 */
150193c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->rc_enable_srq) {
15021a5e258fSJosef 'Jeff' Sipek 			atomic_inc_32(
15031a5e258fSJosef 'Jeff' Sipek 			    &state->rc_srq_rwqe_list.dl_bufs_outstanding);
150493c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
15051a5e258fSJosef 'Jeff' Sipek 			atomic_inc_32(&chan->rx_wqe_list.dl_bufs_outstanding);
150693c426a1Ske ge - Sun Microsystems - Beijing China 		}
150793c426a1Ske ge - Sun Microsystems - Beijing China 		mp = rwqe->rwqe_im_mblk;
150893c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
150993c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_add_64(&state->rc_rcv_copy_byte, wc->wc_bytes_xfer);
151093c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_inc_64(&state->rc_rcv_copy_pkt);
151193c426a1Ske ge - Sun Microsystems - Beijing China 
151293c426a1Ske ge - Sun Microsystems - Beijing China 		if ((mp = allocb(wc->wc_bytes_xfer + IPOIB_GRH_SIZE,
151393c426a1Ske ge - Sun Microsystems - Beijing China 		    BPRI_HI)) == NULL) {	/* no memory */
151493c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_process_rx: allocb() failed");
151593c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rcv_alloc_fail++;
151693c426a1Ske ge - Sun Microsystems - Beijing China 			if (state->rc_enable_srq) {
151793c426a1Ske ge - Sun Microsystems - Beijing China 				if (ibd_rc_post_srq(state, rwqe) ==
151893c426a1Ske ge - Sun Microsystems - Beijing China 				    DDI_FAILURE) {
151993c426a1Ske ge - Sun Microsystems - Beijing China 					ibd_rc_srq_free_rwqe(state, rwqe);
152093c426a1Ske ge - Sun Microsystems - Beijing China 				}
152193c426a1Ske ge - Sun Microsystems - Beijing China 			} else {
152293c426a1Ske ge - Sun Microsystems - Beijing China 				if (ibd_rc_post_rwqe(chan, rwqe) ==
152393c426a1Ske ge - Sun Microsystems - Beijing China 				    DDI_FAILURE) {
152493c426a1Ske ge - Sun Microsystems - Beijing China 					ibd_rc_free_rwqe(chan, rwqe);
152593c426a1Ske ge - Sun Microsystems - Beijing China 				}
152693c426a1Ske ge - Sun Microsystems - Beijing China 			}
152793c426a1Ske ge - Sun Microsystems - Beijing China 			return;
152893c426a1Ske ge - Sun Microsystems - Beijing China 		}
152993c426a1Ske ge - Sun Microsystems - Beijing China 
153093c426a1Ske ge - Sun Microsystems - Beijing China 		bcopy(rwqe->rwqe_im_mblk->b_rptr + IPOIB_GRH_SIZE,
153193c426a1Ske ge - Sun Microsystems - Beijing China 		    mp->b_wptr + IPOIB_GRH_SIZE, wc->wc_bytes_xfer);
153293c426a1Ske ge - Sun Microsystems - Beijing China 
153393c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->rc_enable_srq) {
153493c426a1Ske ge - Sun Microsystems - Beijing China 			if (ibd_rc_post_srq(state, rwqe) == DDI_FAILURE) {
153593c426a1Ske ge - Sun Microsystems - Beijing China 				ibd_rc_srq_free_rwqe(state, rwqe);
153693c426a1Ske ge - Sun Microsystems - Beijing China 			}
153793c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
153893c426a1Ske ge - Sun Microsystems - Beijing China 			if (ibd_rc_post_rwqe(chan, rwqe) == DDI_FAILURE) {
153993c426a1Ske ge - Sun Microsystems - Beijing China 				ibd_rc_free_rwqe(chan, rwqe);
154093c426a1Ske ge - Sun Microsystems - Beijing China 			}
154193c426a1Ske ge - Sun Microsystems - Beijing China 		}
154293c426a1Ske ge - Sun Microsystems - Beijing China 	}
154393c426a1Ske ge - Sun Microsystems - Beijing China 
154493c426a1Ske ge - Sun Microsystems - Beijing China 	ipibp = (ipoib_hdr_t *)((uchar_t *)mp->b_rptr + IPOIB_GRH_SIZE);
154593c426a1Ske ge - Sun Microsystems - Beijing China 	if (ntohs(ipibp->ipoib_type) == ETHERTYPE_IPV6) {
154693c426a1Ske ge - Sun Microsystems - Beijing China 		ip6h = (ip6_t *)((uchar_t *)ipibp + sizeof (ipoib_hdr_t));
154793c426a1Ske ge - Sun Microsystems - Beijing China 		len = ntohs(ip6h->ip6_plen);
154893c426a1Ske ge - Sun Microsystems - Beijing China 		if (ip6h->ip6_nxt == IPPROTO_ICMPV6) {
154993c426a1Ske ge - Sun Microsystems - Beijing China 			/* LINTED: E_CONSTANT_CONDITION */
155093c426a1Ske ge - Sun Microsystems - Beijing China 			IBD_PAD_NSNA(ip6h, len, IBD_RECV);
155193c426a1Ske ge - Sun Microsystems - Beijing China 		}
155293c426a1Ske ge - Sun Microsystems - Beijing China 	}
155393c426a1Ske ge - Sun Microsystems - Beijing China 
155493c426a1Ske ge - Sun Microsystems - Beijing China 	phdr = (ib_header_info_t *)mp->b_rptr;
155593c426a1Ske ge - Sun Microsystems - Beijing China 	phdr->ib_grh.ipoib_vertcflow = 0;
155693c426a1Ske ge - Sun Microsystems - Beijing China 	ovbcopy(&state->id_macaddr, &phdr->ib_dst,
155793c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ipoib_mac_t));
155893c426a1Ske ge - Sun Microsystems - Beijing China 	mp->b_wptr = mp->b_rptr + wc->wc_bytes_xfer+ IPOIB_GRH_SIZE;
155993c426a1Ske ge - Sun Microsystems - Beijing China 
156093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
156193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Can RC mode in IB guarantee its checksum correctness?
156293c426a1Ske ge - Sun Microsystems - Beijing China 	 *
1563*ec71f88eSPatrick Mooney 	 * mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM | HCK_FULLCKSUM_OK);
156493c426a1Ske ge - Sun Microsystems - Beijing China 	 */
156593c426a1Ske ge - Sun Microsystems - Beijing China 
156693c426a1Ske ge - Sun Microsystems - Beijing China 	/*
156793c426a1Ske ge - Sun Microsystems - Beijing China 	 * Make sure this is NULL or we're in trouble.
156893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
156993c426a1Ske ge - Sun Microsystems - Beijing China 	if (mp->b_next != NULL) {
157093c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state,
157193c426a1Ske ge - Sun Microsystems - Beijing China 		    "ibd_rc_process_rx: got duplicate mp from rcq?");
157293c426a1Ske ge - Sun Microsystems - Beijing China 		mp->b_next = NULL;
157393c426a1Ske ge - Sun Microsystems - Beijing China 	}
157493c426a1Ske ge - Sun Microsystems - Beijing China 
157593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
157693c426a1Ske ge - Sun Microsystems - Beijing China 	 * Add this mp to the list of processed mp's to send to
157793c426a1Ske ge - Sun Microsystems - Beijing China 	 * the nw layer
157893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
157993c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_enable_srq) {
158093c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->rc_rx_lock);
158193c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->rc_rx_mp) {
158293c426a1Ske ge - Sun Microsystems - Beijing China 			ASSERT(state->rc_rx_mp_tail != NULL);
158393c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp_tail->b_next = mp;
158493c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
158593c426a1Ske ge - Sun Microsystems - Beijing China 			ASSERT(state->rc_rx_mp_tail == NULL);
158693c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp = mp;
158793c426a1Ske ge - Sun Microsystems - Beijing China 		}
158893c426a1Ske ge - Sun Microsystems - Beijing China 
158993c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_rx_mp_tail = mp;
159093c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_rx_mp_len++;
159193c426a1Ske ge - Sun Microsystems - Beijing China 
159293c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->rc_rx_mp_len  >= IBD_MAX_RX_MP_LEN) {
159393c426a1Ske ge - Sun Microsystems - Beijing China 			mpc = state->rc_rx_mp;
159493c426a1Ske ge - Sun Microsystems - Beijing China 
159593c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp = NULL;
159693c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp_tail = NULL;
159793c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp_len = 0;
159893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->rc_rx_lock);
159993c426a1Ske ge - Sun Microsystems - Beijing China 			mac_rx(state->id_mh, NULL, mpc);
160093c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
160193c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->rc_rx_lock);
160293c426a1Ske ge - Sun Microsystems - Beijing China 		}
160393c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
160493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->rx_lock);
160593c426a1Ske ge - Sun Microsystems - Beijing China 		if (chan->rx_mp) {
160693c426a1Ske ge - Sun Microsystems - Beijing China 			ASSERT(chan->rx_mp_tail != NULL);
160793c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp_tail->b_next = mp;
160893c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
160993c426a1Ske ge - Sun Microsystems - Beijing China 			ASSERT(chan->rx_mp_tail == NULL);
161093c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp = mp;
161193c426a1Ske ge - Sun Microsystems - Beijing China 		}
161293c426a1Ske ge - Sun Microsystems - Beijing China 
161393c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rx_mp_tail = mp;
161493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->rx_mp_len++;
161593c426a1Ske ge - Sun Microsystems - Beijing China 
161693c426a1Ske ge - Sun Microsystems - Beijing China 		if (chan->rx_mp_len  >= IBD_MAX_RX_MP_LEN) {
161793c426a1Ske ge - Sun Microsystems - Beijing China 			mpc = chan->rx_mp;
161893c426a1Ske ge - Sun Microsystems - Beijing China 
161993c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp = NULL;
162093c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp_tail = NULL;
162193c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp_len = 0;
162293c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->rx_lock);
162393c426a1Ske ge - Sun Microsystems - Beijing China 			mac_rx(state->id_mh, NULL, mpc);
162493c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
162593c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->rx_lock);
162693c426a1Ske ge - Sun Microsystems - Beijing China 		}
162793c426a1Ske ge - Sun Microsystems - Beijing China 	}
162893c426a1Ske ge - Sun Microsystems - Beijing China }
162993c426a1Ske ge - Sun Microsystems - Beijing China 
163093c426a1Ske ge - Sun Microsystems - Beijing China /*
163193c426a1Ske ge - Sun Microsystems - Beijing China  * Callback code invoked from STREAMs when the recv data buffer is free
163293c426a1Ske ge - Sun Microsystems - Beijing China  * for recycling.
163393c426a1Ske ge - Sun Microsystems - Beijing China  */
163493c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_freemsg_cb(char * arg)163593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_freemsg_cb(char *arg)
163693c426a1Ske ge - Sun Microsystems - Beijing China {
163793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rwqe_t *rwqe = (ibd_rwqe_t *)arg;
163893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan = rwqe->w_chan;
163993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = rwqe->w_state;
164093c426a1Ske ge - Sun Microsystems - Beijing China 
164193c426a1Ske ge - Sun Microsystems - Beijing China 	/*
164293c426a1Ske ge - Sun Microsystems - Beijing China 	 * If the wqe is being destructed, do not attempt recycling.
164393c426a1Ske ge - Sun Microsystems - Beijing China 	 */
164493c426a1Ske ge - Sun Microsystems - Beijing China 	if (rwqe->w_freeing_wqe == B_TRUE) {
164593c426a1Ske ge - Sun Microsystems - Beijing China 		return;
164693c426a1Ske ge - Sun Microsystems - Beijing China 	}
164793c426a1Ske ge - Sun Microsystems - Beijing China 
164893c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(!state->rc_enable_srq);
164993c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan->rx_wqe_list.dl_cnt < chan->rcq_size);
165093c426a1Ske ge - Sun Microsystems - Beijing China 
165193c426a1Ske ge - Sun Microsystems - Beijing China 	rwqe->rwqe_im_mblk = desballoc(rwqe->rwqe_copybuf.ic_bufaddr,
165293c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_mtu + IPOIB_GRH_SIZE, 0, &rwqe->w_freemsg_cb);
165393c426a1Ske ge - Sun Microsystems - Beijing China 	if (rwqe->rwqe_im_mblk == NULL) {
165493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_freemsg_cb: desballoc() failed");
165593c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_rwqe(chan, rwqe);
165693c426a1Ske ge - Sun Microsystems - Beijing China 		return;
165793c426a1Ske ge - Sun Microsystems - Beijing China 	}
165893c426a1Ske ge - Sun Microsystems - Beijing China 
165993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
166093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Post back to h/w. We could actually have more than
166193c426a1Ske ge - Sun Microsystems - Beijing China 	 * id_num_rwqe WQEs on the list if there were multiple
166293c426a1Ske ge - Sun Microsystems - Beijing China 	 * ibd_freemsg_cb() calls outstanding (since the lock is
166393c426a1Ske ge - Sun Microsystems - Beijing China 	 * not held the entire time). This will start getting
166493c426a1Ske ge - Sun Microsystems - Beijing China 	 * corrected over subsequent ibd_freemsg_cb() calls.
166593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
166693c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_post_rwqe(chan, rwqe) == DDI_FAILURE) {
166793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_rwqe(chan, rwqe);
166893c426a1Ske ge - Sun Microsystems - Beijing China 		return;
166993c426a1Ske ge - Sun Microsystems - Beijing China 	}
16701a5e258fSJosef 'Jeff' Sipek 	atomic_dec_32(&chan->rx_wqe_list.dl_bufs_outstanding);
167193c426a1Ske ge - Sun Microsystems - Beijing China }
167293c426a1Ske ge - Sun Microsystems - Beijing China 
167393c426a1Ske ge - Sun Microsystems - Beijing China /*
167493c426a1Ske ge - Sun Microsystems - Beijing China  * Common code for interrupt handling as well as for polling
167593c426a1Ske ge - Sun Microsystems - Beijing China  * for all completed wqe's while detaching.
167693c426a1Ske ge - Sun Microsystems - Beijing China  */
167793c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_poll_rcq(ibd_rc_chan_t * chan,ibt_cq_hdl_t cq_hdl)167893c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_poll_rcq(ibd_rc_chan_t *chan, ibt_cq_hdl_t cq_hdl)
167993c426a1Ske ge - Sun Microsystems - Beijing China {
168093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_wqe_t *wqe;
168193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_wc_t *wc, *wcs;
168293c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t numwcs, real_numwcs;
168393c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
168493c426a1Ske ge - Sun Microsystems - Beijing China 
168593c426a1Ske ge - Sun Microsystems - Beijing China 	wcs = chan->rx_wc;
168693c426a1Ske ge - Sun Microsystems - Beijing China 	numwcs = IBD_RC_MAX_CQ_WC;
168793c426a1Ske ge - Sun Microsystems - Beijing China 
168893c426a1Ske ge - Sun Microsystems - Beijing China 	while (ibt_poll_cq(cq_hdl, wcs, numwcs, &real_numwcs) == IBT_SUCCESS) {
168993c426a1Ske ge - Sun Microsystems - Beijing China 		for (i = 0, wc = wcs; i < real_numwcs; i++, wc++) {
169093c426a1Ske ge - Sun Microsystems - Beijing China 			wqe = (ibd_wqe_t *)(uintptr_t)wc->wc_id;
169193c426a1Ske ge - Sun Microsystems - Beijing China 			if (wc->wc_status != IBT_WC_SUCCESS) {
169293c426a1Ske ge - Sun Microsystems - Beijing China 				chan->state->rc_rcq_err++;
169393c426a1Ske ge - Sun Microsystems - Beijing China 				/*
169493c426a1Ske ge - Sun Microsystems - Beijing China 				 * Channel being torn down.
169593c426a1Ske ge - Sun Microsystems - Beijing China 				 */
169693c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_poll_rcq: wc_status(%d) != "
169793c426a1Ske ge - Sun Microsystems - Beijing China 				    "SUCC, chan=%p", wc->wc_status, chan);
169893c426a1Ske ge - Sun Microsystems - Beijing China 				if (wc->wc_status == IBT_WC_WR_FLUSHED_ERR) {
169993c426a1Ske ge - Sun Microsystems - Beijing China 					/*
170093c426a1Ske ge - Sun Microsystems - Beijing China 					 * Do not invoke Rx handler because
170193c426a1Ske ge - Sun Microsystems - Beijing China 					 * it might add buffers to the Rx pool
170293c426a1Ske ge - Sun Microsystems - Beijing China 					 * when we are trying to deinitialize.
170393c426a1Ske ge - Sun Microsystems - Beijing China 					 */
170493c426a1Ske ge - Sun Microsystems - Beijing China 					continue;
170593c426a1Ske ge - Sun Microsystems - Beijing China 				}
170693c426a1Ske ge - Sun Microsystems - Beijing China 			}
170793c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_process_rx(chan, WQE_TO_RWQE(wqe), wc);
170893c426a1Ske ge - Sun Microsystems - Beijing China 		}
170993c426a1Ske ge - Sun Microsystems - Beijing China 	}
171093c426a1Ske ge - Sun Microsystems - Beijing China }
171193c426a1Ske ge - Sun Microsystems - Beijing China 
171293c426a1Ske ge - Sun Microsystems - Beijing China /* Receive CQ handler */
171393c426a1Ske ge - Sun Microsystems - Beijing China /* ARGSUSED */
171493c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_rcq_handler(ibt_cq_hdl_t cq_hdl,void * arg)171593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_rcq_handler(ibt_cq_hdl_t cq_hdl, void *arg)
171693c426a1Ske ge - Sun Microsystems - Beijing China {
171793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan = (ibd_rc_chan_t *)arg;
171893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
171993c426a1Ske ge - Sun Microsystems - Beijing China 
172003514dd7Ske ge - Sun Microsystems - Beijing China 	atomic_inc_32(&chan->rcq_invoking);
172193c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan->chan_state == IBD_RC_STATE_PAS_ESTAB);
172293c426a1Ske ge - Sun Microsystems - Beijing China 
172393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
172493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Poll for completed entries; the CQ will not interrupt any
172593c426a1Ske ge - Sun Microsystems - Beijing China 	 * more for incoming (or transmitted) packets.
172693c426a1Ske ge - Sun Microsystems - Beijing China 	 */
172793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_poll_rcq(chan, chan->rcq_hdl);
172893c426a1Ske ge - Sun Microsystems - Beijing China 
172993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
173093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Now enable CQ notifications; all packets that arrive now
173193c426a1Ske ge - Sun Microsystems - Beijing China 	 * (or complete transmission) will cause new interrupts.
173293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
173393c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_enable_cq_notify(chan->rcq_hdl, IBT_NEXT_COMPLETION) !=
173493c426a1Ske ge - Sun Microsystems - Beijing China 	    IBT_SUCCESS) {
173593c426a1Ske ge - Sun Microsystems - Beijing China 		/*
173693c426a1Ske ge - Sun Microsystems - Beijing China 		 * We do not expect a failure here.
173793c426a1Ske ge - Sun Microsystems - Beijing China 		 */
173893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_rcq_handler: ibt_enable_cq_notify() failed");
173993c426a1Ske ge - Sun Microsystems - Beijing China 	}
174093c426a1Ske ge - Sun Microsystems - Beijing China 
174193c426a1Ske ge - Sun Microsystems - Beijing China 	/*
174293c426a1Ske ge - Sun Microsystems - Beijing China 	 * Repoll to catch all packets that might have arrived after
174393c426a1Ske ge - Sun Microsystems - Beijing China 	 * we finished the first poll loop and before interrupts got
174493c426a1Ske ge - Sun Microsystems - Beijing China 	 * armed.
174593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
174693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_poll_rcq(chan, chan->rcq_hdl);
174793c426a1Ske ge - Sun Microsystems - Beijing China 
174893c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_enable_srq) {
174993c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->rc_rx_lock);
175093c426a1Ske ge - Sun Microsystems - Beijing China 
175193c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->rc_rx_mp != NULL) {
175293c426a1Ske ge - Sun Microsystems - Beijing China 			mblk_t *mpc;
175393c426a1Ske ge - Sun Microsystems - Beijing China 			mpc = state->rc_rx_mp;
175493c426a1Ske ge - Sun Microsystems - Beijing China 
175593c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp = NULL;
175693c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp_tail = NULL;
175793c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_rx_mp_len = 0;
175893c426a1Ske ge - Sun Microsystems - Beijing China 
175993c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->rc_rx_lock);
176093c426a1Ske ge - Sun Microsystems - Beijing China 			mac_rx(state->id_mh, NULL, mpc);
176193c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
176293c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->rc_rx_lock);
176393c426a1Ske ge - Sun Microsystems - Beijing China 		}
176493c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
176593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->rx_lock);
176693c426a1Ske ge - Sun Microsystems - Beijing China 
176793c426a1Ske ge - Sun Microsystems - Beijing China 		if (chan->rx_mp != NULL) {
176893c426a1Ske ge - Sun Microsystems - Beijing China 			mblk_t *mpc;
176993c426a1Ske ge - Sun Microsystems - Beijing China 			mpc = chan->rx_mp;
177093c426a1Ske ge - Sun Microsystems - Beijing China 
177193c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp = NULL;
177293c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp_tail = NULL;
177393c426a1Ske ge - Sun Microsystems - Beijing China 			chan->rx_mp_len = 0;
177493c426a1Ske ge - Sun Microsystems - Beijing China 
177593c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->rx_lock);
177693c426a1Ske ge - Sun Microsystems - Beijing China 			mac_rx(state->id_mh, NULL, mpc);
177793c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
177893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->rx_lock);
177993c426a1Ske ge - Sun Microsystems - Beijing China 		}
178093c426a1Ske ge - Sun Microsystems - Beijing China 	}
178103514dd7Ske ge - Sun Microsystems - Beijing China 	atomic_dec_32(&chan->rcq_invoking);
178293c426a1Ske ge - Sun Microsystems - Beijing China }
178393c426a1Ske ge - Sun Microsystems - Beijing China 
178493c426a1Ske ge - Sun Microsystems - Beijing China /*
178593c426a1Ske ge - Sun Microsystems - Beijing China  * Allocate the statically allocated Tx buffer list.
178693c426a1Ske ge - Sun Microsystems - Beijing China  */
178793c426a1Ske ge - Sun Microsystems - Beijing China int
ibd_rc_init_tx_largebuf_list(ibd_state_t * state)178893c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_init_tx_largebuf_list(ibd_state_t *state)
178993c426a1Ske ge - Sun Microsystems - Beijing China {
179093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_tx_largebuf_t *lbufp;
179193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_tx_largebuf_t *tail;
179293c426a1Ske ge - Sun Microsystems - Beijing China 	uint8_t *memp;
179393c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_mr_attr_t mem_attr;
179493c426a1Ske ge - Sun Microsystems - Beijing China 	uint32_t num_swqe;
179593c426a1Ske ge - Sun Microsystems - Beijing China 	size_t  mem_size;
179693c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
179793c426a1Ske ge - Sun Microsystems - Beijing China 
17981cfa752fSRamaswamy Tummala 	num_swqe = state->id_rc_num_swqe - 1;
179993c426a1Ske ge - Sun Microsystems - Beijing China 
180093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
180193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate one big chunk for all Tx large copy bufs
180293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
180393c426a1Ske ge - Sun Microsystems - Beijing China 	/* Don't transfer IPOIB_GRH_SIZE bytes (40 bytes) */
180493c426a1Ske ge - Sun Microsystems - Beijing China 	mem_size = num_swqe * state->rc_mtu;
180593c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_mr_bufs = kmem_zalloc(mem_size, KM_SLEEP);
180693c426a1Ske ge - Sun Microsystems - Beijing China 
180793c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_len = mem_size;
180893c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_vaddr = (uint64_t)(uintptr_t)state->rc_tx_mr_bufs;
180993c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_as = NULL;
181093c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_flags = IBT_MR_SLEEP;
181193c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_register_mr(state->id_hca_hdl, state->id_pd_hdl, &mem_attr,
181293c426a1Ske ge - Sun Microsystems - Beijing China 	    &state->rc_tx_mr_hdl, &state->rc_tx_mr_desc) != IBT_SUCCESS) {
181393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_init_tx_largebuf_list: ibt_register_mr "
181493c426a1Ske ge - Sun Microsystems - Beijing China 		    "failed");
181593c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(state->rc_tx_mr_bufs, mem_size);
181693c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_tx_mr_bufs = NULL;
181793c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
181893c426a1Ske ge - Sun Microsystems - Beijing China 	}
181993c426a1Ske ge - Sun Microsystems - Beijing China 
182093c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_largebuf_desc_base = kmem_zalloc(num_swqe *
182193c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ibd_rc_tx_largebuf_t), KM_SLEEP);
182293c426a1Ske ge - Sun Microsystems - Beijing China 
182393c426a1Ske ge - Sun Microsystems - Beijing China 	/*
182493c426a1Ske ge - Sun Microsystems - Beijing China 	 * Set up the buf chain
182593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
182693c426a1Ske ge - Sun Microsystems - Beijing China 	memp = state->rc_tx_mr_bufs;
182793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_tx_large_bufs_lock);
182893c426a1Ske ge - Sun Microsystems - Beijing China 	lbufp = state->rc_tx_largebuf_desc_base;
182993c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < num_swqe; i++) {
183093c426a1Ske ge - Sun Microsystems - Beijing China 		lbufp->lb_buf = memp;
183193c426a1Ske ge - Sun Microsystems - Beijing China 		lbufp->lb_next = lbufp + 1;
183293c426a1Ske ge - Sun Microsystems - Beijing China 
183393c426a1Ske ge - Sun Microsystems - Beijing China 		tail = lbufp;
183493c426a1Ske ge - Sun Microsystems - Beijing China 
183593c426a1Ske ge - Sun Microsystems - Beijing China 		memp += state->rc_mtu;
183693c426a1Ske ge - Sun Microsystems - Beijing China 		lbufp++;
183793c426a1Ske ge - Sun Microsystems - Beijing China 	}
183893c426a1Ske ge - Sun Microsystems - Beijing China 	tail->lb_next = NULL;
183993c426a1Ske ge - Sun Microsystems - Beijing China 
184093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
184193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Set up the buffer information in ibd state
184293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
184393c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_largebuf_free_head = state->rc_tx_largebuf_desc_base;
184493c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_largebuf_nfree = num_swqe;
184593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_tx_large_bufs_lock);
184693c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
184793c426a1Ske ge - Sun Microsystems - Beijing China }
184893c426a1Ske ge - Sun Microsystems - Beijing China 
184993c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_fini_tx_largebuf_list(ibd_state_t * state)185093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_fini_tx_largebuf_list(ibd_state_t *state)
185193c426a1Ske ge - Sun Microsystems - Beijing China {
185293c426a1Ske ge - Sun Microsystems - Beijing China 	uint32_t num_swqe;
185393c426a1Ske ge - Sun Microsystems - Beijing China 
18541cfa752fSRamaswamy Tummala 	num_swqe = state->id_rc_num_swqe - 1;
185593c426a1Ske ge - Sun Microsystems - Beijing China 
185693c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_deregister_mr(state->id_hca_hdl,
185793c426a1Ske ge - Sun Microsystems - Beijing China 	    state->rc_tx_mr_hdl) != IBT_SUCCESS) {
185893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_fini_tx_largebuf_list: ibt_deregister_mr() "
185993c426a1Ske ge - Sun Microsystems - Beijing China 		    "failed");
186093c426a1Ske ge - Sun Microsystems - Beijing China 	}
186193c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_mr_hdl = NULL;
186293c426a1Ske ge - Sun Microsystems - Beijing China 
186393c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(state->rc_tx_mr_bufs, num_swqe * state->rc_mtu);
186493c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_mr_bufs = NULL;
186593c426a1Ske ge - Sun Microsystems - Beijing China 
186693c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(state->rc_tx_largebuf_desc_base,
186793c426a1Ske ge - Sun Microsystems - Beijing China 	    num_swqe * sizeof (ibd_rc_tx_largebuf_t));
186893c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_tx_largebuf_desc_base = NULL;
186993c426a1Ske ge - Sun Microsystems - Beijing China }
187093c426a1Ske ge - Sun Microsystems - Beijing China 
187193c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_alloc_tx_copybufs(ibd_rc_chan_t * chan)187293c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_alloc_tx_copybufs(ibd_rc_chan_t *chan)
187393c426a1Ske ge - Sun Microsystems - Beijing China {
187493c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_mr_attr_t mem_attr;
187593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state;
187693c426a1Ske ge - Sun Microsystems - Beijing China 
187793c426a1Ske ge - Sun Microsystems - Beijing China 	state = chan->state;
187893c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state != NULL);
187993c426a1Ske ge - Sun Microsystems - Beijing China 
188093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
188193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate one big chunk for all regular tx copy bufs
188293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
18831cfa752fSRamaswamy Tummala 	mem_attr.mr_len = chan->scq_size * state->id_rc_tx_copy_thresh;
188493c426a1Ske ge - Sun Microsystems - Beijing China 
188593c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_mr_bufs = kmem_zalloc(mem_attr.mr_len, KM_SLEEP);
188693c426a1Ske ge - Sun Microsystems - Beijing China 
188793c426a1Ske ge - Sun Microsystems - Beijing China 	/*
188893c426a1Ske ge - Sun Microsystems - Beijing China 	 * Do one memory registration on the entire txbuf area
188993c426a1Ske ge - Sun Microsystems - Beijing China 	 */
189093c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_vaddr = (uint64_t)(uintptr_t)chan->tx_mr_bufs;
189193c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_as = NULL;
189293c426a1Ske ge - Sun Microsystems - Beijing China 	mem_attr.mr_flags = IBT_MR_SLEEP;
189393c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_register_mr(state->id_hca_hdl, state->id_pd_hdl, &mem_attr,
189493c426a1Ske ge - Sun Microsystems - Beijing China 	    &chan->tx_mr_hdl, &chan->tx_mr_desc) != IBT_SUCCESS) {
189593c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_alloc_tx_copybufs: ibt_register_mr failed");
189693c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(mem_attr.mr_len ==
18971cfa752fSRamaswamy Tummala 		    chan->scq_size * state->id_rc_tx_copy_thresh);
189893c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(chan->tx_mr_bufs, mem_attr.mr_len);
189993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_mr_bufs = NULL;
190093c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
190193c426a1Ske ge - Sun Microsystems - Beijing China 	}
190293c426a1Ske ge - Sun Microsystems - Beijing China 
190393c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
190493c426a1Ske ge - Sun Microsystems - Beijing China }
190593c426a1Ske ge - Sun Microsystems - Beijing China 
190693c426a1Ske ge - Sun Microsystems - Beijing China /*
190793c426a1Ske ge - Sun Microsystems - Beijing China  * Allocate the statically allocated Tx buffer list.
190893c426a1Ske ge - Sun Microsystems - Beijing China  */
190993c426a1Ske ge - Sun Microsystems - Beijing China static int
ibd_rc_init_txlist(ibd_rc_chan_t * chan)191093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_init_txlist(ibd_rc_chan_t *chan)
191193c426a1Ske ge - Sun Microsystems - Beijing China {
191293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_swqe_t *swqe;
191393c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
191493c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_lkey_t lkey;
19151cfa752fSRamaswamy Tummala 	ibd_state_t *state = chan->state;
191693c426a1Ske ge - Sun Microsystems - Beijing China 
191793c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_alloc_tx_copybufs(chan) != DDI_SUCCESS)
191893c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
191993c426a1Ske ge - Sun Microsystems - Beijing China 
192093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
192193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Allocate and setup the swqe list
192293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
192393c426a1Ske ge - Sun Microsystems - Beijing China 	lkey = chan->tx_mr_desc.md_lkey;
192493c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_wqes = kmem_zalloc(chan->scq_size *
192593c426a1Ske ge - Sun Microsystems - Beijing China 	    sizeof (ibd_swqe_t), KM_SLEEP);
192693c426a1Ske ge - Sun Microsystems - Beijing China 	swqe = chan->tx_wqes;
192793c426a1Ske ge - Sun Microsystems - Beijing China 	for (i = 0; i < chan->scq_size; i++, swqe++) {
192893c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_next = NULL;
192993c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_im_mblk = NULL;
193093c426a1Ske ge - Sun Microsystems - Beijing China 
193193c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_copybuf.ic_sgl.ds_key = lkey;
193293c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_copybuf.ic_sgl.ds_len = 0; /* set in send */
193393c426a1Ske ge - Sun Microsystems - Beijing China 
193493c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->w_swr.wr_id = (ibt_wrid_t)(uintptr_t)swqe;
193593c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->w_swr.wr_flags = IBT_WR_SEND_SIGNAL;
193693c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_copybuf.ic_sgl.ds_va = (ib_vaddr_t)(uintptr_t)
19371cfa752fSRamaswamy Tummala 		    (chan->tx_mr_bufs + i * state->id_rc_tx_copy_thresh);
193893c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->w_swr.wr_trans = IBT_RC_SRV;
193993c426a1Ske ge - Sun Microsystems - Beijing China 
194093c426a1Ske ge - Sun Microsystems - Beijing China 		/* Add to list */
194193c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->tx_wqe_list.dl_mutex);
194293c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_cnt++;
194393c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_next = chan->tx_wqe_list.dl_head;
194493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_head = SWQE_TO_WQE(swqe);
194593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&chan->tx_wqe_list.dl_mutex);
194693c426a1Ske ge - Sun Microsystems - Beijing China 	}
194793c426a1Ske ge - Sun Microsystems - Beijing China 
194893c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
194993c426a1Ske ge - Sun Microsystems - Beijing China }
195093c426a1Ske ge - Sun Microsystems - Beijing China 
195193c426a1Ske ge - Sun Microsystems - Beijing China /*
195293c426a1Ske ge - Sun Microsystems - Beijing China  * Free the statically allocated Tx buffer list.
195393c426a1Ske ge - Sun Microsystems - Beijing China  */
195493c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_fini_txlist(ibd_rc_chan_t * chan)195593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_fini_txlist(ibd_rc_chan_t *chan)
195693c426a1Ske ge - Sun Microsystems - Beijing China {
19571cfa752fSRamaswamy Tummala 	ibd_state_t *state = chan->state;
195893c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->tx_mr_hdl != NULL) {
195993c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibt_deregister_mr(chan->state->id_hca_hdl,
196093c426a1Ske ge - Sun Microsystems - Beijing China 		    chan->tx_mr_hdl) != IBT_SUCCESS) {
196193c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_fini_txlist: ibt_deregister_mr "
196293c426a1Ske ge - Sun Microsystems - Beijing China 			    "failed");
196393c426a1Ske ge - Sun Microsystems - Beijing China 		}
196493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_mr_hdl = NULL;
196593c426a1Ske ge - Sun Microsystems - Beijing China 	}
196693c426a1Ske ge - Sun Microsystems - Beijing China 
196793c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->tx_mr_bufs != NULL) {
196893c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(chan->tx_mr_bufs, chan->scq_size *
19691cfa752fSRamaswamy Tummala 		    state->id_rc_tx_copy_thresh);
197093c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_mr_bufs = NULL;
197193c426a1Ske ge - Sun Microsystems - Beijing China 	}
197293c426a1Ske ge - Sun Microsystems - Beijing China 
197393c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->tx_wqes != NULL) {
197493c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(chan->tx_wqes, chan->scq_size *
197593c426a1Ske ge - Sun Microsystems - Beijing China 		    sizeof (ibd_swqe_t));
197693c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqes = NULL;
197793c426a1Ske ge - Sun Microsystems - Beijing China 	}
197893c426a1Ske ge - Sun Microsystems - Beijing China }
197993c426a1Ske ge - Sun Microsystems - Beijing China 
198093c426a1Ske ge - Sun Microsystems - Beijing China /*
198193c426a1Ske ge - Sun Microsystems - Beijing China  * Acquire send wqe from free list.
198293c426a1Ske ge - Sun Microsystems - Beijing China  * Returns error number and send wqe pointer.
198393c426a1Ske ge - Sun Microsystems - Beijing China  */
198493c426a1Ske ge - Sun Microsystems - Beijing China ibd_swqe_t *
ibd_rc_acquire_swqes(ibd_rc_chan_t * chan)198593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_acquire_swqes(ibd_rc_chan_t *chan)
198693c426a1Ske ge - Sun Microsystems - Beijing China {
198793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_swqe_t *wqe;
198893c426a1Ske ge - Sun Microsystems - Beijing China 
198993c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&chan->tx_rel_list.dl_mutex);
199093c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->tx_rel_list.dl_head != NULL) {
199193c426a1Ske ge - Sun Microsystems - Beijing China 		/* transfer id_tx_rel_list to id_tx_list */
199293c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_head =
199393c426a1Ske ge - Sun Microsystems - Beijing China 		    chan->tx_rel_list.dl_head;
199493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_cnt =
199593c426a1Ske ge - Sun Microsystems - Beijing China 		    chan->tx_rel_list.dl_cnt;
199693c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_pending_sends = B_FALSE;
199793c426a1Ske ge - Sun Microsystems - Beijing China 
199893c426a1Ske ge - Sun Microsystems - Beijing China 		/* clear id_tx_rel_list */
199993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_rel_list.dl_head = NULL;
200093c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_rel_list.dl_cnt = 0;
200193c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&chan->tx_rel_list.dl_mutex);
200293c426a1Ske ge - Sun Microsystems - Beijing China 
200393c426a1Ske ge - Sun Microsystems - Beijing China 		wqe = WQE_TO_SWQE(chan->tx_wqe_list.dl_head);
200493c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_cnt -= 1;
200593c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_head = wqe->swqe_next;
200693c426a1Ske ge - Sun Microsystems - Beijing China 	} else {	/* no free swqe */
200793c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&chan->tx_rel_list.dl_mutex);
200893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_wqe_list.dl_pending_sends = B_TRUE;
200993c426a1Ske ge - Sun Microsystems - Beijing China 		wqe = NULL;
201093c426a1Ske ge - Sun Microsystems - Beijing China 	}
201193c426a1Ske ge - Sun Microsystems - Beijing China 	return (wqe);
201293c426a1Ske ge - Sun Microsystems - Beijing China }
201393c426a1Ske ge - Sun Microsystems - Beijing China 
201493c426a1Ske ge - Sun Microsystems - Beijing China /*
201593c426a1Ske ge - Sun Microsystems - Beijing China  * Release send wqe back into free list.
201693c426a1Ske ge - Sun Microsystems - Beijing China  */
201793c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_release_swqe(ibd_rc_chan_t * chan,ibd_swqe_t * swqe)201893c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_release_swqe(ibd_rc_chan_t *chan, ibd_swqe_t *swqe)
201993c426a1Ske ge - Sun Microsystems - Beijing China {
202093c426a1Ske ge - Sun Microsystems - Beijing China 	/*
202193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Add back on Tx list for reuse.
202293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
202393c426a1Ske ge - Sun Microsystems - Beijing China 	swqe->swqe_next = NULL;
202493c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&chan->tx_rel_list.dl_mutex);
202593c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_rel_list.dl_pending_sends = B_FALSE;
202693c426a1Ske ge - Sun Microsystems - Beijing China 	swqe->swqe_next = chan->tx_rel_list.dl_head;
202793c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_rel_list.dl_head = SWQE_TO_WQE(swqe);
202893c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_rel_list.dl_cnt++;
202993c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&chan->tx_rel_list.dl_mutex);
203093c426a1Ske ge - Sun Microsystems - Beijing China }
203193c426a1Ske ge - Sun Microsystems - Beijing China 
203293c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_post_send(ibd_rc_chan_t * chan,ibd_swqe_t * node)203393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_post_send(ibd_rc_chan_t *chan, ibd_swqe_t *node)
203493c426a1Ske ge - Sun Microsystems - Beijing China {
203593c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t		i;
203693c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t		num_posted;
203793c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t		n_wrs;
203893c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t	ibt_status;
203993c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_send_wr_t	wrs[IBD_MAX_TX_POST_MULTIPLE];
204093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_swqe_t	*tx_head, *elem;
204193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_swqe_t	*nodes[IBD_MAX_TX_POST_MULTIPLE];
204293c426a1Ske ge - Sun Microsystems - Beijing China 
204393c426a1Ske ge - Sun Microsystems - Beijing China 	/* post the one request, then check for more */
204493c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status = ibt_post_send(chan->chan_hdl,
204593c426a1Ske ge - Sun Microsystems - Beijing China 	    &node->w_swr, 1, NULL);
204693c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_status != IBT_SUCCESS) {
204793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(chan->state, "ibd_post_send: "
204893c426a1Ske ge - Sun Microsystems - Beijing China 		    "posting one wr failed: ret=%d", ibt_status);
204993c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_tx_cleanup(node);
205093c426a1Ske ge - Sun Microsystems - Beijing China 	}
205193c426a1Ske ge - Sun Microsystems - Beijing China 
205293c426a1Ske ge - Sun Microsystems - Beijing China 	tx_head = NULL;
205393c426a1Ske ge - Sun Microsystems - Beijing China 	for (;;) {
205493c426a1Ske ge - Sun Microsystems - Beijing China 		if (tx_head == NULL) {
205593c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_post_lock);
205693c426a1Ske ge - Sun Microsystems - Beijing China 			tx_head = chan->tx_head;
205793c426a1Ske ge - Sun Microsystems - Beijing China 			if (tx_head == NULL) {
205893c426a1Ske ge - Sun Microsystems - Beijing China 				chan->tx_busy = 0;
205993c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_post_lock);
206093c426a1Ske ge - Sun Microsystems - Beijing China 				return;
206193c426a1Ske ge - Sun Microsystems - Beijing China 			}
206293c426a1Ske ge - Sun Microsystems - Beijing China 			chan->tx_head = NULL;
206393c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_post_lock);
206493c426a1Ske ge - Sun Microsystems - Beijing China 		}
206593c426a1Ske ge - Sun Microsystems - Beijing China 
206693c426a1Ske ge - Sun Microsystems - Beijing China 		/*
206793c426a1Ske ge - Sun Microsystems - Beijing China 		 * Collect pending requests, IBD_MAX_TX_POST_MULTIPLE wrs
206893c426a1Ske ge - Sun Microsystems - Beijing China 		 * at a time if possible, and keep posting them.
206993c426a1Ske ge - Sun Microsystems - Beijing China 		 */
207093c426a1Ske ge - Sun Microsystems - Beijing China 		for (n_wrs = 0, elem = tx_head;
207193c426a1Ske ge - Sun Microsystems - Beijing China 		    (elem) && (n_wrs < IBD_MAX_TX_POST_MULTIPLE);
207293c426a1Ske ge - Sun Microsystems - Beijing China 		    elem = WQE_TO_SWQE(elem->swqe_next), n_wrs++) {
207393c426a1Ske ge - Sun Microsystems - Beijing China 			nodes[n_wrs] = elem;
207493c426a1Ske ge - Sun Microsystems - Beijing China 			wrs[n_wrs] = elem->w_swr;
207593c426a1Ske ge - Sun Microsystems - Beijing China 		}
207693c426a1Ske ge - Sun Microsystems - Beijing China 		tx_head = elem;
207793c426a1Ske ge - Sun Microsystems - Beijing China 
207893c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(n_wrs != 0);
207993c426a1Ske ge - Sun Microsystems - Beijing China 
208093c426a1Ske ge - Sun Microsystems - Beijing China 		/*
208193c426a1Ske ge - Sun Microsystems - Beijing China 		 * If posting fails for some reason, we'll never receive
208293c426a1Ske ge - Sun Microsystems - Beijing China 		 * completion intimation, so we'll need to cleanup. But
208393c426a1Ske ge - Sun Microsystems - Beijing China 		 * we need to make sure we don't clean up nodes whose
208493c426a1Ske ge - Sun Microsystems - Beijing China 		 * wrs have been successfully posted. We assume that the
208593c426a1Ske ge - Sun Microsystems - Beijing China 		 * hca driver returns on the first failure to post and
208693c426a1Ske ge - Sun Microsystems - Beijing China 		 * therefore the first 'num_posted' entries don't need
208793c426a1Ske ge - Sun Microsystems - Beijing China 		 * cleanup here.
208893c426a1Ske ge - Sun Microsystems - Beijing China 		 */
208993c426a1Ske ge - Sun Microsystems - Beijing China 		num_posted = 0;
209093c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_status = ibt_post_send(chan->chan_hdl,
209193c426a1Ske ge - Sun Microsystems - Beijing China 		    wrs, n_wrs, &num_posted);
209293c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibt_status != IBT_SUCCESS) {
209393c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_print_warn(chan->state, "ibd_post_send: "
209493c426a1Ske ge - Sun Microsystems - Beijing China 			    "posting multiple wrs failed: "
209593c426a1Ske ge - Sun Microsystems - Beijing China 			    "requested=%d, done=%d, ret=%d",
209693c426a1Ske ge - Sun Microsystems - Beijing China 			    n_wrs, num_posted, ibt_status);
209793c426a1Ske ge - Sun Microsystems - Beijing China 
209893c426a1Ske ge - Sun Microsystems - Beijing China 			for (i = num_posted; i < n_wrs; i++)
209993c426a1Ske ge - Sun Microsystems - Beijing China 				ibd_rc_tx_cleanup(nodes[i]);
210093c426a1Ske ge - Sun Microsystems - Beijing China 		}
210193c426a1Ske ge - Sun Microsystems - Beijing China 	}
210293c426a1Ske ge - Sun Microsystems - Beijing China }
210393c426a1Ske ge - Sun Microsystems - Beijing China 
210493c426a1Ske ge - Sun Microsystems - Beijing China /*
210593c426a1Ske ge - Sun Microsystems - Beijing China  * Common code that deals with clean ups after a successful or
210693c426a1Ske ge - Sun Microsystems - Beijing China  * erroneous transmission attempt.
210793c426a1Ske ge - Sun Microsystems - Beijing China  */
210893c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_tx_cleanup(ibd_swqe_t * swqe)210993c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_tx_cleanup(ibd_swqe_t *swqe)
211093c426a1Ske ge - Sun Microsystems - Beijing China {
211193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace = swqe->w_ahandle;
211293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state;
211393c426a1Ske ge - Sun Microsystems - Beijing China 
211493c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace != NULL);
211593c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace->ac_chan != NULL);
211693c426a1Ske ge - Sun Microsystems - Beijing China 
211793c426a1Ske ge - Sun Microsystems - Beijing China 	state = ace->ac_chan->state;
211893c426a1Ske ge - Sun Microsystems - Beijing China 
211993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
212093c426a1Ske ge - Sun Microsystems - Beijing China 	 * If this was a dynamic registration in ibd_send(),
212193c426a1Ske ge - Sun Microsystems - Beijing China 	 * deregister now.
212293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
212393c426a1Ske ge - Sun Microsystems - Beijing China 	if (swqe->swqe_im_mblk != NULL) {
212493c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(swqe->w_buftype == IBD_WQE_MAPPED);
212593c426a1Ske ge - Sun Microsystems - Beijing China 		if (swqe->w_buftype == IBD_WQE_MAPPED) {
212693c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_unmap_mem(state, swqe);
212793c426a1Ske ge - Sun Microsystems - Beijing China 		}
212893c426a1Ske ge - Sun Microsystems - Beijing China 		freemsg(swqe->swqe_im_mblk);
212993c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->swqe_im_mblk = NULL;
213093c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
213193c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(swqe->w_buftype != IBD_WQE_MAPPED);
213293c426a1Ske ge - Sun Microsystems - Beijing China 	}
213393c426a1Ske ge - Sun Microsystems - Beijing China 
213493c426a1Ske ge - Sun Microsystems - Beijing China 	if (swqe->w_buftype == IBD_WQE_RC_COPYBUF) {
213593c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_tx_largebuf_t *lbufp;
213693c426a1Ske ge - Sun Microsystems - Beijing China 
213793c426a1Ske ge - Sun Microsystems - Beijing China 		lbufp = swqe->w_rc_tx_largebuf;
213893c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(lbufp != NULL);
213993c426a1Ske ge - Sun Microsystems - Beijing China 
214093c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->rc_tx_large_bufs_lock);
214193c426a1Ske ge - Sun Microsystems - Beijing China 		lbufp->lb_next = state->rc_tx_largebuf_free_head;
214293c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_tx_largebuf_free_head = lbufp;
214393c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_tx_largebuf_nfree ++;
214493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_tx_large_bufs_lock);
214593c426a1Ske ge - Sun Microsystems - Beijing China 		swqe->w_rc_tx_largebuf = NULL;
214693c426a1Ske ge - Sun Microsystems - Beijing China 	}
214793c426a1Ske ge - Sun Microsystems - Beijing China 
214893c426a1Ske ge - Sun Microsystems - Beijing China 
214993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
215093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Release the send wqe for reuse.
215193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
215293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_release_swqe(ace->ac_chan, swqe);
215393c426a1Ske ge - Sun Microsystems - Beijing China 
215493c426a1Ske ge - Sun Microsystems - Beijing China 	/*
215593c426a1Ske ge - Sun Microsystems - Beijing China 	 * Drop the reference count on the AH; it can be reused
215693c426a1Ske ge - Sun Microsystems - Beijing China 	 * now for a different destination if there are no more
215793c426a1Ske ge - Sun Microsystems - Beijing China 	 * posted sends that will use it. This can be eliminated
215893c426a1Ske ge - Sun Microsystems - Beijing China 	 * if we can always associate each Tx buffer with an AH.
215993c426a1Ske ge - Sun Microsystems - Beijing China 	 * The ace can be null if we are cleaning up from the
216093c426a1Ske ge - Sun Microsystems - Beijing China 	 * ibd_send() error path.
216193c426a1Ske ge - Sun Microsystems - Beijing China 	 */
216293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_dec_ref_ace(state, ace);
216393c426a1Ske ge - Sun Microsystems - Beijing China }
216493c426a1Ske ge - Sun Microsystems - Beijing China 
216593c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_drain_scq(ibd_rc_chan_t * chan,ibt_cq_hdl_t cq_hdl)216693c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_drain_scq(ibd_rc_chan_t *chan, ibt_cq_hdl_t cq_hdl)
216793c426a1Ske ge - Sun Microsystems - Beijing China {
216893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
216993c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_wqe_t *wqe;
217093c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_wc_t *wc, *wcs;
217103514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace;
217293c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t numwcs, real_numwcs;
217393c426a1Ske ge - Sun Microsystems - Beijing China 	int i;
217403514dd7Ske ge - Sun Microsystems - Beijing China 	boolean_t encount_error;
217593c426a1Ske ge - Sun Microsystems - Beijing China 
217693c426a1Ske ge - Sun Microsystems - Beijing China 	wcs = chan->tx_wc;
217793c426a1Ske ge - Sun Microsystems - Beijing China 	numwcs = IBD_RC_MAX_CQ_WC;
217803514dd7Ske ge - Sun Microsystems - Beijing China 	encount_error = B_FALSE;
217993c426a1Ske ge - Sun Microsystems - Beijing China 
218093c426a1Ske ge - Sun Microsystems - Beijing China 	while (ibt_poll_cq(cq_hdl, wcs, numwcs, &real_numwcs) == IBT_SUCCESS) {
218193c426a1Ske ge - Sun Microsystems - Beijing China 		for (i = 0, wc = wcs; i < real_numwcs; i++, wc++) {
218293c426a1Ske ge - Sun Microsystems - Beijing China 			wqe = (ibd_wqe_t *)(uintptr_t)wc->wc_id;
218393c426a1Ske ge - Sun Microsystems - Beijing China 			if (wc->wc_status != IBT_WC_SUCCESS) {
218403514dd7Ske ge - Sun Microsystems - Beijing China 				if (encount_error == B_FALSE) {
218503514dd7Ske ge - Sun Microsystems - Beijing China 					/*
218603514dd7Ske ge - Sun Microsystems - Beijing China 					 * This RC channle is in error status,
218703514dd7Ske ge - Sun Microsystems - Beijing China 					 * remove it.
218803514dd7Ske ge - Sun Microsystems - Beijing China 					 */
218903514dd7Ske ge - Sun Microsystems - Beijing China 					encount_error = B_TRUE;
219003514dd7Ske ge - Sun Microsystems - Beijing China 					mutex_enter(&state->id_ac_mutex);
219103514dd7Ske ge - Sun Microsystems - Beijing China 					if ((chan->chan_state ==
219203514dd7Ske ge - Sun Microsystems - Beijing China 					    IBD_RC_STATE_ACT_ESTAB) &&
219303514dd7Ske ge - Sun Microsystems - Beijing China 					    (chan->state->id_link_state ==
219403514dd7Ske ge - Sun Microsystems - Beijing China 					    LINK_STATE_UP) &&
219503514dd7Ske ge - Sun Microsystems - Beijing China 					    ((ace = ibd_acache_find(state,
219603514dd7Ske ge - Sun Microsystems - Beijing China 					    &chan->ace->ac_mac, B_FALSE, 0))
219703514dd7Ske ge - Sun Microsystems - Beijing China 					    != NULL) && (ace == chan->ace)) {
219803514dd7Ske ge - Sun Microsystems - Beijing China 						ASSERT(ace->ac_mce == NULL);
219903514dd7Ske ge - Sun Microsystems - Beijing China 						INC_REF(ace, 1);
220003514dd7Ske ge - Sun Microsystems - Beijing China 						IBD_ACACHE_PULLOUT_ACTIVE(
220103514dd7Ske ge - Sun Microsystems - Beijing China 						    state, ace);
220203514dd7Ske ge - Sun Microsystems - Beijing China 						chan->chan_state =
220303514dd7Ske ge - Sun Microsystems - Beijing China 						    IBD_RC_STATE_ACT_CLOSING;
220403514dd7Ske ge - Sun Microsystems - Beijing China 						mutex_exit(&state->id_ac_mutex);
220503514dd7Ske ge - Sun Microsystems - Beijing China 						state->rc_reset_cnt++;
220603514dd7Ske ge - Sun Microsystems - Beijing China 						DPRINT(30, "ibd_rc_drain_scq: "
220703514dd7Ske ge - Sun Microsystems - Beijing China 						    "wc_status(%d) != SUCC, "
220803514dd7Ske ge - Sun Microsystems - Beijing China 						    "chan=%p, ace=%p, "
220903514dd7Ske ge - Sun Microsystems - Beijing China 						    "link_state=%d"
221003514dd7Ske ge - Sun Microsystems - Beijing China 						    "reset RC channel",
221103514dd7Ske ge - Sun Microsystems - Beijing China 						    wc->wc_status, chan,
221203514dd7Ske ge - Sun Microsystems - Beijing China 						    chan->ace, chan->state->
221303514dd7Ske ge - Sun Microsystems - Beijing China 						    id_link_state);
221403514dd7Ske ge - Sun Microsystems - Beijing China 						ibd_rc_signal_act_close(
221503514dd7Ske ge - Sun Microsystems - Beijing China 						    state, ace);
221603514dd7Ske ge - Sun Microsystems - Beijing China 					} else {
221703514dd7Ske ge - Sun Microsystems - Beijing China 						mutex_exit(&state->id_ac_mutex);
221803514dd7Ske ge - Sun Microsystems - Beijing China 						state->
221903514dd7Ske ge - Sun Microsystems - Beijing China 						    rc_act_close_simultaneous++;
222003514dd7Ske ge - Sun Microsystems - Beijing China 						DPRINT(40, "ibd_rc_drain_scq: "
222103514dd7Ske ge - Sun Microsystems - Beijing China 						    "wc_status(%d) != SUCC, "
222203514dd7Ske ge - Sun Microsystems - Beijing China 						    "chan=%p, chan_state=%d,"
222303514dd7Ske ge - Sun Microsystems - Beijing China 						    "ace=%p, link_state=%d."
222403514dd7Ske ge - Sun Microsystems - Beijing China 						    "other thread is closing "
222503514dd7Ske ge - Sun Microsystems - Beijing China 						    "it", wc->wc_status, chan,
222603514dd7Ske ge - Sun Microsystems - Beijing China 						    chan->chan_state, chan->ace,
222703514dd7Ske ge - Sun Microsystems - Beijing China 						    chan->state->id_link_state);
222803514dd7Ske ge - Sun Microsystems - Beijing China 					}
222903514dd7Ske ge - Sun Microsystems - Beijing China 				}
223093c426a1Ske ge - Sun Microsystems - Beijing China 			}
223193c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_tx_cleanup(WQE_TO_SWQE(wqe));
223293c426a1Ske ge - Sun Microsystems - Beijing China 		}
223393c426a1Ske ge - Sun Microsystems - Beijing China 
223493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->id_sched_lock);
223593c426a1Ske ge - Sun Microsystems - Beijing China 		if (state->id_sched_needed == 0) {
223693c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_sched_lock);
223793c426a1Ske ge - Sun Microsystems - Beijing China 		} else if (state->id_sched_needed & IBD_RSRC_RC_SWQE) {
223893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_wqe_list.dl_mutex);
223993c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_rel_list.dl_mutex);
224093c426a1Ske ge - Sun Microsystems - Beijing China 			if ((chan->tx_rel_list.dl_cnt +
224193c426a1Ske ge - Sun Microsystems - Beijing China 			    chan->tx_wqe_list.dl_cnt) > IBD_RC_TX_FREE_THRESH) {
224293c426a1Ske ge - Sun Microsystems - Beijing China 				state->id_sched_needed &= ~IBD_RSRC_RC_SWQE;
224393c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_rel_list.dl_mutex);
224493c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_wqe_list.dl_mutex);
224593c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
224693c426a1Ske ge - Sun Microsystems - Beijing China 				state->rc_swqe_mac_update++;
224793c426a1Ske ge - Sun Microsystems - Beijing China 				mac_tx_update(state->id_mh);
224893c426a1Ske ge - Sun Microsystems - Beijing China 			} else {
224993c426a1Ske ge - Sun Microsystems - Beijing China 				state->rc_scq_no_swqe++;
225093c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_rel_list.dl_mutex);
225193c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_wqe_list.dl_mutex);
225293c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
225393c426a1Ske ge - Sun Microsystems - Beijing China 			}
225493c426a1Ske ge - Sun Microsystems - Beijing China 		} else if (state->id_sched_needed & IBD_RSRC_RC_TX_LARGEBUF) {
225593c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&state->rc_tx_large_bufs_lock);
225693c426a1Ske ge - Sun Microsystems - Beijing China 			if (state->rc_tx_largebuf_nfree >
225793c426a1Ske ge - Sun Microsystems - Beijing China 			    IBD_RC_TX_FREE_THRESH) {
225893c426a1Ske ge - Sun Microsystems - Beijing China 				ASSERT(state->rc_tx_largebuf_free_head != NULL);
225993c426a1Ske ge - Sun Microsystems - Beijing China 				state->id_sched_needed &=
226093c426a1Ske ge - Sun Microsystems - Beijing China 				    ~IBD_RSRC_RC_TX_LARGEBUF;
226193c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->rc_tx_large_bufs_lock);
226293c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
226393c426a1Ske ge - Sun Microsystems - Beijing China 				state->rc_xmt_buf_mac_update++;
226493c426a1Ske ge - Sun Microsystems - Beijing China 				mac_tx_update(state->id_mh);
226593c426a1Ske ge - Sun Microsystems - Beijing China 			} else {
226693c426a1Ske ge - Sun Microsystems - Beijing China 				state->rc_scq_no_largebuf++;
226793c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->rc_tx_large_bufs_lock);
226893c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
226993c426a1Ske ge - Sun Microsystems - Beijing China 			}
227093c426a1Ske ge - Sun Microsystems - Beijing China 		} else if (state->id_sched_needed & IBD_RSRC_SWQE) {
227193c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&state->id_tx_list.dl_mutex);
227293c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&state->id_tx_rel_list.dl_mutex);
227393c426a1Ske ge - Sun Microsystems - Beijing China 			if ((state->id_tx_list.dl_cnt +
227493c426a1Ske ge - Sun Microsystems - Beijing China 			    state->id_tx_rel_list.dl_cnt)
227593c426a1Ske ge - Sun Microsystems - Beijing China 			    > IBD_FREE_SWQES_THRESH) {
227693c426a1Ske ge - Sun Microsystems - Beijing China 				state->id_sched_needed &= ~IBD_RSRC_SWQE;
227793c426a1Ske ge - Sun Microsystems - Beijing China 				state->id_sched_cnt++;
227893c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_tx_rel_list.dl_mutex);
227993c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_tx_list.dl_mutex);
228093c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
228193c426a1Ske ge - Sun Microsystems - Beijing China 				mac_tx_update(state->id_mh);
228293c426a1Ske ge - Sun Microsystems - Beijing China 			} else {
228393c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_tx_rel_list.dl_mutex);
228493c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_tx_list.dl_mutex);
228593c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&state->id_sched_lock);
228693c426a1Ske ge - Sun Microsystems - Beijing China 			}
228793c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
228893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_sched_lock);
228993c426a1Ske ge - Sun Microsystems - Beijing China 		}
229093c426a1Ske ge - Sun Microsystems - Beijing China 	}
229193c426a1Ske ge - Sun Microsystems - Beijing China }
229293c426a1Ske ge - Sun Microsystems - Beijing China 
229393c426a1Ske ge - Sun Microsystems - Beijing China /* Send CQ handler, call ibd_rx_tx_cleanup to recycle Tx buffers */
229493c426a1Ske ge - Sun Microsystems - Beijing China /* ARGSUSED */
229593c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_scq_handler(ibt_cq_hdl_t cq_hdl,void * arg)229693c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_scq_handler(ibt_cq_hdl_t cq_hdl, void *arg)
229793c426a1Ske ge - Sun Microsystems - Beijing China {
229893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan = (ibd_rc_chan_t *)arg;
229993c426a1Ske ge - Sun Microsystems - Beijing China 
230093c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_tx_softintr == 1) {
230193c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->tx_poll_lock);
230293c426a1Ske ge - Sun Microsystems - Beijing China 		if (chan->tx_poll_busy & IBD_CQ_POLLING) {
230393c426a1Ske ge - Sun Microsystems - Beijing China 			chan->tx_poll_busy |= IBD_REDO_CQ_POLLING;
230493c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_poll_lock);
230593c426a1Ske ge - Sun Microsystems - Beijing China 			return;
230693c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
230793c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_poll_lock);
230893c426a1Ske ge - Sun Microsystems - Beijing China 			ddi_trigger_softintr(chan->scq_softintr);
230993c426a1Ske ge - Sun Microsystems - Beijing China 		}
231093c426a1Ske ge - Sun Microsystems - Beijing China 	} else
231193c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibd_rc_tx_recycle(arg);
231293c426a1Ske ge - Sun Microsystems - Beijing China }
231393c426a1Ske ge - Sun Microsystems - Beijing China 
231493c426a1Ske ge - Sun Microsystems - Beijing China static uint_t
ibd_rc_tx_recycle(caddr_t arg)231593c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_tx_recycle(caddr_t arg)
231693c426a1Ske ge - Sun Microsystems - Beijing China {
231793c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan = (ibd_rc_chan_t *)arg;
231893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = chan->state;
231993c426a1Ske ge - Sun Microsystems - Beijing China 	int flag, redo_flag;
232093c426a1Ske ge - Sun Microsystems - Beijing China 	int redo = 1;
232193c426a1Ske ge - Sun Microsystems - Beijing China 
232293c426a1Ske ge - Sun Microsystems - Beijing China 	flag = IBD_CQ_POLLING;
232393c426a1Ske ge - Sun Microsystems - Beijing China 	redo_flag = IBD_REDO_CQ_POLLING;
232493c426a1Ske ge - Sun Microsystems - Beijing China 
232593c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&chan->tx_poll_lock);
232693c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan->tx_poll_busy & flag) {
232793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_tx_recycle: multiple polling "
232893c426a1Ske ge - Sun Microsystems - Beijing China 		    "threads");
232993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->tx_poll_busy |= redo_flag;
233093c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&chan->tx_poll_lock);
233193c426a1Ske ge - Sun Microsystems - Beijing China 		return (DDI_INTR_CLAIMED);
233293c426a1Ske ge - Sun Microsystems - Beijing China 	}
233393c426a1Ske ge - Sun Microsystems - Beijing China 	chan->tx_poll_busy |= flag;
233493c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&chan->tx_poll_lock);
233593c426a1Ske ge - Sun Microsystems - Beijing China 
233693c426a1Ske ge - Sun Microsystems - Beijing China 	/*
233793c426a1Ske ge - Sun Microsystems - Beijing China 	 * Poll for completed entries; the CQ will not interrupt any
233893c426a1Ske ge - Sun Microsystems - Beijing China 	 * more for completed packets.
233993c426a1Ske ge - Sun Microsystems - Beijing China 	 */
234093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_drain_scq(chan, chan->scq_hdl);
234193c426a1Ske ge - Sun Microsystems - Beijing China 
234293c426a1Ske ge - Sun Microsystems - Beijing China 	/*
234393c426a1Ske ge - Sun Microsystems - Beijing China 	 * Now enable CQ notifications; all completions originating now
234493c426a1Ske ge - Sun Microsystems - Beijing China 	 * will cause new interrupts.
234593c426a1Ske ge - Sun Microsystems - Beijing China 	 */
234693c426a1Ske ge - Sun Microsystems - Beijing China 	do {
234793c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibt_enable_cq_notify(chan->scq_hdl, IBT_NEXT_COMPLETION) !=
234893c426a1Ske ge - Sun Microsystems - Beijing China 		    IBT_SUCCESS) {
234993c426a1Ske ge - Sun Microsystems - Beijing China 			/*
235093c426a1Ske ge - Sun Microsystems - Beijing China 			 * We do not expect a failure here.
235193c426a1Ske ge - Sun Microsystems - Beijing China 			 */
235293c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_scq_handler: ibt_enable_cq_notify()"
235393c426a1Ske ge - Sun Microsystems - Beijing China 			    " failed");
235493c426a1Ske ge - Sun Microsystems - Beijing China 		}
235593c426a1Ske ge - Sun Microsystems - Beijing China 
235693c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_drain_scq(chan, chan->scq_hdl);
235793c426a1Ske ge - Sun Microsystems - Beijing China 
235893c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->tx_poll_lock);
235993c426a1Ske ge - Sun Microsystems - Beijing China 		if (chan->tx_poll_busy & redo_flag)
236093c426a1Ske ge - Sun Microsystems - Beijing China 			chan->tx_poll_busy &= ~redo_flag;
236193c426a1Ske ge - Sun Microsystems - Beijing China 		else {
236293c426a1Ske ge - Sun Microsystems - Beijing China 			chan->tx_poll_busy &= ~flag;
236393c426a1Ske ge - Sun Microsystems - Beijing China 			redo = 0;
236493c426a1Ske ge - Sun Microsystems - Beijing China 		}
236593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&chan->tx_poll_lock);
236693c426a1Ske ge - Sun Microsystems - Beijing China 
236793c426a1Ske ge - Sun Microsystems - Beijing China 	} while (redo);
236893c426a1Ske ge - Sun Microsystems - Beijing China 
236993c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_INTR_CLAIMED);
237093c426a1Ske ge - Sun Microsystems - Beijing China }
237193c426a1Ske ge - Sun Microsystems - Beijing China 
2372a567cb71Ske ge - Sun Microsystems - Beijing China static ibt_status_t
ibd_register_service(ibt_srv_desc_t * srv,ib_svc_id_t sid,int num_sids,ibt_srv_hdl_t * srv_hdl,ib_svc_id_t * ret_sid)2373a567cb71Ske ge - Sun Microsystems - Beijing China ibd_register_service(ibt_srv_desc_t *srv, ib_svc_id_t sid,
2374a567cb71Ske ge - Sun Microsystems - Beijing China     int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
2375a567cb71Ske ge - Sun Microsystems - Beijing China {
2376a567cb71Ske ge - Sun Microsystems - Beijing China 	ibd_service_t *p;
2377a567cb71Ske ge - Sun Microsystems - Beijing China 	ibt_status_t status;
2378a567cb71Ske ge - Sun Microsystems - Beijing China 
2379a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&ibd_gstate.ig_mutex);
2380a567cb71Ske ge - Sun Microsystems - Beijing China 	for (p = ibd_gstate.ig_service_list; p != NULL; p = p->is_link) {
2381a567cb71Ske ge - Sun Microsystems - Beijing China 		if (p->is_sid == sid) {
2382a567cb71Ske ge - Sun Microsystems - Beijing China 			p->is_ref_cnt++;
2383a567cb71Ske ge - Sun Microsystems - Beijing China 			*srv_hdl = p->is_srv_hdl;
2384a567cb71Ske ge - Sun Microsystems - Beijing China 			*ret_sid = sid;
2385a567cb71Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&ibd_gstate.ig_mutex);
2386a567cb71Ske ge - Sun Microsystems - Beijing China 			return (IBT_SUCCESS);
2387a567cb71Ske ge - Sun Microsystems - Beijing China 		}
2388a567cb71Ske ge - Sun Microsystems - Beijing China 	}
2389a567cb71Ske ge - Sun Microsystems - Beijing China 	status = ibt_register_service(ibd_gstate.ig_ibt_hdl, srv, sid,
2390a567cb71Ske ge - Sun Microsystems - Beijing China 	    num_sids, srv_hdl, ret_sid);
2391a567cb71Ske ge - Sun Microsystems - Beijing China 	if (status == IBT_SUCCESS) {
2392a567cb71Ske ge - Sun Microsystems - Beijing China 		p = kmem_alloc(sizeof (*p), KM_SLEEP);
2393a567cb71Ske ge - Sun Microsystems - Beijing China 		p->is_srv_hdl = *srv_hdl;
2394a567cb71Ske ge - Sun Microsystems - Beijing China 		p->is_sid = sid;
2395a567cb71Ske ge - Sun Microsystems - Beijing China 		p->is_ref_cnt = 1;
2396a567cb71Ske ge - Sun Microsystems - Beijing China 		p->is_link = ibd_gstate.ig_service_list;
2397a567cb71Ske ge - Sun Microsystems - Beijing China 		ibd_gstate.ig_service_list = p;
2398a567cb71Ske ge - Sun Microsystems - Beijing China 	}
2399a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&ibd_gstate.ig_mutex);
2400a567cb71Ske ge - Sun Microsystems - Beijing China 	return (status);
2401a567cb71Ske ge - Sun Microsystems - Beijing China }
2402a567cb71Ske ge - Sun Microsystems - Beijing China 
2403a567cb71Ske ge - Sun Microsystems - Beijing China static ibt_status_t
ibd_deregister_service(ibt_srv_hdl_t srv_hdl)2404a567cb71Ske ge - Sun Microsystems - Beijing China ibd_deregister_service(ibt_srv_hdl_t srv_hdl)
2405a567cb71Ske ge - Sun Microsystems - Beijing China {
2406a567cb71Ske ge - Sun Microsystems - Beijing China 	ibd_service_t *p, **pp;
2407a567cb71Ske ge - Sun Microsystems - Beijing China 	ibt_status_t status;
2408a567cb71Ske ge - Sun Microsystems - Beijing China 
2409a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&ibd_gstate.ig_mutex);
2410a567cb71Ske ge - Sun Microsystems - Beijing China 	for (pp = &ibd_gstate.ig_service_list; *pp != NULL;
2411a567cb71Ske ge - Sun Microsystems - Beijing China 	    pp = &((*pp)->is_link)) {
2412a567cb71Ske ge - Sun Microsystems - Beijing China 		p = *pp;
2413a567cb71Ske ge - Sun Microsystems - Beijing China 		if (p->is_srv_hdl == srv_hdl) {	/* Found it */
2414a567cb71Ske ge - Sun Microsystems - Beijing China 			if (--p->is_ref_cnt == 0) {
2415a567cb71Ske ge - Sun Microsystems - Beijing China 				status = ibt_deregister_service(
2416a567cb71Ske ge - Sun Microsystems - Beijing China 				    ibd_gstate.ig_ibt_hdl, srv_hdl);
2417a567cb71Ske ge - Sun Microsystems - Beijing China 				*pp = p->is_link; /* link prev to next */
2418a567cb71Ske ge - Sun Microsystems - Beijing China 				kmem_free(p, sizeof (*p));
2419a567cb71Ske ge - Sun Microsystems - Beijing China 			} else {
2420a567cb71Ske ge - Sun Microsystems - Beijing China 				status = IBT_SUCCESS;
2421a567cb71Ske ge - Sun Microsystems - Beijing China 			}
2422a567cb71Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&ibd_gstate.ig_mutex);
2423a567cb71Ske ge - Sun Microsystems - Beijing China 			return (status);
2424a567cb71Ske ge - Sun Microsystems - Beijing China 		}
2425a567cb71Ske ge - Sun Microsystems - Beijing China 	}
2426a567cb71Ske ge - Sun Microsystems - Beijing China 	/* Should not ever get here */
2427a567cb71Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&ibd_gstate.ig_mutex);
2428a567cb71Ske ge - Sun Microsystems - Beijing China 	return (IBT_FAILURE);
2429a567cb71Ske ge - Sun Microsystems - Beijing China }
2430a567cb71Ske ge - Sun Microsystems - Beijing China 
243193c426a1Ske ge - Sun Microsystems - Beijing China /* Listen with corresponding service ID */
243293c426a1Ske ge - Sun Microsystems - Beijing China ibt_status_t
ibd_rc_listen(ibd_state_t * state)243393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_listen(ibd_state_t *state)
243493c426a1Ske ge - Sun Microsystems - Beijing China {
243593c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_srv_desc_t srvdesc;
243693c426a1Ske ge - Sun Microsystems - Beijing China 	ib_svc_id_t ret_sid;
243793c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t status;
243893c426a1Ske ge - Sun Microsystems - Beijing China 	ib_gid_t gid;
243993c426a1Ske ge - Sun Microsystems - Beijing China 
244093c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_listen_hdl != NULL) {
244193c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_listen: rc_listen_hdl should be NULL");
244293c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_FAILURE);
244393c426a1Ske ge - Sun Microsystems - Beijing China 	}
244493c426a1Ske ge - Sun Microsystems - Beijing China 
244593c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&srvdesc, sizeof (ibt_srv_desc_t));
244693c426a1Ske ge - Sun Microsystems - Beijing China 	srvdesc.sd_handler = ibd_rc_dispatch_pass_mad;
244793c426a1Ske ge - Sun Microsystems - Beijing China 	srvdesc.sd_flags = IBT_SRV_NO_FLAGS;
244893c426a1Ske ge - Sun Microsystems - Beijing China 
244993c426a1Ske ge - Sun Microsystems - Beijing China 	/*
245093c426a1Ske ge - Sun Microsystems - Beijing China 	 * Register the service with service id
245193c426a1Ske ge - Sun Microsystems - Beijing China 	 * Incoming connection requests should arrive on this service id.
245293c426a1Ske ge - Sun Microsystems - Beijing China 	 */
2453a567cb71Ske ge - Sun Microsystems - Beijing China 	status = ibd_register_service(&srvdesc,
245493c426a1Ske ge - Sun Microsystems - Beijing China 	    IBD_RC_QPN_TO_SID(state->id_qpnum),
245593c426a1Ske ge - Sun Microsystems - Beijing China 	    1, &state->rc_listen_hdl, &ret_sid);
245693c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
245793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_listen: Service Registration Failed, "
245893c426a1Ske ge - Sun Microsystems - Beijing China 		    "ret=%d", status);
245993c426a1Ske ge - Sun Microsystems - Beijing China 		return (status);
246093c426a1Ske ge - Sun Microsystems - Beijing China 	}
246193c426a1Ske ge - Sun Microsystems - Beijing China 
246293c426a1Ske ge - Sun Microsystems - Beijing China 	gid = state->id_sgid;
246393c426a1Ske ge - Sun Microsystems - Beijing China 
246493c426a1Ske ge - Sun Microsystems - Beijing China 	/* pass state as cm_private */
246593c426a1Ske ge - Sun Microsystems - Beijing China 	status = ibt_bind_service(state->rc_listen_hdl,
246693c426a1Ske ge - Sun Microsystems - Beijing China 	    gid, NULL, state, &state->rc_listen_bind);
246793c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
246893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_listen:"
246993c426a1Ske ge - Sun Microsystems - Beijing China 		    " fail to bind port: <%d>", status);
2470a567cb71Ske ge - Sun Microsystems - Beijing China 		(void) ibd_deregister_service(state->rc_listen_hdl);
247193c426a1Ske ge - Sun Microsystems - Beijing China 		return (status);
247293c426a1Ske ge - Sun Microsystems - Beijing China 	}
247393c426a1Ske ge - Sun Microsystems - Beijing China 
247493c426a1Ske ge - Sun Microsystems - Beijing China 	/*
247593c426a1Ske ge - Sun Microsystems - Beijing China 	 * Legacy OFED had used a wrong service ID (one additional zero digit)
247693c426a1Ske ge - Sun Microsystems - Beijing China 	 * for many years. To interop with legacy OFED, we support this wrong
247793c426a1Ske ge - Sun Microsystems - Beijing China 	 * service ID here.
247893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
247993c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(state->rc_listen_hdl_OFED_interop == NULL);
248093c426a1Ske ge - Sun Microsystems - Beijing China 
248193c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&srvdesc, sizeof (ibt_srv_desc_t));
248293c426a1Ske ge - Sun Microsystems - Beijing China 	srvdesc.sd_handler = ibd_rc_dispatch_pass_mad;
248393c426a1Ske ge - Sun Microsystems - Beijing China 	srvdesc.sd_flags = IBT_SRV_NO_FLAGS;
248493c426a1Ske ge - Sun Microsystems - Beijing China 
248593c426a1Ske ge - Sun Microsystems - Beijing China 	/*
248693c426a1Ske ge - Sun Microsystems - Beijing China 	 * Register the service with service id
248793c426a1Ske ge - Sun Microsystems - Beijing China 	 * Incoming connection requests should arrive on this service id.
248893c426a1Ske ge - Sun Microsystems - Beijing China 	 */
2489a567cb71Ske ge - Sun Microsystems - Beijing China 	status = ibd_register_service(&srvdesc,
249093c426a1Ske ge - Sun Microsystems - Beijing China 	    IBD_RC_QPN_TO_SID_OFED_INTEROP(state->id_qpnum),
249193c426a1Ske ge - Sun Microsystems - Beijing China 	    1, &state->rc_listen_hdl_OFED_interop, &ret_sid);
249293c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
249393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40,
249493c426a1Ske ge - Sun Microsystems - Beijing China 		    "ibd_rc_listen: Service Registration for Legacy OFED "
249593c426a1Ske ge - Sun Microsystems - Beijing China 		    "Failed %d", status);
249693c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibt_unbind_service(state->rc_listen_hdl,
249793c426a1Ske ge - Sun Microsystems - Beijing China 		    state->rc_listen_bind);
2498a567cb71Ske ge - Sun Microsystems - Beijing China 		(void) ibd_deregister_service(state->rc_listen_hdl);
249993c426a1Ske ge - Sun Microsystems - Beijing China 		return (status);
250093c426a1Ske ge - Sun Microsystems - Beijing China 	}
250193c426a1Ske ge - Sun Microsystems - Beijing China 
250293c426a1Ske ge - Sun Microsystems - Beijing China 	gid = state->id_sgid;
250393c426a1Ske ge - Sun Microsystems - Beijing China 
250493c426a1Ske ge - Sun Microsystems - Beijing China 	/* pass state as cm_private */
250593c426a1Ske ge - Sun Microsystems - Beijing China 	status = ibt_bind_service(state->rc_listen_hdl_OFED_interop,
250693c426a1Ske ge - Sun Microsystems - Beijing China 	    gid, NULL, state, &state->rc_listen_bind_OFED_interop);
250793c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
250893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_listen: fail to bind port: <%d> for "
250993c426a1Ske ge - Sun Microsystems - Beijing China 		    "Legacy OFED listener", status);
2510a567cb71Ske ge - Sun Microsystems - Beijing China 		(void) ibd_deregister_service(
251193c426a1Ske ge - Sun Microsystems - Beijing China 		    state->rc_listen_hdl_OFED_interop);
251293c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibt_unbind_service(state->rc_listen_hdl,
251393c426a1Ske ge - Sun Microsystems - Beijing China 		    state->rc_listen_bind);
2514a567cb71Ske ge - Sun Microsystems - Beijing China 		(void) ibd_deregister_service(state->rc_listen_hdl);
251593c426a1Ske ge - Sun Microsystems - Beijing China 		return (status);
251693c426a1Ske ge - Sun Microsystems - Beijing China 	}
251793c426a1Ske ge - Sun Microsystems - Beijing China 
251893c426a1Ske ge - Sun Microsystems - Beijing China 	return (IBT_SUCCESS);
251993c426a1Ske ge - Sun Microsystems - Beijing China }
252093c426a1Ske ge - Sun Microsystems - Beijing China 
252193c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_stop_listen(ibd_state_t * state)252293c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_stop_listen(ibd_state_t *state)
252393c426a1Ske ge - Sun Microsystems - Beijing China {
252493c426a1Ske ge - Sun Microsystems - Beijing China 	int ret;
252593c426a1Ske ge - Sun Microsystems - Beijing China 
252693c426a1Ske ge - Sun Microsystems - Beijing China 	/* Disable incoming connection requests */
252793c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_listen_hdl != NULL) {
252893c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_unbind_all_services(state->rc_listen_hdl);
252993c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != 0) {
253093c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_stop_listen:"
253193c426a1Ske ge - Sun Microsystems - Beijing China 			    "ibt_unbind_all_services() failed, ret=%d", ret);
253293c426a1Ske ge - Sun Microsystems - Beijing China 		}
2533a567cb71Ske ge - Sun Microsystems - Beijing China 		ret = ibd_deregister_service(state->rc_listen_hdl);
253493c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != 0) {
253593c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_stop_listen:"
2536a567cb71Ske ge - Sun Microsystems - Beijing China 			    "ibd_deregister_service() failed, ret=%d", ret);
253793c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
253893c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_listen_hdl = NULL;
253993c426a1Ske ge - Sun Microsystems - Beijing China 		}
254093c426a1Ske ge - Sun Microsystems - Beijing China 	}
254193c426a1Ske ge - Sun Microsystems - Beijing China 
254293c426a1Ske ge - Sun Microsystems - Beijing China 	/* Disable incoming connection requests */
254393c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_listen_hdl_OFED_interop != NULL) {
254493c426a1Ske ge - Sun Microsystems - Beijing China 		ret = ibt_unbind_all_services(
254593c426a1Ske ge - Sun Microsystems - Beijing China 		    state->rc_listen_hdl_OFED_interop);
254693c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != 0) {
254793c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_stop_listen:"
254893c426a1Ske ge - Sun Microsystems - Beijing China 			    "ibt_unbind_all_services() failed: %d", ret);
254993c426a1Ske ge - Sun Microsystems - Beijing China 		}
2550a567cb71Ske ge - Sun Microsystems - Beijing China 		ret = ibd_deregister_service(state->rc_listen_hdl_OFED_interop);
255193c426a1Ske ge - Sun Microsystems - Beijing China 		if (ret != 0) {
255293c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_stop_listen:"
2553a567cb71Ske ge - Sun Microsystems - Beijing China 			    "ibd_deregister_service() failed: %d", ret);
255493c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
255593c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_listen_hdl_OFED_interop = NULL;
255693c426a1Ske ge - Sun Microsystems - Beijing China 		}
255793c426a1Ske ge - Sun Microsystems - Beijing China 	}
255893c426a1Ske ge - Sun Microsystems - Beijing China }
255993c426a1Ske ge - Sun Microsystems - Beijing China 
2560a567cb71Ske ge - Sun Microsystems - Beijing China void
ibd_rc_close_all_chan(ibd_state_t * state)256193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_close_all_chan(ibd_state_t *state)
256293c426a1Ske ge - Sun Microsystems - Beijing China {
2563a567cb71Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *rc_chan;
256403514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace, *pre_ace;
256593c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t attempts;
256693c426a1Ske ge - Sun Microsystems - Beijing China 
256793c426a1Ske ge - Sun Microsystems - Beijing China 	/* Disable all Rx routines */
256893c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_pass_chan_list.chan_list_mutex);
256993c426a1Ske ge - Sun Microsystems - Beijing China 	rc_chan = state->rc_pass_chan_list.chan_list;
257093c426a1Ske ge - Sun Microsystems - Beijing China 	while (rc_chan != NULL) {
257193c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_set_cq_handler(rc_chan->rcq_hdl, 0, 0);
257293c426a1Ske ge - Sun Microsystems - Beijing China 		rc_chan = rc_chan->next;
257393c426a1Ske ge - Sun Microsystems - Beijing China 	}
257493c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_pass_chan_list.chan_list_mutex);
257593c426a1Ske ge - Sun Microsystems - Beijing China 
257693c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_enable_srq) {
2577a567cb71Ske ge - Sun Microsystems - Beijing China 		attempts = 10;
257893c426a1Ske ge - Sun Microsystems - Beijing China 		while (state->rc_srq_rwqe_list.dl_bufs_outstanding > 0) {
257993c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(30, "ibd_rc_close_all_chan: outstanding > 0");
258093c426a1Ske ge - Sun Microsystems - Beijing China 			delay(drv_usectohz(100000));
258193c426a1Ske ge - Sun Microsystems - Beijing China 			if (--attempts == 0) {
258293c426a1Ske ge - Sun Microsystems - Beijing China 				/*
258393c426a1Ske ge - Sun Microsystems - Beijing China 				 * There are pending bufs with the network
258493c426a1Ske ge - Sun Microsystems - Beijing China 				 * layer and we have no choice but to wait
258593c426a1Ske ge - Sun Microsystems - Beijing China 				 * for them to be done with. Reap all the
258693c426a1Ske ge - Sun Microsystems - Beijing China 				 * Tx/Rx completions that were posted since
258793c426a1Ske ge - Sun Microsystems - Beijing China 				 * we turned off the notification and
258893c426a1Ske ge - Sun Microsystems - Beijing China 				 * return failure.
258993c426a1Ske ge - Sun Microsystems - Beijing China 				 */
2590a567cb71Ske ge - Sun Microsystems - Beijing China 				break;
259193c426a1Ske ge - Sun Microsystems - Beijing China 			}
259293c426a1Ske ge - Sun Microsystems - Beijing China 		}
259393c426a1Ske ge - Sun Microsystems - Beijing China 	}
259493c426a1Ske ge - Sun Microsystems - Beijing China 
259593c426a1Ske ge - Sun Microsystems - Beijing China 	/* Close all passive RC channels */
259693c426a1Ske ge - Sun Microsystems - Beijing China 	rc_chan = ibd_rc_rm_header_chan_list(&state->rc_pass_chan_list);
259793c426a1Ske ge - Sun Microsystems - Beijing China 	while (rc_chan != NULL) {
259803514dd7Ske ge - Sun Microsystems - Beijing China 		(void) ibd_rc_pas_close(rc_chan, B_TRUE, B_FALSE);
259993c426a1Ske ge - Sun Microsystems - Beijing China 		rc_chan = ibd_rc_rm_header_chan_list(&state->rc_pass_chan_list);
260093c426a1Ske ge - Sun Microsystems - Beijing China 	}
260193c426a1Ske ge - Sun Microsystems - Beijing China 
260293c426a1Ske ge - Sun Microsystems - Beijing China 	/* Close all active RC channels */
260393c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->id_ac_mutex);
260403514dd7Ske ge - Sun Microsystems - Beijing China 	state->id_ac_hot_ace = NULL;
260593c426a1Ske ge - Sun Microsystems - Beijing China 	ace = list_head(&state->id_ah_active);
260603514dd7Ske ge - Sun Microsystems - Beijing China 	while ((pre_ace = ace) != NULL) {
260703514dd7Ske ge - Sun Microsystems - Beijing China 		ace = list_next(&state->id_ah_active, ace);
260803514dd7Ske ge - Sun Microsystems - Beijing China 		if (pre_ace->ac_chan != NULL) {
260903514dd7Ske ge - Sun Microsystems - Beijing China 			INC_REF(pre_ace, 1);
261003514dd7Ske ge - Sun Microsystems - Beijing China 			IBD_ACACHE_PULLOUT_ACTIVE(state, pre_ace);
261103514dd7Ske ge - Sun Microsystems - Beijing China 			pre_ace->ac_chan->chan_state = IBD_RC_STATE_ACT_CLOSING;
261293c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_add_to_chan_list(&state->rc_obs_act_chan_list,
261303514dd7Ske ge - Sun Microsystems - Beijing China 			    pre_ace->ac_chan);
261493c426a1Ske ge - Sun Microsystems - Beijing China 		}
261593c426a1Ske ge - Sun Microsystems - Beijing China 	}
261693c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->id_ac_mutex);
261793c426a1Ske ge - Sun Microsystems - Beijing China 
261893c426a1Ske ge - Sun Microsystems - Beijing China 	rc_chan = ibd_rc_rm_header_chan_list(&state->rc_obs_act_chan_list);
261993c426a1Ske ge - Sun Microsystems - Beijing China 	while (rc_chan != NULL) {
262093c426a1Ske ge - Sun Microsystems - Beijing China 		ace = rc_chan->ace;
262103514dd7Ske ge - Sun Microsystems - Beijing China 		ibd_rc_act_close(rc_chan, B_TRUE);
262203514dd7Ske ge - Sun Microsystems - Beijing China 		if (ace != NULL) {
262303514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&state->id_ac_mutex);
262403514dd7Ske ge - Sun Microsystems - Beijing China 			ASSERT(ace->ac_ref != 0);
262503514dd7Ske ge - Sun Microsystems - Beijing China 			atomic_dec_32(&ace->ac_ref);
262693c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_chan = NULL;
262703514dd7Ske ge - Sun Microsystems - Beijing China 			if ((ace->ac_ref == 0) || (ace->ac_ref == CYCLEVAL)) {
262803514dd7Ske ge - Sun Microsystems - Beijing China 				IBD_ACACHE_INSERT_FREE(state, ace);
262903514dd7Ske ge - Sun Microsystems - Beijing China 				ace->ac_ref = 0;
263003514dd7Ske ge - Sun Microsystems - Beijing China 			} else {
263103514dd7Ske ge - Sun Microsystems - Beijing China 				ace->ac_ref |= CYCLEVAL;
263203514dd7Ske ge - Sun Microsystems - Beijing China 				state->rc_delay_ace_recycle++;
263303514dd7Ske ge - Sun Microsystems - Beijing China 			}
263403514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_ac_mutex);
263503514dd7Ske ge - Sun Microsystems - Beijing China 		}
263693c426a1Ske ge - Sun Microsystems - Beijing China 		rc_chan = ibd_rc_rm_header_chan_list(
263793c426a1Ske ge - Sun Microsystems - Beijing China 		    &state->rc_obs_act_chan_list);
263893c426a1Ske ge - Sun Microsystems - Beijing China 	}
263903514dd7Ske ge - Sun Microsystems - Beijing China 
264003514dd7Ske ge - Sun Microsystems - Beijing China 	attempts = 400;
264103514dd7Ske ge - Sun Microsystems - Beijing China 	while (((state->rc_num_tx_chan != 0) ||
264203514dd7Ske ge - Sun Microsystems - Beijing China 	    (state->rc_num_rx_chan != 0)) && (attempts > 0)) {
264303514dd7Ske ge - Sun Microsystems - Beijing China 		/* Other thread is closing CM channel, wait it */
264403514dd7Ske ge - Sun Microsystems - Beijing China 		delay(drv_usectohz(100000));
264503514dd7Ske ge - Sun Microsystems - Beijing China 		attempts--;
264603514dd7Ske ge - Sun Microsystems - Beijing China 	}
264793c426a1Ske ge - Sun Microsystems - Beijing China }
264893c426a1Ske ge - Sun Microsystems - Beijing China 
264993c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_try_connect(ibd_state_t * state,ibd_ace_t * ace,ibt_path_info_t * path)265093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_try_connect(ibd_state_t *state, ibd_ace_t *ace,  ibt_path_info_t *path)
265193c426a1Ske ge - Sun Microsystems - Beijing China {
265293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t status;
265393c426a1Ske ge - Sun Microsystems - Beijing China 
265403514dd7Ske ge - Sun Microsystems - Beijing China 	if ((state->id_mac_state & IBD_DRV_STARTED) == 0)
265503514dd7Ske ge - Sun Microsystems - Beijing China 		return;
265603514dd7Ske ge - Sun Microsystems - Beijing China 
265793c426a1Ske ge - Sun Microsystems - Beijing China 	status = ibd_rc_connect(state, ace, path,
265893c426a1Ske ge - Sun Microsystems - Beijing China 	    IBD_RC_SERVICE_ID_OFED_INTEROP);
265993c426a1Ske ge - Sun Microsystems - Beijing China 
266093c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
266193c426a1Ske ge - Sun Microsystems - Beijing China 		/* wait peer side remove stale channel */
266293c426a1Ske ge - Sun Microsystems - Beijing China 		delay(drv_usectohz(10000));
266303514dd7Ske ge - Sun Microsystems - Beijing China 		if ((state->id_mac_state & IBD_DRV_STARTED) == 0)
266403514dd7Ske ge - Sun Microsystems - Beijing China 			return;
266593c426a1Ske ge - Sun Microsystems - Beijing China 		status = ibd_rc_connect(state, ace, path,
266693c426a1Ske ge - Sun Microsystems - Beijing China 		    IBD_RC_SERVICE_ID_OFED_INTEROP);
266793c426a1Ske ge - Sun Microsystems - Beijing China 	}
266893c426a1Ske ge - Sun Microsystems - Beijing China 
266993c426a1Ske ge - Sun Microsystems - Beijing China 	if (status != IBT_SUCCESS) {
267093c426a1Ske ge - Sun Microsystems - Beijing China 		/* wait peer side remove stale channel */
267193c426a1Ske ge - Sun Microsystems - Beijing China 		delay(drv_usectohz(10000));
267203514dd7Ske ge - Sun Microsystems - Beijing China 		if ((state->id_mac_state & IBD_DRV_STARTED) == 0)
267303514dd7Ske ge - Sun Microsystems - Beijing China 			return;
267493c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibd_rc_connect(state, ace, path,
267593c426a1Ske ge - Sun Microsystems - Beijing China 		    IBD_RC_SERVICE_ID);
267693c426a1Ske ge - Sun Microsystems - Beijing China 	}
267793c426a1Ske ge - Sun Microsystems - Beijing China }
267893c426a1Ske ge - Sun Microsystems - Beijing China 
267993c426a1Ske ge - Sun Microsystems - Beijing China /*
268093c426a1Ske ge - Sun Microsystems - Beijing China  * Allocates channel and sets the ace->ac_chan to it.
268193c426a1Ske ge - Sun Microsystems - Beijing China  * Opens the channel.
268293c426a1Ske ge - Sun Microsystems - Beijing China  */
268393c426a1Ske ge - Sun Microsystems - Beijing China ibt_status_t
ibd_rc_connect(ibd_state_t * state,ibd_ace_t * ace,ibt_path_info_t * path,uint64_t ietf_cm_service_id)268493c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_connect(ibd_state_t *state, ibd_ace_t *ace,  ibt_path_info_t *path,
268593c426a1Ske ge - Sun Microsystems - Beijing China     uint64_t ietf_cm_service_id)
268693c426a1Ske ge - Sun Microsystems - Beijing China {
268793c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t status = 0;
268893c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_rc_returns_t open_returns;
268993c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_chan_open_args_t open_args;
269093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_msg_hello_t hello_req_msg;
269193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_msg_hello_t *hello_ack_msg;
269293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan;
269303514dd7Ske ge - Sun Microsystems - Beijing China 	ibt_ud_dest_query_attr_t dest_attrs;
269493c426a1Ske ge - Sun Microsystems - Beijing China 
269593c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace != NULL);
269693c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace->ac_mce == NULL);
269793c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace->ac_chan == NULL);
269893c426a1Ske ge - Sun Microsystems - Beijing China 
269993c426a1Ske ge - Sun Microsystems - Beijing China 	if ((status = ibd_rc_alloc_chan(&chan, state, B_TRUE)) != IBT_SUCCESS) {
270093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(10, "ibd_rc_connect: ibd_rc_alloc_chan() failed");
270193c426a1Ske ge - Sun Microsystems - Beijing China 		return (status);
270293c426a1Ske ge - Sun Microsystems - Beijing China 	}
270393c426a1Ske ge - Sun Microsystems - Beijing China 
270493c426a1Ske ge - Sun Microsystems - Beijing China 	ace->ac_chan = chan;
270593c426a1Ske ge - Sun Microsystems - Beijing China 	chan->state = state;
270693c426a1Ske ge - Sun Microsystems - Beijing China 	chan->ace = ace;
270793c426a1Ske ge - Sun Microsystems - Beijing China 
270893c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_chan_private(chan->chan_hdl, (void *)(uintptr_t)ace);
270993c426a1Ske ge - Sun Microsystems - Beijing China 
271093c426a1Ske ge - Sun Microsystems - Beijing China 	hello_ack_msg = kmem_zalloc(sizeof (ibd_rc_msg_hello_t), KM_SLEEP);
271193c426a1Ske ge - Sun Microsystems - Beijing China 
271293c426a1Ske ge - Sun Microsystems - Beijing China 	/*
271393c426a1Ske ge - Sun Microsystems - Beijing China 	 * open the channels
271493c426a1Ske ge - Sun Microsystems - Beijing China 	 */
271593c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&open_args, sizeof (ibt_chan_open_args_t));
271693c426a1Ske ge - Sun Microsystems - Beijing China 	bzero(&open_returns, sizeof (ibt_rc_returns_t));
271793c426a1Ske ge - Sun Microsystems - Beijing China 
271893c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_cm_handler = ibd_rc_dispatch_actv_mad;
271993c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_cm_clnt_private = (void *)(uintptr_t)ace;
272093c426a1Ske ge - Sun Microsystems - Beijing China 
272193c426a1Ske ge - Sun Microsystems - Beijing China 	/*
272293c426a1Ske ge - Sun Microsystems - Beijing China 	 * update path record with the SID
272393c426a1Ske ge - Sun Microsystems - Beijing China 	 */
272403514dd7Ske ge - Sun Microsystems - Beijing China 	if ((status = ibt_query_ud_dest(ace->ac_dest, &dest_attrs))
272503514dd7Ske ge - Sun Microsystems - Beijing China 	    != IBT_SUCCESS) {
272603514dd7Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_connect: ibt_query_ud_dest() failed, "
272703514dd7Ske ge - Sun Microsystems - Beijing China 		    "ret=%d", status);
272803514dd7Ske ge - Sun Microsystems - Beijing China 		return (status);
272903514dd7Ske ge - Sun Microsystems - Beijing China 	}
273003514dd7Ske ge - Sun Microsystems - Beijing China 
273193c426a1Ske ge - Sun Microsystems - Beijing China 	path->pi_sid =
273203514dd7Ske ge - Sun Microsystems - Beijing China 	    ietf_cm_service_id | ((dest_attrs.ud_dst_qpn) & 0xffffff);
273393c426a1Ske ge - Sun Microsystems - Beijing China 
273493c426a1Ske ge - Sun Microsystems - Beijing China 
273593c426a1Ske ge - Sun Microsystems - Beijing China 	/* pre-allocate memory for hello ack message */
273693c426a1Ske ge - Sun Microsystems - Beijing China 	open_returns.rc_priv_data_len = sizeof (ibd_rc_msg_hello_t);
273793c426a1Ske ge - Sun Microsystems - Beijing China 	open_returns.rc_priv_data = hello_ack_msg;
273893c426a1Ske ge - Sun Microsystems - Beijing China 
273993c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_path = path;
274093c426a1Ske ge - Sun Microsystems - Beijing China 
274103514dd7Ske ge - Sun Microsystems - Beijing China 	open_args.oc_path_rnr_retry_cnt	= 1;
274203514dd7Ske ge - Sun Microsystems - Beijing China 	open_args.oc_path_retry_cnt = 1;
274393c426a1Ske ge - Sun Microsystems - Beijing China 
274493c426a1Ske ge - Sun Microsystems - Beijing China 	/* We don't do RDMA */
274593c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_rdma_ra_out = 0;
274693c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_rdma_ra_in	= 0;
274793c426a1Ske ge - Sun Microsystems - Beijing China 
274893c426a1Ske ge - Sun Microsystems - Beijing China 	hello_req_msg.reserved_qpn = htonl(state->id_qpnum);
274993c426a1Ske ge - Sun Microsystems - Beijing China 	hello_req_msg.rx_mtu = htonl(state->rc_mtu);
275093c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_priv_data_len = sizeof (ibd_rc_msg_hello_t);
275193c426a1Ske ge - Sun Microsystems - Beijing China 	open_args.oc_priv_data = (void *)(&hello_req_msg);
275293c426a1Ske ge - Sun Microsystems - Beijing China 
275393c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(open_args.oc_priv_data_len <= IBT_REQ_PRIV_DATA_SZ);
275493c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(open_returns.rc_priv_data_len <= IBT_REP_PRIV_DATA_SZ);
275593c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(open_args.oc_cm_handler != NULL);
275693c426a1Ske ge - Sun Microsystems - Beijing China 
275793c426a1Ske ge - Sun Microsystems - Beijing China 	status = ibt_open_rc_channel(chan->chan_hdl, IBT_OCHAN_NO_FLAGS,
275893c426a1Ske ge - Sun Microsystems - Beijing China 	    IBT_BLOCKING, &open_args, &open_returns);
275993c426a1Ske ge - Sun Microsystems - Beijing China 
276093c426a1Ske ge - Sun Microsystems - Beijing China 	if (status == IBT_SUCCESS) {
276193c426a1Ske ge - Sun Microsystems - Beijing China 		/* Success! */
276293c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(2, "ibd_rc_connect: call ibt_open_rc_channel succ!");
276393c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_conn_succ++;
276493c426a1Ske ge - Sun Microsystems - Beijing China 		kmem_free(hello_ack_msg, sizeof (ibd_rc_msg_hello_t));
276593c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_SUCCESS);
276693c426a1Ske ge - Sun Microsystems - Beijing China 	}
276793c426a1Ske ge - Sun Microsystems - Beijing China 
276893c426a1Ske ge - Sun Microsystems - Beijing China 	/* failure */
276993c426a1Ske ge - Sun Microsystems - Beijing China 	(void) ibt_flush_channel(chan->chan_hdl);
277093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_free_chan(chan);
277193c426a1Ske ge - Sun Microsystems - Beijing China 	ace->ac_chan = NULL;
277293c426a1Ske ge - Sun Microsystems - Beijing China 
277393c426a1Ske ge - Sun Microsystems - Beijing China 	/* check open_returns report error and exit */
277493c426a1Ske ge - Sun Microsystems - Beijing China 	DPRINT(30, "ibd_rc_connect: call ibt_open_rc_chan fail."
277593c426a1Ske ge - Sun Microsystems - Beijing China 	    "ret status = %d, reason=%d, ace=%p, mtu=0x%x, qpn=0x%x,"
277693c426a1Ske ge - Sun Microsystems - Beijing China 	    " peer qpn=0x%x", status, (int)open_returns.rc_status, ace,
277793c426a1Ske ge - Sun Microsystems - Beijing China 	    hello_req_msg.rx_mtu, hello_req_msg.reserved_qpn,
277803514dd7Ske ge - Sun Microsystems - Beijing China 	    dest_attrs.ud_dst_qpn);
277993c426a1Ske ge - Sun Microsystems - Beijing China 	kmem_free(hello_ack_msg, sizeof (ibd_rc_msg_hello_t));
278093c426a1Ske ge - Sun Microsystems - Beijing China 	return (status);
278193c426a1Ske ge - Sun Microsystems - Beijing China }
278293c426a1Ske ge - Sun Microsystems - Beijing China 
278393c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_signal_act_close(ibd_state_t * state,ibd_ace_t * ace)278493c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_signal_act_close(ibd_state_t *state, ibd_ace_t *ace)
278593c426a1Ske ge - Sun Microsystems - Beijing China {
278693c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_req_t *req;
278793c426a1Ske ge - Sun Microsystems - Beijing China 
278893c426a1Ske ge - Sun Microsystems - Beijing China 	req = kmem_cache_alloc(state->id_req_kmc, KM_NOSLEEP);
278993c426a1Ske ge - Sun Microsystems - Beijing China 	if (req == NULL) {
279093c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_print_warn(state, "ibd_rc_signal_act_close: alloc "
279193c426a1Ske ge - Sun Microsystems - Beijing China 		    "ibd_req_t fail");
279293c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->rc_obs_act_chan_list.chan_list_mutex);
279393c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_chan->next = state->rc_obs_act_chan_list.chan_list;
279493c426a1Ske ge - Sun Microsystems - Beijing China 		state->rc_obs_act_chan_list.chan_list = ace->ac_chan;
279593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_obs_act_chan_list.chan_list_mutex);
279693c426a1Ske ge - Sun Microsystems - Beijing China 	} else {
279793c426a1Ske ge - Sun Microsystems - Beijing China 		req->rq_ptr = ace->ac_chan;
279893c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_queue_work_slot(state, req, IBD_ASYNC_RC_CLOSE_ACT_CHAN);
279993c426a1Ske ge - Sun Microsystems - Beijing China 	}
280093c426a1Ske ge - Sun Microsystems - Beijing China }
280193c426a1Ske ge - Sun Microsystems - Beijing China 
280293c426a1Ske ge - Sun Microsystems - Beijing China void
ibd_rc_signal_ace_recycle(ibd_state_t * state,ibd_ace_t * ace)280393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_signal_ace_recycle(ibd_state_t *state, ibd_ace_t *ace)
280493c426a1Ske ge - Sun Microsystems - Beijing China {
280593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_req_t *req;
280693c426a1Ske ge - Sun Microsystems - Beijing China 
280793c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_enter(&state->rc_ace_recycle_lock);
280893c426a1Ske ge - Sun Microsystems - Beijing China 	if (state->rc_ace_recycle != NULL) {
280993c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_ace_recycle_lock);
281093c426a1Ske ge - Sun Microsystems - Beijing China 		return;
281193c426a1Ske ge - Sun Microsystems - Beijing China 	}
281293c426a1Ske ge - Sun Microsystems - Beijing China 
281393c426a1Ske ge - Sun Microsystems - Beijing China 	req = kmem_cache_alloc(state->id_req_kmc, KM_NOSLEEP);
281493c426a1Ske ge - Sun Microsystems - Beijing China 	if (req == NULL) {
281593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->rc_ace_recycle_lock);
281693c426a1Ske ge - Sun Microsystems - Beijing China 		return;
281793c426a1Ske ge - Sun Microsystems - Beijing China 	}
281893c426a1Ske ge - Sun Microsystems - Beijing China 
281993c426a1Ske ge - Sun Microsystems - Beijing China 	state->rc_ace_recycle = ace;
282093c426a1Ske ge - Sun Microsystems - Beijing China 	mutex_exit(&state->rc_ace_recycle_lock);
282193c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(ace->ac_mce == NULL);
282293c426a1Ske ge - Sun Microsystems - Beijing China 	INC_REF(ace, 1);
282393c426a1Ske ge - Sun Microsystems - Beijing China 	IBD_ACACHE_PULLOUT_ACTIVE(state, ace);
282493c426a1Ske ge - Sun Microsystems - Beijing China 	req->rq_ptr = ace;
282593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_queue_work_slot(state, req, IBD_ASYNC_RC_RECYCLE_ACE);
282693c426a1Ske ge - Sun Microsystems - Beijing China }
282793c426a1Ske ge - Sun Microsystems - Beijing China 
282803514dd7Ske ge - Sun Microsystems - Beijing China /*
282903514dd7Ske ge - Sun Microsystems - Beijing China  * Close an active channel
283003514dd7Ske ge - Sun Microsystems - Beijing China  *
283103514dd7Ske ge - Sun Microsystems - Beijing China  * is_close_rc_chan: if B_TRUE, we will call ibt_close_rc_channel()
283203514dd7Ske ge - Sun Microsystems - Beijing China  */
283393c426a1Ske ge - Sun Microsystems - Beijing China static void
ibd_rc_act_close(ibd_rc_chan_t * chan,boolean_t is_close_rc_chan)283403514dd7Ske ge - Sun Microsystems - Beijing China ibd_rc_act_close(ibd_rc_chan_t *chan, boolean_t is_close_rc_chan)
283593c426a1Ske ge - Sun Microsystems - Beijing China {
283603514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state;
283703514dd7Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace;
283893c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t times;
283993c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t ret;
284093c426a1Ske ge - Sun Microsystems - Beijing China 
284193c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan != NULL);
284293c426a1Ske ge - Sun Microsystems - Beijing China 
284393c426a1Ske ge - Sun Microsystems - Beijing China 	chan->state->rc_act_close++;
284493c426a1Ske ge - Sun Microsystems - Beijing China 	switch (chan->chan_state) {
284593c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_ACT_CLOSING:	/* stale, close it */
284693c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_ACT_ESTAB:
284793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_act_close-1: close and free chan, "
284893c426a1Ske ge - Sun Microsystems - Beijing China 		    "act_state=%d, chan=%p", chan->chan_state, chan);
284993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->chan_state = IBD_RC_STATE_ACT_CLOSED;
285093c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_set_cq_handler(chan->rcq_hdl, 0, 0);
285103514dd7Ske ge - Sun Microsystems - Beijing China 		/*
285203514dd7Ske ge - Sun Microsystems - Beijing China 		 * Wait send queue empty. Its old value is 50 (5 seconds). But
285303514dd7Ske ge - Sun Microsystems - Beijing China 		 * in my experiment, 5 seconds is not enough time to let IBTL
285403514dd7Ske ge - Sun Microsystems - Beijing China 		 * return all buffers and ace->ac_ref. I tried 25 seconds, it
285503514dd7Ske ge - Sun Microsystems - Beijing China 		 * works well. As another evidence, I saw IBTL takes about 17
285603514dd7Ske ge - Sun Microsystems - Beijing China 		 * seconds every time it cleans a stale RC channel.
285703514dd7Ske ge - Sun Microsystems - Beijing China 		 */
285803514dd7Ske ge - Sun Microsystems - Beijing China 		times = 250;
285903514dd7Ske ge - Sun Microsystems - Beijing China 		ace = chan->ace;
286003514dd7Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace != NULL);
286103514dd7Ske ge - Sun Microsystems - Beijing China 		state = chan->state;
286203514dd7Ske ge - Sun Microsystems - Beijing China 		ASSERT(state != NULL);
286303514dd7Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->id_ac_mutex);
286493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->tx_wqe_list.dl_mutex);
286593c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&chan->tx_rel_list.dl_mutex);
286693c426a1Ske ge - Sun Microsystems - Beijing China 		while (((chan->tx_wqe_list.dl_cnt + chan->tx_rel_list.dl_cnt)
286703514dd7Ske ge - Sun Microsystems - Beijing China 		    != chan->scq_size) || ((ace->ac_ref != 1) &&
286803514dd7Ske ge - Sun Microsystems - Beijing China 		    (ace->ac_ref != (CYCLEVAL+1)))) {
286993c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_rel_list.dl_mutex);
287093c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_wqe_list.dl_mutex);
287103514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_ac_mutex);
287203514dd7Ske ge - Sun Microsystems - Beijing China 			times--;
287303514dd7Ske ge - Sun Microsystems - Beijing China 			if (times == 0) {
287403514dd7Ske ge - Sun Microsystems - Beijing China 				state->rc_act_close_not_clean++;
287503514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_act_close: dl_cnt(tx_wqe_"
287603514dd7Ske ge - Sun Microsystems - Beijing China 				    "list=%d, tx_rel_list=%d) != chan->"
287703514dd7Ske ge - Sun Microsystems - Beijing China 				    "scq_size=%d, OR ac_ref(=%d) not clean",
287803514dd7Ske ge - Sun Microsystems - Beijing China 				    chan->tx_wqe_list.dl_cnt,
287903514dd7Ske ge - Sun Microsystems - Beijing China 				    chan->tx_rel_list.dl_cnt,
288003514dd7Ske ge - Sun Microsystems - Beijing China 				    chan->scq_size, ace->ac_ref);
288103514dd7Ske ge - Sun Microsystems - Beijing China 				break;
288203514dd7Ske ge - Sun Microsystems - Beijing China 			}
288393c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_poll_lock);
288493c426a1Ske ge - Sun Microsystems - Beijing China 			if (chan->tx_poll_busy & IBD_CQ_POLLING) {
288593c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_act_close: multiple "
288693c426a1Ske ge - Sun Microsystems - Beijing China 				    "polling threads");
288793c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_poll_lock);
288893c426a1Ske ge - Sun Microsystems - Beijing China 			} else {
288993c426a1Ske ge - Sun Microsystems - Beijing China 				chan->tx_poll_busy = IBD_CQ_POLLING;
289093c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_poll_lock);
289193c426a1Ske ge - Sun Microsystems - Beijing China 				ibd_rc_drain_scq(chan, chan->scq_hdl);
289293c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_enter(&chan->tx_poll_lock);
289393c426a1Ske ge - Sun Microsystems - Beijing China 				chan->tx_poll_busy = 0;
289493c426a1Ske ge - Sun Microsystems - Beijing China 				mutex_exit(&chan->tx_poll_lock);
289593c426a1Ske ge - Sun Microsystems - Beijing China 			}
289693c426a1Ske ge - Sun Microsystems - Beijing China 			delay(drv_usectohz(100000));
289703514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&state->id_ac_mutex);
289893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_wqe_list.dl_mutex);
289993c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_enter(&chan->tx_rel_list.dl_mutex);
290093c426a1Ske ge - Sun Microsystems - Beijing China 		}
290103514dd7Ske ge - Sun Microsystems - Beijing China 		if (times != 0) {
290203514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_rel_list.dl_mutex);
290303514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&chan->tx_wqe_list.dl_mutex);
290403514dd7Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_ac_mutex);
290503514dd7Ske ge - Sun Microsystems - Beijing China 		}
290603514dd7Ske ge - Sun Microsystems - Beijing China 
290793c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_set_cq_handler(chan->scq_hdl, 0, 0);
290803514dd7Ske ge - Sun Microsystems - Beijing China 		if (is_close_rc_chan) {
290903514dd7Ske ge - Sun Microsystems - Beijing China 			ret = ibt_close_rc_channel(chan->chan_hdl,
291003514dd7Ske ge - Sun Microsystems - Beijing China 			    IBT_BLOCKING|IBT_NOCALLBACKS, NULL, 0, NULL, NULL,
291103514dd7Ske ge - Sun Microsystems - Beijing China 			    0);
291203514dd7Ske ge - Sun Microsystems - Beijing China 			if (ret != IBT_SUCCESS) {
291303514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_act_close: ibt_close_rc_"
291403514dd7Ske ge - Sun Microsystems - Beijing China 				    "channel fail, chan=%p, ret=%d",
291503514dd7Ske ge - Sun Microsystems - Beijing China 				    chan, ret);
291603514dd7Ske ge - Sun Microsystems - Beijing China 			} else {
291703514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(30, "ibd_rc_act_close: ibt_close_rc_"
291803514dd7Ske ge - Sun Microsystems - Beijing China 				    "channel succ, chan=%p", chan);
291903514dd7Ske ge - Sun Microsystems - Beijing China 			}
292093c426a1Ske ge - Sun Microsystems - Beijing China 		}
292193c426a1Ske ge - Sun Microsystems - Beijing China 
292293c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_chan(chan);
292393c426a1Ske ge - Sun Microsystems - Beijing China 		break;
292493c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_ACT_REP_RECV:
292593c426a1Ske ge - Sun Microsystems - Beijing China 		chan->chan_state = IBD_RC_STATE_ACT_CLOSED;
292693c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibt_flush_channel(chan->chan_hdl);
292793c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_chan(chan);
292893c426a1Ske ge - Sun Microsystems - Beijing China 		break;
292993c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_ACT_ERROR:
293093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_act_close: IBD_RC_STATE_ERROR branch");
293193c426a1Ske ge - Sun Microsystems - Beijing China 		break;
293293c426a1Ske ge - Sun Microsystems - Beijing China 	default:
293393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_act_close: default branch, act_state=%d, "
293493c426a1Ske ge - Sun Microsystems - Beijing China 		    "chan=%p", chan->chan_state, chan);
293593c426a1Ske ge - Sun Microsystems - Beijing China 	}
293693c426a1Ske ge - Sun Microsystems - Beijing China }
293793c426a1Ske ge - Sun Microsystems - Beijing China 
293803514dd7Ske ge - Sun Microsystems - Beijing China /*
293903514dd7Ske ge - Sun Microsystems - Beijing China  * Close a passive channel
294003514dd7Ske ge - Sun Microsystems - Beijing China  *
294103514dd7Ske ge - Sun Microsystems - Beijing China  * is_close_rc_chan: if B_TRUE, we will call ibt_close_rc_channel()
294203514dd7Ske ge - Sun Microsystems - Beijing China  *
294303514dd7Ske ge - Sun Microsystems - Beijing China  * is_timeout_close: if B_TRUE, this function is called by the connection
294403514dd7Ske ge - Sun Microsystems - Beijing China  * reaper (refer to function ibd_rc_conn_timeout_call). When the connection
294503514dd7Ske ge - Sun Microsystems - Beijing China  * reaper calls ibd_rc_pas_close(), and if it finds that dl_bufs_outstanding
294603514dd7Ske ge - Sun Microsystems - Beijing China  * or chan->rcq_invoking is non-zero, then it can simply put that channel back
294703514dd7Ske ge - Sun Microsystems - Beijing China  * on the passive channels list and move on, since it might be an indication
294803514dd7Ske ge - Sun Microsystems - Beijing China  * that the channel became active again by the time we started it's cleanup.
294903514dd7Ske ge - Sun Microsystems - Beijing China  * It is costlier to do the cleanup and then reinitiate the channel
295003514dd7Ske ge - Sun Microsystems - Beijing China  * establishment and hence it will help to be conservative when we do the
295103514dd7Ske ge - Sun Microsystems - Beijing China  * cleanup.
295203514dd7Ske ge - Sun Microsystems - Beijing China  */
295303514dd7Ske ge - Sun Microsystems - Beijing China int
ibd_rc_pas_close(ibd_rc_chan_t * chan,boolean_t is_close_rc_chan,boolean_t is_timeout_close)295403514dd7Ske ge - Sun Microsystems - Beijing China ibd_rc_pas_close(ibd_rc_chan_t *chan, boolean_t is_close_rc_chan,
295503514dd7Ske ge - Sun Microsystems - Beijing China     boolean_t is_timeout_close)
295693c426a1Ske ge - Sun Microsystems - Beijing China {
295793c426a1Ske ge - Sun Microsystems - Beijing China 	uint_t times;
295893c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t ret;
295993c426a1Ske ge - Sun Microsystems - Beijing China 
296093c426a1Ske ge - Sun Microsystems - Beijing China 	ASSERT(chan != NULL);
296193c426a1Ske ge - Sun Microsystems - Beijing China 	chan->state->rc_pas_close++;
296293c426a1Ske ge - Sun Microsystems - Beijing China 
296393c426a1Ske ge - Sun Microsystems - Beijing China 	switch (chan->chan_state) {
296493c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_PAS_ESTAB:
296503514dd7Ske ge - Sun Microsystems - Beijing China 		if (is_timeout_close) {
296603514dd7Ske ge - Sun Microsystems - Beijing China 			if ((chan->rcq_invoking != 0) ||
296703514dd7Ske ge - Sun Microsystems - Beijing China 			    ((!chan->state->rc_enable_srq) &&
296803514dd7Ske ge - Sun Microsystems - Beijing China 			    (chan->rx_wqe_list.dl_bufs_outstanding > 0))) {
296903514dd7Ske ge - Sun Microsystems - Beijing China 				if (ibd_rc_re_add_to_pas_chan_list(chan)) {
297003514dd7Ske ge - Sun Microsystems - Beijing China 					return (DDI_FAILURE);
297103514dd7Ske ge - Sun Microsystems - Beijing China 				}
297203514dd7Ske ge - Sun Microsystems - Beijing China 			}
297303514dd7Ske ge - Sun Microsystems - Beijing China 		}
297493c426a1Ske ge - Sun Microsystems - Beijing China 		/*
297593c426a1Ske ge - Sun Microsystems - Beijing China 		 * First, stop receive interrupts; this stops the
297693c426a1Ske ge - Sun Microsystems - Beijing China 		 * connection from handing up buffers to higher layers.
297793c426a1Ske ge - Sun Microsystems - Beijing China 		 * Wait for receive buffers to be returned; give up
297893c426a1Ske ge - Sun Microsystems - Beijing China 		 * after 5 seconds.
297993c426a1Ske ge - Sun Microsystems - Beijing China 		 */
298093c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_set_cq_handler(chan->rcq_hdl, 0, 0);
298103514dd7Ske ge - Sun Microsystems - Beijing China 		/* Wait 0.01 second to let ibt_set_cq_handler() take effect */
298203514dd7Ske ge - Sun Microsystems - Beijing China 		delay(drv_usectohz(10000));
298393c426a1Ske ge - Sun Microsystems - Beijing China 		if (!chan->state->rc_enable_srq) {
298493c426a1Ske ge - Sun Microsystems - Beijing China 			times = 50;
298593c426a1Ske ge - Sun Microsystems - Beijing China 			while (chan->rx_wqe_list.dl_bufs_outstanding > 0) {
298693c426a1Ske ge - Sun Microsystems - Beijing China 				delay(drv_usectohz(100000));
298793c426a1Ske ge - Sun Microsystems - Beijing China 				if (--times == 0) {
298893c426a1Ske ge - Sun Microsystems - Beijing China 					DPRINT(40, "ibd_rc_pas_close : "
298993c426a1Ske ge - Sun Microsystems - Beijing China 					    "reclaiming failed");
299093c426a1Ske ge - Sun Microsystems - Beijing China 					ibd_rc_poll_rcq(chan, chan->rcq_hdl);
299193c426a1Ske ge - Sun Microsystems - Beijing China 					ibt_set_cq_handler(chan->rcq_hdl,
299293c426a1Ske ge - Sun Microsystems - Beijing China 					    ibd_rc_rcq_handler,
299393c426a1Ske ge - Sun Microsystems - Beijing China 					    (void *)(uintptr_t)chan);
299493c426a1Ske ge - Sun Microsystems - Beijing China 					return (DDI_FAILURE);
299593c426a1Ske ge - Sun Microsystems - Beijing China 				}
299693c426a1Ske ge - Sun Microsystems - Beijing China 			}
299793c426a1Ske ge - Sun Microsystems - Beijing China 		}
299803514dd7Ske ge - Sun Microsystems - Beijing China 		times = 50;
299903514dd7Ske ge - Sun Microsystems - Beijing China 		while (chan->rcq_invoking != 0) {
300003514dd7Ske ge - Sun Microsystems - Beijing China 			delay(drv_usectohz(100000));
300103514dd7Ske ge - Sun Microsystems - Beijing China 			if (--times == 0) {
300203514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_pas_close : "
300303514dd7Ske ge - Sun Microsystems - Beijing China 				    "rcq handler is being invoked");
300403514dd7Ske ge - Sun Microsystems - Beijing China 				chan->state->rc_pas_close_rcq_invoking++;
300503514dd7Ske ge - Sun Microsystems - Beijing China 				break;
300603514dd7Ske ge - Sun Microsystems - Beijing China 			}
300703514dd7Ske ge - Sun Microsystems - Beijing China 		}
300893c426a1Ske ge - Sun Microsystems - Beijing China 		ibt_set_cq_handler(chan->scq_hdl, 0, 0);
300993c426a1Ske ge - Sun Microsystems - Beijing China 		chan->chan_state = IBD_RC_STATE_PAS_CLOSED;
301093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_pas_close-1: close and free chan, "
301193c426a1Ske ge - Sun Microsystems - Beijing China 		    "chan_state=%d, chan=%p", chan->chan_state, chan);
301203514dd7Ske ge - Sun Microsystems - Beijing China 		if (is_close_rc_chan) {
301303514dd7Ske ge - Sun Microsystems - Beijing China 			ret = ibt_close_rc_channel(chan->chan_hdl,
301403514dd7Ske ge - Sun Microsystems - Beijing China 			    IBT_BLOCKING|IBT_NOCALLBACKS, NULL, 0, NULL, NULL,
301503514dd7Ske ge - Sun Microsystems - Beijing China 			    0);
301603514dd7Ske ge - Sun Microsystems - Beijing China 			if (ret != IBT_SUCCESS) {
301703514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_pas_close: ibt_close_rc_"
301803514dd7Ske ge - Sun Microsystems - Beijing China 				    "channel() fail, chan=%p, ret=%d", chan,
301903514dd7Ske ge - Sun Microsystems - Beijing China 				    ret);
302003514dd7Ske ge - Sun Microsystems - Beijing China 			} else {
302103514dd7Ske ge - Sun Microsystems - Beijing China 				DPRINT(30, "ibd_rc_pas_close: ibt_close_rc_"
302203514dd7Ske ge - Sun Microsystems - Beijing China 				    "channel() succ, chan=%p", chan);
302303514dd7Ske ge - Sun Microsystems - Beijing China 			}
302493c426a1Ske ge - Sun Microsystems - Beijing China 		}
302593c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_chan(chan);
302693c426a1Ske ge - Sun Microsystems - Beijing China 		break;
302793c426a1Ske ge - Sun Microsystems - Beijing China 	case IBD_RC_STATE_PAS_REQ_RECV:
302893c426a1Ske ge - Sun Microsystems - Beijing China 		chan->chan_state = IBD_RC_STATE_PAS_CLOSED;
302993c426a1Ske ge - Sun Microsystems - Beijing China 		(void) ibt_flush_channel(chan->chan_hdl);
303093c426a1Ske ge - Sun Microsystems - Beijing China 		ibd_rc_free_chan(chan);
303193c426a1Ske ge - Sun Microsystems - Beijing China 		break;
303293c426a1Ske ge - Sun Microsystems - Beijing China 	default:
303393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_pas_close: default, chan_state=%d, chan=%p",
303493c426a1Ske ge - Sun Microsystems - Beijing China 		    chan->chan_state, chan);
303593c426a1Ske ge - Sun Microsystems - Beijing China 	}
303693c426a1Ske ge - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
303793c426a1Ske ge - Sun Microsystems - Beijing China }
303893c426a1Ske ge - Sun Microsystems - Beijing China 
303993c426a1Ske ge - Sun Microsystems - Beijing China /*
304093c426a1Ske ge - Sun Microsystems - Beijing China  * Passive Side:
304193c426a1Ske ge - Sun Microsystems - Beijing China  *	Handle an incoming CM REQ from active side.
304293c426a1Ske ge - Sun Microsystems - Beijing China  *
304393c426a1Ske ge - Sun Microsystems - Beijing China  *	If success, this function allocates an ibd_rc_chan_t, then
304493c426a1Ske ge - Sun Microsystems - Beijing China  * assigns it to "*ret_conn".
304593c426a1Ske ge - Sun Microsystems - Beijing China  */
304693c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t
ibd_rc_handle_req(void * arg,ibd_rc_chan_t ** ret_conn,ibt_cm_event_t * ibt_cm_event,ibt_cm_return_args_t * ret_args,void * ret_priv_data)304793c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_handle_req(void *arg, ibd_rc_chan_t **ret_conn,
304893c426a1Ske ge - Sun Microsystems - Beijing China     ibt_cm_event_t *ibt_cm_event, ibt_cm_return_args_t *ret_args,
304993c426a1Ske ge - Sun Microsystems - Beijing China     void *ret_priv_data)
305093c426a1Ske ge - Sun Microsystems - Beijing China {
305193c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_msg_hello_t *hello_msg;
305293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state = (ibd_state_t *)arg;
305393c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan;
305493c426a1Ske ge - Sun Microsystems - Beijing China 
305593c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibd_rc_alloc_chan(&chan, state, B_FALSE) != IBT_SUCCESS) {
305693c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_handle_req: ibd_rc_alloc_chan() failed");
305793c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_CM_REJECT);
305893c426a1Ske ge - Sun Microsystems - Beijing China 	}
305993c426a1Ske ge - Sun Microsystems - Beijing China 
306093c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_add_to_chan_list(&state->rc_pass_chan_list, chan);
306193c426a1Ske ge - Sun Microsystems - Beijing China 
306293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_set_chan_private(chan->chan_hdl, (void *)(uintptr_t)chan);
306393c426a1Ske ge - Sun Microsystems - Beijing China 
306493c426a1Ske ge - Sun Microsystems - Beijing China 	if (!state->rc_enable_srq) {
306593c426a1Ske ge - Sun Microsystems - Beijing China 		if (ibd_rc_init_rxlist(chan) != DDI_SUCCESS) {
306693c426a1Ske ge - Sun Microsystems - Beijing China 			ibd_rc_free_chan(chan);
306793c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_handle_req: ibd_rc_init_rxlist() "
306893c426a1Ske ge - Sun Microsystems - Beijing China 			    "failed");
306993c426a1Ske ge - Sun Microsystems - Beijing China 			return (IBT_CM_REJECT);
307093c426a1Ske ge - Sun Microsystems - Beijing China 		}
307193c426a1Ske ge - Sun Microsystems - Beijing China 	}
307293c426a1Ske ge - Sun Microsystems - Beijing China 
307393c426a1Ske ge - Sun Microsystems - Beijing China 	ret_args->cm_ret.rep.cm_channel = chan->chan_hdl;
307493c426a1Ske ge - Sun Microsystems - Beijing China 
307593c426a1Ske ge - Sun Microsystems - Beijing China 	/* We don't do RDMA */
307693c426a1Ske ge - Sun Microsystems - Beijing China 	ret_args->cm_ret.rep.cm_rdma_ra_out = 0;
307793c426a1Ske ge - Sun Microsystems - Beijing China 	ret_args->cm_ret.rep.cm_rdma_ra_in = 0;
307893c426a1Ske ge - Sun Microsystems - Beijing China 
307993c426a1Ske ge - Sun Microsystems - Beijing China 	ret_args->cm_ret.rep.cm_rnr_retry_cnt = 7;
308093c426a1Ske ge - Sun Microsystems - Beijing China 	ret_args->cm_ret_len = sizeof (ibd_rc_msg_hello_t);
308193c426a1Ske ge - Sun Microsystems - Beijing China 
308293c426a1Ske ge - Sun Microsystems - Beijing China 	hello_msg = (ibd_rc_msg_hello_t *)ibt_cm_event->cm_priv_data;
308393c426a1Ske ge - Sun Microsystems - Beijing China 	DPRINT(30, "ibd_rc_handle_req(): peer qpn=0x%x, peer mtu=0x%x",
308493c426a1Ske ge - Sun Microsystems - Beijing China 	    ntohl(hello_msg->reserved_qpn), ntohl(hello_msg->rx_mtu));
308593c426a1Ske ge - Sun Microsystems - Beijing China 
308693c426a1Ske ge - Sun Microsystems - Beijing China 	hello_msg = (ibd_rc_msg_hello_t *)ret_priv_data;
308793c426a1Ske ge - Sun Microsystems - Beijing China 	hello_msg->reserved_qpn = htonl(state->id_qpnum);
308893c426a1Ske ge - Sun Microsystems - Beijing China 	hello_msg->rx_mtu = htonl(state->rc_mtu);
308993c426a1Ske ge - Sun Microsystems - Beijing China 
309093c426a1Ske ge - Sun Microsystems - Beijing China 	chan->chan_state = IBD_RC_STATE_PAS_REQ_RECV;	/* ready to receive */
309193c426a1Ske ge - Sun Microsystems - Beijing China 	*ret_conn = chan;
309293c426a1Ske ge - Sun Microsystems - Beijing China 
309393c426a1Ske ge - Sun Microsystems - Beijing China 	return (IBT_CM_ACCEPT);
309493c426a1Ske ge - Sun Microsystems - Beijing China }
309593c426a1Ske ge - Sun Microsystems - Beijing China 
309693c426a1Ske ge - Sun Microsystems - Beijing China /*
309793c426a1Ske ge - Sun Microsystems - Beijing China  * ibd_rc_handle_act_estab -- handler for connection established completion
309893c426a1Ske ge - Sun Microsystems - Beijing China  * for active side.
309993c426a1Ske ge - Sun Microsystems - Beijing China  */
310093c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t
ibd_rc_handle_act_estab(ibd_ace_t * ace)310193c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_handle_act_estab(ibd_ace_t *ace)
310293c426a1Ske ge - Sun Microsystems - Beijing China {
310393c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t result;
310493c426a1Ske ge - Sun Microsystems - Beijing China 
310593c426a1Ske ge - Sun Microsystems - Beijing China 	switch (ace->ac_chan->chan_state) {
310693c426a1Ske ge - Sun Microsystems - Beijing China 		case IBD_RC_STATE_ACT_REP_RECV:
310793c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_chan->chan_state = IBD_RC_STATE_ACT_ESTAB;
310893c426a1Ske ge - Sun Microsystems - Beijing China 			result = ibt_enable_cq_notify(ace->ac_chan->rcq_hdl,
310993c426a1Ske ge - Sun Microsystems - Beijing China 			    IBT_NEXT_COMPLETION);
311093c426a1Ske ge - Sun Microsystems - Beijing China 			if (result != IBT_SUCCESS) {
311193c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_handle_act_estab: "
311293c426a1Ske ge - Sun Microsystems - Beijing China 				    "ibt_enable_cq_notify(rcq) "
311393c426a1Ske ge - Sun Microsystems - Beijing China 				    "failed: status %d", result);
311493c426a1Ske ge - Sun Microsystems - Beijing China 				return (IBT_CM_REJECT);
311593c426a1Ske ge - Sun Microsystems - Beijing China 			}
311693c426a1Ske ge - Sun Microsystems - Beijing China 			break;
311793c426a1Ske ge - Sun Microsystems - Beijing China 		default:
311893c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_handle_act_estab: default "
311993c426a1Ske ge - Sun Microsystems - Beijing China 			    "branch, act_state=%d", ace->ac_chan->chan_state);
312093c426a1Ske ge - Sun Microsystems - Beijing China 			return (IBT_CM_REJECT);
312193c426a1Ske ge - Sun Microsystems - Beijing China 	}
312293c426a1Ske ge - Sun Microsystems - Beijing China 	return (IBT_CM_ACCEPT);
312393c426a1Ske ge - Sun Microsystems - Beijing China }
312493c426a1Ske ge - Sun Microsystems - Beijing China 
312593c426a1Ske ge - Sun Microsystems - Beijing China /*
312693c426a1Ske ge - Sun Microsystems - Beijing China  * ibd_rc_handle_pas_estab -- handler for connection established completion
312793c426a1Ske ge - Sun Microsystems - Beijing China  * for passive side.
312893c426a1Ske ge - Sun Microsystems - Beijing China  */
312993c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t
ibd_rc_handle_pas_estab(ibd_rc_chan_t * chan)313093c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_handle_pas_estab(ibd_rc_chan_t *chan)
313193c426a1Ske ge - Sun Microsystems - Beijing China {
313293c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_status_t result;
313393c426a1Ske ge - Sun Microsystems - Beijing China 
313493c426a1Ske ge - Sun Microsystems - Beijing China 	switch (chan->chan_state) {
313593c426a1Ske ge - Sun Microsystems - Beijing China 		case IBD_RC_STATE_PAS_REQ_RECV:
313693c426a1Ske ge - Sun Microsystems - Beijing China 			chan->chan_state = IBD_RC_STATE_PAS_ESTAB;
313793c426a1Ske ge - Sun Microsystems - Beijing China 
313893c426a1Ske ge - Sun Microsystems - Beijing China 			result = ibt_enable_cq_notify(chan->rcq_hdl,
313993c426a1Ske ge - Sun Microsystems - Beijing China 			    IBT_NEXT_COMPLETION);
314093c426a1Ske ge - Sun Microsystems - Beijing China 			if (result != IBT_SUCCESS) {
314193c426a1Ske ge - Sun Microsystems - Beijing China 				DPRINT(40, "ibd_rc_handle_pas_estab: "
314293c426a1Ske ge - Sun Microsystems - Beijing China 				    "ibt_enable_cq_notify(rcq) "
314393c426a1Ske ge - Sun Microsystems - Beijing China 				    "failed: status %d", result);
314493c426a1Ske ge - Sun Microsystems - Beijing China 				return (IBT_CM_REJECT);
314593c426a1Ske ge - Sun Microsystems - Beijing China 			}
314693c426a1Ske ge - Sun Microsystems - Beijing China 			break;
314793c426a1Ske ge - Sun Microsystems - Beijing China 		default:
314893c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_handle_pas_estab: default "
314993c426a1Ske ge - Sun Microsystems - Beijing China 			    "branch, chan_state=%d", chan->chan_state);
315093c426a1Ske ge - Sun Microsystems - Beijing China 			return (IBT_CM_REJECT);
315193c426a1Ske ge - Sun Microsystems - Beijing China 	}
315293c426a1Ske ge - Sun Microsystems - Beijing China 	return (IBT_CM_ACCEPT);
315393c426a1Ske ge - Sun Microsystems - Beijing China }
315493c426a1Ske ge - Sun Microsystems - Beijing China 
315593c426a1Ske ge - Sun Microsystems - Beijing China /* ARGSUSED */
315693c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t
ibd_rc_dispatch_actv_mad(void * arg,ibt_cm_event_t * ibt_cm_event,ibt_cm_return_args_t * ret_args,void * ret_priv_data,ibt_priv_data_len_t ret_len_max)315793c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_dispatch_actv_mad(void *arg, ibt_cm_event_t *ibt_cm_event,
315893c426a1Ske ge - Sun Microsystems - Beijing China     ibt_cm_return_args_t *ret_args, void *ret_priv_data,
315993c426a1Ske ge - Sun Microsystems - Beijing China     ibt_priv_data_len_t ret_len_max)
316093c426a1Ske ge - Sun Microsystems - Beijing China {
316193c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_cm_status_t result = IBT_CM_ACCEPT;
316293c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_ace_t *ace = (ibd_ace_t *)(uintptr_t)arg;
316393c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *rc_chan;
316493c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_state_t *state;
316593c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_msg_hello_t *hello_ack;
316693c426a1Ske ge - Sun Microsystems - Beijing China 
316793c426a1Ske ge - Sun Microsystems - Beijing China 	switch (ibt_cm_event->cm_type) {
316893c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_REP_RCV:
316993c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace->ac_chan != NULL);
317093c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace->ac_chan->chan_state == IBD_RC_STATE_INIT);
317193c426a1Ske ge - Sun Microsystems - Beijing China 		hello_ack = (ibd_rc_msg_hello_t *)ibt_cm_event->cm_priv_data;
317293c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_handle_rep: hello_ack->mtu=0x%x, "
317393c426a1Ske ge - Sun Microsystems - Beijing China 		    "hello_ack->qpn=0x%x", ntohl(hello_ack->rx_mtu),
317493c426a1Ske ge - Sun Microsystems - Beijing China 		    ntohl(hello_ack->reserved_qpn));
317593c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_chan->chan_state = IBD_RC_STATE_ACT_REP_RECV;
317693c426a1Ske ge - Sun Microsystems - Beijing China 		break;
317793c426a1Ske ge - Sun Microsystems - Beijing China 
317893c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_CONN_EST:
317993c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace->ac_chan != NULL);
318093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_actv_mad: IBT_CM_EVENT_CONN_EST, "
318193c426a1Ske ge - Sun Microsystems - Beijing China 		    "ace=%p, act_state=%d, chan=%p",
318293c426a1Ske ge - Sun Microsystems - Beijing China 		    ace, ace->ac_chan->chan_state, ace->ac_chan);
318393c426a1Ske ge - Sun Microsystems - Beijing China 		result = ibd_rc_handle_act_estab(ace);
318493c426a1Ske ge - Sun Microsystems - Beijing China 		break;
318593c426a1Ske ge - Sun Microsystems - Beijing China 
318693c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_CONN_CLOSED:
318793c426a1Ske ge - Sun Microsystems - Beijing China 		rc_chan = ace->ac_chan;
318893c426a1Ske ge - Sun Microsystems - Beijing China 		if (rc_chan == NULL) {
318993c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_dispatch_actv_mad: "
319093c426a1Ske ge - Sun Microsystems - Beijing China 			    "rc_chan==NULL, IBT_CM_EVENT_CONN_CLOSED");
319193c426a1Ske ge - Sun Microsystems - Beijing China 			return (IBT_CM_ACCEPT);
319293c426a1Ske ge - Sun Microsystems - Beijing China 		}
319393c426a1Ske ge - Sun Microsystems - Beijing China 		state = rc_chan->state;
319493c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->id_ac_mutex);
319593c426a1Ske ge - Sun Microsystems - Beijing China 		if ((rc_chan->chan_state == IBD_RC_STATE_ACT_ESTAB) &&
319693c426a1Ske ge - Sun Microsystems - Beijing China 		    ((ace = ibd_acache_find(state, &ace->ac_mac, B_FALSE, 0))
319793c426a1Ske ge - Sun Microsystems - Beijing China 		    != NULL) && (ace == rc_chan->ace)) {
319893c426a1Ske ge - Sun Microsystems - Beijing China 			rc_chan->chan_state = IBD_RC_STATE_ACT_CLOSING;
319993c426a1Ske ge - Sun Microsystems - Beijing China 			ASSERT(ace->ac_mce == NULL);
320093c426a1Ske ge - Sun Microsystems - Beijing China 			INC_REF(ace, 1);
320193c426a1Ske ge - Sun Microsystems - Beijing China 			IBD_ACACHE_PULLOUT_ACTIVE(state, ace);
320293c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_ac_mutex);
320393c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(30, "ibd_rc_dispatch_actv_mad: "
320493c426a1Ske ge - Sun Microsystems - Beijing China 			    "IBT_CM_EVENT_CONN_CLOSED, ace=%p, chan=%p, "
320593c426a1Ske ge - Sun Microsystems - Beijing China 			    "reason=%d", ace, rc_chan,
320693c426a1Ske ge - Sun Microsystems - Beijing China 			    ibt_cm_event->cm_event.closed);
320793c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
320893c426a1Ske ge - Sun Microsystems - Beijing China 			mutex_exit(&state->id_ac_mutex);
320993c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_act_close_simultaneous++;
321093c426a1Ske ge - Sun Microsystems - Beijing China 			DPRINT(40, "ibd_rc_dispatch_actv_mad: other thread "
321193c426a1Ske ge - Sun Microsystems - Beijing China 			    "is closing it, IBT_CM_EVENT_CONN_CLOSED, "
321293c426a1Ske ge - Sun Microsystems - Beijing China 			    "chan_state=%d", rc_chan->chan_state);
321393c426a1Ske ge - Sun Microsystems - Beijing China 			return (IBT_CM_ACCEPT);
321493c426a1Ske ge - Sun Microsystems - Beijing China 		}
321503514dd7Ske ge - Sun Microsystems - Beijing China 		ibd_rc_act_close(rc_chan, B_FALSE);
321693c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_enter(&state->id_ac_mutex);
321793c426a1Ske ge - Sun Microsystems - Beijing China 		ace->ac_chan = NULL;
321893c426a1Ske ge - Sun Microsystems - Beijing China 		ASSERT(ace->ac_ref != 0);
321993c426a1Ske ge - Sun Microsystems - Beijing China 		atomic_dec_32(&ace->ac_ref);
322093c426a1Ske ge - Sun Microsystems - Beijing China 		if ((ace->ac_ref == 0) || (ace->ac_ref == CYCLEVAL)) {
322193c426a1Ske ge - Sun Microsystems - Beijing China 			IBD_ACACHE_INSERT_FREE(state, ace);
322293c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_ref = 0;
322393c426a1Ske ge - Sun Microsystems - Beijing China 		} else {
322493c426a1Ske ge - Sun Microsystems - Beijing China 			ace->ac_ref |= CYCLEVAL;
322593c426a1Ske ge - Sun Microsystems - Beijing China 			state->rc_delay_ace_recycle++;
322693c426a1Ske ge - Sun Microsystems - Beijing China 		}
322793c426a1Ske ge - Sun Microsystems - Beijing China 		mutex_exit(&state->id_ac_mutex);
322893c426a1Ske ge - Sun Microsystems - Beijing China 		break;
322993c426a1Ske ge - Sun Microsystems - Beijing China 
323093c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_FAILURE:
323193c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_actv_mad: IBT_CM_EVENT_FAILURE,"
323293c426a1Ske ge - Sun Microsystems - Beijing China 		    "ace=%p, chan=%p, code: %d, msg: %d, reason=%d",
323393c426a1Ske ge - Sun Microsystems - Beijing China 		    ace, ace->ac_chan,
323493c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_code,
323593c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_msg,
323693c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_reason);
323793c426a1Ske ge - Sun Microsystems - Beijing China 		/*
323893c426a1Ske ge - Sun Microsystems - Beijing China 		 * Don't need free resource here. The resource is freed
323993c426a1Ske ge - Sun Microsystems - Beijing China 		 * at function ibd_rc_connect()
324093c426a1Ske ge - Sun Microsystems - Beijing China 		 */
324193c426a1Ske ge - Sun Microsystems - Beijing China 		break;
324293c426a1Ske ge - Sun Microsystems - Beijing China 
324393c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_MRA_RCV:
324493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_actv_mad: IBT_CM_EVENT_MRA_RCV");
324593c426a1Ske ge - Sun Microsystems - Beijing China 		break;
324693c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_LAP_RCV:
324793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_actv_mad: LAP message received");
324893c426a1Ske ge - Sun Microsystems - Beijing China 		break;
324993c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_APR_RCV:
325093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_actv_mad: APR message received");
325193c426a1Ske ge - Sun Microsystems - Beijing China 		break;
325293c426a1Ske ge - Sun Microsystems - Beijing China 	default:
325393c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_actv_mad: default branch, "
325493c426a1Ske ge - Sun Microsystems - Beijing China 		    "ibt_cm_event->cm_type=%d", ibt_cm_event->cm_type);
325593c426a1Ske ge - Sun Microsystems - Beijing China 		break;
325693c426a1Ske ge - Sun Microsystems - Beijing China 	}
325793c426a1Ske ge - Sun Microsystems - Beijing China 
325893c426a1Ske ge - Sun Microsystems - Beijing China 	return (result);
325993c426a1Ske ge - Sun Microsystems - Beijing China }
326093c426a1Ske ge - Sun Microsystems - Beijing China 
326193c426a1Ske ge - Sun Microsystems - Beijing China /* ARGSUSED */
326293c426a1Ske ge - Sun Microsystems - Beijing China static ibt_cm_status_t
ibd_rc_dispatch_pass_mad(void * arg,ibt_cm_event_t * ibt_cm_event,ibt_cm_return_args_t * ret_args,void * ret_priv_data,ibt_priv_data_len_t ret_len_max)326393c426a1Ske ge - Sun Microsystems - Beijing China ibd_rc_dispatch_pass_mad(void *arg, ibt_cm_event_t *ibt_cm_event,
326493c426a1Ske ge - Sun Microsystems - Beijing China     ibt_cm_return_args_t *ret_args, void *ret_priv_data,
326593c426a1Ske ge - Sun Microsystems - Beijing China     ibt_priv_data_len_t ret_len_max)
326693c426a1Ske ge - Sun Microsystems - Beijing China {
326793c426a1Ske ge - Sun Microsystems - Beijing China 	ibt_cm_status_t result = IBT_CM_ACCEPT;
326893c426a1Ske ge - Sun Microsystems - Beijing China 	ibd_rc_chan_t *chan;
326993c426a1Ske ge - Sun Microsystems - Beijing China 
327093c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_cm_event->cm_type == IBT_CM_EVENT_REQ_RCV) {
327193c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_pass_mad: IBT_CM_EVENT_REQ_RCV,"
327293c426a1Ske ge - Sun Microsystems - Beijing China 		    "req_pkey=%x", ibt_cm_event->cm_event.req.req_pkey);
327393c426a1Ske ge - Sun Microsystems - Beijing China 		/* Receive an incoming CM REQ from active side */
327493c426a1Ske ge - Sun Microsystems - Beijing China 		result = ibd_rc_handle_req(arg, &chan, ibt_cm_event, ret_args,
327593c426a1Ske ge - Sun Microsystems - Beijing China 		    ret_priv_data);
327693c426a1Ske ge - Sun Microsystems - Beijing China 		return (result);
327793c426a1Ske ge - Sun Microsystems - Beijing China 	}
327893c426a1Ske ge - Sun Microsystems - Beijing China 
327993c426a1Ske ge - Sun Microsystems - Beijing China 	if (ibt_cm_event->cm_channel == 0) {
328093c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_pass_mad: "
328193c426a1Ske ge - Sun Microsystems - Beijing China 		    "ERROR ibt_cm_event->cm_channel == 0");
328293c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_CM_REJECT);
328393c426a1Ske ge - Sun Microsystems - Beijing China 	}
328493c426a1Ske ge - Sun Microsystems - Beijing China 
328593c426a1Ske ge - Sun Microsystems - Beijing China 	chan =
328693c426a1Ske ge - Sun Microsystems - Beijing China 	    (ibd_rc_chan_t *)ibt_get_chan_private(ibt_cm_event->cm_channel);
328793c426a1Ske ge - Sun Microsystems - Beijing China 	if (chan == NULL) {
328893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_pass_mad: conn == 0");
328993c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_CM_REJECT);
329093c426a1Ske ge - Sun Microsystems - Beijing China 	}
329193c426a1Ske ge - Sun Microsystems - Beijing China 
329293c426a1Ske ge - Sun Microsystems - Beijing China 	switch (ibt_cm_event->cm_type) {
329393c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_CONN_EST:
329493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_pass_mad: IBT_CM_EVENT_CONN_EST, "
329593c426a1Ske ge - Sun Microsystems - Beijing China 		    "chan=%p", chan);
329693c426a1Ske ge - Sun Microsystems - Beijing China 		result = ibd_rc_handle_pas_estab(chan);
329793c426a1Ske ge - Sun Microsystems - Beijing China 		break;
329893c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_CONN_CLOSED:
329993c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_pass_mad: IBT_CM_EVENT_CONN_CLOSED,"
330093c426a1Ske ge - Sun Microsystems - Beijing China 		    " chan=%p, reason=%d", chan, ibt_cm_event->cm_event.closed);
330103514dd7Ske ge - Sun Microsystems - Beijing China 		chan = ibd_rc_rm_from_chan_list(&chan->state->rc_pass_chan_list,
330203514dd7Ske ge - Sun Microsystems - Beijing China 		    chan);
330303514dd7Ske ge - Sun Microsystems - Beijing China 		if (chan != NULL)
330403514dd7Ske ge - Sun Microsystems - Beijing China 			(void) ibd_rc_pas_close(chan, B_FALSE, B_FALSE);
330593c426a1Ske ge - Sun Microsystems - Beijing China 		break;
330693c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_FAILURE:
330793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(30, "ibd_rc_dispatch_pass_mad: IBT_CM_EVENT_FAILURE,"
330893c426a1Ske ge - Sun Microsystems - Beijing China 		    " chan=%p, code: %d, msg: %d, reason=%d", chan,
330993c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_code,
331093c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_msg,
331193c426a1Ske ge - Sun Microsystems - Beijing China 		    ibt_cm_event->cm_event.failed.cf_reason);
331203514dd7Ske ge - Sun Microsystems - Beijing China 		chan = ibd_rc_rm_from_chan_list(&chan->state->rc_pass_chan_list,
331303514dd7Ske ge - Sun Microsystems - Beijing China 		    chan);
331403514dd7Ske ge - Sun Microsystems - Beijing China 		if (chan != NULL)
331503514dd7Ske ge - Sun Microsystems - Beijing China 			(void) ibd_rc_pas_close(chan, B_FALSE, B_FALSE);
331693c426a1Ske ge - Sun Microsystems - Beijing China 		return (IBT_CM_ACCEPT);
331793c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_MRA_RCV:
331893c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_pass_mad: IBT_CM_EVENT_MRA_RCV");
331993c426a1Ske ge - Sun Microsystems - Beijing China 		break;
332093c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_LAP_RCV:
332193c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_pass_mad: LAP message received");
332293c426a1Ske ge - Sun Microsystems - Beijing China 		break;
332393c426a1Ske ge - Sun Microsystems - Beijing China 	case IBT_CM_EVENT_APR_RCV:
332493c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_pass_mad: APR message received");
332593c426a1Ske ge - Sun Microsystems - Beijing China 		break;
332693c426a1Ske ge - Sun Microsystems - Beijing China 	default:
332793c426a1Ske ge - Sun Microsystems - Beijing China 		DPRINT(40, "ibd_rc_dispatch_pass_mad: default, type=%d, "
332893c426a1Ske ge - Sun Microsystems - Beijing China 		    "chan=%p", ibt_cm_event->cm_type, chan);
332993c426a1Ske ge - Sun Microsystems - Beijing China 		break;
333093c426a1Ske ge - Sun Microsystems - Beijing China 	}
333193c426a1Ske ge - Sun Microsystems - Beijing China 
333293c426a1Ske ge - Sun Microsystems - Beijing China 	return (result);
333393c426a1Ske ge - Sun Microsystems - Beijing China }
3334