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