xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/enx_q.c (revision 13101:da7b13ec3a28)
1*13101SVenki.Rajagopalan@Sun.COM /*
2*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER START
3*13101SVenki.Rajagopalan@Sun.COM  *
4*13101SVenki.Rajagopalan@Sun.COM  * The contents of this file are subject to the terms of the
5*13101SVenki.Rajagopalan@Sun.COM  * Common Development and Distribution License (the "License").
6*13101SVenki.Rajagopalan@Sun.COM  * You may not use this file except in compliance with the License.
7*13101SVenki.Rajagopalan@Sun.COM  *
8*13101SVenki.Rajagopalan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13101SVenki.Rajagopalan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*13101SVenki.Rajagopalan@Sun.COM  * See the License for the specific language governing permissions
11*13101SVenki.Rajagopalan@Sun.COM  * and limitations under the License.
12*13101SVenki.Rajagopalan@Sun.COM  *
13*13101SVenki.Rajagopalan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13101SVenki.Rajagopalan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13101SVenki.Rajagopalan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13101SVenki.Rajagopalan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13101SVenki.Rajagopalan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13101SVenki.Rajagopalan@Sun.COM  *
19*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER END
20*13101SVenki.Rajagopalan@Sun.COM  */
21*13101SVenki.Rajagopalan@Sun.COM 
22*13101SVenki.Rajagopalan@Sun.COM /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13101SVenki.Rajagopalan@Sun.COM  */
25*13101SVenki.Rajagopalan@Sun.COM 
26*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
27*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
32*13101SVenki.Rajagopalan@Sun.COM 
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/enx_impl.h>
34*13101SVenki.Rajagopalan@Sun.COM 
35*13101SVenki.Rajagopalan@Sun.COM /*
36*13101SVenki.Rajagopalan@Sun.COM  * Acquire an SWQE
37*13101SVenki.Rajagopalan@Sun.COM  */
38*13101SVenki.Rajagopalan@Sun.COM 
39*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
40*13101SVenki.Rajagopalan@Sun.COM eibnx_wqe_t *
eibnx_acquire_swqe(eibnx_thr_info_t * info,int flag)41*13101SVenki.Rajagopalan@Sun.COM eibnx_acquire_swqe(eibnx_thr_info_t *info, int flag)
42*13101SVenki.Rajagopalan@Sun.COM {
43*13101SVenki.Rajagopalan@Sun.COM 	eibnx_wqe_t *wqe = NULL;
44*13101SVenki.Rajagopalan@Sun.COM 	eibnx_tx_t *snd_p = &info->ti_snd;
45*13101SVenki.Rajagopalan@Sun.COM 	int i;
46*13101SVenki.Rajagopalan@Sun.COM 
47*13101SVenki.Rajagopalan@Sun.COM 	for (i = 0; i < ENX_NUM_SWQE; i++) {
48*13101SVenki.Rajagopalan@Sun.COM 		wqe = &(snd_p->tx_wqe[i]);
49*13101SVenki.Rajagopalan@Sun.COM 
50*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&wqe->qe_lock);
51*13101SVenki.Rajagopalan@Sun.COM 		if ((wqe->qe_flags & ENX_QEFL_INUSE) == 0) {
52*13101SVenki.Rajagopalan@Sun.COM 			wqe->qe_flags |= ENX_QEFL_INUSE;
53*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&wqe->qe_lock);
54*13101SVenki.Rajagopalan@Sun.COM 			break;
55*13101SVenki.Rajagopalan@Sun.COM 		}
56*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&wqe->qe_lock);
57*13101SVenki.Rajagopalan@Sun.COM 	}
58*13101SVenki.Rajagopalan@Sun.COM 
59*13101SVenki.Rajagopalan@Sun.COM 	/*
60*13101SVenki.Rajagopalan@Sun.COM 	 * We probably have enough swqe entries for doing our solicitations.
61*13101SVenki.Rajagopalan@Sun.COM 	 * If we find it not enough in practice, we need to implement some
62*13101SVenki.Rajagopalan@Sun.COM 	 * sort of dynamic allocation.
63*13101SVenki.Rajagopalan@Sun.COM 	 */
64*13101SVenki.Rajagopalan@Sun.COM 	if (i == ENX_NUM_SWQE)
65*13101SVenki.Rajagopalan@Sun.COM 		wqe = NULL;
66*13101SVenki.Rajagopalan@Sun.COM 
67*13101SVenki.Rajagopalan@Sun.COM 	return (wqe);
68*13101SVenki.Rajagopalan@Sun.COM }
69*13101SVenki.Rajagopalan@Sun.COM 
70*13101SVenki.Rajagopalan@Sun.COM /*
71*13101SVenki.Rajagopalan@Sun.COM  * Return a SWQE from completion. We may have to release
72*13101SVenki.Rajagopalan@Sun.COM  * it or keep it.
73*13101SVenki.Rajagopalan@Sun.COM  */
74*13101SVenki.Rajagopalan@Sun.COM void
eibnx_return_swqe(eibnx_wqe_t * wqe)75*13101SVenki.Rajagopalan@Sun.COM eibnx_return_swqe(eibnx_wqe_t *wqe)
76*13101SVenki.Rajagopalan@Sun.COM {
77*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(wqe->qe_type == ENX_QETYP_SWQE);
78*13101SVenki.Rajagopalan@Sun.COM 
79*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&wqe->qe_lock);
80*13101SVenki.Rajagopalan@Sun.COM 
81*13101SVenki.Rajagopalan@Sun.COM 	/*
82*13101SVenki.Rajagopalan@Sun.COM 	 * This send wqe is from the completion queue.  We need to
83*13101SVenki.Rajagopalan@Sun.COM 	 * clear the 'posted' flag first.
84*13101SVenki.Rajagopalan@Sun.COM 	 */
85*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((wqe->qe_flags & ENX_QEFL_POSTED) == ENX_QEFL_POSTED);
86*13101SVenki.Rajagopalan@Sun.COM 	wqe->qe_flags &= (~ENX_QEFL_POSTED);
87*13101SVenki.Rajagopalan@Sun.COM 
88*13101SVenki.Rajagopalan@Sun.COM 	/*
89*13101SVenki.Rajagopalan@Sun.COM 	 * See if we need to release this send wqe back to the pool
90*13101SVenki.Rajagopalan@Sun.COM 	 * on completion. We may not need to do so if, for example,
91*13101SVenki.Rajagopalan@Sun.COM 	 * this were a swqe acquired specifically for a particular gw.
92*13101SVenki.Rajagopalan@Sun.COM 	 */
93*13101SVenki.Rajagopalan@Sun.COM 	if (wqe->qe_flags & ENX_QEFL_RELONCOMP) {
94*13101SVenki.Rajagopalan@Sun.COM 		wqe->qe_sgl.ds_len = wqe->qe_bufsz;
95*13101SVenki.Rajagopalan@Sun.COM 		wqe->qe_flags &= (~ENX_QEFL_INUSE);
96*13101SVenki.Rajagopalan@Sun.COM 
97*13101SVenki.Rajagopalan@Sun.COM 		wqe->qe_flags &= (~ENX_QEFL_RELONCOMP);
98*13101SVenki.Rajagopalan@Sun.COM 	}
99*13101SVenki.Rajagopalan@Sun.COM 
100*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&wqe->qe_lock);
101*13101SVenki.Rajagopalan@Sun.COM }
102*13101SVenki.Rajagopalan@Sun.COM 
103*13101SVenki.Rajagopalan@Sun.COM /*
104*13101SVenki.Rajagopalan@Sun.COM  * Return a RWQE from completion. We probably have to repost it.
105*13101SVenki.Rajagopalan@Sun.COM  */
106*13101SVenki.Rajagopalan@Sun.COM void
eibnx_return_rwqe(eibnx_thr_info_t * info,eibnx_wqe_t * wqe)107*13101SVenki.Rajagopalan@Sun.COM eibnx_return_rwqe(eibnx_thr_info_t *info, eibnx_wqe_t *wqe)
108*13101SVenki.Rajagopalan@Sun.COM {
109*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
110*13101SVenki.Rajagopalan@Sun.COM 
111*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(wqe->qe_type == ENX_QETYP_RWQE);
112*13101SVenki.Rajagopalan@Sun.COM 
113*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&wqe->qe_lock);
114*13101SVenki.Rajagopalan@Sun.COM 
115*13101SVenki.Rajagopalan@Sun.COM 	/*
116*13101SVenki.Rajagopalan@Sun.COM 	 * We should never need to free an rwqe on completion.
117*13101SVenki.Rajagopalan@Sun.COM 	 */
118*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((wqe->qe_flags & ENX_QEFL_RELONCOMP) == 0);
119*13101SVenki.Rajagopalan@Sun.COM 
120*13101SVenki.Rajagopalan@Sun.COM 	/*
121*13101SVenki.Rajagopalan@Sun.COM 	 * An rwqe is always in-use and posted, so we only need to make
122*13101SVenki.Rajagopalan@Sun.COM 	 * sure the ds_len is adjusted back to the value it's supposed
123*13101SVenki.Rajagopalan@Sun.COM 	 * to have.
124*13101SVenki.Rajagopalan@Sun.COM 	 */
125*13101SVenki.Rajagopalan@Sun.COM 	wqe->qe_sgl.ds_len = wqe->qe_bufsz;
126*13101SVenki.Rajagopalan@Sun.COM 
127*13101SVenki.Rajagopalan@Sun.COM 	/*
128*13101SVenki.Rajagopalan@Sun.COM 	 * Repost the recv wqe
129*13101SVenki.Rajagopalan@Sun.COM 	 */
130*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_post_recv(info->ti_chan, &(wqe->qe_wr.recv), 1, NULL);
131*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
132*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt_post_recv(chan_hdl=0x%llx) failed, "
133*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", info->ti_chan, ret);
134*13101SVenki.Rajagopalan@Sun.COM 	}
135*13101SVenki.Rajagopalan@Sun.COM 
136*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&wqe->qe_lock);
137*13101SVenki.Rajagopalan@Sun.COM }
138*13101SVenki.Rajagopalan@Sun.COM 
139*13101SVenki.Rajagopalan@Sun.COM /*
140*13101SVenki.Rajagopalan@Sun.COM  * Release an SWQE that was acquired earlier.
141*13101SVenki.Rajagopalan@Sun.COM  */
142*13101SVenki.Rajagopalan@Sun.COM void
eibnx_release_swqe(eibnx_wqe_t * wqe)143*13101SVenki.Rajagopalan@Sun.COM eibnx_release_swqe(eibnx_wqe_t *wqe)
144*13101SVenki.Rajagopalan@Sun.COM {
145*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(wqe->qe_type == ENX_QETYP_SWQE);
146*13101SVenki.Rajagopalan@Sun.COM 
147*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&wqe->qe_lock);
148*13101SVenki.Rajagopalan@Sun.COM 
149*13101SVenki.Rajagopalan@Sun.COM 	/*
150*13101SVenki.Rajagopalan@Sun.COM 	 * Make sure this swqe is in use. Since this routine may also be
151*13101SVenki.Rajagopalan@Sun.COM 	 * called when we're trying to cleanup the eoib nodes, we
152*13101SVenki.Rajagopalan@Sun.COM 	 * should clear all flag bits.
153*13101SVenki.Rajagopalan@Sun.COM 	 */
154*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((wqe->qe_flags & ENX_QEFL_INUSE) == ENX_QEFL_INUSE);
155*13101SVenki.Rajagopalan@Sun.COM 	wqe->qe_flags = 0;
156*13101SVenki.Rajagopalan@Sun.COM 
157*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&wqe->qe_lock);
158*13101SVenki.Rajagopalan@Sun.COM }
159*13101SVenki.Rajagopalan@Sun.COM 
160*13101SVenki.Rajagopalan@Sun.COM /*
161*13101SVenki.Rajagopalan@Sun.COM  * Insert the passed child to the head of the queue
162*13101SVenki.Rajagopalan@Sun.COM  */
163*13101SVenki.Rajagopalan@Sun.COM void
eibnx_enqueue_child(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi,char * node_name,dev_info_t * dip)164*13101SVenki.Rajagopalan@Sun.COM eibnx_enqueue_child(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi,
165*13101SVenki.Rajagopalan@Sun.COM     char *node_name, dev_info_t *dip)
166*13101SVenki.Rajagopalan@Sun.COM {
167*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *ch;
168*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *new_ch;
169*13101SVenki.Rajagopalan@Sun.COM 
170*13101SVenki.Rajagopalan@Sun.COM 	new_ch = kmem_zalloc(sizeof (eibnx_child_t), KM_SLEEP);
171*13101SVenki.Rajagopalan@Sun.COM 	new_ch->ch_dip = dip;
172*13101SVenki.Rajagopalan@Sun.COM 	new_ch->ch_node_name = node_name;
173*13101SVenki.Rajagopalan@Sun.COM 	new_ch->ch_gwi = gwi;
174*13101SVenki.Rajagopalan@Sun.COM 
175*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_child_lock);
176*13101SVenki.Rajagopalan@Sun.COM 
177*13101SVenki.Rajagopalan@Sun.COM 	/*
178*13101SVenki.Rajagopalan@Sun.COM 	 * Search existing children to see if we already have this
179*13101SVenki.Rajagopalan@Sun.COM 	 * child.  If so, simply update its dip and node_name
180*13101SVenki.Rajagopalan@Sun.COM 	 */
181*13101SVenki.Rajagopalan@Sun.COM 	for (ch = info->ti_child; ch; ch = ch->ch_next) {
182*13101SVenki.Rajagopalan@Sun.COM 		if (ch->ch_gwi->gw_portid == gwi->gw_portid) {
183*13101SVenki.Rajagopalan@Sun.COM 			ch->ch_dip = dip;
184*13101SVenki.Rajagopalan@Sun.COM 			if (ch->ch_node_name) {
185*13101SVenki.Rajagopalan@Sun.COM 				kmem_free(ch->ch_node_name, MAXNAMELEN);
186*13101SVenki.Rajagopalan@Sun.COM 			}
187*13101SVenki.Rajagopalan@Sun.COM 			ch->ch_node_name = node_name;
188*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(new_ch, sizeof (eibnx_child_t));
189*13101SVenki.Rajagopalan@Sun.COM 			return;
190*13101SVenki.Rajagopalan@Sun.COM 		}
191*13101SVenki.Rajagopalan@Sun.COM 	}
192*13101SVenki.Rajagopalan@Sun.COM 
193*13101SVenki.Rajagopalan@Sun.COM 	/*
194*13101SVenki.Rajagopalan@Sun.COM 	 * If not, add the new child to the list of children
195*13101SVenki.Rajagopalan@Sun.COM 	 */
196*13101SVenki.Rajagopalan@Sun.COM 	new_ch->ch_next = info->ti_child;
197*13101SVenki.Rajagopalan@Sun.COM 	info->ti_child = new_ch;
198*13101SVenki.Rajagopalan@Sun.COM 
199*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_child_lock);
200*13101SVenki.Rajagopalan@Sun.COM }
201*13101SVenki.Rajagopalan@Sun.COM 
202*13101SVenki.Rajagopalan@Sun.COM int
eibnx_update_child(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi,dev_info_t * dip)203*13101SVenki.Rajagopalan@Sun.COM eibnx_update_child(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi,
204*13101SVenki.Rajagopalan@Sun.COM     dev_info_t *dip)
205*13101SVenki.Rajagopalan@Sun.COM {
206*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *ch;
207*13101SVenki.Rajagopalan@Sun.COM 
208*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_child_lock);
209*13101SVenki.Rajagopalan@Sun.COM 	for (ch = info->ti_child; ch; ch = ch->ch_next) {
210*13101SVenki.Rajagopalan@Sun.COM 		if (ch->ch_gwi->gw_portid == gwi->gw_portid) {
211*13101SVenki.Rajagopalan@Sun.COM 			if (ch->ch_dip != dip) {
212*13101SVenki.Rajagopalan@Sun.COM 				ENX_DPRINTF_DEBUG("updating child dip for "
213*13101SVenki.Rajagopalan@Sun.COM 				    "gw portid 0x%x to 0x%llx",
214*13101SVenki.Rajagopalan@Sun.COM 				    gwi->gw_portid, dip);
215*13101SVenki.Rajagopalan@Sun.COM 				ch->ch_dip = dip;
216*13101SVenki.Rajagopalan@Sun.COM 			}
217*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&info->ti_child_lock);
218*13101SVenki.Rajagopalan@Sun.COM 
219*13101SVenki.Rajagopalan@Sun.COM 			return (ENX_E_SUCCESS);
220*13101SVenki.Rajagopalan@Sun.COM 		}
221*13101SVenki.Rajagopalan@Sun.COM 	}
222*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_child_lock);
223*13101SVenki.Rajagopalan@Sun.COM 
224*13101SVenki.Rajagopalan@Sun.COM 	return (ENX_E_FAILURE);
225*13101SVenki.Rajagopalan@Sun.COM }
226*13101SVenki.Rajagopalan@Sun.COM 
227*13101SVenki.Rajagopalan@Sun.COM dev_info_t *
eibnx_find_child_dip_by_inst(eibnx_thr_info_t * info,int inst)228*13101SVenki.Rajagopalan@Sun.COM eibnx_find_child_dip_by_inst(eibnx_thr_info_t *info, int inst)
229*13101SVenki.Rajagopalan@Sun.COM {
230*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *ch;
231*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *dip = NULL;
232*13101SVenki.Rajagopalan@Sun.COM 
233*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_child_lock);
234*13101SVenki.Rajagopalan@Sun.COM 	for (ch = info->ti_child; ch != NULL; ch = ch->ch_next) {
235*13101SVenki.Rajagopalan@Sun.COM 		dip = ch->ch_dip;
236*13101SVenki.Rajagopalan@Sun.COM 		if (ddi_get_instance(dip) == inst)
237*13101SVenki.Rajagopalan@Sun.COM 			break;
238*13101SVenki.Rajagopalan@Sun.COM 	}
239*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_child_lock);
240*13101SVenki.Rajagopalan@Sun.COM 
241*13101SVenki.Rajagopalan@Sun.COM 	return (dip);
242*13101SVenki.Rajagopalan@Sun.COM }
243*13101SVenki.Rajagopalan@Sun.COM 
244*13101SVenki.Rajagopalan@Sun.COM dev_info_t *
eibnx_find_child_dip_by_gw(eibnx_thr_info_t * info,uint16_t gw_portid)245*13101SVenki.Rajagopalan@Sun.COM eibnx_find_child_dip_by_gw(eibnx_thr_info_t *info, uint16_t gw_portid)
246*13101SVenki.Rajagopalan@Sun.COM {
247*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *ch;
248*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *dip = NULL;
249*13101SVenki.Rajagopalan@Sun.COM 
250*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_child_lock);
251*13101SVenki.Rajagopalan@Sun.COM 	for (ch = info->ti_child; ch != NULL; ch = ch->ch_next) {
252*13101SVenki.Rajagopalan@Sun.COM 		dip = ch->ch_dip;
253*13101SVenki.Rajagopalan@Sun.COM 		if (ch->ch_gwi->gw_portid == gw_portid)
254*13101SVenki.Rajagopalan@Sun.COM 			break;
255*13101SVenki.Rajagopalan@Sun.COM 	}
256*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_child_lock);
257*13101SVenki.Rajagopalan@Sun.COM 
258*13101SVenki.Rajagopalan@Sun.COM 	return (dip);
259*13101SVenki.Rajagopalan@Sun.COM }
260*13101SVenki.Rajagopalan@Sun.COM 
261*13101SVenki.Rajagopalan@Sun.COM /*
262*13101SVenki.Rajagopalan@Sun.COM  * See if the passed gateway is already found in our list.  Note
263*13101SVenki.Rajagopalan@Sun.COM  * that we assume that the gateway port id uniquely identifies each
264*13101SVenki.Rajagopalan@Sun.COM  * gateway.
265*13101SVenki.Rajagopalan@Sun.COM  */
266*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_info_t *
eibnx_find_gw_in_gwlist(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi)267*13101SVenki.Rajagopalan@Sun.COM eibnx_find_gw_in_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi)
268*13101SVenki.Rajagopalan@Sun.COM {
269*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *lgw = NULL;
270*13101SVenki.Rajagopalan@Sun.COM 
271*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_gw_lock);
272*13101SVenki.Rajagopalan@Sun.COM 	for (lgw = info->ti_gw; lgw; lgw = lgw->gw_next) {
273*13101SVenki.Rajagopalan@Sun.COM 		if (lgw->gw_portid == gwi->gw_portid)
274*13101SVenki.Rajagopalan@Sun.COM 			break;
275*13101SVenki.Rajagopalan@Sun.COM 	}
276*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_gw_lock);
277*13101SVenki.Rajagopalan@Sun.COM 
278*13101SVenki.Rajagopalan@Sun.COM 	return (lgw);
279*13101SVenki.Rajagopalan@Sun.COM }
280*13101SVenki.Rajagopalan@Sun.COM 
281*13101SVenki.Rajagopalan@Sun.COM /*
282*13101SVenki.Rajagopalan@Sun.COM  * Add a newly discovered gateway to the gateway list.  Since we'll
283*13101SVenki.Rajagopalan@Sun.COM  * need to send unicast solicitations to this gateway soon, we'll
284*13101SVenki.Rajagopalan@Sun.COM  * also grab a swqe entry, and initialize basic gw adress parameters
285*13101SVenki.Rajagopalan@Sun.COM  * such as the gid, qpn, qkey and pkey of the GW.  When we eventually
286*13101SVenki.Rajagopalan@Sun.COM  * get to sending the unicast to this gateway for the first time,
287*13101SVenki.Rajagopalan@Sun.COM  * we'll discover the path to this gateway using these parameters
288*13101SVenki.Rajagopalan@Sun.COM  * and modify the ud destination handle appropriately.
289*13101SVenki.Rajagopalan@Sun.COM  */
290*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_info_t *
eibnx_add_gw_to_gwlist(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi,ibt_wc_t * wc,uint8_t * recv_buf)291*13101SVenki.Rajagopalan@Sun.COM eibnx_add_gw_to_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi,
292*13101SVenki.Rajagopalan@Sun.COM     ibt_wc_t *wc, uint8_t *recv_buf)
293*13101SVenki.Rajagopalan@Sun.COM {
294*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *new_gwi;
295*13101SVenki.Rajagopalan@Sun.COM 	eibnx_wqe_t *wqe;
296*13101SVenki.Rajagopalan@Sun.COM 	ib_grh_t *grh;
297*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t sgid;
298*13101SVenki.Rajagopalan@Sun.COM 	clock_t timeout_usecs;
299*13101SVenki.Rajagopalan@Sun.COM 
300*13101SVenki.Rajagopalan@Sun.COM 	/*
301*13101SVenki.Rajagopalan@Sun.COM 	 * For now, we'll simply do KM_NOSLEEP allocation, since this code
302*13101SVenki.Rajagopalan@Sun.COM 	 * is called from within rx processing
303*13101SVenki.Rajagopalan@Sun.COM 	 */
304*13101SVenki.Rajagopalan@Sun.COM 	new_gwi = kmem_zalloc(sizeof (eibnx_gw_info_t), KM_NOSLEEP);
305*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi == NULL) {
306*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no memory, gw port_id 0x%x "
307*13101SVenki.Rajagopalan@Sun.COM 		    "will be ignored by hca_guid=0x%llx, port=0x%x",
308*13101SVenki.Rajagopalan@Sun.COM 		    gwi->gw_portid, info->ti_hca_guid,
309*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_pi->p_port_num);
310*13101SVenki.Rajagopalan@Sun.COM 		return (NULL);
311*13101SVenki.Rajagopalan@Sun.COM 	}
312*13101SVenki.Rajagopalan@Sun.COM 
313*13101SVenki.Rajagopalan@Sun.COM 	/*
314*13101SVenki.Rajagopalan@Sun.COM 	 * We also need to acquire a send wqe to do unicast solicitations
315*13101SVenki.Rajagopalan@Sun.COM 	 * to this gateway later on. We should've enough pre-allocated swqes
316*13101SVenki.Rajagopalan@Sun.COM 	 * to do this without sleeping.
317*13101SVenki.Rajagopalan@Sun.COM 	 */
318*13101SVenki.Rajagopalan@Sun.COM 	if ((wqe = eibnx_acquire_swqe(info, KM_NOSLEEP)) == NULL) {
319*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no swqe available, gw port_id 0x%x "
320*13101SVenki.Rajagopalan@Sun.COM 		    "will be ignored by hca_guid=0x%llx, port=0x%x",
321*13101SVenki.Rajagopalan@Sun.COM 		    gwi->gw_portid, info->ti_hca_guid,
322*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_pi->p_port_num);
323*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(new_gwi, sizeof (eibnx_gw_info_t));
324*13101SVenki.Rajagopalan@Sun.COM 		return (NULL);
325*13101SVenki.Rajagopalan@Sun.COM 	}
326*13101SVenki.Rajagopalan@Sun.COM 
327*13101SVenki.Rajagopalan@Sun.COM 	/*
328*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize gw state and wqe information.
329*13101SVenki.Rajagopalan@Sun.COM 	 */
330*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_next = NULL;
331*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_swqe = wqe;
332*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_state = gwi->gw_state;
333*13101SVenki.Rajagopalan@Sun.COM 
334*13101SVenki.Rajagopalan@Sun.COM 	/*
335*13101SVenki.Rajagopalan@Sun.COM 	 * Set up gateway advertisement monitoring parameters. Since we
336*13101SVenki.Rajagopalan@Sun.COM 	 * always need to check against a timeout value of 2.5 * gw_adv_period,
337*13101SVenki.Rajagopalan@Sun.COM 	 * we'll keep this pre-calculated value as well.
338*13101SVenki.Rajagopalan@Sun.COM 	 */
339*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&new_gwi->gw_adv_lock, NULL, MUTEX_DRIVER, NULL);
340*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_adv_flag = gwi->gw_adv_flag;
341*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_adv_last_lbolt = ddi_get_lbolt64();
342*13101SVenki.Rajagopalan@Sun.COM 	timeout_usecs = gwi->gw_adv_period * 1000;
343*13101SVenki.Rajagopalan@Sun.COM 	timeout_usecs = ((timeout_usecs << 2) + timeout_usecs) >> 1;
344*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_adv_timeout_ticks = drv_usectohz(timeout_usecs);
345*13101SVenki.Rajagopalan@Sun.COM 
346*13101SVenki.Rajagopalan@Sun.COM 	/*
347*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize gateway address information. Note that if the message has
348*13101SVenki.Rajagopalan@Sun.COM 	 * a GRH, we'll use the subnet prefix, otherwise we'll assume that the
349*13101SVenki.Rajagopalan@Sun.COM 	 * gateway is in the same subnet as ourselves.
350*13101SVenki.Rajagopalan@Sun.COM 	 */
351*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_addr.ga_vect = NULL;
352*13101SVenki.Rajagopalan@Sun.COM 	if (wc->wc_flags & IBT_WC_GRH_PRESENT) {
353*13101SVenki.Rajagopalan@Sun.COM 		grh = (ib_grh_t *)(uintptr_t)recv_buf;
354*13101SVenki.Rajagopalan@Sun.COM 		new_gwi->gw_addr.ga_gid.gid_prefix =
355*13101SVenki.Rajagopalan@Sun.COM 		    ntohll(grh->SGID.gid_prefix);
356*13101SVenki.Rajagopalan@Sun.COM 	} else {
357*13101SVenki.Rajagopalan@Sun.COM 		sgid = info->ti_pi->p_sgid_tbl[0];
358*13101SVenki.Rajagopalan@Sun.COM 		new_gwi->gw_addr.ga_gid.gid_prefix =
359*13101SVenki.Rajagopalan@Sun.COM 		    sgid.gid_prefix;
360*13101SVenki.Rajagopalan@Sun.COM 	}
361*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_addr.ga_gid.gid_guid = gwi->gw_guid;
362*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_addr.ga_qpn = gwi->gw_ctrl_qpn;
363*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_addr.ga_qkey = EIB_FIP_QKEY;
364*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_addr.ga_pkey = EIB_ADMIN_PKEY;
365*13101SVenki.Rajagopalan@Sun.COM 
366*13101SVenki.Rajagopalan@Sun.COM 	/*
367*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize gateway parameters received via the advertisement
368*13101SVenki.Rajagopalan@Sun.COM 	 */
369*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_system_guid = gwi->gw_system_guid;
370*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_guid = gwi->gw_guid;
371*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_adv_period = gwi->gw_adv_period;
372*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_ka_period = gwi->gw_ka_period;
373*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_vnic_ka_period = gwi->gw_vnic_ka_period;
374*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_ctrl_qpn = gwi->gw_ctrl_qpn;
375*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_lid = gwi->gw_lid;
376*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_portid = gwi->gw_portid;
377*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_num_net_vnics = gwi->gw_num_net_vnics;
378*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_is_host_adm_vnics = gwi->gw_is_host_adm_vnics;
379*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_sl = gwi->gw_sl;
380*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_n_rss_qpn = gwi->gw_n_rss_qpn;
381*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_flag_ucast_advt = gwi->gw_flag_ucast_advt;
382*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_flag_available = gwi->gw_flag_available;
383*13101SVenki.Rajagopalan@Sun.COM 	bcopy(gwi->gw_system_name, new_gwi->gw_system_name,
384*13101SVenki.Rajagopalan@Sun.COM 	    sizeof (new_gwi->gw_system_name));
385*13101SVenki.Rajagopalan@Sun.COM 	bcopy(gwi->gw_port_name, new_gwi->gw_port_name,
386*13101SVenki.Rajagopalan@Sun.COM 	    sizeof (new_gwi->gw_port_name));
387*13101SVenki.Rajagopalan@Sun.COM 	bcopy(gwi->gw_vendor_id, new_gwi->gw_vendor_id,
388*13101SVenki.Rajagopalan@Sun.COM 	    sizeof (new_gwi->gw_vendor_id));
389*13101SVenki.Rajagopalan@Sun.COM 
390*13101SVenki.Rajagopalan@Sun.COM 	/*
391*13101SVenki.Rajagopalan@Sun.COM 	 * Queue up the new gwi and return it
392*13101SVenki.Rajagopalan@Sun.COM 	 */
393*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_gw_lock);
394*13101SVenki.Rajagopalan@Sun.COM 	new_gwi->gw_next = info->ti_gw;
395*13101SVenki.Rajagopalan@Sun.COM 	info->ti_gw = new_gwi;
396*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_gw_lock);
397*13101SVenki.Rajagopalan@Sun.COM 
398*13101SVenki.Rajagopalan@Sun.COM 	return (new_gwi);
399*13101SVenki.Rajagopalan@Sun.COM }
400*13101SVenki.Rajagopalan@Sun.COM 
401*13101SVenki.Rajagopalan@Sun.COM /*
402*13101SVenki.Rajagopalan@Sun.COM  * Update old data for the gateway in our list with the new data.
403*13101SVenki.Rajagopalan@Sun.COM  */
404*13101SVenki.Rajagopalan@Sun.COM void
eibnx_replace_gw_in_gwlist(eibnx_thr_info_t * info,eibnx_gw_info_t * orig_gwi,eibnx_gw_info_t * new_gwi,ibt_wc_t * wc,uint8_t * recv_buf,boolean_t * gwi_changed)405*13101SVenki.Rajagopalan@Sun.COM eibnx_replace_gw_in_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *orig_gwi,
406*13101SVenki.Rajagopalan@Sun.COM     eibnx_gw_info_t *new_gwi, ibt_wc_t *wc, uint8_t *recv_buf,
407*13101SVenki.Rajagopalan@Sun.COM     boolean_t *gwi_changed)
408*13101SVenki.Rajagopalan@Sun.COM {
409*13101SVenki.Rajagopalan@Sun.COM 	ib_sn_prefix_t new_gw_sn_prefix;
410*13101SVenki.Rajagopalan@Sun.COM 	ib_grh_t *grh;
411*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t sgid;
412*13101SVenki.Rajagopalan@Sun.COM 	boolean_t changed = B_FALSE;
413*13101SVenki.Rajagopalan@Sun.COM 	boolean_t gw_addr_changed = B_TRUE;
414*13101SVenki.Rajagopalan@Sun.COM 
415*13101SVenki.Rajagopalan@Sun.COM 	/*
416*13101SVenki.Rajagopalan@Sun.COM 	 * We'll update all info received in the new advertisement in
417*13101SVenki.Rajagopalan@Sun.COM 	 * the original gwi and also move the gw_state to that of the state
418*13101SVenki.Rajagopalan@Sun.COM 	 * in the new gwi.
419*13101SVenki.Rajagopalan@Sun.COM 	 */
420*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_gw_lock);
421*13101SVenki.Rajagopalan@Sun.COM 
422*13101SVenki.Rajagopalan@Sun.COM 	orig_gwi->gw_state = new_gwi->gw_state;
423*13101SVenki.Rajagopalan@Sun.COM 
424*13101SVenki.Rajagopalan@Sun.COM 	/*
425*13101SVenki.Rajagopalan@Sun.COM 	 * The guids shouldn't really change for the "same" gateway
426*13101SVenki.Rajagopalan@Sun.COM 	 */
427*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_system_guid != orig_gwi->gw_system_guid) {
428*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("gateway system guid changed for the "
429*13101SVenki.Rajagopalan@Sun.COM 		    "*same* gateway from 0x%llx to 0x%llx",
430*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_system_guid, new_gwi->gw_system_guid);
431*13101SVenki.Rajagopalan@Sun.COM 
432*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_system_guid = new_gwi->gw_system_guid;
433*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
434*13101SVenki.Rajagopalan@Sun.COM 	}
435*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_guid != orig_gwi->gw_guid) {
436*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("gateway guid changed for the "
437*13101SVenki.Rajagopalan@Sun.COM 		    "*same* gateway from 0x%llx to 0x%llx",
438*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_guid, new_gwi->gw_guid);
439*13101SVenki.Rajagopalan@Sun.COM 
440*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_guid = new_gwi->gw_guid;
441*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
442*13101SVenki.Rajagopalan@Sun.COM 		gw_addr_changed = B_TRUE;
443*13101SVenki.Rajagopalan@Sun.COM 	}
444*13101SVenki.Rajagopalan@Sun.COM 
445*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_adv_period != orig_gwi->gw_adv_period) {
446*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway adv period changed "
447*13101SVenki.Rajagopalan@Sun.COM 		    "from 0x%lx to 0x%lx", orig_gwi->gw_adv_period,
448*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_adv_period);
449*13101SVenki.Rajagopalan@Sun.COM 
450*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_adv_period = new_gwi->gw_adv_period;
451*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
452*13101SVenki.Rajagopalan@Sun.COM 	}
453*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_ka_period != orig_gwi->gw_ka_period) {
454*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway ka period changed "
455*13101SVenki.Rajagopalan@Sun.COM 		    "from 0x%lx to 0x%lx", orig_gwi->gw_ka_period,
456*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_ka_period);
457*13101SVenki.Rajagopalan@Sun.COM 
458*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_ka_period = new_gwi->gw_ka_period;
459*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
460*13101SVenki.Rajagopalan@Sun.COM 	}
461*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_vnic_ka_period != orig_gwi->gw_vnic_ka_period) {
462*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("vnic ka period changed "
463*13101SVenki.Rajagopalan@Sun.COM 		    "from 0x%lx to 0x%lx", orig_gwi->gw_vnic_ka_period,
464*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_vnic_ka_period);
465*13101SVenki.Rajagopalan@Sun.COM 
466*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_vnic_ka_period = new_gwi->gw_vnic_ka_period;
467*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
468*13101SVenki.Rajagopalan@Sun.COM 	}
469*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_ctrl_qpn != orig_gwi->gw_ctrl_qpn) {
470*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway control qpn changed "
471*13101SVenki.Rajagopalan@Sun.COM 		    "from 0x%lx to 0x%lx", orig_gwi->gw_ctrl_qpn,
472*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_ctrl_qpn);
473*13101SVenki.Rajagopalan@Sun.COM 
474*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_ctrl_qpn = new_gwi->gw_ctrl_qpn;
475*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
476*13101SVenki.Rajagopalan@Sun.COM 	}
477*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_lid != orig_gwi->gw_lid) {
478*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway lid changed from 0x%x to 0x%x",
479*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_lid, new_gwi->gw_lid);
480*13101SVenki.Rajagopalan@Sun.COM 
481*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_lid = new_gwi->gw_lid;
482*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
483*13101SVenki.Rajagopalan@Sun.COM 		gw_addr_changed = B_TRUE;
484*13101SVenki.Rajagopalan@Sun.COM 	}
485*13101SVenki.Rajagopalan@Sun.COM 
486*13101SVenki.Rajagopalan@Sun.COM 	/*
487*13101SVenki.Rajagopalan@Sun.COM 	 * The identity of the gateway is currently defined by its portid,
488*13101SVenki.Rajagopalan@Sun.COM 	 * so this cannot be different or eibnx_find_gw_in_gwlist() wouldn't
489*13101SVenki.Rajagopalan@Sun.COM 	 * have thought it's the same.  For now though, we'll treat it
490*13101SVenki.Rajagopalan@Sun.COM 	 * like any other parameter, and flag it if we find this different.
491*13101SVenki.Rajagopalan@Sun.COM 	 */
492*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_portid != orig_gwi->gw_portid) {
493*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("gateway portid changed for the *same* "
494*13101SVenki.Rajagopalan@Sun.COM 		    "gateway from 0x%x to 0x%x", orig_gwi->gw_portid,
495*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_portid);
496*13101SVenki.Rajagopalan@Sun.COM 
497*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_portid = new_gwi->gw_portid;
498*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
499*13101SVenki.Rajagopalan@Sun.COM 	}
500*13101SVenki.Rajagopalan@Sun.COM 
501*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_is_host_adm_vnics != orig_gwi->gw_is_host_adm_vnics) {
502*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("host adm vnics changed from 0x%x to 0x%x",
503*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_is_host_adm_vnics,
504*13101SVenki.Rajagopalan@Sun.COM 		    new_gwi->gw_is_host_adm_vnics);
505*13101SVenki.Rajagopalan@Sun.COM 
506*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_is_host_adm_vnics = new_gwi->gw_is_host_adm_vnics;
507*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
508*13101SVenki.Rajagopalan@Sun.COM 	}
509*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_sl != orig_gwi->gw_sl) {
510*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway sl changed from 0x%x to 0x%x",
511*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_sl, new_gwi->gw_sl);
512*13101SVenki.Rajagopalan@Sun.COM 
513*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_sl = new_gwi->gw_sl;
514*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
515*13101SVenki.Rajagopalan@Sun.COM 	}
516*13101SVenki.Rajagopalan@Sun.COM 	if (new_gwi->gw_n_rss_qpn != orig_gwi->gw_n_rss_qpn) {
517*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway n_rss_qpn changed from 0x%x to 0x%x",
518*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_n_rss_qpn, new_gwi->gw_n_rss_qpn);
519*13101SVenki.Rajagopalan@Sun.COM 
520*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_n_rss_qpn = new_gwi->gw_n_rss_qpn;
521*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
522*13101SVenki.Rajagopalan@Sun.COM 	}
523*13101SVenki.Rajagopalan@Sun.COM 
524*13101SVenki.Rajagopalan@Sun.COM 	/*
525*13101SVenki.Rajagopalan@Sun.COM 	 * The gw_flag_ucast_advt and gw_flag_available are expected to
526*13101SVenki.Rajagopalan@Sun.COM 	 * change over time (and even gw_num_net_vnics could change, but
527*13101SVenki.Rajagopalan@Sun.COM 	 * it's of no use to us presently), and we shouldn't trigger any
528*13101SVenki.Rajagopalan@Sun.COM 	 * flag for these
529*13101SVenki.Rajagopalan@Sun.COM 	 */
530*13101SVenki.Rajagopalan@Sun.COM 	orig_gwi->gw_flag_ucast_advt = new_gwi->gw_flag_ucast_advt;
531*13101SVenki.Rajagopalan@Sun.COM 	orig_gwi->gw_flag_available = new_gwi->gw_flag_available;
532*13101SVenki.Rajagopalan@Sun.COM 	orig_gwi->gw_num_net_vnics = new_gwi->gw_num_net_vnics;
533*13101SVenki.Rajagopalan@Sun.COM 
534*13101SVenki.Rajagopalan@Sun.COM 	if (strncmp((const char *)new_gwi->gw_system_name,
535*13101SVenki.Rajagopalan@Sun.COM 	    (const char *)orig_gwi->gw_system_name, EIB_GW_SYSNAME_LEN) != 0) {
536*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway system name changed from %s to %s",
537*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_system_name, new_gwi->gw_system_name);
538*13101SVenki.Rajagopalan@Sun.COM 
539*13101SVenki.Rajagopalan@Sun.COM 		bcopy(new_gwi->gw_system_name, orig_gwi->gw_system_name,
540*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_SYSNAME_LEN);
541*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
542*13101SVenki.Rajagopalan@Sun.COM 	}
543*13101SVenki.Rajagopalan@Sun.COM 	if (strncmp((const char *)new_gwi->gw_port_name,
544*13101SVenki.Rajagopalan@Sun.COM 	    (const char *)orig_gwi->gw_port_name, EIB_GW_PORTNAME_LEN) != 0) {
545*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("gateway port name changed from %s to %s",
546*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_port_name, new_gwi->gw_port_name);
547*13101SVenki.Rajagopalan@Sun.COM 
548*13101SVenki.Rajagopalan@Sun.COM 		bcopy(new_gwi->gw_port_name, orig_gwi->gw_port_name,
549*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_PORTNAME_LEN);
550*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
551*13101SVenki.Rajagopalan@Sun.COM 	}
552*13101SVenki.Rajagopalan@Sun.COM 	if (strncmp((const char *)new_gwi->gw_vendor_id,
553*13101SVenki.Rajagopalan@Sun.COM 	    (const char *)orig_gwi->gw_vendor_id, EIB_GW_VENDOR_LEN) != 0) {
554*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("vendor id changed from %s to %s",
555*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_vendor_id, new_gwi->gw_vendor_id);
556*13101SVenki.Rajagopalan@Sun.COM 
557*13101SVenki.Rajagopalan@Sun.COM 		bcopy(new_gwi->gw_vendor_id, orig_gwi->gw_vendor_id,
558*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_VENDOR_LEN);
559*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
560*13101SVenki.Rajagopalan@Sun.COM 	}
561*13101SVenki.Rajagopalan@Sun.COM 
562*13101SVenki.Rajagopalan@Sun.COM 	/*
563*13101SVenki.Rajagopalan@Sun.COM 	 * See if the subnet prefix for the gateway has changed
564*13101SVenki.Rajagopalan@Sun.COM 	 */
565*13101SVenki.Rajagopalan@Sun.COM 	if (wc->wc_flags & IBT_WC_GRH_PRESENT) {
566*13101SVenki.Rajagopalan@Sun.COM 		grh = (ib_grh_t *)(uintptr_t)recv_buf;
567*13101SVenki.Rajagopalan@Sun.COM 		new_gw_sn_prefix = ntohll(grh->SGID.gid_prefix);
568*13101SVenki.Rajagopalan@Sun.COM 	} else {
569*13101SVenki.Rajagopalan@Sun.COM 		sgid = info->ti_pi->p_sgid_tbl[0];
570*13101SVenki.Rajagopalan@Sun.COM 		new_gw_sn_prefix = sgid.gid_prefix;
571*13101SVenki.Rajagopalan@Sun.COM 	}
572*13101SVenki.Rajagopalan@Sun.COM 	if (new_gw_sn_prefix != orig_gwi->gw_addr.ga_gid.gid_prefix) {
573*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("subnet prefix changed from 0x%llx to 0x%llx",
574*13101SVenki.Rajagopalan@Sun.COM 		    orig_gwi->gw_addr.ga_gid.gid_prefix, new_gw_sn_prefix);
575*13101SVenki.Rajagopalan@Sun.COM 
576*13101SVenki.Rajagopalan@Sun.COM 		changed = B_TRUE;
577*13101SVenki.Rajagopalan@Sun.COM 		gw_addr_changed = B_TRUE;
578*13101SVenki.Rajagopalan@Sun.COM 	}
579*13101SVenki.Rajagopalan@Sun.COM 
580*13101SVenki.Rajagopalan@Sun.COM 	/*
581*13101SVenki.Rajagopalan@Sun.COM 	 * If the gateway address has changed in any way, clear the current
582*13101SVenki.Rajagopalan@Sun.COM 	 * address vector and update the gateway guid and gateway qpn. The
583*13101SVenki.Rajagopalan@Sun.COM 	 * address vector will be created the next time a unicast solicit
584*13101SVenki.Rajagopalan@Sun.COM 	 * is attempted for this gateway.
585*13101SVenki.Rajagopalan@Sun.COM 	 */
586*13101SVenki.Rajagopalan@Sun.COM 	if (gw_addr_changed) {
587*13101SVenki.Rajagopalan@Sun.COM 		if (orig_gwi->gw_addr.ga_vect != NULL) {
588*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(orig_gwi->gw_addr.ga_vect,
589*13101SVenki.Rajagopalan@Sun.COM 			    sizeof (ibt_adds_vect_t));
590*13101SVenki.Rajagopalan@Sun.COM 			orig_gwi->gw_addr.ga_vect = NULL;
591*13101SVenki.Rajagopalan@Sun.COM 		}
592*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_addr.ga_gid.gid_prefix = new_gw_sn_prefix;
593*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_addr.ga_gid.gid_guid = new_gwi->gw_guid;
594*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_addr.ga_qpn = new_gwi->gw_ctrl_qpn;
595*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_addr.ga_qkey = EIB_FIP_QKEY;
596*13101SVenki.Rajagopalan@Sun.COM 		orig_gwi->gw_addr.ga_pkey = EIB_ADMIN_PKEY;
597*13101SVenki.Rajagopalan@Sun.COM 	}
598*13101SVenki.Rajagopalan@Sun.COM 
599*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_gw_lock);
600*13101SVenki.Rajagopalan@Sun.COM 
601*13101SVenki.Rajagopalan@Sun.COM 	if (gwi_changed) {
602*13101SVenki.Rajagopalan@Sun.COM 		*gwi_changed = changed;
603*13101SVenki.Rajagopalan@Sun.COM 	}
604*13101SVenki.Rajagopalan@Sun.COM }
605*13101SVenki.Rajagopalan@Sun.COM 
606*13101SVenki.Rajagopalan@Sun.COM /*
607*13101SVenki.Rajagopalan@Sun.COM  * Queue up a node for EoIB instantiation and wake up the thread
608*13101SVenki.Rajagopalan@Sun.COM  * that creates eoib nodes.
609*13101SVenki.Rajagopalan@Sun.COM  */
610*13101SVenki.Rajagopalan@Sun.COM void
eibnx_queue_for_creation(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi)611*13101SVenki.Rajagopalan@Sun.COM eibnx_queue_for_creation(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi)
612*13101SVenki.Rajagopalan@Sun.COM {
613*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
614*13101SVenki.Rajagopalan@Sun.COM 	eibnx_nodeq_t *new_node;
615*13101SVenki.Rajagopalan@Sun.COM 
616*13101SVenki.Rajagopalan@Sun.COM 	/*
617*13101SVenki.Rajagopalan@Sun.COM 	 * For now, we'll simply do KM_NOSLEEP allocation, since this
618*13101SVenki.Rajagopalan@Sun.COM 	 * code is called from within rx processing
619*13101SVenki.Rajagopalan@Sun.COM 	 */
620*13101SVenki.Rajagopalan@Sun.COM 	new_node = kmem_zalloc(sizeof (eibnx_nodeq_t), KM_NOSLEEP);
621*13101SVenki.Rajagopalan@Sun.COM 	if (new_node == NULL) {
622*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no memory, eoib node will not be "
623*13101SVenki.Rajagopalan@Sun.COM 		    "created for hca_guid=0x%llx, hca_port=0x%x, "
624*13101SVenki.Rajagopalan@Sun.COM 		    "gw_port_id=0x%x", info->ti_hca_guid,
625*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_pi->p_port_num, gwi->gw_portid);
626*13101SVenki.Rajagopalan@Sun.COM 		return;
627*13101SVenki.Rajagopalan@Sun.COM 	}
628*13101SVenki.Rajagopalan@Sun.COM 	new_node->nc_info = info;
629*13101SVenki.Rajagopalan@Sun.COM 	new_node->nc_gwi = gwi;
630*13101SVenki.Rajagopalan@Sun.COM 
631*13101SVenki.Rajagopalan@Sun.COM 	/*
632*13101SVenki.Rajagopalan@Sun.COM 	 * If the eoib node creation thread is dying (or dead), don't
633*13101SVenki.Rajagopalan@Sun.COM 	 * queue up any more requests for creation
634*13101SVenki.Rajagopalan@Sun.COM 	 */
635*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_nodeq_lock);
636*13101SVenki.Rajagopalan@Sun.COM 	if (ss->nx_nodeq_thr_die) {
637*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(new_node, sizeof (eibnx_nodeq_t));
638*13101SVenki.Rajagopalan@Sun.COM 	} else {
639*13101SVenki.Rajagopalan@Sun.COM 		new_node->nc_next = ss->nx_nodeq;
640*13101SVenki.Rajagopalan@Sun.COM 		ss->nx_nodeq = new_node;
641*13101SVenki.Rajagopalan@Sun.COM 		cv_signal(&ss->nx_nodeq_cv);
642*13101SVenki.Rajagopalan@Sun.COM 	}
643*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_nodeq_lock);
644*13101SVenki.Rajagopalan@Sun.COM }
645