xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/enx_hdlrs.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/sunndi.h>
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/callb.h>
34*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/mgt/sm_attr.h>		/* SM_INIT_TYPE_REPLY_... */
35*13101SVenki.Rajagopalan@Sun.COM 
36*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/enx_impl.h>
37*13101SVenki.Rajagopalan@Sun.COM 
38*13101SVenki.Rajagopalan@Sun.COM /*
39*13101SVenki.Rajagopalan@Sun.COM  * Static function declarations
40*13101SVenki.Rajagopalan@Sun.COM  */
41*13101SVenki.Rajagopalan@Sun.COM static void eibnx_gw_is_alive(eibnx_gw_info_t *);
42*13101SVenki.Rajagopalan@Sun.COM static void eibnx_gw_is_aware(eibnx_thr_info_t *, eibnx_gw_info_t *, boolean_t);
43*13101SVenki.Rajagopalan@Sun.COM static void eibnx_process_rx(eibnx_thr_info_t *, ibt_wc_t *, eibnx_wqe_t *);
44*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_wcerr(uint8_t, eibnx_wqe_t *, eibnx_thr_info_t *);
45*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_login_ack(eibnx_thr_info_t *, uint8_t *);
46*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_gw_rebirth(eibnx_thr_info_t *, uint16_t);
47*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_gw_info_update(eibnx_thr_info_t *, uint16_t, void *);
48*13101SVenki.Rajagopalan@Sun.COM static int eibnx_replace_portinfo(eibnx_thr_info_t *, ibt_hca_portinfo_t *,
49*13101SVenki.Rajagopalan@Sun.COM     uint_t);
50*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_port_events(ibt_hca_hdl_t, uint8_t);
51*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_hca_attach(ib_guid_t);
52*13101SVenki.Rajagopalan@Sun.COM static void eibnx_handle_hca_detach(ib_guid_t);
53*13101SVenki.Rajagopalan@Sun.COM 
54*13101SVenki.Rajagopalan@Sun.COM /*
55*13101SVenki.Rajagopalan@Sun.COM  * NDI event handle we need
56*13101SVenki.Rajagopalan@Sun.COM  */
57*13101SVenki.Rajagopalan@Sun.COM extern ndi_event_hdl_t enx_ndi_event_hdl;
58*13101SVenki.Rajagopalan@Sun.COM 
59*13101SVenki.Rajagopalan@Sun.COM /*
60*13101SVenki.Rajagopalan@Sun.COM  * SM's init type reply flags
61*13101SVenki.Rajagopalan@Sun.COM  */
62*13101SVenki.Rajagopalan@Sun.COM #define	ENX_PORT_ATTR_LOADED(itr)				\
63*13101SVenki.Rajagopalan@Sun.COM 	(((itr) & SM_INIT_TYPE_REPLY_NO_LOAD_REPLY) == 0)
64*13101SVenki.Rajagopalan@Sun.COM #define	ENX_PORT_ATTR_NOT_PRESERVED(itr)			\
65*13101SVenki.Rajagopalan@Sun.COM 	(((itr) & SM_INIT_TYPE_PRESERVE_CONTENT_REPLY) == 0)
66*13101SVenki.Rajagopalan@Sun.COM #define	ENX_PORT_PRES_NOT_PRESERVED(itr)			\
67*13101SVenki.Rajagopalan@Sun.COM 	(((itr) & SM_INIT_TYPE_PRESERVE_PRESENCE_REPLY) == 0)
68*13101SVenki.Rajagopalan@Sun.COM 
69*13101SVenki.Rajagopalan@Sun.COM /*
70*13101SVenki.Rajagopalan@Sun.COM  * Port monitor progress flags (all flag values should be non-zero)
71*13101SVenki.Rajagopalan@Sun.COM  */
72*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_LINKSTATE_UP		0x01
73*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_FOUND_MCGS		0x02
74*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_SETUP_CQ		0x04
75*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_SETUP_UD_CHAN		0x08
76*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_SETUP_BUFS		0x10
77*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_SETUP_CQ_HDLR		0x20
78*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_JOINED_MCGS		0x40
79*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_MULTICAST_SLCT		0x80
80*13101SVenki.Rajagopalan@Sun.COM #define	ENX_MON_MAX			0xFF
81*13101SVenki.Rajagopalan@Sun.COM 
82*13101SVenki.Rajagopalan@Sun.COM /*
83*13101SVenki.Rajagopalan@Sun.COM  * Per-port thread to solicit, monitor and discover EoIB gateways
84*13101SVenki.Rajagopalan@Sun.COM  * and create the corresponding EoIB driver instances on the host.
85*13101SVenki.Rajagopalan@Sun.COM  */
86*13101SVenki.Rajagopalan@Sun.COM void
eibnx_port_monitor(eibnx_thr_info_t * info)87*13101SVenki.Rajagopalan@Sun.COM eibnx_port_monitor(eibnx_thr_info_t *info)
88*13101SVenki.Rajagopalan@Sun.COM {
89*13101SVenki.Rajagopalan@Sun.COM 	clock_t solicit_period_ticks;
90*13101SVenki.Rajagopalan@Sun.COM 	clock_t deadline;
91*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
92*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
93*13101SVenki.Rajagopalan@Sun.COM 	char thr_name[MAXNAMELEN];
94*13101SVenki.Rajagopalan@Sun.COM 
95*13101SVenki.Rajagopalan@Sun.COM 	(void) snprintf(thr_name, MAXNAMELEN, ENX_PORT_MONITOR,
96*13101SVenki.Rajagopalan@Sun.COM 	    info->ti_pi->p_port_num);
97*13101SVenki.Rajagopalan@Sun.COM 
98*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
99*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, thr_name);
100*13101SVenki.Rajagopalan@Sun.COM 
101*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress = 0;
102*13101SVenki.Rajagopalan@Sun.COM 
103*13101SVenki.Rajagopalan@Sun.COM 	/*
104*13101SVenki.Rajagopalan@Sun.COM 	 * If the port is not active yet, wait for a port up event. The
105*13101SVenki.Rajagopalan@Sun.COM 	 * async handler, when it sees a port-up event, is expected to
106*13101SVenki.Rajagopalan@Sun.COM 	 * update the port_monitor's portinfo structure's p_linkstate
107*13101SVenki.Rajagopalan@Sun.COM 	 * and wake us up with ENX_EVENT_LINK_UP.
108*13101SVenki.Rajagopalan@Sun.COM 	 */
109*13101SVenki.Rajagopalan@Sun.COM 	while (info->ti_pi->p_linkstate != IBT_PORT_ACTIVE) {
110*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&info->ti_event_lock);
111*13101SVenki.Rajagopalan@Sun.COM 		while ((info->ti_event &
112*13101SVenki.Rajagopalan@Sun.COM 		    (ENX_EVENT_LINK_UP | ENX_EVENT_DIE)) == 0) {
113*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ci_lock);
114*13101SVenki.Rajagopalan@Sun.COM 			CALLB_CPR_SAFE_BEGIN(&ci);
115*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ci_lock);
116*13101SVenki.Rajagopalan@Sun.COM 
117*13101SVenki.Rajagopalan@Sun.COM 			cv_wait(&info->ti_event_cv, &info->ti_event_lock);
118*13101SVenki.Rajagopalan@Sun.COM 
119*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ci_lock);
120*13101SVenki.Rajagopalan@Sun.COM 			CALLB_CPR_SAFE_END(&ci, &ci_lock);
121*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ci_lock);
122*13101SVenki.Rajagopalan@Sun.COM 		}
123*13101SVenki.Rajagopalan@Sun.COM 		if (info->ti_event & ENX_EVENT_DIE) {
124*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&info->ti_event_lock);
125*13101SVenki.Rajagopalan@Sun.COM 			goto port_monitor_exit;
126*13101SVenki.Rajagopalan@Sun.COM 		}
127*13101SVenki.Rajagopalan@Sun.COM 		info->ti_event &= (~ENX_EVENT_LINK_UP);
128*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&info->ti_event_lock);
129*13101SVenki.Rajagopalan@Sun.COM 	}
130*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_LINKSTATE_UP;
131*13101SVenki.Rajagopalan@Sun.COM 
132*13101SVenki.Rajagopalan@Sun.COM 	/*
133*13101SVenki.Rajagopalan@Sun.COM 	 * Locate the multicast groups for sending solicit requests
134*13101SVenki.Rajagopalan@Sun.COM 	 * to the GW and receiving advertisements from the GW. If
135*13101SVenki.Rajagopalan@Sun.COM 	 * either of the mcg is not present, wait for them to be
136*13101SVenki.Rajagopalan@Sun.COM 	 * created by the GW.
137*13101SVenki.Rajagopalan@Sun.COM 	 */
138*13101SVenki.Rajagopalan@Sun.COM 	while (eibnx_find_mgroups(info) != ENX_E_SUCCESS) {
139*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&info->ti_event_lock);
140*13101SVenki.Rajagopalan@Sun.COM 		while ((info->ti_event &
141*13101SVenki.Rajagopalan@Sun.COM 		    (ENX_EVENT_MCGS_AVAILABLE | ENX_EVENT_DIE)) == 0) {
142*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ci_lock);
143*13101SVenki.Rajagopalan@Sun.COM 			CALLB_CPR_SAFE_BEGIN(&ci);
144*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ci_lock);
145*13101SVenki.Rajagopalan@Sun.COM 
146*13101SVenki.Rajagopalan@Sun.COM 			cv_wait(&info->ti_event_cv, &info->ti_event_lock);
147*13101SVenki.Rajagopalan@Sun.COM 
148*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ci_lock);
149*13101SVenki.Rajagopalan@Sun.COM 			CALLB_CPR_SAFE_END(&ci, &ci_lock);
150*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ci_lock);
151*13101SVenki.Rajagopalan@Sun.COM 		}
152*13101SVenki.Rajagopalan@Sun.COM 		if (info->ti_event & ENX_EVENT_DIE) {
153*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&info->ti_event_lock);
154*13101SVenki.Rajagopalan@Sun.COM 			goto port_monitor_exit;
155*13101SVenki.Rajagopalan@Sun.COM 		}
156*13101SVenki.Rajagopalan@Sun.COM 		info->ti_event &= (~ENX_EVENT_MCGS_AVAILABLE);
157*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&info->ti_event_lock);
158*13101SVenki.Rajagopalan@Sun.COM 	}
159*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_FOUND_MCGS;
160*13101SVenki.Rajagopalan@Sun.COM 
161*13101SVenki.Rajagopalan@Sun.COM 	/*
162*13101SVenki.Rajagopalan@Sun.COM 	 * Setup a shared CQ
163*13101SVenki.Rajagopalan@Sun.COM 	 */
164*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_setup_cq(info) != ENX_E_SUCCESS) {
165*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_setup_cq() failed, terminating "
166*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
167*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
168*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
169*13101SVenki.Rajagopalan@Sun.COM 	}
170*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_SETUP_CQ;
171*13101SVenki.Rajagopalan@Sun.COM 
172*13101SVenki.Rajagopalan@Sun.COM 	/*
173*13101SVenki.Rajagopalan@Sun.COM 	 * Setup UD channel
174*13101SVenki.Rajagopalan@Sun.COM 	 */
175*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_setup_ud_channel(info) != ENX_E_SUCCESS) {
176*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_setup_ud_channel() failed, terminating "
177*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
178*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
179*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
180*13101SVenki.Rajagopalan@Sun.COM 	}
181*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_SETUP_UD_CHAN;
182*13101SVenki.Rajagopalan@Sun.COM 
183*13101SVenki.Rajagopalan@Sun.COM 	/*
184*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate/initialize any tx/rx buffers
185*13101SVenki.Rajagopalan@Sun.COM 	 */
186*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_setup_bufs(info) != ENX_E_SUCCESS) {
187*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_setup_bufs() failed, terminating "
188*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
189*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
190*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
191*13101SVenki.Rajagopalan@Sun.COM 	}
192*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_SETUP_BUFS;
193*13101SVenki.Rajagopalan@Sun.COM 
194*13101SVenki.Rajagopalan@Sun.COM 	/*
195*13101SVenki.Rajagopalan@Sun.COM 	 * Setup completion handler
196*13101SVenki.Rajagopalan@Sun.COM 	 */
197*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_setup_cq_handler(info) != ENX_E_SUCCESS) {
198*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_setup_cq_handler() failed, terminating "
199*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
200*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
201*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
202*13101SVenki.Rajagopalan@Sun.COM 	}
203*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_SETUP_CQ_HDLR;
204*13101SVenki.Rajagopalan@Sun.COM 
205*13101SVenki.Rajagopalan@Sun.COM 	/*
206*13101SVenki.Rajagopalan@Sun.COM 	 * Join EoIB multicast groups
207*13101SVenki.Rajagopalan@Sun.COM 	 */
208*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_join_mcgs(info) != ENX_E_SUCCESS) {
209*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_join_mcgs() failed, terminating ",
210*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
211*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
212*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
213*13101SVenki.Rajagopalan@Sun.COM 	}
214*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_JOINED_MCGS;
215*13101SVenki.Rajagopalan@Sun.COM 
216*13101SVenki.Rajagopalan@Sun.COM 	/*
217*13101SVenki.Rajagopalan@Sun.COM 	 * Send SOLICIT pkt to the EoIB multicast group
218*13101SVenki.Rajagopalan@Sun.COM 	 */
219*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_fip_solicit_mcast(info) != ENX_E_SUCCESS) {
220*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("eibnx_fip_solicit_mcast() failed, terminating "
221*13101SVenki.Rajagopalan@Sun.COM 		    "port monitor for (hca_guid=0x%llx, port_num=0x%x)",
222*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
223*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
224*13101SVenki.Rajagopalan@Sun.COM 	}
225*13101SVenki.Rajagopalan@Sun.COM 	info->ti_progress |= ENX_MON_MULTICAST_SLCT;
226*13101SVenki.Rajagopalan@Sun.COM 
227*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_event_lock);
228*13101SVenki.Rajagopalan@Sun.COM 
229*13101SVenki.Rajagopalan@Sun.COM 	solicit_period_ticks = drv_usectohz(ENX_DFL_SOLICIT_PERIOD_USEC);
230*13101SVenki.Rajagopalan@Sun.COM 
231*13101SVenki.Rajagopalan@Sun.COM periodic_solicit:
232*13101SVenki.Rajagopalan@Sun.COM 	deadline = ddi_get_lbolt() + solicit_period_ticks;
233*13101SVenki.Rajagopalan@Sun.COM 	while ((info->ti_event & (ENX_EVENT_TIMED_OUT | ENX_EVENT_DIE)) == 0) {
234*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
235*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
236*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
237*13101SVenki.Rajagopalan@Sun.COM 
238*13101SVenki.Rajagopalan@Sun.COM 		if (cv_timedwait(&info->ti_event_cv, &info->ti_event_lock,
239*13101SVenki.Rajagopalan@Sun.COM 		    deadline) == -1) {
240*13101SVenki.Rajagopalan@Sun.COM 			info->ti_event |= ENX_EVENT_TIMED_OUT;
241*13101SVenki.Rajagopalan@Sun.COM 		}
242*13101SVenki.Rajagopalan@Sun.COM 
243*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
244*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
245*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
246*13101SVenki.Rajagopalan@Sun.COM 	}
247*13101SVenki.Rajagopalan@Sun.COM 
248*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_event & ENX_EVENT_DIE) {
249*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&info->ti_event_lock);
250*13101SVenki.Rajagopalan@Sun.COM 		goto port_monitor_exit;
251*13101SVenki.Rajagopalan@Sun.COM 	}
252*13101SVenki.Rajagopalan@Sun.COM 
253*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_event & ENX_EVENT_TIMED_OUT) {
254*13101SVenki.Rajagopalan@Sun.COM 		if (eibnx_fip_solicit_ucast(info,
255*13101SVenki.Rajagopalan@Sun.COM 		    &solicit_period_ticks) != ENX_E_SUCCESS) {
256*13101SVenki.Rajagopalan@Sun.COM 			ENX_DPRINTF_WARN("failed to send solicit ucast to "
257*13101SVenki.Rajagopalan@Sun.COM 			    "gateways (hca_guid=0x%llx, port_num=0x%x)",
258*13101SVenki.Rajagopalan@Sun.COM 			    info->ti_hca_guid, info->ti_pi->p_port_num);
259*13101SVenki.Rajagopalan@Sun.COM 		}
260*13101SVenki.Rajagopalan@Sun.COM 		info->ti_event &= ~ENX_EVENT_TIMED_OUT;
261*13101SVenki.Rajagopalan@Sun.COM 	}
262*13101SVenki.Rajagopalan@Sun.COM 
263*13101SVenki.Rajagopalan@Sun.COM 	goto periodic_solicit;
264*13101SVenki.Rajagopalan@Sun.COM 
265*13101SVenki.Rajagopalan@Sun.COM port_monitor_exit:
266*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_MULTICAST_SLCT) {
267*13101SVenki.Rajagopalan@Sun.COM 		eibnx_cleanup_port_nodes(info);
268*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_MULTICAST_SLCT);
269*13101SVenki.Rajagopalan@Sun.COM 	}
270*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_JOINED_MCGS) {
271*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_join_mcgs(info);
272*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_JOINED_MCGS);
273*13101SVenki.Rajagopalan@Sun.COM 	}
274*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_SETUP_CQ_HDLR) {
275*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_setup_cq_handler(info);
276*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_SETUP_CQ_HDLR);
277*13101SVenki.Rajagopalan@Sun.COM 	}
278*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_SETUP_BUFS) {
279*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_setup_bufs(info);
280*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_SETUP_BUFS);
281*13101SVenki.Rajagopalan@Sun.COM 	}
282*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_SETUP_UD_CHAN) {
283*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_setup_ud_channel(info);
284*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_SETUP_UD_CHAN);
285*13101SVenki.Rajagopalan@Sun.COM 	}
286*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_SETUP_CQ) {
287*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_setup_cq(info);
288*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_SETUP_CQ);
289*13101SVenki.Rajagopalan@Sun.COM 	}
290*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_progress & ENX_MON_FOUND_MCGS) {
291*13101SVenki.Rajagopalan@Sun.COM 		eibnx_rb_find_mgroups(info);
292*13101SVenki.Rajagopalan@Sun.COM 		info->ti_progress &= (~ENX_MON_FOUND_MCGS);
293*13101SVenki.Rajagopalan@Sun.COM 	}
294*13101SVenki.Rajagopalan@Sun.COM 
295*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ci_lock);
296*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_EXIT(&ci);
297*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ci_lock);
298*13101SVenki.Rajagopalan@Sun.COM }
299*13101SVenki.Rajagopalan@Sun.COM 
300*13101SVenki.Rajagopalan@Sun.COM /*
301*13101SVenki.Rajagopalan@Sun.COM  * Async subnet notices handler registered with IBTF
302*13101SVenki.Rajagopalan@Sun.COM  */
303*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
304*13101SVenki.Rajagopalan@Sun.COM void
eibnx_subnet_notices_handler(void * arg,ib_gid_t gid,ibt_subnet_event_code_t sn_evcode,ibt_subnet_event_t * sn_event)305*13101SVenki.Rajagopalan@Sun.COM eibnx_subnet_notices_handler(void *arg, ib_gid_t gid,
306*13101SVenki.Rajagopalan@Sun.COM     ibt_subnet_event_code_t sn_evcode, ibt_subnet_event_t *sn_event)
307*13101SVenki.Rajagopalan@Sun.COM {
308*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
309*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
310*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t notice_gid;
311*13101SVenki.Rajagopalan@Sun.COM 
312*13101SVenki.Rajagopalan@Sun.COM 	switch (sn_evcode) {
313*13101SVenki.Rajagopalan@Sun.COM 	case IBT_SM_EVENT_MCG_CREATED:
314*13101SVenki.Rajagopalan@Sun.COM 		notice_gid = sn_event->sm_notice_gid;
315*13101SVenki.Rajagopalan@Sun.COM 
316*13101SVenki.Rajagopalan@Sun.COM 		if ((notice_gid.gid_prefix == enx_solicit_mgid.gid_prefix &&
317*13101SVenki.Rajagopalan@Sun.COM 		    notice_gid.gid_guid == enx_solicit_mgid.gid_guid) ||
318*13101SVenki.Rajagopalan@Sun.COM 		    (notice_gid.gid_prefix == enx_advertise_mgid.gid_prefix &&
319*13101SVenki.Rajagopalan@Sun.COM 		    notice_gid.gid_guid == enx_advertise_mgid.gid_guid)) {
320*13101SVenki.Rajagopalan@Sun.COM 
321*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ss->nx_lock);
322*13101SVenki.Rajagopalan@Sun.COM 			for (ti = ss->nx_thr_info; ti; ti = ti->ti_next) {
323*13101SVenki.Rajagopalan@Sun.COM 				mutex_enter(&ti->ti_event_lock);
324*13101SVenki.Rajagopalan@Sun.COM 				ti->ti_event |= ENX_EVENT_MCGS_AVAILABLE;
325*13101SVenki.Rajagopalan@Sun.COM 				cv_broadcast(&ti->ti_event_cv);
326*13101SVenki.Rajagopalan@Sun.COM 				mutex_exit(&ti->ti_event_lock);
327*13101SVenki.Rajagopalan@Sun.COM 			}
328*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->nx_lock);
329*13101SVenki.Rajagopalan@Sun.COM 		}
330*13101SVenki.Rajagopalan@Sun.COM 		break;
331*13101SVenki.Rajagopalan@Sun.COM 
332*13101SVenki.Rajagopalan@Sun.COM 	case IBT_SM_EVENT_MCG_DELETED:
333*13101SVenki.Rajagopalan@Sun.COM 		break;
334*13101SVenki.Rajagopalan@Sun.COM 
335*13101SVenki.Rajagopalan@Sun.COM 	default:
336*13101SVenki.Rajagopalan@Sun.COM 		break;
337*13101SVenki.Rajagopalan@Sun.COM 	}
338*13101SVenki.Rajagopalan@Sun.COM }
339*13101SVenki.Rajagopalan@Sun.COM 
340*13101SVenki.Rajagopalan@Sun.COM /*
341*13101SVenki.Rajagopalan@Sun.COM  * Async event handler registered with IBTF
342*13101SVenki.Rajagopalan@Sun.COM  */
343*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
344*13101SVenki.Rajagopalan@Sun.COM void
eibnx_async_handler(void * clnt_pvt,ibt_hca_hdl_t hca,ibt_async_code_t code,ibt_async_event_t * event)345*13101SVenki.Rajagopalan@Sun.COM eibnx_async_handler(void *clnt_pvt, ibt_hca_hdl_t hca,
346*13101SVenki.Rajagopalan@Sun.COM     ibt_async_code_t code, ibt_async_event_t *event)
347*13101SVenki.Rajagopalan@Sun.COM {
348*13101SVenki.Rajagopalan@Sun.COM 	switch (code) {
349*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_CATASTROPHIC_CHAN:
350*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_INVALID_REQUEST_CHAN:
351*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_ACCESS_VIOLATION_CHAN:
352*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_CQ:
353*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_CATASTROPHIC_SRQ:
354*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("ibt ERROR event 0x%x received "
355*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx)", code, event->ev_hca_guid);
356*13101SVenki.Rajagopalan@Sun.COM 		break;
357*13101SVenki.Rajagopalan@Sun.COM 
358*13101SVenki.Rajagopalan@Sun.COM 	case IBT_ERROR_PORT_DOWN:
359*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt PORT_DOWN event received "
360*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x)",
361*13101SVenki.Rajagopalan@Sun.COM 		    event->ev_hca_guid, event->ev_port);
362*13101SVenki.Rajagopalan@Sun.COM 		break;
363*13101SVenki.Rajagopalan@Sun.COM 
364*13101SVenki.Rajagopalan@Sun.COM 	case IBT_EVENT_PORT_UP:
365*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt PORT_UP event received "
366*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x)",
367*13101SVenki.Rajagopalan@Sun.COM 		    event->ev_hca_guid, event->ev_port);
368*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_port_events(hca, event->ev_port);
369*13101SVenki.Rajagopalan@Sun.COM 		break;
370*13101SVenki.Rajagopalan@Sun.COM 
371*13101SVenki.Rajagopalan@Sun.COM 	case IBT_PORT_CHANGE_EVENT:
372*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt PORT_CHANGE event received "
373*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x)",
374*13101SVenki.Rajagopalan@Sun.COM 		    event->ev_hca_guid, event->ev_port);
375*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_port_events(hca, event->ev_port);
376*13101SVenki.Rajagopalan@Sun.COM 		break;
377*13101SVenki.Rajagopalan@Sun.COM 
378*13101SVenki.Rajagopalan@Sun.COM 	case IBT_CLNT_REREG_EVENT:
379*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt CLNT_REREG event received "
380*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x)",
381*13101SVenki.Rajagopalan@Sun.COM 		    event->ev_hca_guid, event->ev_port);
382*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_port_events(hca, event->ev_port);
383*13101SVenki.Rajagopalan@Sun.COM 		break;
384*13101SVenki.Rajagopalan@Sun.COM 
385*13101SVenki.Rajagopalan@Sun.COM 	case IBT_HCA_ATTACH_EVENT:
386*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_VERBOSE("ibt HCA_ATTACH event received "
387*13101SVenki.Rajagopalan@Sun.COM 		    "(new hca_guid=0x%llx)", event->ev_hca_guid);
388*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_hca_attach(event->ev_hca_guid);
389*13101SVenki.Rajagopalan@Sun.COM 		break;
390*13101SVenki.Rajagopalan@Sun.COM 
391*13101SVenki.Rajagopalan@Sun.COM 	case IBT_HCA_DETACH_EVENT:
392*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_VERBOSE("ibt HCA_DETACH event received "
393*13101SVenki.Rajagopalan@Sun.COM 		    "(target hca_guid=0x%llx)", event->ev_hca_guid);
394*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_hca_detach(event->ev_hca_guid);
395*13101SVenki.Rajagopalan@Sun.COM 		break;
396*13101SVenki.Rajagopalan@Sun.COM 
397*13101SVenki.Rajagopalan@Sun.COM 	default:
398*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_VERBOSE("ibt UNSUPPORTED event 0x%x received "
399*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx)", code, event->ev_hca_guid);
400*13101SVenki.Rajagopalan@Sun.COM 		break;
401*13101SVenki.Rajagopalan@Sun.COM 	}
402*13101SVenki.Rajagopalan@Sun.COM }
403*13101SVenki.Rajagopalan@Sun.COM 
404*13101SVenki.Rajagopalan@Sun.COM boolean_t
eibnx_is_gw_dead(eibnx_gw_info_t * gwi)405*13101SVenki.Rajagopalan@Sun.COM eibnx_is_gw_dead(eibnx_gw_info_t *gwi)
406*13101SVenki.Rajagopalan@Sun.COM {
407*13101SVenki.Rajagopalan@Sun.COM 	int64_t cur_lbolt;
408*13101SVenki.Rajagopalan@Sun.COM 
409*13101SVenki.Rajagopalan@Sun.COM 	cur_lbolt = ddi_get_lbolt64();
410*13101SVenki.Rajagopalan@Sun.COM 
411*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&gwi->gw_adv_lock);
412*13101SVenki.Rajagopalan@Sun.COM 	if ((cur_lbolt - gwi->gw_adv_last_lbolt) > gwi->gw_adv_timeout_ticks) {
413*13101SVenki.Rajagopalan@Sun.COM 		gwi->gw_adv_flag = ENX_GW_DEAD;
414*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&gwi->gw_adv_lock);
415*13101SVenki.Rajagopalan@Sun.COM 		return (B_TRUE);
416*13101SVenki.Rajagopalan@Sun.COM 	}
417*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&gwi->gw_adv_lock);
418*13101SVenki.Rajagopalan@Sun.COM 
419*13101SVenki.Rajagopalan@Sun.COM 	return (B_FALSE);
420*13101SVenki.Rajagopalan@Sun.COM }
421*13101SVenki.Rajagopalan@Sun.COM 
422*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_gw_is_alive(eibnx_gw_info_t * gwi)423*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_is_alive(eibnx_gw_info_t *gwi)
424*13101SVenki.Rajagopalan@Sun.COM {
425*13101SVenki.Rajagopalan@Sun.COM 	/*
426*13101SVenki.Rajagopalan@Sun.COM 	 * We've just received a multicast advertisement from this
427*13101SVenki.Rajagopalan@Sun.COM 	 * gateway.  Multicast or unicast, this means that the gateway
428*13101SVenki.Rajagopalan@Sun.COM 	 * is alive. Record this timestamp (in ticks).
429*13101SVenki.Rajagopalan@Sun.COM 	 */
430*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&gwi->gw_adv_lock);
431*13101SVenki.Rajagopalan@Sun.COM 	gwi->gw_adv_last_lbolt = ddi_get_lbolt64();
432*13101SVenki.Rajagopalan@Sun.COM 	if (gwi->gw_adv_flag == ENX_GW_DEAD) {
433*13101SVenki.Rajagopalan@Sun.COM 		gwi->gw_adv_flag = ENX_GW_ALIVE;
434*13101SVenki.Rajagopalan@Sun.COM 	}
435*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&gwi->gw_adv_lock);
436*13101SVenki.Rajagopalan@Sun.COM }
437*13101SVenki.Rajagopalan@Sun.COM 
438*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_gw_is_aware(eibnx_thr_info_t * info,eibnx_gw_info_t * gwi,boolean_t gwi_changed)439*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_is_aware(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi,
440*13101SVenki.Rajagopalan@Sun.COM     boolean_t gwi_changed)
441*13101SVenki.Rajagopalan@Sun.COM {
442*13101SVenki.Rajagopalan@Sun.COM 	eib_gw_info_t eib_gwi;
443*13101SVenki.Rajagopalan@Sun.COM 	boolean_t post_rebirth_event = B_FALSE;
444*13101SVenki.Rajagopalan@Sun.COM 
445*13101SVenki.Rajagopalan@Sun.COM 	/*
446*13101SVenki.Rajagopalan@Sun.COM 	 * We're here when we receive a unicast advertisement from a
447*13101SVenki.Rajagopalan@Sun.COM 	 * gateway. If this gateway was discovered earlier but was in
448*13101SVenki.Rajagopalan@Sun.COM 	 * a dead state, this means it has come back alive and become
449*13101SVenki.Rajagopalan@Sun.COM 	 * aware of us.  We may need to inform any EoIB children
450*13101SVenki.Rajagopalan@Sun.COM 	 * waiting for notification.  Note that if this gateway is
451*13101SVenki.Rajagopalan@Sun.COM 	 * being discovered for the first time now, we wouldn't have
452*13101SVenki.Rajagopalan@Sun.COM 	 * created the binding eoib node for it (we will do that when
453*13101SVenki.Rajagopalan@Sun.COM 	 * we return from this routine), so the "rebirth" and "gw info
454*13101SVenki.Rajagopalan@Sun.COM 	 * update" event postings will be NOPs.
455*13101SVenki.Rajagopalan@Sun.COM 	 */
456*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&gwi->gw_adv_lock);
457*13101SVenki.Rajagopalan@Sun.COM 	gwi->gw_adv_last_lbolt = ddi_get_lbolt64();
458*13101SVenki.Rajagopalan@Sun.COM 	if (gwi->gw_adv_flag != ENX_GW_AWARE) {
459*13101SVenki.Rajagopalan@Sun.COM 		post_rebirth_event = B_TRUE;
460*13101SVenki.Rajagopalan@Sun.COM 	}
461*13101SVenki.Rajagopalan@Sun.COM 	gwi->gw_adv_flag = ENX_GW_AWARE;
462*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&gwi->gw_adv_lock);
463*13101SVenki.Rajagopalan@Sun.COM 
464*13101SVenki.Rajagopalan@Sun.COM 	/*
465*13101SVenki.Rajagopalan@Sun.COM 	 * If we have a gateway information update event, we post that
466*13101SVenki.Rajagopalan@Sun.COM 	 * first, so any rebirth event processed later will have the
467*13101SVenki.Rajagopalan@Sun.COM 	 * correct gateway information.
468*13101SVenki.Rajagopalan@Sun.COM 	 */
469*13101SVenki.Rajagopalan@Sun.COM 	if (gwi_changed) {
470*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_system_guid = gwi->gw_system_guid;
471*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_guid = gwi->gw_guid;
472*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_sn_prefix = gwi->gw_addr.ga_gid.gid_prefix;
473*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_adv_period = gwi->gw_adv_period;
474*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_ka_period = gwi->gw_ka_period;
475*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_vnic_ka_period = gwi->gw_vnic_ka_period;
476*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_ctrl_qpn = gwi->gw_ctrl_qpn;
477*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_lid = gwi->gw_lid;
478*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_portid = gwi->gw_portid;
479*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_num_net_vnics = gwi->gw_num_net_vnics;
480*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_flag_available = gwi->gw_flag_available;
481*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_is_host_adm_vnics = gwi->gw_is_host_adm_vnics;
482*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_sl = gwi->gw_sl;
483*13101SVenki.Rajagopalan@Sun.COM 		eib_gwi.gi_n_rss_qpn = gwi->gw_n_rss_qpn;
484*13101SVenki.Rajagopalan@Sun.COM 		bcopy(gwi->gw_system_name, eib_gwi.gi_system_name,
485*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_SYSNAME_LEN);
486*13101SVenki.Rajagopalan@Sun.COM 		bcopy(gwi->gw_port_name, eib_gwi.gi_port_name,
487*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_PORTNAME_LEN);
488*13101SVenki.Rajagopalan@Sun.COM 		bcopy(gwi->gw_vendor_id, eib_gwi.gi_vendor_id,
489*13101SVenki.Rajagopalan@Sun.COM 		    EIB_GW_VENDOR_LEN);
490*13101SVenki.Rajagopalan@Sun.COM 
491*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_gw_info_update(info, eib_gwi.gi_portid, &eib_gwi);
492*13101SVenki.Rajagopalan@Sun.COM 	}
493*13101SVenki.Rajagopalan@Sun.COM 	if (post_rebirth_event) {
494*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_gw_rebirth(info, gwi->gw_portid);
495*13101SVenki.Rajagopalan@Sun.COM 	}
496*13101SVenki.Rajagopalan@Sun.COM }
497*13101SVenki.Rajagopalan@Sun.COM 
498*13101SVenki.Rajagopalan@Sun.COM /*
499*13101SVenki.Rajagopalan@Sun.COM  * Thread to create eoib nodes and online instances
500*13101SVenki.Rajagopalan@Sun.COM  */
501*13101SVenki.Rajagopalan@Sun.COM void
eibnx_create_eoib_node(void)502*13101SVenki.Rajagopalan@Sun.COM eibnx_create_eoib_node(void)
503*13101SVenki.Rajagopalan@Sun.COM {
504*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
505*13101SVenki.Rajagopalan@Sun.COM 	eibnx_nodeq_t *node;
506*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
507*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
508*13101SVenki.Rajagopalan@Sun.COM 
509*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
510*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, ENX_NODE_CREATOR);
511*13101SVenki.Rajagopalan@Sun.COM 
512*13101SVenki.Rajagopalan@Sun.COM wait_for_node_to_create:
513*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_nodeq_lock);
514*13101SVenki.Rajagopalan@Sun.COM 
515*13101SVenki.Rajagopalan@Sun.COM 	while ((ss->nx_nodeq == NULL) && (ss->nx_nodeq_thr_die == 0)) {
516*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
517*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
518*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
519*13101SVenki.Rajagopalan@Sun.COM 
520*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ss->nx_nodeq_cv, &ss->nx_nodeq_lock);
521*13101SVenki.Rajagopalan@Sun.COM 
522*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
523*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
524*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
525*13101SVenki.Rajagopalan@Sun.COM 	}
526*13101SVenki.Rajagopalan@Sun.COM 
527*13101SVenki.Rajagopalan@Sun.COM 	/*
528*13101SVenki.Rajagopalan@Sun.COM 	 * If this is not really a work item, but a request for us to
529*13101SVenki.Rajagopalan@Sun.COM 	 * die, throwaway all pending work requests and just die.
530*13101SVenki.Rajagopalan@Sun.COM 	 */
531*13101SVenki.Rajagopalan@Sun.COM 	if (ss->nx_nodeq_thr_die) {
532*13101SVenki.Rajagopalan@Sun.COM 		while (ss->nx_nodeq) {
533*13101SVenki.Rajagopalan@Sun.COM 			node = ss->nx_nodeq;
534*13101SVenki.Rajagopalan@Sun.COM 			ss->nx_nodeq = node->nc_next;
535*13101SVenki.Rajagopalan@Sun.COM 			node->nc_next = NULL;
536*13101SVenki.Rajagopalan@Sun.COM 
537*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(node, sizeof (eibnx_nodeq_t));
538*13101SVenki.Rajagopalan@Sun.COM 		}
539*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->nx_nodeq_lock);
540*13101SVenki.Rajagopalan@Sun.COM 
541*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
542*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
543*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
544*13101SVenki.Rajagopalan@Sun.COM 
545*13101SVenki.Rajagopalan@Sun.COM 		return;
546*13101SVenki.Rajagopalan@Sun.COM 	}
547*13101SVenki.Rajagopalan@Sun.COM 
548*13101SVenki.Rajagopalan@Sun.COM 	/*
549*13101SVenki.Rajagopalan@Sun.COM 	 * Grab the first node entry from the queue
550*13101SVenki.Rajagopalan@Sun.COM 	 */
551*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(ss->nx_nodeq != NULL);
552*13101SVenki.Rajagopalan@Sun.COM 	node = ss->nx_nodeq;
553*13101SVenki.Rajagopalan@Sun.COM 	ss->nx_nodeq = node->nc_next;
554*13101SVenki.Rajagopalan@Sun.COM 	node->nc_next = NULL;
555*13101SVenki.Rajagopalan@Sun.COM 
556*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_nodeq_lock);
557*13101SVenki.Rajagopalan@Sun.COM 
558*13101SVenki.Rajagopalan@Sun.COM 	(void) eibnx_configure_node(node->nc_info, node->nc_gwi, NULL);
559*13101SVenki.Rajagopalan@Sun.COM 
560*13101SVenki.Rajagopalan@Sun.COM 	kmem_free(node, sizeof (eibnx_nodeq_t));
561*13101SVenki.Rajagopalan@Sun.COM 	goto wait_for_node_to_create;
562*13101SVenki.Rajagopalan@Sun.COM 
563*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
564*13101SVenki.Rajagopalan@Sun.COM }
565*13101SVenki.Rajagopalan@Sun.COM 
566*13101SVenki.Rajagopalan@Sun.COM /*
567*13101SVenki.Rajagopalan@Sun.COM  * Tx and Rx completion interrupt handler. Guaranteed to be single
568*13101SVenki.Rajagopalan@Sun.COM  * threaded and nonreentrant for this CQ.
569*13101SVenki.Rajagopalan@Sun.COM  */
570*13101SVenki.Rajagopalan@Sun.COM void
eibnx_comp_intr(ibt_cq_hdl_t cq_hdl,void * arg)571*13101SVenki.Rajagopalan@Sun.COM eibnx_comp_intr(ibt_cq_hdl_t cq_hdl, void *arg)
572*13101SVenki.Rajagopalan@Sun.COM {
573*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *info = arg;
574*13101SVenki.Rajagopalan@Sun.COM 
575*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_cq_hdl != cq_hdl) {
576*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("eibnx_comp_intr: "
577*13101SVenki.Rajagopalan@Sun.COM 		    "cq_hdl(0x%llx) != info->ti_cq_hdl(0x%llx), "
578*13101SVenki.Rajagopalan@Sun.COM 		    "ignoring completion", cq_hdl, info->ti_cq_hdl);
579*13101SVenki.Rajagopalan@Sun.COM 		return;
580*13101SVenki.Rajagopalan@Sun.COM 	}
581*13101SVenki.Rajagopalan@Sun.COM 
582*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(info->ti_softint_hdl != NULL);
583*13101SVenki.Rajagopalan@Sun.COM 
584*13101SVenki.Rajagopalan@Sun.COM 	(void) ddi_intr_trigger_softint(info->ti_softint_hdl, NULL);
585*13101SVenki.Rajagopalan@Sun.COM }
586*13101SVenki.Rajagopalan@Sun.COM 
587*13101SVenki.Rajagopalan@Sun.COM /*
588*13101SVenki.Rajagopalan@Sun.COM  * Send and Receive completion handler functions for EoIB nexus
589*13101SVenki.Rajagopalan@Sun.COM  */
590*13101SVenki.Rajagopalan@Sun.COM 
591*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
592*13101SVenki.Rajagopalan@Sun.COM uint_t
eibnx_comp_handler(caddr_t arg1,caddr_t arg2)593*13101SVenki.Rajagopalan@Sun.COM eibnx_comp_handler(caddr_t arg1, caddr_t arg2)
594*13101SVenki.Rajagopalan@Sun.COM {
595*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *info = (eibnx_thr_info_t *)arg1;
596*13101SVenki.Rajagopalan@Sun.COM 	ibt_wc_t *wc;
597*13101SVenki.Rajagopalan@Sun.COM 	eibnx_wqe_t *wqe;
598*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
599*13101SVenki.Rajagopalan@Sun.COM 	uint_t polled;
600*13101SVenki.Rajagopalan@Sun.COM 	int i;
601*13101SVenki.Rajagopalan@Sun.COM 
602*13101SVenki.Rajagopalan@Sun.COM 	/*
603*13101SVenki.Rajagopalan@Sun.COM 	 * Make sure the port monitor isn't killed if we're in the completion
604*13101SVenki.Rajagopalan@Sun.COM 	 * handler. If the port monitor thread is already being killed, we'll
605*13101SVenki.Rajagopalan@Sun.COM 	 * stop processing completions.
606*13101SVenki.Rajagopalan@Sun.COM 	 */
607*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_event_lock);
608*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_event & (ENX_EVENT_DIE | ENX_EVENT_COMPLETION)) {
609*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&info->ti_event_lock);
610*13101SVenki.Rajagopalan@Sun.COM 		return ((uint_t)ENX_E_SUCCESS);
611*13101SVenki.Rajagopalan@Sun.COM 	}
612*13101SVenki.Rajagopalan@Sun.COM 	info->ti_event |= ENX_EVENT_COMPLETION;
613*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_event_lock);
614*13101SVenki.Rajagopalan@Sun.COM 
615*13101SVenki.Rajagopalan@Sun.COM 	/*
616*13101SVenki.Rajagopalan@Sun.COM 	 * Re-arm the notification callback before we start polling
617*13101SVenki.Rajagopalan@Sun.COM 	 * the completion queue.  There's nothing much we can do if the
618*13101SVenki.Rajagopalan@Sun.COM 	 * enable_cq_notify fails - we issue a warning and move on.
619*13101SVenki.Rajagopalan@Sun.COM 	 */
620*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_enable_cq_notify(info->ti_cq_hdl, IBT_NEXT_COMPLETION);
621*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
622*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt_enable_cq_notify(cq_hdl=0x%llx) "
623*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", info->ti_cq_hdl, ret);
624*13101SVenki.Rajagopalan@Sun.COM 	}
625*13101SVenki.Rajagopalan@Sun.COM 
626*13101SVenki.Rajagopalan@Sun.COM 	/*
627*13101SVenki.Rajagopalan@Sun.COM 	 * Handle tx and rx completions
628*13101SVenki.Rajagopalan@Sun.COM 	 */
629*13101SVenki.Rajagopalan@Sun.COM 	while ((ret = ibt_poll_cq(info->ti_cq_hdl, info->ti_wc, info->ti_cq_sz,
630*13101SVenki.Rajagopalan@Sun.COM 	    &polled)) == IBT_SUCCESS) {
631*13101SVenki.Rajagopalan@Sun.COM 		for (wc = info->ti_wc, i = 0; i < polled; i++, wc++) {
632*13101SVenki.Rajagopalan@Sun.COM 			wqe = (eibnx_wqe_t *)(uintptr_t)wc->wc_id;
633*13101SVenki.Rajagopalan@Sun.COM 			if (wc->wc_status != IBT_WC_SUCCESS) {
634*13101SVenki.Rajagopalan@Sun.COM 				eibnx_handle_wcerr(wc->wc_status, wqe, info);
635*13101SVenki.Rajagopalan@Sun.COM 			} else if (wqe->qe_type == ENX_QETYP_RWQE) {
636*13101SVenki.Rajagopalan@Sun.COM 				eibnx_process_rx(info, wc, wqe);
637*13101SVenki.Rajagopalan@Sun.COM 				eibnx_return_rwqe(info, wqe);
638*13101SVenki.Rajagopalan@Sun.COM 			} else {
639*13101SVenki.Rajagopalan@Sun.COM 				eibnx_return_swqe(wqe);
640*13101SVenki.Rajagopalan@Sun.COM 			}
641*13101SVenki.Rajagopalan@Sun.COM 		}
642*13101SVenki.Rajagopalan@Sun.COM 	}
643*13101SVenki.Rajagopalan@Sun.COM 
644*13101SVenki.Rajagopalan@Sun.COM 	/*
645*13101SVenki.Rajagopalan@Sun.COM 	 * On the way out, make sure we wake up any pending death requestor
646*13101SVenki.Rajagopalan@Sun.COM 	 * for the port-monitor thread. Note that we need to do a cv_broadcast()
647*13101SVenki.Rajagopalan@Sun.COM 	 * here since there could be multiple threads sleeping on the event cv
648*13101SVenki.Rajagopalan@Sun.COM 	 * and we want to make sure all waiters get a chance to see if it's
649*13101SVenki.Rajagopalan@Sun.COM 	 * their turn.
650*13101SVenki.Rajagopalan@Sun.COM 	 */
651*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&info->ti_event_lock);
652*13101SVenki.Rajagopalan@Sun.COM 	info->ti_event &= (~ENX_EVENT_COMPLETION);
653*13101SVenki.Rajagopalan@Sun.COM 	cv_broadcast(&info->ti_event_cv);
654*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&info->ti_event_lock);
655*13101SVenki.Rajagopalan@Sun.COM 
656*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_INTR_CLAIMED);
657*13101SVenki.Rajagopalan@Sun.COM }
658*13101SVenki.Rajagopalan@Sun.COM 
659*13101SVenki.Rajagopalan@Sun.COM /*
660*13101SVenki.Rajagopalan@Sun.COM  * Rx processing code
661*13101SVenki.Rajagopalan@Sun.COM  */
662*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_process_rx(eibnx_thr_info_t * info,ibt_wc_t * wc,eibnx_wqe_t * wqe)663*13101SVenki.Rajagopalan@Sun.COM eibnx_process_rx(eibnx_thr_info_t *info, ibt_wc_t *wc, eibnx_wqe_t *wqe)
664*13101SVenki.Rajagopalan@Sun.COM {
665*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_msg_t msg;
666*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *gwi;
667*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *orig_gwi;
668*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *new_gwi;
669*13101SVenki.Rajagopalan@Sun.COM 	uint_t orig_gw_state;
670*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *pkt = (uint8_t *)(uintptr_t)(wqe->qe_sgl.ds_va);
671*13101SVenki.Rajagopalan@Sun.COM 	boolean_t gwi_changed;
672*13101SVenki.Rajagopalan@Sun.COM 
673*13101SVenki.Rajagopalan@Sun.COM 	/*
674*13101SVenki.Rajagopalan@Sun.COM 	 * We'll simply drop any packet (including broadcast advertisements
675*13101SVenki.Rajagopalan@Sun.COM 	 * from gws) we receive before we've done our solicitation broadcast.
676*13101SVenki.Rajagopalan@Sun.COM 	 */
677*13101SVenki.Rajagopalan@Sun.COM 	if (info->ti_mcast_done == 0) {
678*13101SVenki.Rajagopalan@Sun.COM 		return;
679*13101SVenki.Rajagopalan@Sun.COM 	}
680*13101SVenki.Rajagopalan@Sun.COM 
681*13101SVenki.Rajagopalan@Sun.COM 	/*
682*13101SVenki.Rajagopalan@Sun.COM 	 * Skip the GRH and parse the message in the packet
683*13101SVenki.Rajagopalan@Sun.COM 	 */
684*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_fip_parse_pkt(pkt + ENX_GRH_SZ, &msg) != ENX_E_SUCCESS) {
685*13101SVenki.Rajagopalan@Sun.COM 		return;
686*13101SVenki.Rajagopalan@Sun.COM 	}
687*13101SVenki.Rajagopalan@Sun.COM 
688*13101SVenki.Rajagopalan@Sun.COM 	/*
689*13101SVenki.Rajagopalan@Sun.COM 	 * If it was a login ack for one of our children, we need to pass
690*13101SVenki.Rajagopalan@Sun.COM 	 * it on to the child
691*13101SVenki.Rajagopalan@Sun.COM 	 */
692*13101SVenki.Rajagopalan@Sun.COM 	if (msg.gm_type == FIP_VNIC_LOGIN_ACK) {
693*13101SVenki.Rajagopalan@Sun.COM 		eibnx_handle_login_ack(info, pkt);
694*13101SVenki.Rajagopalan@Sun.COM 		return;
695*13101SVenki.Rajagopalan@Sun.COM 	}
696*13101SVenki.Rajagopalan@Sun.COM 
697*13101SVenki.Rajagopalan@Sun.COM 	/*
698*13101SVenki.Rajagopalan@Sun.COM 	 * Other than that, we only handle gateway advertisements
699*13101SVenki.Rajagopalan@Sun.COM 	 */
700*13101SVenki.Rajagopalan@Sun.COM 	if (msg.gm_type != FIP_GW_ADVERTISE_MCAST &&
701*13101SVenki.Rajagopalan@Sun.COM 	    msg.gm_type != FIP_GW_ADVERTISE_UCAST) {
702*13101SVenki.Rajagopalan@Sun.COM 		return;
703*13101SVenki.Rajagopalan@Sun.COM 	}
704*13101SVenki.Rajagopalan@Sun.COM 
705*13101SVenki.Rajagopalan@Sun.COM 	gwi = &msg.u.gm_info;
706*13101SVenki.Rajagopalan@Sun.COM 
707*13101SVenki.Rajagopalan@Sun.COM 	/*
708*13101SVenki.Rajagopalan@Sun.COM 	 * State machine to create eoib instances. Whether this advertisement
709*13101SVenki.Rajagopalan@Sun.COM 	 * is from a new gateway or an old gateway that we already know about,
710*13101SVenki.Rajagopalan@Sun.COM 	 * if this was a unicast response to our earlier solicitation and it's
711*13101SVenki.Rajagopalan@Sun.COM 	 * the first time we're receiving it from this gateway, we're ready to
712*13101SVenki.Rajagopalan@Sun.COM 	 * login, so we create the EoIB instance for it.
713*13101SVenki.Rajagopalan@Sun.COM 	 */
714*13101SVenki.Rajagopalan@Sun.COM 	orig_gwi = eibnx_find_gw_in_gwlist(info, gwi);
715*13101SVenki.Rajagopalan@Sun.COM 	if (orig_gwi == NULL) {
716*13101SVenki.Rajagopalan@Sun.COM 		if (gwi->gw_flag_available == 0) {
717*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_state = ENX_GW_STATE_UNAVAILABLE;
718*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_adv_flag = ENX_GW_ALIVE;
719*13101SVenki.Rajagopalan@Sun.COM 			(void) eibnx_add_gw_to_gwlist(info, gwi, wc, pkt);
720*13101SVenki.Rajagopalan@Sun.COM 		} else if (gwi->gw_flag_ucast_advt == 0) {
721*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_state = ENX_GW_STATE_AVAILABLE;
722*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_adv_flag = ENX_GW_ALIVE;
723*13101SVenki.Rajagopalan@Sun.COM 			(void) eibnx_add_gw_to_gwlist(info, gwi, wc, pkt);
724*13101SVenki.Rajagopalan@Sun.COM 		} else {
725*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_state = ENX_GW_STATE_READY_TO_LOGIN;
726*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_adv_flag = ENX_GW_AWARE;
727*13101SVenki.Rajagopalan@Sun.COM 			if ((new_gwi = eibnx_add_gw_to_gwlist(info, gwi,
728*13101SVenki.Rajagopalan@Sun.COM 			    wc, pkt)) != NULL) {
729*13101SVenki.Rajagopalan@Sun.COM 				eibnx_queue_for_creation(info, new_gwi);
730*13101SVenki.Rajagopalan@Sun.COM 			}
731*13101SVenki.Rajagopalan@Sun.COM 		}
732*13101SVenki.Rajagopalan@Sun.COM 	} else {
733*13101SVenki.Rajagopalan@Sun.COM 		orig_gw_state = orig_gwi->gw_state;
734*13101SVenki.Rajagopalan@Sun.COM 		if (gwi->gw_flag_available == 0) {
735*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_state = ENX_GW_STATE_UNAVAILABLE;
736*13101SVenki.Rajagopalan@Sun.COM 			eibnx_replace_gw_in_gwlist(info, orig_gwi, gwi,
737*13101SVenki.Rajagopalan@Sun.COM 			    wc, pkt, NULL);
738*13101SVenki.Rajagopalan@Sun.COM 			eibnx_gw_is_alive(orig_gwi);
739*13101SVenki.Rajagopalan@Sun.COM 
740*13101SVenki.Rajagopalan@Sun.COM 		} else if (gwi->gw_flag_ucast_advt == 0) {
741*13101SVenki.Rajagopalan@Sun.COM 			if (orig_gw_state == ENX_GW_STATE_UNAVAILABLE) {
742*13101SVenki.Rajagopalan@Sun.COM 				gwi->gw_state = ENX_GW_STATE_AVAILABLE;
743*13101SVenki.Rajagopalan@Sun.COM 			} else {
744*13101SVenki.Rajagopalan@Sun.COM 				gwi->gw_state = orig_gw_state;
745*13101SVenki.Rajagopalan@Sun.COM 			}
746*13101SVenki.Rajagopalan@Sun.COM 			eibnx_replace_gw_in_gwlist(info, orig_gwi, gwi,
747*13101SVenki.Rajagopalan@Sun.COM 			    wc, pkt, NULL);
748*13101SVenki.Rajagopalan@Sun.COM 			eibnx_gw_is_alive(orig_gwi);
749*13101SVenki.Rajagopalan@Sun.COM 
750*13101SVenki.Rajagopalan@Sun.COM 		} else {
751*13101SVenki.Rajagopalan@Sun.COM 			gwi->gw_state = ENX_GW_STATE_READY_TO_LOGIN;
752*13101SVenki.Rajagopalan@Sun.COM 			eibnx_replace_gw_in_gwlist(info, orig_gwi, gwi,
753*13101SVenki.Rajagopalan@Sun.COM 			    wc, pkt, &gwi_changed);
754*13101SVenki.Rajagopalan@Sun.COM 			eibnx_gw_is_aware(info, orig_gwi, gwi_changed);
755*13101SVenki.Rajagopalan@Sun.COM 
756*13101SVenki.Rajagopalan@Sun.COM 			if (orig_gw_state != ENX_GW_STATE_READY_TO_LOGIN)
757*13101SVenki.Rajagopalan@Sun.COM 				eibnx_queue_for_creation(info, orig_gwi);
758*13101SVenki.Rajagopalan@Sun.COM 		}
759*13101SVenki.Rajagopalan@Sun.COM 	}
760*13101SVenki.Rajagopalan@Sun.COM }
761*13101SVenki.Rajagopalan@Sun.COM 
762*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
763*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_wcerr(uint8_t wcerr,eibnx_wqe_t * wqe,eibnx_thr_info_t * info)764*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_wcerr(uint8_t wcerr, eibnx_wqe_t *wqe, eibnx_thr_info_t *info)
765*13101SVenki.Rajagopalan@Sun.COM {
766*13101SVenki.Rajagopalan@Sun.COM 	/*
767*13101SVenki.Rajagopalan@Sun.COM 	 * Currently, all we do is report
768*13101SVenki.Rajagopalan@Sun.COM 	 */
769*13101SVenki.Rajagopalan@Sun.COM 	switch (wcerr) {
770*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_WR_FLUSHED_ERR:
771*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_VERBOSE("IBT_WC_WR_FLUSHED_ERR seen "
772*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x, wqe_type=0x%x)",
773*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num, wqe->qe_type);
774*13101SVenki.Rajagopalan@Sun.COM 		break;
775*13101SVenki.Rajagopalan@Sun.COM 
776*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_LOCAL_CHAN_OP_ERR:
777*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("IBT_WC_LOCAL_CHAN_OP_ERR seen "
778*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x, wqe_type=0x%x)",
779*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num, wqe->qe_type);
780*13101SVenki.Rajagopalan@Sun.COM 		break;
781*13101SVenki.Rajagopalan@Sun.COM 
782*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_LOCAL_PROTECT_ERR:
783*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("IBT_WC_LOCAL_PROTECT_ERR seen "
784*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x, wqe_type=0x%x)",
785*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num, wqe->qe_type);
786*13101SVenki.Rajagopalan@Sun.COM 		break;
787*13101SVenki.Rajagopalan@Sun.COM 	}
788*13101SVenki.Rajagopalan@Sun.COM }
789*13101SVenki.Rajagopalan@Sun.COM 
790*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_login_ack(eibnx_thr_info_t * info,uint8_t * pkt)791*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_login_ack(eibnx_thr_info_t *info, uint8_t *pkt)
792*13101SVenki.Rajagopalan@Sun.COM {
793*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
794*13101SVenki.Rajagopalan@Sun.COM 	fip_login_ack_t *ack;
795*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vnic_login_t *login;
796*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t cookie;
797*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *rdip;
798*13101SVenki.Rajagopalan@Sun.COM 	uint16_t vnic_id;
799*13101SVenki.Rajagopalan@Sun.COM 	uint16_t inst;
800*13101SVenki.Rajagopalan@Sun.COM 	int ret;
801*13101SVenki.Rajagopalan@Sun.COM 
802*13101SVenki.Rajagopalan@Sun.COM 	/*
803*13101SVenki.Rajagopalan@Sun.COM 	 * When we get login acknowledgements, we simply invoke the
804*13101SVenki.Rajagopalan@Sun.COM 	 * appropriate EoIB driver callback to process it on behalf
805*13101SVenki.Rajagopalan@Sun.COM 	 * of the driver instance. We will let the callback do error
806*13101SVenki.Rajagopalan@Sun.COM 	 * checks.
807*13101SVenki.Rajagopalan@Sun.COM 	 */
808*13101SVenki.Rajagopalan@Sun.COM 	ack = (fip_login_ack_t *)(pkt + ENX_GRH_SZ);
809*13101SVenki.Rajagopalan@Sun.COM 	login = &(ack->ak_vnic_login);
810*13101SVenki.Rajagopalan@Sun.COM 	vnic_id = ntohs(login->vl_vnic_id);
811*13101SVenki.Rajagopalan@Sun.COM 	inst = EIB_DEVI_INSTANCE(vnic_id);
812*13101SVenki.Rajagopalan@Sun.COM 
813*13101SVenki.Rajagopalan@Sun.COM 	if ((rdip = eibnx_find_child_dip_by_inst(info, inst)) == NULL) {
814*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("no eoib child with instance 0x%x found "
815*13101SVenki.Rajagopalan@Sun.COM 		    "for (hca_guid=0x%llx, port_num=0x%x)", inst,
816*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_hca_guid, info->ti_pi->p_port_num);
817*13101SVenki.Rajagopalan@Sun.COM 		return;
818*13101SVenki.Rajagopalan@Sun.COM 	}
819*13101SVenki.Rajagopalan@Sun.COM 
820*13101SVenki.Rajagopalan@Sun.COM 	ret = ndi_event_retrieve_cookie(enx_ndi_event_hdl, rdip,
821*13101SVenki.Rajagopalan@Sun.COM 	    EIB_NDI_EVENT_LOGIN_ACK, &cookie, NDI_EVENT_NOPASS);
822*13101SVenki.Rajagopalan@Sun.COM 	if (ret != NDI_SUCCESS) {
823*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no login-ack cookie for (hca_guid=0x%llx, "
824*13101SVenki.Rajagopalan@Sun.COM 		    "port_num=0x%x, eoib_inst=0x%x), ret=%d", info->ti_hca_guid,
825*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_pi->p_port_num, inst, ret);
826*13101SVenki.Rajagopalan@Sun.COM 		return;
827*13101SVenki.Rajagopalan@Sun.COM 	}
828*13101SVenki.Rajagopalan@Sun.COM 
829*13101SVenki.Rajagopalan@Sun.COM 	(void) ndi_post_event(ss->nx_dip, rdip, cookie, (void *)pkt);
830*13101SVenki.Rajagopalan@Sun.COM }
831*13101SVenki.Rajagopalan@Sun.COM 
832*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_gw_rebirth(eibnx_thr_info_t * info,uint16_t portid)833*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_gw_rebirth(eibnx_thr_info_t *info, uint16_t portid)
834*13101SVenki.Rajagopalan@Sun.COM {
835*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
836*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t cookie;
837*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *rdip;
838*13101SVenki.Rajagopalan@Sun.COM 	int ret;
839*13101SVenki.Rajagopalan@Sun.COM 
840*13101SVenki.Rajagopalan@Sun.COM 	if ((rdip = eibnx_find_child_dip_by_gw(info, portid)) == NULL) {
841*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no eoib child bound to gw portid 0x%x "
842*13101SVenki.Rajagopalan@Sun.COM 		    "found for (hca_guid=0x%llx, port_num=0x%x)",
843*13101SVenki.Rajagopalan@Sun.COM 		    portid, info->ti_hca_guid, info->ti_pi->p_port_num);
844*13101SVenki.Rajagopalan@Sun.COM 		return;
845*13101SVenki.Rajagopalan@Sun.COM 	}
846*13101SVenki.Rajagopalan@Sun.COM 
847*13101SVenki.Rajagopalan@Sun.COM 	ret = ndi_event_retrieve_cookie(enx_ndi_event_hdl, rdip,
848*13101SVenki.Rajagopalan@Sun.COM 	    EIB_NDI_EVENT_GW_AVAILABLE, &cookie, NDI_EVENT_NOPASS);
849*13101SVenki.Rajagopalan@Sun.COM 	if (ret != NDI_SUCCESS) {
850*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no gw-available cookie for (hca_guid=0x%llx, "
851*13101SVenki.Rajagopalan@Sun.COM 		    "port_num=0x%x, gw_portid=0x%x), ret=%d", info->ti_hca_guid,
852*13101SVenki.Rajagopalan@Sun.COM 		    info->ti_pi->p_port_num, portid, ret);
853*13101SVenki.Rajagopalan@Sun.COM 		return;
854*13101SVenki.Rajagopalan@Sun.COM 	}
855*13101SVenki.Rajagopalan@Sun.COM 
856*13101SVenki.Rajagopalan@Sun.COM 	(void) ndi_post_event(ss->nx_dip, rdip, cookie, NULL);
857*13101SVenki.Rajagopalan@Sun.COM }
858*13101SVenki.Rajagopalan@Sun.COM 
859*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_gw_info_update(eibnx_thr_info_t * info,uint16_t portid,void * new_gw_info)860*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_gw_info_update(eibnx_thr_info_t *info, uint16_t portid,
861*13101SVenki.Rajagopalan@Sun.COM     void *new_gw_info)
862*13101SVenki.Rajagopalan@Sun.COM {
863*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
864*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t cookie;
865*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *rdip;
866*13101SVenki.Rajagopalan@Sun.COM 	int ret;
867*13101SVenki.Rajagopalan@Sun.COM 
868*13101SVenki.Rajagopalan@Sun.COM 	if ((rdip = eibnx_find_child_dip_by_gw(info, portid)) == NULL) {
869*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no eoib child bound to gw portid 0x%x "
870*13101SVenki.Rajagopalan@Sun.COM 		    "found for (hca_guid=0x%llx, port_num=0x%x)",
871*13101SVenki.Rajagopalan@Sun.COM 		    portid, info->ti_hca_guid, info->ti_pi->p_port_num);
872*13101SVenki.Rajagopalan@Sun.COM 		return;
873*13101SVenki.Rajagopalan@Sun.COM 	}
874*13101SVenki.Rajagopalan@Sun.COM 
875*13101SVenki.Rajagopalan@Sun.COM 	ret = ndi_event_retrieve_cookie(enx_ndi_event_hdl, rdip,
876*13101SVenki.Rajagopalan@Sun.COM 	    EIB_NDI_EVENT_GW_INFO_UPDATE, &cookie, NDI_EVENT_NOPASS);
877*13101SVenki.Rajagopalan@Sun.COM 	if (ret != NDI_SUCCESS) {
878*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("no gw-info-update cookie for "
879*13101SVenki.Rajagopalan@Sun.COM 		    "(hca_guid=0x%llx, port_num=0x%x, gw_portid=0x%x), "
880*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", info->ti_hca_guid, info->ti_pi->p_port_num,
881*13101SVenki.Rajagopalan@Sun.COM 		    portid, ret);
882*13101SVenki.Rajagopalan@Sun.COM 		return;
883*13101SVenki.Rajagopalan@Sun.COM 	}
884*13101SVenki.Rajagopalan@Sun.COM 
885*13101SVenki.Rajagopalan@Sun.COM 	(void) ndi_post_event(ss->nx_dip, rdip, cookie, new_gw_info);
886*13101SVenki.Rajagopalan@Sun.COM }
887*13101SVenki.Rajagopalan@Sun.COM 
888*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_replace_portinfo(eibnx_thr_info_t * ti,ibt_hca_portinfo_t * new_pi,uint_t new_size_pi)889*13101SVenki.Rajagopalan@Sun.COM eibnx_replace_portinfo(eibnx_thr_info_t *ti, ibt_hca_portinfo_t *new_pi,
890*13101SVenki.Rajagopalan@Sun.COM     uint_t new_size_pi)
891*13101SVenki.Rajagopalan@Sun.COM {
892*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
893*13101SVenki.Rajagopalan@Sun.COM 	eibnx_hca_t *hca;
894*13101SVenki.Rajagopalan@Sun.COM 	eibnx_port_t *port;
895*13101SVenki.Rajagopalan@Sun.COM 
896*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
897*13101SVenki.Rajagopalan@Sun.COM 
898*13101SVenki.Rajagopalan@Sun.COM 	for (hca = ss->nx_hca; hca; hca = hca->hc_next) {
899*13101SVenki.Rajagopalan@Sun.COM 		if (hca->hc_hdl == ti->ti_hca)
900*13101SVenki.Rajagopalan@Sun.COM 			break;
901*13101SVenki.Rajagopalan@Sun.COM 	}
902*13101SVenki.Rajagopalan@Sun.COM 
903*13101SVenki.Rajagopalan@Sun.COM 	if (hca == NULL) {
904*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("hca hdl (0x%llx) not found in hca list",
905*13101SVenki.Rajagopalan@Sun.COM 		    ti->ti_hca);
906*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->nx_lock);
907*13101SVenki.Rajagopalan@Sun.COM 		return (ENX_E_FAILURE);
908*13101SVenki.Rajagopalan@Sun.COM 	}
909*13101SVenki.Rajagopalan@Sun.COM 
910*13101SVenki.Rajagopalan@Sun.COM 	for (port = hca->hc_port; port; port = port->po_next) {
911*13101SVenki.Rajagopalan@Sun.COM 		if (port->po_pi == ti->ti_pi) {
912*13101SVenki.Rajagopalan@Sun.COM 			ibt_free_portinfo(port->po_pi, port->po_pi_size);
913*13101SVenki.Rajagopalan@Sun.COM 			port->po_pi = new_pi;
914*13101SVenki.Rajagopalan@Sun.COM 			port->po_pi_size = new_size_pi;
915*13101SVenki.Rajagopalan@Sun.COM 			ti->ti_pi = port->po_pi;
916*13101SVenki.Rajagopalan@Sun.COM 			break;
917*13101SVenki.Rajagopalan@Sun.COM 		}
918*13101SVenki.Rajagopalan@Sun.COM 	}
919*13101SVenki.Rajagopalan@Sun.COM 
920*13101SVenki.Rajagopalan@Sun.COM 	if (port == NULL) {
921*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("portinfo (0x%llx) not found in hca list",
922*13101SVenki.Rajagopalan@Sun.COM 		    ti->ti_pi);
923*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->nx_lock);
924*13101SVenki.Rajagopalan@Sun.COM 		return (ENX_E_FAILURE);
925*13101SVenki.Rajagopalan@Sun.COM 	}
926*13101SVenki.Rajagopalan@Sun.COM 
927*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
928*13101SVenki.Rajagopalan@Sun.COM 
929*13101SVenki.Rajagopalan@Sun.COM 	return (ENX_E_SUCCESS);
930*13101SVenki.Rajagopalan@Sun.COM }
931*13101SVenki.Rajagopalan@Sun.COM 
932*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_port_events(ibt_hca_hdl_t ev_hca,uint8_t ev_portnum)933*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_port_events(ibt_hca_hdl_t ev_hca, uint8_t ev_portnum)
934*13101SVenki.Rajagopalan@Sun.COM {
935*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
936*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
937*13101SVenki.Rajagopalan@Sun.COM 	ibt_hca_portinfo_t *pi;
938*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
939*13101SVenki.Rajagopalan@Sun.COM 	uint_t num_pi;
940*13101SVenki.Rajagopalan@Sun.COM 	uint_t size_pi;
941*13101SVenki.Rajagopalan@Sun.COM 	uint8_t itr;
942*13101SVenki.Rajagopalan@Sun.COM 
943*13101SVenki.Rajagopalan@Sun.COM 	/*
944*13101SVenki.Rajagopalan@Sun.COM 	 * Find the port monitor thread that matches the event hca and
945*13101SVenki.Rajagopalan@Sun.COM 	 * portnum
946*13101SVenki.Rajagopalan@Sun.COM 	 */
947*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
948*13101SVenki.Rajagopalan@Sun.COM 	for (ti = ss->nx_thr_info; ti; ti = ti->ti_next) {
949*13101SVenki.Rajagopalan@Sun.COM 		if ((ti->ti_hca == ev_hca) &&
950*13101SVenki.Rajagopalan@Sun.COM 		    (ti->ti_pi->p_port_num == ev_portnum)) {
951*13101SVenki.Rajagopalan@Sun.COM 			break;
952*13101SVenki.Rajagopalan@Sun.COM 		}
953*13101SVenki.Rajagopalan@Sun.COM 	}
954*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
955*13101SVenki.Rajagopalan@Sun.COM 
956*13101SVenki.Rajagopalan@Sun.COM 	if (ti == NULL)
957*13101SVenki.Rajagopalan@Sun.COM 		return;
958*13101SVenki.Rajagopalan@Sun.COM 
959*13101SVenki.Rajagopalan@Sun.COM 	/*
960*13101SVenki.Rajagopalan@Sun.COM 	 * See if we need to rejoin the mcgs for this port and do so if true
961*13101SVenki.Rajagopalan@Sun.COM 	 */
962*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_query_hca_ports(ev_hca, ev_portnum, &pi, &num_pi, &size_pi);
963*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
964*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt_query_hca_ports() failed with %d", ret);
965*13101SVenki.Rajagopalan@Sun.COM 		return;
966*13101SVenki.Rajagopalan@Sun.COM 	} else if (num_pi != 1 || pi->p_linkstate != IBT_PORT_ACTIVE) {
967*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("ibt_query_hca_ports(port_num=%d) failed, "
968*13101SVenki.Rajagopalan@Sun.COM 		    "num_pi=%d, linkstate=0x%x", ev_portnum, num_pi,
969*13101SVenki.Rajagopalan@Sun.COM 		    pi->p_linkstate);
970*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_portinfo(pi, size_pi);
971*13101SVenki.Rajagopalan@Sun.COM 		return;
972*13101SVenki.Rajagopalan@Sun.COM 	}
973*13101SVenki.Rajagopalan@Sun.COM 
974*13101SVenki.Rajagopalan@Sun.COM 	itr = pi->p_init_type_reply;
975*13101SVenki.Rajagopalan@Sun.COM 	if (ENX_PORT_ATTR_LOADED(itr) && ENX_PORT_ATTR_NOT_PRESERVED(itr)) {
976*13101SVenki.Rajagopalan@Sun.COM 		/*
977*13101SVenki.Rajagopalan@Sun.COM 		 * If our port's base lid has changed, we need to replace
978*13101SVenki.Rajagopalan@Sun.COM 		 * the saved portinfo in our lists with the new one before
979*13101SVenki.Rajagopalan@Sun.COM 		 * going further.
980*13101SVenki.Rajagopalan@Sun.COM 		 */
981*13101SVenki.Rajagopalan@Sun.COM 		if (ti->ti_pi->p_base_lid != pi->p_base_lid) {
982*13101SVenki.Rajagopalan@Sun.COM 			if (eibnx_replace_portinfo(ti, pi, size_pi) ==
983*13101SVenki.Rajagopalan@Sun.COM 			    ENX_E_SUCCESS) {
984*13101SVenki.Rajagopalan@Sun.COM 				pi = NULL;
985*13101SVenki.Rajagopalan@Sun.COM 				size_pi = 0;
986*13101SVenki.Rajagopalan@Sun.COM 			}
987*13101SVenki.Rajagopalan@Sun.COM 		}
988*13101SVenki.Rajagopalan@Sun.COM 	}
989*13101SVenki.Rajagopalan@Sun.COM 
990*13101SVenki.Rajagopalan@Sun.COM 	/*
991*13101SVenki.Rajagopalan@Sun.COM 	 * If the port monitor was stuck waiting for the link to come up,
992*13101SVenki.Rajagopalan@Sun.COM 	 * let it know that it is up now.
993*13101SVenki.Rajagopalan@Sun.COM 	 */
994*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ti->ti_event_lock);
995*13101SVenki.Rajagopalan@Sun.COM 	if ((ti->ti_progress & ENX_MON_LINKSTATE_UP) != ENX_MON_LINKSTATE_UP) {
996*13101SVenki.Rajagopalan@Sun.COM 		ti->ti_pi->p_linkstate = IBT_PORT_ACTIVE;
997*13101SVenki.Rajagopalan@Sun.COM 		ti->ti_event |= ENX_EVENT_LINK_UP;
998*13101SVenki.Rajagopalan@Sun.COM 		cv_broadcast(&ti->ti_event_cv);
999*13101SVenki.Rajagopalan@Sun.COM 	}
1000*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ti->ti_event_lock);
1001*13101SVenki.Rajagopalan@Sun.COM 
1002*13101SVenki.Rajagopalan@Sun.COM 	if (ENX_PORT_PRES_NOT_PRESERVED(itr)) {
1003*13101SVenki.Rajagopalan@Sun.COM 		if (ti->ti_progress & ENX_MON_JOINED_MCGS)
1004*13101SVenki.Rajagopalan@Sun.COM 			(void) eibnx_rejoin_mcgs(ti);
1005*13101SVenki.Rajagopalan@Sun.COM 	}
1006*13101SVenki.Rajagopalan@Sun.COM 
1007*13101SVenki.Rajagopalan@Sun.COM 	if (pi != NULL)
1008*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_portinfo(pi, size_pi);
1009*13101SVenki.Rajagopalan@Sun.COM }
1010*13101SVenki.Rajagopalan@Sun.COM 
1011*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_hca_attach(ib_guid_t new_hca_guid)1012*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_hca_attach(ib_guid_t new_hca_guid)
1013*13101SVenki.Rajagopalan@Sun.COM {
1014*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
1015*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
1016*13101SVenki.Rajagopalan@Sun.COM 	eibnx_hca_t *hca;
1017*13101SVenki.Rajagopalan@Sun.COM 	eibnx_port_t *port;
1018*13101SVenki.Rajagopalan@Sun.COM 
1019*13101SVenki.Rajagopalan@Sun.COM 	/*
1020*13101SVenki.Rajagopalan@Sun.COM 	 * All we need to do is to start a port monitor for all the ports
1021*13101SVenki.Rajagopalan@Sun.COM 	 * on the new HCA.  To do this, go through our current port monitors
1022*13101SVenki.Rajagopalan@Sun.COM 	 * and see if we already have a monitor for this HCA - if so, print
1023*13101SVenki.Rajagopalan@Sun.COM 	 * a warning and return.
1024*13101SVenki.Rajagopalan@Sun.COM 	 */
1025*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
1026*13101SVenki.Rajagopalan@Sun.COM 	for (ti = ss->nx_thr_info; ti; ti = ti->ti_next) {
1027*13101SVenki.Rajagopalan@Sun.COM 		if (ti->ti_hca_guid == new_hca_guid) {
1028*13101SVenki.Rajagopalan@Sun.COM 			ENX_DPRINTF_VERBOSE("hca (guid=0x%llx) already "
1029*13101SVenki.Rajagopalan@Sun.COM 			    "attached", new_hca_guid);
1030*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->nx_lock);
1031*13101SVenki.Rajagopalan@Sun.COM 			return;
1032*13101SVenki.Rajagopalan@Sun.COM 		}
1033*13101SVenki.Rajagopalan@Sun.COM 	}
1034*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
1035*13101SVenki.Rajagopalan@Sun.COM 
1036*13101SVenki.Rajagopalan@Sun.COM 	/*
1037*13101SVenki.Rajagopalan@Sun.COM 	 * If we don't have it in our list, process the HCA and start the
1038*13101SVenki.Rajagopalan@Sun.COM 	 * port monitors
1039*13101SVenki.Rajagopalan@Sun.COM 	 */
1040*13101SVenki.Rajagopalan@Sun.COM 	if ((hca = eibnx_prepare_hca(new_hca_guid)) != NULL) {
1041*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->nx_lock);
1042*13101SVenki.Rajagopalan@Sun.COM 
1043*13101SVenki.Rajagopalan@Sun.COM 		hca->hc_next = ss->nx_hca;
1044*13101SVenki.Rajagopalan@Sun.COM 		ss->nx_hca = hca;
1045*13101SVenki.Rajagopalan@Sun.COM 
1046*13101SVenki.Rajagopalan@Sun.COM 		for (port = hca->hc_port; port; port = port->po_next) {
1047*13101SVenki.Rajagopalan@Sun.COM 			ti = eibnx_start_port_monitor(hca, port);
1048*13101SVenki.Rajagopalan@Sun.COM 
1049*13101SVenki.Rajagopalan@Sun.COM 			ti->ti_next = ss->nx_thr_info;
1050*13101SVenki.Rajagopalan@Sun.COM 			ss->nx_thr_info = ti;
1051*13101SVenki.Rajagopalan@Sun.COM 		}
1052*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->nx_lock);
1053*13101SVenki.Rajagopalan@Sun.COM 	}
1054*13101SVenki.Rajagopalan@Sun.COM }
1055*13101SVenki.Rajagopalan@Sun.COM 
1056*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_handle_hca_detach(ib_guid_t del_hca_guid)1057*13101SVenki.Rajagopalan@Sun.COM eibnx_handle_hca_detach(ib_guid_t del_hca_guid)
1058*13101SVenki.Rajagopalan@Sun.COM {
1059*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
1060*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
1061*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti_stop_list = NULL;
1062*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti_prev;
1063*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti_next;
1064*13101SVenki.Rajagopalan@Sun.COM 	eibnx_hca_t *hca;
1065*13101SVenki.Rajagopalan@Sun.COM 	eibnx_hca_t *hca_prev;
1066*13101SVenki.Rajagopalan@Sun.COM 
1067*13101SVenki.Rajagopalan@Sun.COM 	/*
1068*13101SVenki.Rajagopalan@Sun.COM 	 * We need to locate all monitor threads for this HCA and stop them
1069*13101SVenki.Rajagopalan@Sun.COM 	 */
1070*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
1071*13101SVenki.Rajagopalan@Sun.COM 	ti_prev = NULL;
1072*13101SVenki.Rajagopalan@Sun.COM 	for (ti = ss->nx_thr_info; ti; ti = ti_next) {
1073*13101SVenki.Rajagopalan@Sun.COM 		ti_next = ti->ti_next;
1074*13101SVenki.Rajagopalan@Sun.COM 
1075*13101SVenki.Rajagopalan@Sun.COM 		if (ti->ti_hca_guid != del_hca_guid) {
1076*13101SVenki.Rajagopalan@Sun.COM 			ti_prev = ti;
1077*13101SVenki.Rajagopalan@Sun.COM 		} else {
1078*13101SVenki.Rajagopalan@Sun.COM 			/*
1079*13101SVenki.Rajagopalan@Sun.COM 			 * Take it out from the good list
1080*13101SVenki.Rajagopalan@Sun.COM 			 */
1081*13101SVenki.Rajagopalan@Sun.COM 			if (ti_prev)
1082*13101SVenki.Rajagopalan@Sun.COM 				ti_prev->ti_next = ti_next;
1083*13101SVenki.Rajagopalan@Sun.COM 			else
1084*13101SVenki.Rajagopalan@Sun.COM 				ss->nx_thr_info = ti_next;
1085*13101SVenki.Rajagopalan@Sun.COM 
1086*13101SVenki.Rajagopalan@Sun.COM 			/*
1087*13101SVenki.Rajagopalan@Sun.COM 			 * And put it in the to-stop list
1088*13101SVenki.Rajagopalan@Sun.COM 			 */
1089*13101SVenki.Rajagopalan@Sun.COM 			ti->ti_next = ti_stop_list;
1090*13101SVenki.Rajagopalan@Sun.COM 			ti_stop_list = ti;
1091*13101SVenki.Rajagopalan@Sun.COM 		}
1092*13101SVenki.Rajagopalan@Sun.COM 	}
1093*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
1094*13101SVenki.Rajagopalan@Sun.COM 
1095*13101SVenki.Rajagopalan@Sun.COM 	/*
1096*13101SVenki.Rajagopalan@Sun.COM 	 * Ask all the port_monitor threads to die.
1097*13101SVenki.Rajagopalan@Sun.COM 	 */
1098*13101SVenki.Rajagopalan@Sun.COM 	for (ti = ti_stop_list; ti; ti = ti_next) {
1099*13101SVenki.Rajagopalan@Sun.COM 		ti_next = ti->ti_next;
1100*13101SVenki.Rajagopalan@Sun.COM 		eibnx_stop_port_monitor(ti);
1101*13101SVenki.Rajagopalan@Sun.COM 	}
1102*13101SVenki.Rajagopalan@Sun.COM 
1103*13101SVenki.Rajagopalan@Sun.COM 	/*
1104*13101SVenki.Rajagopalan@Sun.COM 	 * Now, locate the HCA in our list and release all HCA related
1105*13101SVenki.Rajagopalan@Sun.COM 	 * resources.
1106*13101SVenki.Rajagopalan@Sun.COM 	 */
1107*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
1108*13101SVenki.Rajagopalan@Sun.COM 	hca_prev = NULL;
1109*13101SVenki.Rajagopalan@Sun.COM 	for (hca = ss->nx_hca; hca; hca = hca->hc_next) {
1110*13101SVenki.Rajagopalan@Sun.COM 		if (hca->hc_guid != del_hca_guid) {
1111*13101SVenki.Rajagopalan@Sun.COM 			hca_prev = hca;
1112*13101SVenki.Rajagopalan@Sun.COM 		} else {
1113*13101SVenki.Rajagopalan@Sun.COM 			if (hca_prev) {
1114*13101SVenki.Rajagopalan@Sun.COM 				hca_prev->hc_next = hca->hc_next;
1115*13101SVenki.Rajagopalan@Sun.COM 			} else {
1116*13101SVenki.Rajagopalan@Sun.COM 				ss->nx_hca = hca->hc_next;
1117*13101SVenki.Rajagopalan@Sun.COM 			}
1118*13101SVenki.Rajagopalan@Sun.COM 			hca->hc_next = NULL;
1119*13101SVenki.Rajagopalan@Sun.COM 			break;
1120*13101SVenki.Rajagopalan@Sun.COM 		}
1121*13101SVenki.Rajagopalan@Sun.COM 	}
1122*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
1123*13101SVenki.Rajagopalan@Sun.COM 
1124*13101SVenki.Rajagopalan@Sun.COM 	if (hca) {
1125*13101SVenki.Rajagopalan@Sun.COM 		(void) eibnx_cleanup_hca(hca);
1126*13101SVenki.Rajagopalan@Sun.COM 	}
1127*13101SVenki.Rajagopalan@Sun.COM }
1128