xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_svc.c (revision 13101:da7b13ec3a28)
1*13101SVenki.Rajagopalan@Sun.COM /*
2*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER START
3*13101SVenki.Rajagopalan@Sun.COM  *
4*13101SVenki.Rajagopalan@Sun.COM  * The contents of this file are subject to the terms of the
5*13101SVenki.Rajagopalan@Sun.COM  * Common Development and Distribution License (the "License").
6*13101SVenki.Rajagopalan@Sun.COM  * You may not use this file except in compliance with the License.
7*13101SVenki.Rajagopalan@Sun.COM  *
8*13101SVenki.Rajagopalan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13101SVenki.Rajagopalan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*13101SVenki.Rajagopalan@Sun.COM  * See the License for the specific language governing permissions
11*13101SVenki.Rajagopalan@Sun.COM  * and limitations under the License.
12*13101SVenki.Rajagopalan@Sun.COM  *
13*13101SVenki.Rajagopalan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13101SVenki.Rajagopalan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13101SVenki.Rajagopalan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13101SVenki.Rajagopalan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13101SVenki.Rajagopalan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13101SVenki.Rajagopalan@Sun.COM  *
19*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER END
20*13101SVenki.Rajagopalan@Sun.COM  */
21*13101SVenki.Rajagopalan@Sun.COM 
22*13101SVenki.Rajagopalan@Sun.COM /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13101SVenki.Rajagopalan@Sun.COM  */
25*13101SVenki.Rajagopalan@Sun.COM 
26*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
27*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/callb.h>
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/mac_provider.h>
34*13101SVenki.Rajagopalan@Sun.COM 
35*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
36*13101SVenki.Rajagopalan@Sun.COM 
37*13101SVenki.Rajagopalan@Sun.COM /*
38*13101SVenki.Rajagopalan@Sun.COM  * Thread to handle EoIB events asynchronously
39*13101SVenki.Rajagopalan@Sun.COM  */
40*13101SVenki.Rajagopalan@Sun.COM void
eib_events_handler(eib_t * ss)41*13101SVenki.Rajagopalan@Sun.COM eib_events_handler(eib_t *ss)
42*13101SVenki.Rajagopalan@Sun.COM {
43*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *evi;
44*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *nxt;
45*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
46*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
47*13101SVenki.Rajagopalan@Sun.COM 
48*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
49*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_EVENTS_HDLR);
50*13101SVenki.Rajagopalan@Sun.COM 
51*13101SVenki.Rajagopalan@Sun.COM wait_for_event:
52*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ev_lock);
53*13101SVenki.Rajagopalan@Sun.COM 	while ((evi = ss->ei_event) == NULL) {
54*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
55*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
56*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
57*13101SVenki.Rajagopalan@Sun.COM 
58*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ss->ei_ev_cv, &ss->ei_ev_lock);
59*13101SVenki.Rajagopalan@Sun.COM 
60*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
61*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
62*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
63*13101SVenki.Rajagopalan@Sun.COM 	}
64*13101SVenki.Rajagopalan@Sun.COM 
65*13101SVenki.Rajagopalan@Sun.COM 	/*
66*13101SVenki.Rajagopalan@Sun.COM 	 * Are we being asked to die ?
67*13101SVenki.Rajagopalan@Sun.COM 	 */
68*13101SVenki.Rajagopalan@Sun.COM 	if (evi->ev_code == EIB_EV_SHUTDOWN) {
69*13101SVenki.Rajagopalan@Sun.COM 		while (evi) {
70*13101SVenki.Rajagopalan@Sun.COM 			nxt = evi->ev_next;
71*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(evi, sizeof (eib_event_t));
72*13101SVenki.Rajagopalan@Sun.COM 			evi = nxt;
73*13101SVenki.Rajagopalan@Sun.COM 		}
74*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_event = NULL;
75*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_ev_lock);
76*13101SVenki.Rajagopalan@Sun.COM 
77*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
78*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
79*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
80*13101SVenki.Rajagopalan@Sun.COM 
81*13101SVenki.Rajagopalan@Sun.COM 		return;
82*13101SVenki.Rajagopalan@Sun.COM 	}
83*13101SVenki.Rajagopalan@Sun.COM 
84*13101SVenki.Rajagopalan@Sun.COM 	/*
85*13101SVenki.Rajagopalan@Sun.COM 	 * Otherwise, pull out the first entry from our work queue
86*13101SVenki.Rajagopalan@Sun.COM 	 */
87*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_event = evi->ev_next;
88*13101SVenki.Rajagopalan@Sun.COM 	evi->ev_next = NULL;
89*13101SVenki.Rajagopalan@Sun.COM 
90*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_ev_lock);
91*13101SVenki.Rajagopalan@Sun.COM 
92*13101SVenki.Rajagopalan@Sun.COM 	/*
93*13101SVenki.Rajagopalan@Sun.COM 	 * Process this event
94*13101SVenki.Rajagopalan@Sun.COM 	 *
95*13101SVenki.Rajagopalan@Sun.COM 	 * Note that we don't want to race with plumb/unplumb in this
96*13101SVenki.Rajagopalan@Sun.COM 	 * handler, since we may have to restart vnics or do stuff that
97*13101SVenki.Rajagopalan@Sun.COM 	 * may get re-initialized or released if we allowed plumb/unplumb
98*13101SVenki.Rajagopalan@Sun.COM 	 * to happen in parallel.
99*13101SVenki.Rajagopalan@Sun.COM 	 */
100*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_set_nic_state(ss, EIB_NIC_RESTARTING);
101*13101SVenki.Rajagopalan@Sun.COM 
102*13101SVenki.Rajagopalan@Sun.COM 	switch (evi->ev_code) {
103*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_PORT_DOWN:
104*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
105*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_PORT_DOWN");
106*13101SVenki.Rajagopalan@Sun.COM 
107*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_link_down(ss, B_FALSE);
108*13101SVenki.Rajagopalan@Sun.COM 
109*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
110*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_PORT_DOWN");
111*13101SVenki.Rajagopalan@Sun.COM 		break;
112*13101SVenki.Rajagopalan@Sun.COM 
113*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_PORT_UP:
114*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
115*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_PORT_UP");
116*13101SVenki.Rajagopalan@Sun.COM 
117*13101SVenki.Rajagopalan@Sun.COM 		eib_ibt_link_mod(ss);
118*13101SVenki.Rajagopalan@Sun.COM 
119*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
120*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_PORT_UP");
121*13101SVenki.Rajagopalan@Sun.COM 		break;
122*13101SVenki.Rajagopalan@Sun.COM 
123*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_PKEY_CHANGE:
124*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
125*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_PKEY_CHANGE");
126*13101SVenki.Rajagopalan@Sun.COM 
127*13101SVenki.Rajagopalan@Sun.COM 		eib_ibt_link_mod(ss);
128*13101SVenki.Rajagopalan@Sun.COM 
129*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
130*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_PKEY_CHANGE");
131*13101SVenki.Rajagopalan@Sun.COM 		break;
132*13101SVenki.Rajagopalan@Sun.COM 
133*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_SGID_CHANGE:
134*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
135*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_SGID_CHANGE");
136*13101SVenki.Rajagopalan@Sun.COM 
137*13101SVenki.Rajagopalan@Sun.COM 		eib_ibt_link_mod(ss);
138*13101SVenki.Rajagopalan@Sun.COM 
139*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
140*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_SGID_CHANGE");
141*13101SVenki.Rajagopalan@Sun.COM 		break;
142*13101SVenki.Rajagopalan@Sun.COM 
143*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_CLNT_REREG:
144*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
145*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_CLNT_REREG");
146*13101SVenki.Rajagopalan@Sun.COM 
147*13101SVenki.Rajagopalan@Sun.COM 		eib_ibt_link_mod(ss);
148*13101SVenki.Rajagopalan@Sun.COM 
149*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
150*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_CLNT_REREG");
151*13101SVenki.Rajagopalan@Sun.COM 		break;
152*13101SVenki.Rajagopalan@Sun.COM 
153*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_GW_UP:
154*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
155*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_GW_UP");
156*13101SVenki.Rajagopalan@Sun.COM 
157*13101SVenki.Rajagopalan@Sun.COM 		/*
158*13101SVenki.Rajagopalan@Sun.COM 		 * EoIB nexus has notified us that our gateway is now
159*13101SVenki.Rajagopalan@Sun.COM 		 * reachable. Unless we already think it is reachable,
160*13101SVenki.Rajagopalan@Sun.COM 		 * mark it so in our records and try to resurrect dead
161*13101SVenki.Rajagopalan@Sun.COM 		 * vnics.
162*13101SVenki.Rajagopalan@Sun.COM 		 */
163*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->ei_vnic_lock);
164*13101SVenki.Rajagopalan@Sun.COM 		if (ss->ei_gw_unreachable == B_FALSE) {
165*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
166*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: gw reachable");
167*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->ei_vnic_lock);
168*13101SVenki.Rajagopalan@Sun.COM 
169*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
170*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: End EIB_EV_GW_UP");
171*13101SVenki.Rajagopalan@Sun.COM 			break;
172*13101SVenki.Rajagopalan@Sun.COM 		}
173*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_gw_unreachable = B_FALSE;
174*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
175*13101SVenki.Rajagopalan@Sun.COM 
176*13101SVenki.Rajagopalan@Sun.COM 		/*
177*13101SVenki.Rajagopalan@Sun.COM 		 * If we've not even started yet, we have nothing to do.
178*13101SVenki.Rajagopalan@Sun.COM 		 */
179*13101SVenki.Rajagopalan@Sun.COM 		if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0) {
180*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
181*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: End EIB_EV_GW_UP");
182*13101SVenki.Rajagopalan@Sun.COM 			break;
183*13101SVenki.Rajagopalan@Sun.COM 		}
184*13101SVenki.Rajagopalan@Sun.COM 
185*13101SVenki.Rajagopalan@Sun.COM 		if (eib_mac_hca_portstate(ss, NULL, NULL) != EIB_E_SUCCESS) {
186*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
187*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: "
188*13101SVenki.Rajagopalan@Sun.COM 			    "HCA portstate failed, marking link down");
189*13101SVenki.Rajagopalan@Sun.COM 
190*13101SVenki.Rajagopalan@Sun.COM 			eib_mac_link_down(ss, B_FALSE);
191*13101SVenki.Rajagopalan@Sun.COM 		} else {
192*13101SVenki.Rajagopalan@Sun.COM 			uint8_t vn0_mac[ETHERADDRL];
193*13101SVenki.Rajagopalan@Sun.COM 
194*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
195*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: "
196*13101SVenki.Rajagopalan@Sun.COM 			    "HCA portstate ok, resurrecting zombies");
197*13101SVenki.Rajagopalan@Sun.COM 
198*13101SVenki.Rajagopalan@Sun.COM 			bcopy(eib_zero_mac, vn0_mac, ETHERADDRL);
199*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_resurrect_zombies(ss, vn0_mac);
200*13101SVenki.Rajagopalan@Sun.COM 
201*13101SVenki.Rajagopalan@Sun.COM 			/*
202*13101SVenki.Rajagopalan@Sun.COM 			 * If we've resurrected the zombies because the gateway
203*13101SVenki.Rajagopalan@Sun.COM 			 * went down and came back, it is possible our unicast
204*13101SVenki.Rajagopalan@Sun.COM 			 * mac address changed from what it was earlier. If
205*13101SVenki.Rajagopalan@Sun.COM 			 * so, we need to update our unicast address with the
206*13101SVenki.Rajagopalan@Sun.COM 			 * mac layer before marking the link up.
207*13101SVenki.Rajagopalan@Sun.COM 			 */
208*13101SVenki.Rajagopalan@Sun.COM 			if (bcmp(vn0_mac, eib_zero_mac, ETHERADDRL) != 0) {
209*13101SVenki.Rajagopalan@Sun.COM 				EIB_DPRINTF_DEBUG(ss->ei_instance,
210*13101SVenki.Rajagopalan@Sun.COM 				    "eib_events_handler: updating unicast "
211*13101SVenki.Rajagopalan@Sun.COM 				    "addr to %x:%x:%x:%x:%x:%x", vn0_mac[0],
212*13101SVenki.Rajagopalan@Sun.COM 				    vn0_mac[1], vn0_mac[2], vn0_mac[3],
213*13101SVenki.Rajagopalan@Sun.COM 				    vn0_mac[4], vn0_mac[5]);
214*13101SVenki.Rajagopalan@Sun.COM 
215*13101SVenki.Rajagopalan@Sun.COM 				mac_unicst_update(ss->ei_mac_hdl, vn0_mac);
216*13101SVenki.Rajagopalan@Sun.COM 			}
217*13101SVenki.Rajagopalan@Sun.COM 
218*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
219*13101SVenki.Rajagopalan@Sun.COM 			    "eib_events_handler: eib_mac_link_up(B_FALSE)");
220*13101SVenki.Rajagopalan@Sun.COM 
221*13101SVenki.Rajagopalan@Sun.COM 			eib_mac_link_up(ss, B_FALSE);
222*13101SVenki.Rajagopalan@Sun.COM 		}
223*13101SVenki.Rajagopalan@Sun.COM 
224*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
225*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_GW_UP");
226*13101SVenki.Rajagopalan@Sun.COM 		break;
227*13101SVenki.Rajagopalan@Sun.COM 
228*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_GW_INFO_UPDATE:
229*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
230*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin EIB_EV_GW_INFO_UPDATE");
231*13101SVenki.Rajagopalan@Sun.COM 
232*13101SVenki.Rajagopalan@Sun.COM 		if (evi->ev_arg) {
233*13101SVenki.Rajagopalan@Sun.COM 			eib_update_props(ss, (eib_gw_info_t *)(evi->ev_arg));
234*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(evi->ev_arg, sizeof (eib_gw_info_t));
235*13101SVenki.Rajagopalan@Sun.COM 		}
236*13101SVenki.Rajagopalan@Sun.COM 
237*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
238*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: End EIB_EV_GW_INFO_UPDATE");
239*13101SVenki.Rajagopalan@Sun.COM 		break;
240*13101SVenki.Rajagopalan@Sun.COM 
241*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_MCG_DELETED:
242*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
243*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin-End EIB_EV_MCG_DELETED");
244*13101SVenki.Rajagopalan@Sun.COM 		break;
245*13101SVenki.Rajagopalan@Sun.COM 
246*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_MCG_CREATED:
247*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
248*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin-End EIB_EV_MCG_CREATED");
249*13101SVenki.Rajagopalan@Sun.COM 		break;
250*13101SVenki.Rajagopalan@Sun.COM 
251*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_GW_EPORT_DOWN:
252*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
253*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin-End EIB_EV_GW_EPORT_DOWN");
254*13101SVenki.Rajagopalan@Sun.COM 		break;
255*13101SVenki.Rajagopalan@Sun.COM 
256*13101SVenki.Rajagopalan@Sun.COM 	case EIB_EV_GW_DOWN:
257*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
258*13101SVenki.Rajagopalan@Sun.COM 		    "eib_events_handler: Begin-End EIB_EV_GW_DOWN");
259*13101SVenki.Rajagopalan@Sun.COM 		break;
260*13101SVenki.Rajagopalan@Sun.COM 	}
261*13101SVenki.Rajagopalan@Sun.COM 
262*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_clr_nic_state(ss, EIB_NIC_RESTARTING);
263*13101SVenki.Rajagopalan@Sun.COM 
264*13101SVenki.Rajagopalan@Sun.COM 	kmem_free(evi, sizeof (eib_event_t));
265*13101SVenki.Rajagopalan@Sun.COM 	goto wait_for_event;
266*13101SVenki.Rajagopalan@Sun.COM 
267*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
268*13101SVenki.Rajagopalan@Sun.COM }
269*13101SVenki.Rajagopalan@Sun.COM 
270*13101SVenki.Rajagopalan@Sun.COM void
eib_svc_enqueue_event(eib_t * ss,eib_event_t * evi)271*13101SVenki.Rajagopalan@Sun.COM eib_svc_enqueue_event(eib_t *ss, eib_event_t *evi)
272*13101SVenki.Rajagopalan@Sun.COM {
273*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *elem = NULL;
274*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *tail = NULL;
275*13101SVenki.Rajagopalan@Sun.COM 
276*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ev_lock);
277*13101SVenki.Rajagopalan@Sun.COM 
278*13101SVenki.Rajagopalan@Sun.COM 	/*
279*13101SVenki.Rajagopalan@Sun.COM 	 * Notice to shutdown has a higher priority than the
280*13101SVenki.Rajagopalan@Sun.COM 	 * rest and goes to the head of the list. Everything
281*13101SVenki.Rajagopalan@Sun.COM 	 * else goes at the end.
282*13101SVenki.Rajagopalan@Sun.COM 	 */
283*13101SVenki.Rajagopalan@Sun.COM 	if (evi->ev_code == EIB_EV_SHUTDOWN) {
284*13101SVenki.Rajagopalan@Sun.COM 		evi->ev_next = ss->ei_event;
285*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_event = evi;
286*13101SVenki.Rajagopalan@Sun.COM 	} else {
287*13101SVenki.Rajagopalan@Sun.COM 		for (elem = ss->ei_event; elem; elem = elem->ev_next)
288*13101SVenki.Rajagopalan@Sun.COM 			tail = elem;
289*13101SVenki.Rajagopalan@Sun.COM 
290*13101SVenki.Rajagopalan@Sun.COM 		if (tail)
291*13101SVenki.Rajagopalan@Sun.COM 			tail->ev_next = evi;
292*13101SVenki.Rajagopalan@Sun.COM 		else
293*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_event = evi;
294*13101SVenki.Rajagopalan@Sun.COM 	}
295*13101SVenki.Rajagopalan@Sun.COM 
296*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&ss->ei_ev_cv);
297*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_ev_lock);
298*13101SVenki.Rajagopalan@Sun.COM }
299*13101SVenki.Rajagopalan@Sun.COM 
300*13101SVenki.Rajagopalan@Sun.COM /*
301*13101SVenki.Rajagopalan@Sun.COM  * Thread to refill channels with rwqes whenever they get low.
302*13101SVenki.Rajagopalan@Sun.COM  */
303*13101SVenki.Rajagopalan@Sun.COM void
eib_refill_rwqes(eib_t * ss)304*13101SVenki.Rajagopalan@Sun.COM eib_refill_rwqes(eib_t *ss)
305*13101SVenki.Rajagopalan@Sun.COM {
306*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan;
307*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
308*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
309*13101SVenki.Rajagopalan@Sun.COM 
310*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
311*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_RWQES_REFILLER);
312*13101SVenki.Rajagopalan@Sun.COM 
313*13101SVenki.Rajagopalan@Sun.COM wait_for_refill_work:
314*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_rxpost_lock);
315*13101SVenki.Rajagopalan@Sun.COM 
316*13101SVenki.Rajagopalan@Sun.COM 	while ((ss->ei_rxpost == NULL) && (ss->ei_rxpost_die == 0)) {
317*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
318*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
319*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
320*13101SVenki.Rajagopalan@Sun.COM 
321*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ss->ei_rxpost_cv, &ss->ei_rxpost_lock);
322*13101SVenki.Rajagopalan@Sun.COM 
323*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
324*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
325*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
326*13101SVenki.Rajagopalan@Sun.COM 	}
327*13101SVenki.Rajagopalan@Sun.COM 
328*13101SVenki.Rajagopalan@Sun.COM 	/*
329*13101SVenki.Rajagopalan@Sun.COM 	 * Discard all requests for refill if we're being asked to die
330*13101SVenki.Rajagopalan@Sun.COM 	 */
331*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_rxpost_die) {
332*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_rxpost = NULL;
333*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_rxpost_lock);
334*13101SVenki.Rajagopalan@Sun.COM 
335*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
336*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
337*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
338*13101SVenki.Rajagopalan@Sun.COM 
339*13101SVenki.Rajagopalan@Sun.COM 		return;
340*13101SVenki.Rajagopalan@Sun.COM 	}
341*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(ss->ei_rxpost != NULL);
342*13101SVenki.Rajagopalan@Sun.COM 
343*13101SVenki.Rajagopalan@Sun.COM 	/*
344*13101SVenki.Rajagopalan@Sun.COM 	 * Take the first element out of the queue
345*13101SVenki.Rajagopalan@Sun.COM 	 */
346*13101SVenki.Rajagopalan@Sun.COM 	chan = ss->ei_rxpost;
347*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_rxpost = chan->ch_rxpost_next;
348*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_rxpost_next = NULL;
349*13101SVenki.Rajagopalan@Sun.COM 
350*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_rxpost_lock);
351*13101SVenki.Rajagopalan@Sun.COM 
352*13101SVenki.Rajagopalan@Sun.COM 	/*
353*13101SVenki.Rajagopalan@Sun.COM 	 * Try to post a bunch of recv wqes into this channel. If we
354*13101SVenki.Rajagopalan@Sun.COM 	 * fail, it means that we haven't even been able to post a
355*13101SVenki.Rajagopalan@Sun.COM 	 * single recv wqe.  This is alarming, but there's nothing
356*13101SVenki.Rajagopalan@Sun.COM 	 * we can do. We just move on to the next channel needing
357*13101SVenki.Rajagopalan@Sun.COM 	 * our service.
358*13101SVenki.Rajagopalan@Sun.COM 	 */
359*13101SVenki.Rajagopalan@Sun.COM 	if (eib_chan_post_rx(ss, chan, NULL) != EIB_E_SUCCESS) {
360*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
361*13101SVenki.Rajagopalan@Sun.COM 		    "eib_refill_rwqes: eib_chan_post_rx() failed");
362*13101SVenki.Rajagopalan@Sun.COM 	}
363*13101SVenki.Rajagopalan@Sun.COM 
364*13101SVenki.Rajagopalan@Sun.COM 	/*
365*13101SVenki.Rajagopalan@Sun.COM 	 * Mark it to indicate that the refilling is done
366*13101SVenki.Rajagopalan@Sun.COM 	 */
367*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_rx_lock);
368*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_rx_refilling = B_FALSE;
369*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_rx_lock);
370*13101SVenki.Rajagopalan@Sun.COM 
371*13101SVenki.Rajagopalan@Sun.COM 	goto wait_for_refill_work;
372*13101SVenki.Rajagopalan@Sun.COM 
373*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
374*13101SVenki.Rajagopalan@Sun.COM }
375*13101SVenki.Rajagopalan@Sun.COM 
376*13101SVenki.Rajagopalan@Sun.COM /*
377*13101SVenki.Rajagopalan@Sun.COM  * Thread to create or restart vnics when required
378*13101SVenki.Rajagopalan@Sun.COM  */
379*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_creator(eib_t * ss)380*13101SVenki.Rajagopalan@Sun.COM eib_vnic_creator(eib_t *ss)
381*13101SVenki.Rajagopalan@Sun.COM {
382*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *vrq;
383*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *elem;
384*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *nxt;
385*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
386*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
387*13101SVenki.Rajagopalan@Sun.COM 	uint_t vr_req;
388*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *vr_mac;
389*13101SVenki.Rajagopalan@Sun.COM 	int ret;
390*13101SVenki.Rajagopalan@Sun.COM 	int err;
391*13101SVenki.Rajagopalan@Sun.COM 
392*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
393*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_VNIC_CREATOR);
394*13101SVenki.Rajagopalan@Sun.COM 
395*13101SVenki.Rajagopalan@Sun.COM wait_for_vnic_req:
396*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_req_lock);
397*13101SVenki.Rajagopalan@Sun.COM 
398*13101SVenki.Rajagopalan@Sun.COM 	while ((vrq = ss->ei_vnic_req) == NULL) {
399*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
400*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
401*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
402*13101SVenki.Rajagopalan@Sun.COM 
403*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ss->ei_vnic_req_cv, &ss->ei_vnic_req_lock);
404*13101SVenki.Rajagopalan@Sun.COM 
405*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
406*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
407*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
408*13101SVenki.Rajagopalan@Sun.COM 	}
409*13101SVenki.Rajagopalan@Sun.COM 
410*13101SVenki.Rajagopalan@Sun.COM 	/*
411*13101SVenki.Rajagopalan@Sun.COM 	 * Pull out the first request
412*13101SVenki.Rajagopalan@Sun.COM 	 */
413*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_req = vrq->vr_next;
414*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_next = NULL;
415*13101SVenki.Rajagopalan@Sun.COM 
416*13101SVenki.Rajagopalan@Sun.COM 	vr_req = vrq->vr_req;
417*13101SVenki.Rajagopalan@Sun.COM 	vr_mac = vrq->vr_mac;
418*13101SVenki.Rajagopalan@Sun.COM 
419*13101SVenki.Rajagopalan@Sun.COM 	switch (vr_req) {
420*13101SVenki.Rajagopalan@Sun.COM 	case EIB_CR_REQ_DIE:
421*13101SVenki.Rajagopalan@Sun.COM 	case EIB_CR_REQ_FLUSH:
422*13101SVenki.Rajagopalan@Sun.COM 		/*
423*13101SVenki.Rajagopalan@Sun.COM 		 * Cleanup all pending reqs and failed reqs
424*13101SVenki.Rajagopalan@Sun.COM 		 */
425*13101SVenki.Rajagopalan@Sun.COM 		for (elem = ss->ei_vnic_req; elem; elem = nxt) {
426*13101SVenki.Rajagopalan@Sun.COM 			nxt = elem->vr_next;
427*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(elem, sizeof (eib_vnic_req_t));
428*13101SVenki.Rajagopalan@Sun.COM 		}
429*13101SVenki.Rajagopalan@Sun.COM 		for (elem = ss->ei_failed_vnic_req; elem; elem = nxt) {
430*13101SVenki.Rajagopalan@Sun.COM 			nxt = elem->vr_next;
431*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(elem, sizeof (eib_vnic_req_t));
432*13101SVenki.Rajagopalan@Sun.COM 		}
433*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_vnic_req = NULL;
434*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_failed_vnic_req = NULL;
435*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_pending_vnic_req = NULL;
436*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_req_lock);
437*13101SVenki.Rajagopalan@Sun.COM 
438*13101SVenki.Rajagopalan@Sun.COM 		break;
439*13101SVenki.Rajagopalan@Sun.COM 
440*13101SVenki.Rajagopalan@Sun.COM 	case EIB_CR_REQ_NEW_VNIC:
441*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_pending_vnic_req = vrq;
442*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_req_lock);
443*13101SVenki.Rajagopalan@Sun.COM 
444*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance, "eib_vnic_creator: "
445*13101SVenki.Rajagopalan@Sun.COM 		    "new vnic creation request for %x:%x:%x:%x:%x:%x, 0x%x",
446*13101SVenki.Rajagopalan@Sun.COM 		    vr_mac[0], vr_mac[1], vr_mac[2], vr_mac[3], vr_mac[4],
447*13101SVenki.Rajagopalan@Sun.COM 		    vr_mac[5], vrq->vr_vlan);
448*13101SVenki.Rajagopalan@Sun.COM 
449*13101SVenki.Rajagopalan@Sun.COM 		/*
450*13101SVenki.Rajagopalan@Sun.COM 		 * Make sure we don't race with the plumb/unplumb code.  If
451*13101SVenki.Rajagopalan@Sun.COM 		 * the eoib instance has been unplumbed already, we ignore any
452*13101SVenki.Rajagopalan@Sun.COM 		 * creation requests that may have been pending.
453*13101SVenki.Rajagopalan@Sun.COM 		 */
454*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_set_nic_state(ss, EIB_NIC_STARTING);
455*13101SVenki.Rajagopalan@Sun.COM 
456*13101SVenki.Rajagopalan@Sun.COM 		if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) !=
457*13101SVenki.Rajagopalan@Sun.COM 		    EIB_NIC_STARTED) {
458*13101SVenki.Rajagopalan@Sun.COM 			mutex_enter(&ss->ei_vnic_req_lock);
459*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_pending_vnic_req = NULL;
460*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->ei_vnic_req_lock);
461*13101SVenki.Rajagopalan@Sun.COM 			eib_mac_clr_nic_state(ss, EIB_NIC_STARTING);
462*13101SVenki.Rajagopalan@Sun.COM 			break;
463*13101SVenki.Rajagopalan@Sun.COM 		}
464*13101SVenki.Rajagopalan@Sun.COM 
465*13101SVenki.Rajagopalan@Sun.COM 		/*
466*13101SVenki.Rajagopalan@Sun.COM 		 * Try to create a new vnic with the supplied parameters.
467*13101SVenki.Rajagopalan@Sun.COM 		 */
468*13101SVenki.Rajagopalan@Sun.COM 		err = 0;
469*13101SVenki.Rajagopalan@Sun.COM 		if ((ret = eib_vnic_create(ss, vrq->vr_mac, vrq->vr_vlan,
470*13101SVenki.Rajagopalan@Sun.COM 		    NULL, &err)) != EIB_E_SUCCESS) {
471*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_creator: "
472*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_create(mac=%x:%x:%x:%x:%x:%x, vlan=0x%x) "
473*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", vr_mac[0], vr_mac[1], vr_mac[2],
474*13101SVenki.Rajagopalan@Sun.COM 			    vr_mac[3], vr_mac[4], vr_mac[5], vrq->vr_vlan, err);
475*13101SVenki.Rajagopalan@Sun.COM 		}
476*13101SVenki.Rajagopalan@Sun.COM 
477*13101SVenki.Rajagopalan@Sun.COM 		/*
478*13101SVenki.Rajagopalan@Sun.COM 		 * If we failed, add this vnic req to our failed list (unless
479*13101SVenki.Rajagopalan@Sun.COM 		 * it already exists there), so we won't try to create this
480*13101SVenki.Rajagopalan@Sun.COM 		 * vnic again.  Whether we fail or succeed, we're done with
481*13101SVenki.Rajagopalan@Sun.COM 		 * processing this req, so clear the pending req.
482*13101SVenki.Rajagopalan@Sun.COM 		 */
483*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->ei_vnic_req_lock);
484*13101SVenki.Rajagopalan@Sun.COM 		if ((ret != EIB_E_SUCCESS) && (err != EEXIST)) {
485*13101SVenki.Rajagopalan@Sun.COM 			vrq->vr_next = ss->ei_failed_vnic_req;
486*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_failed_vnic_req = vrq;
487*13101SVenki.Rajagopalan@Sun.COM 			vrq = NULL;
488*13101SVenki.Rajagopalan@Sun.COM 		}
489*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_pending_vnic_req = NULL;
490*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_req_lock);
491*13101SVenki.Rajagopalan@Sun.COM 
492*13101SVenki.Rajagopalan@Sun.COM 		/*
493*13101SVenki.Rajagopalan@Sun.COM 		 * Notify the mac layer that it should retry its tx again. If we
494*13101SVenki.Rajagopalan@Sun.COM 		 * had created the vnic successfully, we'll be able to send the
495*13101SVenki.Rajagopalan@Sun.COM 		 * packets; if we had not been successful, we'll drop packets on
496*13101SVenki.Rajagopalan@Sun.COM 		 * this vnic.
497*13101SVenki.Rajagopalan@Sun.COM 		 */
498*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
499*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_creator: calling mac_tx_update()");
500*13101SVenki.Rajagopalan@Sun.COM 		mac_tx_update(ss->ei_mac_hdl);
501*13101SVenki.Rajagopalan@Sun.COM 
502*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_clr_nic_state(ss, EIB_NIC_STARTING);
503*13101SVenki.Rajagopalan@Sun.COM 		break;
504*13101SVenki.Rajagopalan@Sun.COM 
505*13101SVenki.Rajagopalan@Sun.COM 	default:
506*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance, "eib_vnic_creator: "
507*13101SVenki.Rajagopalan@Sun.COM 		    "unknown request 0x%lx, ignoring", vrq->vr_req);
508*13101SVenki.Rajagopalan@Sun.COM 		break;
509*13101SVenki.Rajagopalan@Sun.COM 	}
510*13101SVenki.Rajagopalan@Sun.COM 
511*13101SVenki.Rajagopalan@Sun.COM 	/*
512*13101SVenki.Rajagopalan@Sun.COM 	 * Free the current req and quit if we have to
513*13101SVenki.Rajagopalan@Sun.COM 	 */
514*13101SVenki.Rajagopalan@Sun.COM 	if (vrq) {
515*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(vrq, sizeof (eib_vnic_req_t));
516*13101SVenki.Rajagopalan@Sun.COM 	}
517*13101SVenki.Rajagopalan@Sun.COM 
518*13101SVenki.Rajagopalan@Sun.COM 	if (vr_req == EIB_CR_REQ_DIE) {
519*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
520*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
521*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
522*13101SVenki.Rajagopalan@Sun.COM 
523*13101SVenki.Rajagopalan@Sun.COM 		return;
524*13101SVenki.Rajagopalan@Sun.COM 	}
525*13101SVenki.Rajagopalan@Sun.COM 
526*13101SVenki.Rajagopalan@Sun.COM 	goto wait_for_vnic_req;
527*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
528*13101SVenki.Rajagopalan@Sun.COM }
529*13101SVenki.Rajagopalan@Sun.COM 
530*13101SVenki.Rajagopalan@Sun.COM /*
531*13101SVenki.Rajagopalan@Sun.COM  * Thread to monitor tx wqes and update the mac layer when needed.
532*13101SVenki.Rajagopalan@Sun.COM  * Note that this thread can only be started after the tx wqe pool
533*13101SVenki.Rajagopalan@Sun.COM  * has been allocated and initialized.
534*13101SVenki.Rajagopalan@Sun.COM  */
535*13101SVenki.Rajagopalan@Sun.COM void
eib_monitor_tx_wqes(eib_t * ss)536*13101SVenki.Rajagopalan@Sun.COM eib_monitor_tx_wqes(eib_t *ss)
537*13101SVenki.Rajagopalan@Sun.COM {
538*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_pool_t *wp = ss->ei_tx;
539*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
540*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
541*13101SVenki.Rajagopalan@Sun.COM 
542*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
543*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_TXWQES_MONITOR);
544*13101SVenki.Rajagopalan@Sun.COM 
545*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(wp != NULL);
546*13101SVenki.Rajagopalan@Sun.COM 
547*13101SVenki.Rajagopalan@Sun.COM monitor_wqe_status:
548*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&wp->wp_lock);
549*13101SVenki.Rajagopalan@Sun.COM 
550*13101SVenki.Rajagopalan@Sun.COM 	/*
551*13101SVenki.Rajagopalan@Sun.COM 	 * Wait till someone falls short of wqes
552*13101SVenki.Rajagopalan@Sun.COM 	 */
553*13101SVenki.Rajagopalan@Sun.COM 	while (wp->wp_status == 0) {
554*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
555*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
556*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
557*13101SVenki.Rajagopalan@Sun.COM 
558*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&wp->wp_cv, &wp->wp_lock);
559*13101SVenki.Rajagopalan@Sun.COM 
560*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
561*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
562*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
563*13101SVenki.Rajagopalan@Sun.COM 	}
564*13101SVenki.Rajagopalan@Sun.COM 
565*13101SVenki.Rajagopalan@Sun.COM 	/*
566*13101SVenki.Rajagopalan@Sun.COM 	 * Have we been asked to die ?
567*13101SVenki.Rajagopalan@Sun.COM 	 */
568*13101SVenki.Rajagopalan@Sun.COM 	if (wp->wp_status & EIB_TXWQE_MONITOR_DIE) {
569*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&wp->wp_lock);
570*13101SVenki.Rajagopalan@Sun.COM 
571*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
572*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
573*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
574*13101SVenki.Rajagopalan@Sun.COM 
575*13101SVenki.Rajagopalan@Sun.COM 		return;
576*13101SVenki.Rajagopalan@Sun.COM 	}
577*13101SVenki.Rajagopalan@Sun.COM 
578*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((wp->wp_status & EIB_TXWQE_SHORT) != 0);
579*13101SVenki.Rajagopalan@Sun.COM 
580*13101SVenki.Rajagopalan@Sun.COM 	/*
581*13101SVenki.Rajagopalan@Sun.COM 	 * Start monitoring free wqes till they cross min threshold
582*13101SVenki.Rajagopalan@Sun.COM 	 */
583*13101SVenki.Rajagopalan@Sun.COM 	while ((wp->wp_nfree < EIB_NFREE_SWQES_HWM) &&
584*13101SVenki.Rajagopalan@Sun.COM 	    ((wp->wp_status & EIB_TXWQE_MONITOR_DIE) == 0)) {
585*13101SVenki.Rajagopalan@Sun.COM 
586*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
587*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
588*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
589*13101SVenki.Rajagopalan@Sun.COM 
590*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&wp->wp_cv, &wp->wp_lock);
591*13101SVenki.Rajagopalan@Sun.COM 
592*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
593*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
594*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
595*13101SVenki.Rajagopalan@Sun.COM 	}
596*13101SVenki.Rajagopalan@Sun.COM 
597*13101SVenki.Rajagopalan@Sun.COM 	/*
598*13101SVenki.Rajagopalan@Sun.COM 	 * Have we been asked to die ?
599*13101SVenki.Rajagopalan@Sun.COM 	 */
600*13101SVenki.Rajagopalan@Sun.COM 	if (wp->wp_status & EIB_TXWQE_MONITOR_DIE) {
601*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&wp->wp_lock);
602*13101SVenki.Rajagopalan@Sun.COM 
603*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
604*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
605*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
606*13101SVenki.Rajagopalan@Sun.COM 
607*13101SVenki.Rajagopalan@Sun.COM 		return;
608*13101SVenki.Rajagopalan@Sun.COM 	}
609*13101SVenki.Rajagopalan@Sun.COM 
610*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(wp->wp_nfree >= EIB_NFREE_SWQES_HWM);
611*13101SVenki.Rajagopalan@Sun.COM 	wp->wp_status &= (~EIB_TXWQE_SHORT);
612*13101SVenki.Rajagopalan@Sun.COM 
613*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&wp->wp_lock);
614*13101SVenki.Rajagopalan@Sun.COM 
615*13101SVenki.Rajagopalan@Sun.COM 	/*
616*13101SVenki.Rajagopalan@Sun.COM 	 * Inform the mac layer that tx resources are now available
617*13101SVenki.Rajagopalan@Sun.COM 	 * and go back to monitoring
618*13101SVenki.Rajagopalan@Sun.COM 	 */
619*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_mac_hdl) {
620*13101SVenki.Rajagopalan@Sun.COM 		mac_tx_update(ss->ei_mac_hdl);
621*13101SVenki.Rajagopalan@Sun.COM 	}
622*13101SVenki.Rajagopalan@Sun.COM 	goto monitor_wqe_status;
623*13101SVenki.Rajagopalan@Sun.COM 
624*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
625*13101SVenki.Rajagopalan@Sun.COM }
626*13101SVenki.Rajagopalan@Sun.COM 
627*13101SVenki.Rajagopalan@Sun.COM /*
628*13101SVenki.Rajagopalan@Sun.COM  * Thread to monitor lso bufs and update the mac layer as needed.
629*13101SVenki.Rajagopalan@Sun.COM  * Note that this thread can only be started after the lso buckets
630*13101SVenki.Rajagopalan@Sun.COM  * have been allocated and initialized.
631*13101SVenki.Rajagopalan@Sun.COM  */
632*13101SVenki.Rajagopalan@Sun.COM void
eib_monitor_lso_bufs(eib_t * ss)633*13101SVenki.Rajagopalan@Sun.COM eib_monitor_lso_bufs(eib_t *ss)
634*13101SVenki.Rajagopalan@Sun.COM {
635*13101SVenki.Rajagopalan@Sun.COM 	eib_lsobkt_t *bkt = ss->ei_lso;
636*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
637*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
638*13101SVenki.Rajagopalan@Sun.COM 
639*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
640*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_LSOBUFS_MONITOR);
641*13101SVenki.Rajagopalan@Sun.COM 
642*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(bkt != NULL);
643*13101SVenki.Rajagopalan@Sun.COM 
644*13101SVenki.Rajagopalan@Sun.COM monitor_lso_status:
645*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&bkt->bk_lock);
646*13101SVenki.Rajagopalan@Sun.COM 
647*13101SVenki.Rajagopalan@Sun.COM 	/*
648*13101SVenki.Rajagopalan@Sun.COM 	 * Wait till someone falls short of LSO buffers or we're asked
649*13101SVenki.Rajagopalan@Sun.COM 	 * to die
650*13101SVenki.Rajagopalan@Sun.COM 	 */
651*13101SVenki.Rajagopalan@Sun.COM 	while (bkt->bk_status == 0) {
652*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
653*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
654*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
655*13101SVenki.Rajagopalan@Sun.COM 
656*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&bkt->bk_cv, &bkt->bk_lock);
657*13101SVenki.Rajagopalan@Sun.COM 
658*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
659*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
660*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
661*13101SVenki.Rajagopalan@Sun.COM 	}
662*13101SVenki.Rajagopalan@Sun.COM 
663*13101SVenki.Rajagopalan@Sun.COM 	if (bkt->bk_status & EIB_LBUF_MONITOR_DIE) {
664*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&bkt->bk_lock);
665*13101SVenki.Rajagopalan@Sun.COM 
666*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
667*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
668*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
669*13101SVenki.Rajagopalan@Sun.COM 
670*13101SVenki.Rajagopalan@Sun.COM 		return;
671*13101SVenki.Rajagopalan@Sun.COM 	}
672*13101SVenki.Rajagopalan@Sun.COM 
673*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((bkt->bk_status & EIB_LBUF_SHORT) != 0);
674*13101SVenki.Rajagopalan@Sun.COM 
675*13101SVenki.Rajagopalan@Sun.COM 	/*
676*13101SVenki.Rajagopalan@Sun.COM 	 * Start monitoring free LSO buffers till there are enough
677*13101SVenki.Rajagopalan@Sun.COM 	 * free buffers available
678*13101SVenki.Rajagopalan@Sun.COM 	 */
679*13101SVenki.Rajagopalan@Sun.COM 	while ((bkt->bk_nfree < EIB_LSO_FREE_BUFS_THRESH) &&
680*13101SVenki.Rajagopalan@Sun.COM 	    ((bkt->bk_status & EIB_LBUF_MONITOR_DIE) == 0)) {
681*13101SVenki.Rajagopalan@Sun.COM 
682*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
683*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
684*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
685*13101SVenki.Rajagopalan@Sun.COM 
686*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&bkt->bk_cv, &bkt->bk_lock);
687*13101SVenki.Rajagopalan@Sun.COM 
688*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
689*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
690*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
691*13101SVenki.Rajagopalan@Sun.COM 	}
692*13101SVenki.Rajagopalan@Sun.COM 
693*13101SVenki.Rajagopalan@Sun.COM 	if (bkt->bk_status & EIB_LBUF_MONITOR_DIE) {
694*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&bkt->bk_lock);
695*13101SVenki.Rajagopalan@Sun.COM 
696*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
697*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
698*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
699*13101SVenki.Rajagopalan@Sun.COM 
700*13101SVenki.Rajagopalan@Sun.COM 		return;
701*13101SVenki.Rajagopalan@Sun.COM 	}
702*13101SVenki.Rajagopalan@Sun.COM 
703*13101SVenki.Rajagopalan@Sun.COM 	/*
704*13101SVenki.Rajagopalan@Sun.COM 	 * We have enough lso buffers available now
705*13101SVenki.Rajagopalan@Sun.COM 	 */
706*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(bkt->bk_nfree >= EIB_LSO_FREE_BUFS_THRESH);
707*13101SVenki.Rajagopalan@Sun.COM 	bkt->bk_status &= (~EIB_LBUF_SHORT);
708*13101SVenki.Rajagopalan@Sun.COM 
709*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&bkt->bk_lock);
710*13101SVenki.Rajagopalan@Sun.COM 
711*13101SVenki.Rajagopalan@Sun.COM 	/*
712*13101SVenki.Rajagopalan@Sun.COM 	 * Inform the mac layer that tx lso resources are now available
713*13101SVenki.Rajagopalan@Sun.COM 	 * and go back to monitoring
714*13101SVenki.Rajagopalan@Sun.COM 	 */
715*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_mac_hdl) {
716*13101SVenki.Rajagopalan@Sun.COM 		mac_tx_update(ss->ei_mac_hdl);
717*13101SVenki.Rajagopalan@Sun.COM 	}
718*13101SVenki.Rajagopalan@Sun.COM 	goto monitor_lso_status;
719*13101SVenki.Rajagopalan@Sun.COM 
720*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
721*13101SVenki.Rajagopalan@Sun.COM }
722*13101SVenki.Rajagopalan@Sun.COM 
723*13101SVenki.Rajagopalan@Sun.COM /*
724*13101SVenki.Rajagopalan@Sun.COM  * Thread to manage the keepalive requirements for vnics and the gateway.
725*13101SVenki.Rajagopalan@Sun.COM  */
726*13101SVenki.Rajagopalan@Sun.COM void
eib_manage_keepalives(eib_t * ss)727*13101SVenki.Rajagopalan@Sun.COM eib_manage_keepalives(eib_t *ss)
728*13101SVenki.Rajagopalan@Sun.COM {
729*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *elem;
730*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *nxt;
731*13101SVenki.Rajagopalan@Sun.COM 	clock_t deadline;
732*13101SVenki.Rajagopalan@Sun.COM 	int64_t lbolt64;
733*13101SVenki.Rajagopalan@Sun.COM 	int err;
734*13101SVenki.Rajagopalan@Sun.COM 	kmutex_t ci_lock;
735*13101SVenki.Rajagopalan@Sun.COM 	callb_cpr_t ci;
736*13101SVenki.Rajagopalan@Sun.COM 
737*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ci_lock, NULL, MUTEX_DRIVER, NULL);
738*13101SVenki.Rajagopalan@Sun.COM 	CALLB_CPR_INIT(&ci, &ci_lock, callb_generic_cpr, EIB_EVENTS_HDLR);
739*13101SVenki.Rajagopalan@Sun.COM 
740*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ka_vnics_lock);
741*13101SVenki.Rajagopalan@Sun.COM 
742*13101SVenki.Rajagopalan@Sun.COM periodic_keepalive:
743*13101SVenki.Rajagopalan@Sun.COM 	deadline = ddi_get_lbolt() + ss->ei_gw_props->pp_vnic_ka_ticks;
744*13101SVenki.Rajagopalan@Sun.COM 
745*13101SVenki.Rajagopalan@Sun.COM 	while ((ss->ei_ka_vnics_event &
746*13101SVenki.Rajagopalan@Sun.COM 	    (EIB_KA_VNICS_DIE | EIB_KA_VNICS_TIMED_OUT)) == 0) {
747*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
748*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_BEGIN(&ci);
749*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
750*13101SVenki.Rajagopalan@Sun.COM 
751*13101SVenki.Rajagopalan@Sun.COM 		if (cv_timedwait(&ss->ei_ka_vnics_cv, &ss->ei_ka_vnics_lock,
752*13101SVenki.Rajagopalan@Sun.COM 		    deadline) == -1) {
753*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_ka_vnics_event |= EIB_KA_VNICS_TIMED_OUT;
754*13101SVenki.Rajagopalan@Sun.COM 		}
755*13101SVenki.Rajagopalan@Sun.COM 
756*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
757*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_SAFE_END(&ci, &ci_lock);
758*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ci_lock);
759*13101SVenki.Rajagopalan@Sun.COM 	}
760*13101SVenki.Rajagopalan@Sun.COM 
761*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_ka_vnics_event & EIB_KA_VNICS_DIE) {
762*13101SVenki.Rajagopalan@Sun.COM 		for (elem = ss->ei_ka_vnics; elem; elem = nxt) {
763*13101SVenki.Rajagopalan@Sun.COM 			nxt = elem->ka_next;
764*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(elem, sizeof (eib_ka_vnics_t));
765*13101SVenki.Rajagopalan@Sun.COM 		}
766*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_ka_vnics = NULL;
767*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_ka_vnics_lock);
768*13101SVenki.Rajagopalan@Sun.COM 
769*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ci_lock);
770*13101SVenki.Rajagopalan@Sun.COM 		CALLB_CPR_EXIT(&ci);
771*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ci_lock);
772*13101SVenki.Rajagopalan@Sun.COM 
773*13101SVenki.Rajagopalan@Sun.COM 		return;
774*13101SVenki.Rajagopalan@Sun.COM 	}
775*13101SVenki.Rajagopalan@Sun.COM 
776*13101SVenki.Rajagopalan@Sun.COM 	/*
777*13101SVenki.Rajagopalan@Sun.COM 	 * Are there any vnics that need keepalive management ?
778*13101SVenki.Rajagopalan@Sun.COM 	 */
779*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_ka_vnics_event &= ~EIB_KA_VNICS_TIMED_OUT;
780*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_ka_vnics == NULL)
781*13101SVenki.Rajagopalan@Sun.COM 		goto periodic_keepalive;
782*13101SVenki.Rajagopalan@Sun.COM 
783*13101SVenki.Rajagopalan@Sun.COM 	/*
784*13101SVenki.Rajagopalan@Sun.COM 	 * Ok, we need to send vnic keepalives to our gateway. But first
785*13101SVenki.Rajagopalan@Sun.COM 	 * check if the gateway heartbeat is good as of this moment.  Note
786*13101SVenki.Rajagopalan@Sun.COM 	 * that we need do get the lbolt value after acquiring ei_vnic_lock
787*13101SVenki.Rajagopalan@Sun.COM 	 * to ensure that ei_gw_last_heartbeat does not change before the
788*13101SVenki.Rajagopalan@Sun.COM 	 * comparison (to avoid a negative value in the comparison result
789*13101SVenki.Rajagopalan@Sun.COM 	 * causing us to incorrectly assume that the gateway heartbeat has
790*13101SVenki.Rajagopalan@Sun.COM 	 * stopped).
791*13101SVenki.Rajagopalan@Sun.COM 	 */
792*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
793*13101SVenki.Rajagopalan@Sun.COM 
794*13101SVenki.Rajagopalan@Sun.COM 	lbolt64 = ddi_get_lbolt64();
795*13101SVenki.Rajagopalan@Sun.COM 
796*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_gw_last_heartbeat != 0) {
797*13101SVenki.Rajagopalan@Sun.COM 		if ((lbolt64 - ss->ei_gw_last_heartbeat) >
798*13101SVenki.Rajagopalan@Sun.COM 		    ss->ei_gw_props->pp_gw_ka_ticks) {
799*13101SVenki.Rajagopalan@Sun.COM 
800*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
801*13101SVenki.Rajagopalan@Sun.COM 			    "eib_manage_keepalives: no keepalives from gateway "
802*13101SVenki.Rajagopalan@Sun.COM 			    "0x%x for hca_guid=0x%llx, port=0x%x, "
803*13101SVenki.Rajagopalan@Sun.COM 			    "last_gw_ka=0x%llx", ss->ei_gw_props->pp_gw_portid,
804*13101SVenki.Rajagopalan@Sun.COM 			    ss->ei_props->ep_hca_guid,
805*13101SVenki.Rajagopalan@Sun.COM 			    ss->ei_props->ep_port_num,
806*13101SVenki.Rajagopalan@Sun.COM 			    ss->ei_gw_last_heartbeat);
807*13101SVenki.Rajagopalan@Sun.COM 
808*13101SVenki.Rajagopalan@Sun.COM 			for (elem = ss->ei_ka_vnics; elem; elem = nxt) {
809*13101SVenki.Rajagopalan@Sun.COM 				nxt = elem->ka_next;
810*13101SVenki.Rajagopalan@Sun.COM 				ss->ei_zombie_vnics |=
811*13101SVenki.Rajagopalan@Sun.COM 				    ((uint64_t)1 << elem->ka_vnic->vn_instance);
812*13101SVenki.Rajagopalan@Sun.COM 				kmem_free(elem, sizeof (eib_ka_vnics_t));
813*13101SVenki.Rajagopalan@Sun.COM 			}
814*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_ka_vnics = NULL;
815*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_gw_unreachable = B_TRUE;
816*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->ei_vnic_lock);
817*13101SVenki.Rajagopalan@Sun.COM 
818*13101SVenki.Rajagopalan@Sun.COM 			eib_mac_link_down(ss, B_FALSE);
819*13101SVenki.Rajagopalan@Sun.COM 
820*13101SVenki.Rajagopalan@Sun.COM 			goto periodic_keepalive;
821*13101SVenki.Rajagopalan@Sun.COM 		}
822*13101SVenki.Rajagopalan@Sun.COM 	}
823*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
824*13101SVenki.Rajagopalan@Sun.COM 
825*13101SVenki.Rajagopalan@Sun.COM 	for (elem = ss->ei_ka_vnics; elem; elem = elem->ka_next)
826*13101SVenki.Rajagopalan@Sun.COM 		(void) eib_fip_heartbeat(ss, elem->ka_vnic, &err);
827*13101SVenki.Rajagopalan@Sun.COM 
828*13101SVenki.Rajagopalan@Sun.COM 	goto periodic_keepalive;
829*13101SVenki.Rajagopalan@Sun.COM 	/*NOTREACHED*/
830*13101SVenki.Rajagopalan@Sun.COM }
831*13101SVenki.Rajagopalan@Sun.COM 
832*13101SVenki.Rajagopalan@Sun.COM void
eib_stop_events_handler(eib_t * ss)833*13101SVenki.Rajagopalan@Sun.COM eib_stop_events_handler(eib_t *ss)
834*13101SVenki.Rajagopalan@Sun.COM {
835*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *evi;
836*13101SVenki.Rajagopalan@Sun.COM 
837*13101SVenki.Rajagopalan@Sun.COM 	evi = kmem_zalloc(sizeof (eib_event_t), KM_SLEEP);
838*13101SVenki.Rajagopalan@Sun.COM 	evi->ev_code = EIB_EV_SHUTDOWN;
839*13101SVenki.Rajagopalan@Sun.COM 	evi->ev_arg = NULL;
840*13101SVenki.Rajagopalan@Sun.COM 
841*13101SVenki.Rajagopalan@Sun.COM 	eib_svc_enqueue_event(ss, evi);
842*13101SVenki.Rajagopalan@Sun.COM 
843*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_events_handler);
844*13101SVenki.Rajagopalan@Sun.COM }
845*13101SVenki.Rajagopalan@Sun.COM 
846*13101SVenki.Rajagopalan@Sun.COM void
eib_stop_refill_rwqes(eib_t * ss)847*13101SVenki.Rajagopalan@Sun.COM eib_stop_refill_rwqes(eib_t *ss)
848*13101SVenki.Rajagopalan@Sun.COM {
849*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_rxpost_lock);
850*13101SVenki.Rajagopalan@Sun.COM 
851*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_rxpost_die = 1;
852*13101SVenki.Rajagopalan@Sun.COM 
853*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&ss->ei_rxpost_cv);
854*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_rxpost_lock);
855*13101SVenki.Rajagopalan@Sun.COM 
856*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_rwqes_refiller);
857*13101SVenki.Rajagopalan@Sun.COM }
858*13101SVenki.Rajagopalan@Sun.COM 
859*13101SVenki.Rajagopalan@Sun.COM void
eib_stop_vnic_creator(eib_t * ss)860*13101SVenki.Rajagopalan@Sun.COM eib_stop_vnic_creator(eib_t *ss)
861*13101SVenki.Rajagopalan@Sun.COM {
862*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *vrq;
863*13101SVenki.Rajagopalan@Sun.COM 
864*13101SVenki.Rajagopalan@Sun.COM 	vrq = kmem_zalloc(sizeof (eib_vnic_req_t), KM_SLEEP);
865*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_req = EIB_CR_REQ_DIE;
866*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_next = NULL;
867*13101SVenki.Rajagopalan@Sun.COM 
868*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_enqueue_req(ss, vrq);
869*13101SVenki.Rajagopalan@Sun.COM 
870*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_vnic_creator);
871*13101SVenki.Rajagopalan@Sun.COM }
872*13101SVenki.Rajagopalan@Sun.COM 
873*13101SVenki.Rajagopalan@Sun.COM void
eib_stop_monitor_tx_wqes(eib_t * ss)874*13101SVenki.Rajagopalan@Sun.COM eib_stop_monitor_tx_wqes(eib_t *ss)
875*13101SVenki.Rajagopalan@Sun.COM {
876*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_pool_t *wp = ss->ei_tx;
877*13101SVenki.Rajagopalan@Sun.COM 
878*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&wp->wp_lock);
879*13101SVenki.Rajagopalan@Sun.COM 
880*13101SVenki.Rajagopalan@Sun.COM 	wp->wp_status |= EIB_TXWQE_MONITOR_DIE;
881*13101SVenki.Rajagopalan@Sun.COM 
882*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&wp->wp_cv);
883*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&wp->wp_lock);
884*13101SVenki.Rajagopalan@Sun.COM 
885*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_txwqe_monitor);
886*13101SVenki.Rajagopalan@Sun.COM }
887*13101SVenki.Rajagopalan@Sun.COM 
888*13101SVenki.Rajagopalan@Sun.COM int
eib_stop_monitor_lso_bufs(eib_t * ss,boolean_t force)889*13101SVenki.Rajagopalan@Sun.COM eib_stop_monitor_lso_bufs(eib_t *ss, boolean_t force)
890*13101SVenki.Rajagopalan@Sun.COM {
891*13101SVenki.Rajagopalan@Sun.COM 	eib_lsobkt_t *bkt = ss->ei_lso;
892*13101SVenki.Rajagopalan@Sun.COM 
893*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&bkt->bk_lock);
894*13101SVenki.Rajagopalan@Sun.COM 
895*13101SVenki.Rajagopalan@Sun.COM 	/*
896*13101SVenki.Rajagopalan@Sun.COM 	 * If there are some buffers still not reaped and the force
897*13101SVenki.Rajagopalan@Sun.COM 	 * flag is not set, return without doing anything. Otherwise,
898*13101SVenki.Rajagopalan@Sun.COM 	 * stop the lso bufs monitor and wait for it to die.
899*13101SVenki.Rajagopalan@Sun.COM 	 */
900*13101SVenki.Rajagopalan@Sun.COM 	if ((bkt->bk_nelem != bkt->bk_nfree) && (force == B_FALSE)) {
901*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&bkt->bk_lock);
902*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
903*13101SVenki.Rajagopalan@Sun.COM 	}
904*13101SVenki.Rajagopalan@Sun.COM 
905*13101SVenki.Rajagopalan@Sun.COM 	bkt->bk_status |= EIB_LBUF_MONITOR_DIE;
906*13101SVenki.Rajagopalan@Sun.COM 
907*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&bkt->bk_cv);
908*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&bkt->bk_lock);
909*13101SVenki.Rajagopalan@Sun.COM 
910*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_lsobufs_monitor);
911*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
912*13101SVenki.Rajagopalan@Sun.COM }
913*13101SVenki.Rajagopalan@Sun.COM 
914*13101SVenki.Rajagopalan@Sun.COM void
eib_stop_manage_keepalives(eib_t * ss)915*13101SVenki.Rajagopalan@Sun.COM eib_stop_manage_keepalives(eib_t *ss)
916*13101SVenki.Rajagopalan@Sun.COM {
917*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ka_vnics_lock);
918*13101SVenki.Rajagopalan@Sun.COM 
919*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_ka_vnics_event |= EIB_KA_VNICS_DIE;
920*13101SVenki.Rajagopalan@Sun.COM 
921*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&ss->ei_ka_vnics_cv);
922*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_ka_vnics_lock);
923*13101SVenki.Rajagopalan@Sun.COM 
924*13101SVenki.Rajagopalan@Sun.COM 	thread_join(ss->ei_keepalives_manager);
925*13101SVenki.Rajagopalan@Sun.COM }
926*13101SVenki.Rajagopalan@Sun.COM 
927*13101SVenki.Rajagopalan@Sun.COM void
eib_flush_vnic_reqs(eib_t * ss)928*13101SVenki.Rajagopalan@Sun.COM eib_flush_vnic_reqs(eib_t *ss)
929*13101SVenki.Rajagopalan@Sun.COM {
930*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *vrq;
931*13101SVenki.Rajagopalan@Sun.COM 
932*13101SVenki.Rajagopalan@Sun.COM 	vrq = kmem_zalloc(sizeof (eib_vnic_req_t), KM_SLEEP);
933*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_req = EIB_CR_REQ_FLUSH;
934*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_next = NULL;
935*13101SVenki.Rajagopalan@Sun.COM 
936*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_enqueue_req(ss, vrq);
937*13101SVenki.Rajagopalan@Sun.COM }
938*13101SVenki.Rajagopalan@Sun.COM 
939*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
940*13101SVenki.Rajagopalan@Sun.COM void
eib_gw_alive_cb(dev_info_t * dip,ddi_eventcookie_t cookie,void * arg,void * impl_data)941*13101SVenki.Rajagopalan@Sun.COM eib_gw_alive_cb(dev_info_t *dip, ddi_eventcookie_t cookie, void *arg,
942*13101SVenki.Rajagopalan@Sun.COM     void *impl_data)
943*13101SVenki.Rajagopalan@Sun.COM {
944*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = (eib_t *)arg;
945*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *evi;
946*13101SVenki.Rajagopalan@Sun.COM 
947*13101SVenki.Rajagopalan@Sun.COM 	evi = kmem_zalloc(sizeof (eib_event_t), KM_NOSLEEP);
948*13101SVenki.Rajagopalan@Sun.COM 	if (evi == NULL) {
949*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_gw_alive_cb: "
950*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, ignoring this gateway alive event");
951*13101SVenki.Rajagopalan@Sun.COM 	} else {
952*13101SVenki.Rajagopalan@Sun.COM 		evi->ev_code = EIB_EV_GW_UP;
953*13101SVenki.Rajagopalan@Sun.COM 		evi->ev_arg = NULL;
954*13101SVenki.Rajagopalan@Sun.COM 		eib_svc_enqueue_event(ss, evi);
955*13101SVenki.Rajagopalan@Sun.COM 	}
956*13101SVenki.Rajagopalan@Sun.COM }
957*13101SVenki.Rajagopalan@Sun.COM 
958*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
959*13101SVenki.Rajagopalan@Sun.COM void
eib_login_ack_cb(dev_info_t * dip,ddi_eventcookie_t cookie,void * arg,void * impl_data)960*13101SVenki.Rajagopalan@Sun.COM eib_login_ack_cb(dev_info_t *dip, ddi_eventcookie_t cookie, void *arg,
961*13101SVenki.Rajagopalan@Sun.COM     void *impl_data)
962*13101SVenki.Rajagopalan@Sun.COM {
963*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = (eib_t *)arg;
964*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *pkt = (uint8_t *)impl_data;
965*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t ld;
966*13101SVenki.Rajagopalan@Sun.COM 
967*13101SVenki.Rajagopalan@Sun.COM 	/*
968*13101SVenki.Rajagopalan@Sun.COM 	 * We have received a login ack message from the gateway via the EoIB
969*13101SVenki.Rajagopalan@Sun.COM 	 * nexus (solicitation qpn).  The packet is passed to us raw (unparsed)
970*13101SVenki.Rajagopalan@Sun.COM 	 * and we have to figure out if this is a vnic login ack.
971*13101SVenki.Rajagopalan@Sun.COM 	 */
972*13101SVenki.Rajagopalan@Sun.COM 	if (eib_fip_parse_login_ack(ss, pkt + EIB_GRH_SZ, &ld) == EIB_E_SUCCESS)
973*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_login_ack(ss, &ld);
974*13101SVenki.Rajagopalan@Sun.COM }
975*13101SVenki.Rajagopalan@Sun.COM 
976*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
977*13101SVenki.Rajagopalan@Sun.COM void
eib_gw_info_cb(dev_info_t * dip,ddi_eventcookie_t cookie,void * arg,void * impl_data)978*13101SVenki.Rajagopalan@Sun.COM eib_gw_info_cb(dev_info_t *dip, ddi_eventcookie_t cookie, void *arg,
979*13101SVenki.Rajagopalan@Sun.COM     void *impl_data)
980*13101SVenki.Rajagopalan@Sun.COM {
981*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = (eib_t *)arg;
982*13101SVenki.Rajagopalan@Sun.COM 	eib_event_t *evi;
983*13101SVenki.Rajagopalan@Sun.COM 
984*13101SVenki.Rajagopalan@Sun.COM 	evi = kmem_zalloc(sizeof (eib_event_t), KM_NOSLEEP);
985*13101SVenki.Rajagopalan@Sun.COM 	if (evi == NULL) {
986*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_gw_info_cb: "
987*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, ignoring this gateway props update event");
988*13101SVenki.Rajagopalan@Sun.COM 		return;
989*13101SVenki.Rajagopalan@Sun.COM 	}
990*13101SVenki.Rajagopalan@Sun.COM 	evi->ev_arg = kmem_zalloc(sizeof (eib_gw_info_t), KM_NOSLEEP);
991*13101SVenki.Rajagopalan@Sun.COM 	if (evi->ev_arg == NULL) {
992*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_gw_info_cb: "
993*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, ignoring this gateway props update event");
994*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(evi, sizeof (eib_event_t));
995*13101SVenki.Rajagopalan@Sun.COM 		return;
996*13101SVenki.Rajagopalan@Sun.COM 	}
997*13101SVenki.Rajagopalan@Sun.COM 	bcopy(impl_data, evi->ev_arg, sizeof (eib_gw_info_t));
998*13101SVenki.Rajagopalan@Sun.COM 	evi->ev_code = EIB_EV_GW_INFO_UPDATE;
999*13101SVenki.Rajagopalan@Sun.COM 
1000*13101SVenki.Rajagopalan@Sun.COM 	eib_svc_enqueue_event(ss, evi);
1001*13101SVenki.Rajagopalan@Sun.COM }
1002