xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_main.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 /*
27*13101SVenki.Rajagopalan@Sun.COM  * The Ethernet Over Infiniband driver
28*13101SVenki.Rajagopalan@Sun.COM  */
29*13101SVenki.Rajagopalan@Sun.COM 
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/devops.h>
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
34*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
35*13101SVenki.Rajagopalan@Sun.COM #include <sys/modctl.h>
36*13101SVenki.Rajagopalan@Sun.COM #include <sys/stat.h>
37*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
38*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
39*13101SVenki.Rajagopalan@Sun.COM 
40*13101SVenki.Rajagopalan@Sun.COM #include <sys/mac_provider.h>
41*13101SVenki.Rajagopalan@Sun.COM #include <sys/mac_ether.h>
42*13101SVenki.Rajagopalan@Sun.COM 
43*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
44*13101SVenki.Rajagopalan@Sun.COM 
45*13101SVenki.Rajagopalan@Sun.COM /*
46*13101SVenki.Rajagopalan@Sun.COM  * Driver entry point declarations
47*13101SVenki.Rajagopalan@Sun.COM  */
48*13101SVenki.Rajagopalan@Sun.COM static int eib_attach(dev_info_t *, ddi_attach_cmd_t);
49*13101SVenki.Rajagopalan@Sun.COM static int eib_detach(dev_info_t *, ddi_detach_cmd_t);
50*13101SVenki.Rajagopalan@Sun.COM 
51*13101SVenki.Rajagopalan@Sun.COM /*
52*13101SVenki.Rajagopalan@Sun.COM  * MAC callbacks
53*13101SVenki.Rajagopalan@Sun.COM  */
54*13101SVenki.Rajagopalan@Sun.COM static int eib_m_stat(void *, uint_t, uint64_t *);
55*13101SVenki.Rajagopalan@Sun.COM static int eib_m_start(void *);
56*13101SVenki.Rajagopalan@Sun.COM static void eib_m_stop(void *);
57*13101SVenki.Rajagopalan@Sun.COM static int eib_m_promisc(void *, boolean_t);
58*13101SVenki.Rajagopalan@Sun.COM static int eib_m_multicast(void *, boolean_t, const uint8_t *);
59*13101SVenki.Rajagopalan@Sun.COM static int eib_m_unicast(void *, const uint8_t *);
60*13101SVenki.Rajagopalan@Sun.COM static mblk_t *eib_m_tx(void *, mblk_t *);
61*13101SVenki.Rajagopalan@Sun.COM static boolean_t eib_m_getcapab(void *, mac_capab_t, void *);
62*13101SVenki.Rajagopalan@Sun.COM static int eib_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
63*13101SVenki.Rajagopalan@Sun.COM     const void *);
64*13101SVenki.Rajagopalan@Sun.COM static int eib_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
65*13101SVenki.Rajagopalan@Sun.COM static void eib_m_propinfo(void *, const char *, mac_prop_id_t,
66*13101SVenki.Rajagopalan@Sun.COM     mac_prop_info_handle_t);
67*13101SVenki.Rajagopalan@Sun.COM 
68*13101SVenki.Rajagopalan@Sun.COM /*
69*13101SVenki.Rajagopalan@Sun.COM  * Devops definition
70*13101SVenki.Rajagopalan@Sun.COM  */
71*13101SVenki.Rajagopalan@Sun.COM DDI_DEFINE_STREAM_OPS(eib_ops, nulldev, nulldev, eib_attach, eib_detach,
72*13101SVenki.Rajagopalan@Sun.COM     nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
73*13101SVenki.Rajagopalan@Sun.COM 
74*13101SVenki.Rajagopalan@Sun.COM /*
75*13101SVenki.Rajagopalan@Sun.COM  * Module Driver Info
76*13101SVenki.Rajagopalan@Sun.COM  */
77*13101SVenki.Rajagopalan@Sun.COM static struct modldrv eib_modldrv = {
78*13101SVenki.Rajagopalan@Sun.COM 	&mod_driverops,		/* Driver module */
79*13101SVenki.Rajagopalan@Sun.COM 	"EoIB Driver",		/* Driver name and version */
80*13101SVenki.Rajagopalan@Sun.COM 	&eib_ops,		/* Driver ops */
81*13101SVenki.Rajagopalan@Sun.COM };
82*13101SVenki.Rajagopalan@Sun.COM 
83*13101SVenki.Rajagopalan@Sun.COM /*
84*13101SVenki.Rajagopalan@Sun.COM  * Module Linkage
85*13101SVenki.Rajagopalan@Sun.COM  */
86*13101SVenki.Rajagopalan@Sun.COM static struct modlinkage eib_modlinkage = {
87*13101SVenki.Rajagopalan@Sun.COM 	MODREV_1, (void *)&eib_modldrv, NULL
88*13101SVenki.Rajagopalan@Sun.COM };
89*13101SVenki.Rajagopalan@Sun.COM 
90*13101SVenki.Rajagopalan@Sun.COM /*
91*13101SVenki.Rajagopalan@Sun.COM  * GLDv3 entry points
92*13101SVenki.Rajagopalan@Sun.COM  */
93*13101SVenki.Rajagopalan@Sun.COM #define	EIB_M_CALLBACK_FLAGS	\
94*13101SVenki.Rajagopalan@Sun.COM 	(MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
95*13101SVenki.Rajagopalan@Sun.COM static mac_callbacks_t eib_m_callbacks = {
96*13101SVenki.Rajagopalan@Sun.COM 	EIB_M_CALLBACK_FLAGS,
97*13101SVenki.Rajagopalan@Sun.COM 	eib_m_stat,
98*13101SVenki.Rajagopalan@Sun.COM 	eib_m_start,
99*13101SVenki.Rajagopalan@Sun.COM 	eib_m_stop,
100*13101SVenki.Rajagopalan@Sun.COM 	eib_m_promisc,
101*13101SVenki.Rajagopalan@Sun.COM 	eib_m_multicast,
102*13101SVenki.Rajagopalan@Sun.COM 	eib_m_unicast,
103*13101SVenki.Rajagopalan@Sun.COM 	eib_m_tx,
104*13101SVenki.Rajagopalan@Sun.COM 	NULL,
105*13101SVenki.Rajagopalan@Sun.COM 	NULL,
106*13101SVenki.Rajagopalan@Sun.COM 	eib_m_getcapab,
107*13101SVenki.Rajagopalan@Sun.COM 	NULL,
108*13101SVenki.Rajagopalan@Sun.COM 	NULL,
109*13101SVenki.Rajagopalan@Sun.COM 	eib_m_setprop,
110*13101SVenki.Rajagopalan@Sun.COM 	eib_m_getprop,
111*13101SVenki.Rajagopalan@Sun.COM 	eib_m_propinfo
112*13101SVenki.Rajagopalan@Sun.COM };
113*13101SVenki.Rajagopalan@Sun.COM 
114*13101SVenki.Rajagopalan@Sun.COM /*
115*13101SVenki.Rajagopalan@Sun.COM  * Async handler callback for ibt events
116*13101SVenki.Rajagopalan@Sun.COM  */
117*13101SVenki.Rajagopalan@Sun.COM static ibt_clnt_modinfo_t eib_clnt_modinfo = {
118*13101SVenki.Rajagopalan@Sun.COM 	IBTI_V_CURR,
119*13101SVenki.Rajagopalan@Sun.COM 	IBT_NETWORK,
120*13101SVenki.Rajagopalan@Sun.COM 	eib_ibt_async_handler,
121*13101SVenki.Rajagopalan@Sun.COM 	NULL,
122*13101SVenki.Rajagopalan@Sun.COM 	EIB_DRV_NAME
123*13101SVenki.Rajagopalan@Sun.COM };
124*13101SVenki.Rajagopalan@Sun.COM 
125*13101SVenki.Rajagopalan@Sun.COM /*
126*13101SVenki.Rajagopalan@Sun.COM  * Driver State Pointer
127*13101SVenki.Rajagopalan@Sun.COM  */
128*13101SVenki.Rajagopalan@Sun.COM void *eib_state;
129*13101SVenki.Rajagopalan@Sun.COM 
130*13101SVenki.Rajagopalan@Sun.COM /*
131*13101SVenki.Rajagopalan@Sun.COM  * Declarations private to this file
132*13101SVenki.Rajagopalan@Sun.COM  */
133*13101SVenki.Rajagopalan@Sun.COM static int eib_state_init(eib_t *);
134*13101SVenki.Rajagopalan@Sun.COM static int eib_add_event_callbacks(eib_t *);
135*13101SVenki.Rajagopalan@Sun.COM static int eib_register_with_mac(eib_t *, dev_info_t *);
136*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_attach(eib_t *, uint_t);
137*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_state_init(eib_t *);
138*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_add_event_callbacks(eib_t *);
139*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_register_with_mac(eib_t *);
140*13101SVenki.Rajagopalan@Sun.COM 
141*13101SVenki.Rajagopalan@Sun.COM /*
142*13101SVenki.Rajagopalan@Sun.COM  * Definitions private to this file
143*13101SVenki.Rajagopalan@Sun.COM  */
144*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_STATE_ALLOCD		0x01
145*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_PROPS_PARSED		0x02
146*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_STATE_INIT_DONE	0x04
147*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_IBT_ATT_DONE		0x08
148*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_EV_CBS_ADDED		0x10
149*13101SVenki.Rajagopalan@Sun.COM #define	EIB_ATTACH_REGISTER_MAC_DONE	0x20
150*13101SVenki.Rajagopalan@Sun.COM 
151*13101SVenki.Rajagopalan@Sun.COM int
_init()152*13101SVenki.Rajagopalan@Sun.COM _init()
153*13101SVenki.Rajagopalan@Sun.COM {
154*13101SVenki.Rajagopalan@Sun.COM 	int ret;
155*13101SVenki.Rajagopalan@Sun.COM 
156*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_name_to_major(EIB_DRV_NAME) == (major_t)-1)
157*13101SVenki.Rajagopalan@Sun.COM 		return (ENODEV);
158*13101SVenki.Rajagopalan@Sun.COM 
159*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_soft_state_init(&eib_state, sizeof (eib_t), 0)) != 0)
160*13101SVenki.Rajagopalan@Sun.COM 		return (ret);
161*13101SVenki.Rajagopalan@Sun.COM 
162*13101SVenki.Rajagopalan@Sun.COM 	mac_init_ops(&eib_ops, EIB_DRV_NAME);
163*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = mod_install(&eib_modlinkage)) != 0) {
164*13101SVenki.Rajagopalan@Sun.COM 		mac_fini_ops(&eib_ops);
165*13101SVenki.Rajagopalan@Sun.COM 		ddi_soft_state_fini(&eib_state);
166*13101SVenki.Rajagopalan@Sun.COM 		return (ret);
167*13101SVenki.Rajagopalan@Sun.COM 	}
168*13101SVenki.Rajagopalan@Sun.COM 
169*13101SVenki.Rajagopalan@Sun.COM 	eib_debug_init();
170*13101SVenki.Rajagopalan@Sun.COM 
171*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
172*13101SVenki.Rajagopalan@Sun.COM }
173*13101SVenki.Rajagopalan@Sun.COM 
174*13101SVenki.Rajagopalan@Sun.COM int
_info(struct modinfo * modinfop)175*13101SVenki.Rajagopalan@Sun.COM _info(struct modinfo *modinfop)
176*13101SVenki.Rajagopalan@Sun.COM {
177*13101SVenki.Rajagopalan@Sun.COM 	return (mod_info(&eib_modlinkage, modinfop));
178*13101SVenki.Rajagopalan@Sun.COM }
179*13101SVenki.Rajagopalan@Sun.COM 
180*13101SVenki.Rajagopalan@Sun.COM int
_fini()181*13101SVenki.Rajagopalan@Sun.COM _fini()
182*13101SVenki.Rajagopalan@Sun.COM {
183*13101SVenki.Rajagopalan@Sun.COM 	int ret;
184*13101SVenki.Rajagopalan@Sun.COM 
185*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = mod_remove(&eib_modlinkage)) != 0)
186*13101SVenki.Rajagopalan@Sun.COM 		return (ret);
187*13101SVenki.Rajagopalan@Sun.COM 
188*13101SVenki.Rajagopalan@Sun.COM 	eib_debug_fini();
189*13101SVenki.Rajagopalan@Sun.COM 
190*13101SVenki.Rajagopalan@Sun.COM 	mac_fini_ops(&eib_ops);
191*13101SVenki.Rajagopalan@Sun.COM 	ddi_soft_state_fini(&eib_state);
192*13101SVenki.Rajagopalan@Sun.COM 
193*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
194*13101SVenki.Rajagopalan@Sun.COM }
195*13101SVenki.Rajagopalan@Sun.COM 
196*13101SVenki.Rajagopalan@Sun.COM static int
eib_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)197*13101SVenki.Rajagopalan@Sun.COM eib_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
198*13101SVenki.Rajagopalan@Sun.COM {
199*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss;
200*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
201*13101SVenki.Rajagopalan@Sun.COM 	int instance;
202*13101SVenki.Rajagopalan@Sun.COM 	uint_t progress = 0;
203*13101SVenki.Rajagopalan@Sun.COM 
204*13101SVenki.Rajagopalan@Sun.COM 	if (cmd != DDI_ATTACH)
205*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
206*13101SVenki.Rajagopalan@Sun.COM 
207*13101SVenki.Rajagopalan@Sun.COM 	/*
208*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate softstate for this instance
209*13101SVenki.Rajagopalan@Sun.COM 	 */
210*13101SVenki.Rajagopalan@Sun.COM 	instance = ddi_get_instance(dip);
211*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_soft_state_zalloc(eib_state, instance) == DDI_FAILURE)
212*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
213*13101SVenki.Rajagopalan@Sun.COM 
214*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_STATE_ALLOCD;
215*13101SVenki.Rajagopalan@Sun.COM 
216*13101SVenki.Rajagopalan@Sun.COM 	ss = ddi_get_soft_state(eib_state, instance);
217*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_dip = dip;
218*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_instance = (uint_t)instance;
219*13101SVenki.Rajagopalan@Sun.COM 
220*13101SVenki.Rajagopalan@Sun.COM 	/*
221*13101SVenki.Rajagopalan@Sun.COM 	 * Parse the node properties and get the gateway parameters
222*13101SVenki.Rajagopalan@Sun.COM 	 * for this instance
223*13101SVenki.Rajagopalan@Sun.COM 	 */
224*13101SVenki.Rajagopalan@Sun.COM 	if (eib_get_props(ss) != EIB_E_SUCCESS) {
225*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
226*13101SVenki.Rajagopalan@Sun.COM 		    "eib_attach: eib_get_props() failed");
227*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
228*13101SVenki.Rajagopalan@Sun.COM 	}
229*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_PROPS_PARSED;
230*13101SVenki.Rajagopalan@Sun.COM 
231*13101SVenki.Rajagopalan@Sun.COM 	/*
232*13101SVenki.Rajagopalan@Sun.COM 	 * Do per-state initialization
233*13101SVenki.Rajagopalan@Sun.COM 	 */
234*13101SVenki.Rajagopalan@Sun.COM 	if (eib_state_init(ss) != EIB_E_SUCCESS) {
235*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
236*13101SVenki.Rajagopalan@Sun.COM 		    "eib_attach: eib_state_init() failed");
237*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
238*13101SVenki.Rajagopalan@Sun.COM 	}
239*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_STATE_INIT_DONE;
240*13101SVenki.Rajagopalan@Sun.COM 
241*13101SVenki.Rajagopalan@Sun.COM 	/*
242*13101SVenki.Rajagopalan@Sun.COM 	 * Attach to IBTL
243*13101SVenki.Rajagopalan@Sun.COM 	 */
244*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ibt_attach(&eib_clnt_modinfo, ss->ei_dip, ss,
245*13101SVenki.Rajagopalan@Sun.COM 	    &ss->ei_ibt_hdl)) != IBT_SUCCESS) {
246*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
247*13101SVenki.Rajagopalan@Sun.COM 		    "eib_attach: ibt_attach() failed, ret=%d", ret);
248*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
249*13101SVenki.Rajagopalan@Sun.COM 	}
250*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_IBT_ATT_DONE;
251*13101SVenki.Rajagopalan@Sun.COM 
252*13101SVenki.Rajagopalan@Sun.COM 	/*
253*13101SVenki.Rajagopalan@Sun.COM 	 * Register NDI event callbacks with EoIB nexus
254*13101SVenki.Rajagopalan@Sun.COM 	 */
255*13101SVenki.Rajagopalan@Sun.COM 	if (eib_add_event_callbacks(ss) != EIB_E_SUCCESS) {
256*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
257*13101SVenki.Rajagopalan@Sun.COM 		    "eib_attach: eib_add_event_callbacks() failed");
258*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
259*13101SVenki.Rajagopalan@Sun.COM 	}
260*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_EV_CBS_ADDED;
261*13101SVenki.Rajagopalan@Sun.COM 
262*13101SVenki.Rajagopalan@Sun.COM 	/*
263*13101SVenki.Rajagopalan@Sun.COM 	 * Register with mac layer
264*13101SVenki.Rajagopalan@Sun.COM 	 */
265*13101SVenki.Rajagopalan@Sun.COM 	if (eib_register_with_mac(ss, dip) != EIB_E_SUCCESS) {
266*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
267*13101SVenki.Rajagopalan@Sun.COM 		    "eib_attach: eib_register_with_mac() failed");
268*13101SVenki.Rajagopalan@Sun.COM 		goto attach_fail;
269*13101SVenki.Rajagopalan@Sun.COM 	}
270*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_ATTACH_REGISTER_MAC_DONE;
271*13101SVenki.Rajagopalan@Sun.COM 
272*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_SUCCESS);
273*13101SVenki.Rajagopalan@Sun.COM 
274*13101SVenki.Rajagopalan@Sun.COM attach_fail:
275*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_attach(ss, progress);
276*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_FAILURE);
277*13101SVenki.Rajagopalan@Sun.COM }
278*13101SVenki.Rajagopalan@Sun.COM 
279*13101SVenki.Rajagopalan@Sun.COM static int
eib_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)280*13101SVenki.Rajagopalan@Sun.COM eib_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
281*13101SVenki.Rajagopalan@Sun.COM {
282*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss;
283*13101SVenki.Rajagopalan@Sun.COM 	int instance;
284*13101SVenki.Rajagopalan@Sun.COM 
285*13101SVenki.Rajagopalan@Sun.COM 	if (cmd != DDI_DETACH)
286*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
287*13101SVenki.Rajagopalan@Sun.COM 
288*13101SVenki.Rajagopalan@Sun.COM 	instance = ddi_get_instance(dip);
289*13101SVenki.Rajagopalan@Sun.COM 	ss = ddi_get_soft_state(eib_state, instance);
290*13101SVenki.Rajagopalan@Sun.COM 
291*13101SVenki.Rajagopalan@Sun.COM 	/*
292*13101SVenki.Rajagopalan@Sun.COM 	 * If we had not cleaned up rx buffers (and hca resources) during
293*13101SVenki.Rajagopalan@Sun.COM 	 * unplumb because they were stuck with the nw layer at the time,
294*13101SVenki.Rajagopalan@Sun.COM 	 * we can try to clean them up now before doing the detach.
295*13101SVenki.Rajagopalan@Sun.COM 	 */
296*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_set_nic_state(ss, EIB_NIC_STOPPING);
297*13101SVenki.Rajagopalan@Sun.COM 
298*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_rsrc_setup_bufs(ss, B_FALSE);
299*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_tx || ss->ei_rx || ss->ei_lso) {
300*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
301*13101SVenki.Rajagopalan@Sun.COM 		    "eib_detach: buffers still not returned "
302*13101SVenki.Rajagopalan@Sun.COM 		    "(tx=0x%llx, rx=0x%llx, lso=0x%llx), could "
303*13101SVenki.Rajagopalan@Sun.COM 		    "not detach", ss->ei_tx, ss->ei_rx, ss->ei_lso);
304*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_clr_nic_state(ss, EIB_NIC_STOPPING);
305*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
306*13101SVenki.Rajagopalan@Sun.COM 	}
307*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_hca_hdl) {
308*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_ibt_hca_init(ss, ~0);
309*13101SVenki.Rajagopalan@Sun.COM 	}
310*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_clr_nic_state(ss, EIB_NIC_STOPPING);
311*13101SVenki.Rajagopalan@Sun.COM 
312*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_attach(ss, ~0);
313*13101SVenki.Rajagopalan@Sun.COM 
314*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_SUCCESS);
315*13101SVenki.Rajagopalan@Sun.COM }
316*13101SVenki.Rajagopalan@Sun.COM 
317*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_stat(void * arg,uint_t stat,uint64_t * val)318*13101SVenki.Rajagopalan@Sun.COM eib_m_stat(void *arg, uint_t stat, uint64_t *val)
319*13101SVenki.Rajagopalan@Sun.COM {
320*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
321*13101SVenki.Rajagopalan@Sun.COM 	eib_stats_t *stats = ss->ei_stats;
322*13101SVenki.Rajagopalan@Sun.COM 
323*13101SVenki.Rajagopalan@Sun.COM 	switch (stat) {
324*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_IFSPEED:
325*13101SVenki.Rajagopalan@Sun.COM 		*val = ss->ei_props->ep_ifspeed;
326*13101SVenki.Rajagopalan@Sun.COM 		break;
327*13101SVenki.Rajagopalan@Sun.COM 
328*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_OBYTES:
329*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_obytes;
330*13101SVenki.Rajagopalan@Sun.COM 		break;
331*13101SVenki.Rajagopalan@Sun.COM 
332*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_OPACKETS:
333*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_opkts;
334*13101SVenki.Rajagopalan@Sun.COM 		break;
335*13101SVenki.Rajagopalan@Sun.COM 
336*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_BRDCSTXMT:
337*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_brdcstxmit;
338*13101SVenki.Rajagopalan@Sun.COM 		break;
339*13101SVenki.Rajagopalan@Sun.COM 
340*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_MULTIXMT:
341*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_multixmit;
342*13101SVenki.Rajagopalan@Sun.COM 		break;
343*13101SVenki.Rajagopalan@Sun.COM 
344*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_OERRORS:
345*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_oerrors;
346*13101SVenki.Rajagopalan@Sun.COM 		break;
347*13101SVenki.Rajagopalan@Sun.COM 
348*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_NOXMTBUF:
349*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_noxmitbuf;
350*13101SVenki.Rajagopalan@Sun.COM 		break;
351*13101SVenki.Rajagopalan@Sun.COM 
352*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_RBYTES:
353*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_rbytes;
354*13101SVenki.Rajagopalan@Sun.COM 		break;
355*13101SVenki.Rajagopalan@Sun.COM 
356*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_IPACKETS:
357*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_ipkts;
358*13101SVenki.Rajagopalan@Sun.COM 		break;
359*13101SVenki.Rajagopalan@Sun.COM 
360*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_BRDCSTRCV:
361*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_brdcstrcv;
362*13101SVenki.Rajagopalan@Sun.COM 		break;
363*13101SVenki.Rajagopalan@Sun.COM 
364*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_MULTIRCV:
365*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_multircv;
366*13101SVenki.Rajagopalan@Sun.COM 		break;
367*13101SVenki.Rajagopalan@Sun.COM 
368*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_IERRORS:
369*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_ierrors;
370*13101SVenki.Rajagopalan@Sun.COM 		break;
371*13101SVenki.Rajagopalan@Sun.COM 
372*13101SVenki.Rajagopalan@Sun.COM 	case MAC_STAT_NORCVBUF:
373*13101SVenki.Rajagopalan@Sun.COM 		*val = stats->st_norcvbuf;
374*13101SVenki.Rajagopalan@Sun.COM 		break;
375*13101SVenki.Rajagopalan@Sun.COM 
376*13101SVenki.Rajagopalan@Sun.COM 	case ETHER_STAT_LINK_DUPLEX:
377*13101SVenki.Rajagopalan@Sun.COM 		*val = LINK_DUPLEX_FULL;
378*13101SVenki.Rajagopalan@Sun.COM 		break;
379*13101SVenki.Rajagopalan@Sun.COM 
380*13101SVenki.Rajagopalan@Sun.COM 	default:
381*13101SVenki.Rajagopalan@Sun.COM 		return (ENOTSUP);
382*13101SVenki.Rajagopalan@Sun.COM 	}
383*13101SVenki.Rajagopalan@Sun.COM 
384*13101SVenki.Rajagopalan@Sun.COM 	return (0);
385*13101SVenki.Rajagopalan@Sun.COM }
386*13101SVenki.Rajagopalan@Sun.COM 
387*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_start(void * arg)388*13101SVenki.Rajagopalan@Sun.COM eib_m_start(void *arg)
389*13101SVenki.Rajagopalan@Sun.COM {
390*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
391*13101SVenki.Rajagopalan@Sun.COM 	int ret = -1;
392*13101SVenki.Rajagopalan@Sun.COM 
393*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_set_nic_state(ss, EIB_NIC_STARTING);
394*13101SVenki.Rajagopalan@Sun.COM 
395*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0)
396*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_mac_start(ss);
397*13101SVenki.Rajagopalan@Sun.COM 
398*13101SVenki.Rajagopalan@Sun.COM 	if (ret == 0)
399*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_upd_nic_state(ss, EIB_NIC_STARTING, EIB_NIC_STARTED);
400*13101SVenki.Rajagopalan@Sun.COM 	else
401*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_clr_nic_state(ss, EIB_NIC_STARTING);
402*13101SVenki.Rajagopalan@Sun.COM 
403*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
404*13101SVenki.Rajagopalan@Sun.COM }
405*13101SVenki.Rajagopalan@Sun.COM 
406*13101SVenki.Rajagopalan@Sun.COM static void
eib_m_stop(void * arg)407*13101SVenki.Rajagopalan@Sun.COM eib_m_stop(void *arg)
408*13101SVenki.Rajagopalan@Sun.COM {
409*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
410*13101SVenki.Rajagopalan@Sun.COM 
411*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_set_nic_state(ss, EIB_NIC_STOPPING);
412*13101SVenki.Rajagopalan@Sun.COM 
413*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) != 0)
414*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_stop(ss);
415*13101SVenki.Rajagopalan@Sun.COM 
416*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_clr_nic_state(ss, EIB_NIC_STARTED|EIB_NIC_STOPPING);
417*13101SVenki.Rajagopalan@Sun.COM }
418*13101SVenki.Rajagopalan@Sun.COM 
419*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_promisc(void * arg,boolean_t flag)420*13101SVenki.Rajagopalan@Sun.COM eib_m_promisc(void *arg, boolean_t flag)
421*13101SVenki.Rajagopalan@Sun.COM {
422*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
423*13101SVenki.Rajagopalan@Sun.COM 
424*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0)
425*13101SVenki.Rajagopalan@Sun.COM 		return (0);
426*13101SVenki.Rajagopalan@Sun.COM 
427*13101SVenki.Rajagopalan@Sun.COM 	return (eib_mac_promisc(ss, flag));
428*13101SVenki.Rajagopalan@Sun.COM }
429*13101SVenki.Rajagopalan@Sun.COM 
430*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_multicast(void * arg,boolean_t add,const uint8_t * mcast_mac)431*13101SVenki.Rajagopalan@Sun.COM eib_m_multicast(void *arg, boolean_t add, const uint8_t *mcast_mac)
432*13101SVenki.Rajagopalan@Sun.COM {
433*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
434*13101SVenki.Rajagopalan@Sun.COM 
435*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0)
436*13101SVenki.Rajagopalan@Sun.COM 		return (0);
437*13101SVenki.Rajagopalan@Sun.COM 
438*13101SVenki.Rajagopalan@Sun.COM 	/*
439*13101SVenki.Rajagopalan@Sun.COM 	 * We don't have any knowledge which of the vnics built on top of
440*13101SVenki.Rajagopalan@Sun.COM 	 * the physlink is this multicast group relevant for.  We'll join
441*13101SVenki.Rajagopalan@Sun.COM 	 * it for vnic0 for now.
442*13101SVenki.Rajagopalan@Sun.COM 	 *
443*13101SVenki.Rajagopalan@Sun.COM 	 * Since the tx routine in EoIB currently piggy backs all multicast
444*13101SVenki.Rajagopalan@Sun.COM 	 * traffic over the broadcast channel, and all vnics are joined to
445*13101SVenki.Rajagopalan@Sun.COM 	 * the broadcast address when they're created, everyone should receive
446*13101SVenki.Rajagopalan@Sun.COM 	 * all multicast traffic anyway.
447*13101SVenki.Rajagopalan@Sun.COM 	 *
448*13101SVenki.Rajagopalan@Sun.COM 	 * On the rx side, we'll check if the incoming multicast address is
449*13101SVenki.Rajagopalan@Sun.COM 	 * either on the vnic's list of mcgs joined to (which will only be the
450*13101SVenki.Rajagopalan@Sun.COM 	 * broadcast address) or on vnic0's list of mcgs.  If we find a match,
451*13101SVenki.Rajagopalan@Sun.COM 	 * we let the packet come through.
452*13101SVenki.Rajagopalan@Sun.COM 	 *
453*13101SVenki.Rajagopalan@Sun.COM 	 * This isn't perfect, but it's the best we can do given that we don't
454*13101SVenki.Rajagopalan@Sun.COM 	 * have any vlan information corresponding to this multicast address.
455*13101SVenki.Rajagopalan@Sun.COM 	 *
456*13101SVenki.Rajagopalan@Sun.COM 	 * Also, for now we'll use the synchronous multicast joins and
457*13101SVenki.Rajagopalan@Sun.COM 	 * leaves instead of the asynchronous mechanism provided by
458*13101SVenki.Rajagopalan@Sun.COM 	 * ibt_join_mcg() since that involves additional complexity for failed
459*13101SVenki.Rajagopalan@Sun.COM 	 * joins and removals.
460*13101SVenki.Rajagopalan@Sun.COM 	 */
461*13101SVenki.Rajagopalan@Sun.COM 	return (eib_mac_multicast(ss, add, (uint8_t *)mcast_mac));
462*13101SVenki.Rajagopalan@Sun.COM }
463*13101SVenki.Rajagopalan@Sun.COM 
464*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_unicast(void * arg,const uint8_t * macaddr)465*13101SVenki.Rajagopalan@Sun.COM eib_m_unicast(void *arg, const uint8_t *macaddr)
466*13101SVenki.Rajagopalan@Sun.COM {
467*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
468*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
469*13101SVenki.Rajagopalan@Sun.COM 
470*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0)
471*13101SVenki.Rajagopalan@Sun.COM 		return (0);
472*13101SVenki.Rajagopalan@Sun.COM 
473*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
474*13101SVenki.Rajagopalan@Sun.COM 
475*13101SVenki.Rajagopalan@Sun.COM 	vnic = ss->ei_vnic[0];
476*13101SVenki.Rajagopalan@Sun.COM 	if (bcmp(macaddr, vnic->vn_login_data.ld_assigned_mac,
477*13101SVenki.Rajagopalan@Sun.COM 	    ETHERADDRL) == 0) {
478*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
479*13101SVenki.Rajagopalan@Sun.COM 		return (0);
480*13101SVenki.Rajagopalan@Sun.COM 	}
481*13101SVenki.Rajagopalan@Sun.COM 
482*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
483*13101SVenki.Rajagopalan@Sun.COM 
484*13101SVenki.Rajagopalan@Sun.COM 	return (EINVAL);
485*13101SVenki.Rajagopalan@Sun.COM }
486*13101SVenki.Rajagopalan@Sun.COM 
487*13101SVenki.Rajagopalan@Sun.COM static mblk_t *
eib_m_tx(void * arg,mblk_t * mp)488*13101SVenki.Rajagopalan@Sun.COM eib_m_tx(void *arg, mblk_t *mp)
489*13101SVenki.Rajagopalan@Sun.COM {
490*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
491*13101SVenki.Rajagopalan@Sun.COM 	mblk_t *next;
492*13101SVenki.Rajagopalan@Sun.COM 
493*13101SVenki.Rajagopalan@Sun.COM 	/*
494*13101SVenki.Rajagopalan@Sun.COM 	 * If the nic hasn't been started, drop the message(s)
495*13101SVenki.Rajagopalan@Sun.COM 	 */
496*13101SVenki.Rajagopalan@Sun.COM 	if ((ss->ei_node_state->ns_nic_state & EIB_NIC_STARTED) == 0) {
497*13101SVenki.Rajagopalan@Sun.COM 		freemsgchain(mp);
498*13101SVenki.Rajagopalan@Sun.COM 		return (NULL);
499*13101SVenki.Rajagopalan@Sun.COM 	}
500*13101SVenki.Rajagopalan@Sun.COM 
501*13101SVenki.Rajagopalan@Sun.COM 	for (; mp != NULL; mp = next) {
502*13101SVenki.Rajagopalan@Sun.COM 		/*
503*13101SVenki.Rajagopalan@Sun.COM 		 * Detach this message from the message chain
504*13101SVenki.Rajagopalan@Sun.COM 		 */
505*13101SVenki.Rajagopalan@Sun.COM 		next = mp->b_next;
506*13101SVenki.Rajagopalan@Sun.COM 		mp->b_next = NULL;
507*13101SVenki.Rajagopalan@Sun.COM 
508*13101SVenki.Rajagopalan@Sun.COM 		/*
509*13101SVenki.Rajagopalan@Sun.COM 		 * Attempt to send the message; if we fail (likely due
510*13101SVenki.Rajagopalan@Sun.COM 		 * to lack of resources), reattach this message to the
511*13101SVenki.Rajagopalan@Sun.COM 		 * chain and return the unsent chain back.  When we're
512*13101SVenki.Rajagopalan@Sun.COM 		 * ready to send again, we'll issue a mac_tx_update().
513*13101SVenki.Rajagopalan@Sun.COM 		 */
514*13101SVenki.Rajagopalan@Sun.COM 		if (eib_mac_tx(ss, mp) != EIB_E_SUCCESS) {
515*13101SVenki.Rajagopalan@Sun.COM 			mp->b_next = next;
516*13101SVenki.Rajagopalan@Sun.COM 			break;
517*13101SVenki.Rajagopalan@Sun.COM 		}
518*13101SVenki.Rajagopalan@Sun.COM 	}
519*13101SVenki.Rajagopalan@Sun.COM 
520*13101SVenki.Rajagopalan@Sun.COM 	return (mp);
521*13101SVenki.Rajagopalan@Sun.COM }
522*13101SVenki.Rajagopalan@Sun.COM 
523*13101SVenki.Rajagopalan@Sun.COM static boolean_t
eib_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)524*13101SVenki.Rajagopalan@Sun.COM eib_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
525*13101SVenki.Rajagopalan@Sun.COM {
526*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
527*13101SVenki.Rajagopalan@Sun.COM 	eib_caps_t *caps = ss->ei_caps;
528*13101SVenki.Rajagopalan@Sun.COM 	eib_caps_t s_caps;
529*13101SVenki.Rajagopalan@Sun.COM 	ibt_hca_attr_t hca_attrs;
530*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
531*13101SVenki.Rajagopalan@Sun.COM 
532*13101SVenki.Rajagopalan@Sun.COM 	/*
533*13101SVenki.Rajagopalan@Sun.COM 	 * If we haven't been plumbed yet, try getting the hca attributes
534*13101SVenki.Rajagopalan@Sun.COM 	 * and figure out the capabilities now
535*13101SVenki.Rajagopalan@Sun.COM 	 */
536*13101SVenki.Rajagopalan@Sun.COM 	if (caps == NULL) {
537*13101SVenki.Rajagopalan@Sun.COM 		ASSERT(ss->ei_props != NULL);
538*13101SVenki.Rajagopalan@Sun.COM 
539*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_query_hca_byguid(ss->ei_props->ep_hca_guid,
540*13101SVenki.Rajagopalan@Sun.COM 		    &hca_attrs);
541*13101SVenki.Rajagopalan@Sun.COM 		if (ret == IBT_SUCCESS) {
542*13101SVenki.Rajagopalan@Sun.COM 			eib_ibt_record_capab(ss, &hca_attrs, &s_caps);
543*13101SVenki.Rajagopalan@Sun.COM 			caps = &s_caps;
544*13101SVenki.Rajagopalan@Sun.COM 		}
545*13101SVenki.Rajagopalan@Sun.COM 	}
546*13101SVenki.Rajagopalan@Sun.COM 
547*13101SVenki.Rajagopalan@Sun.COM 	if ((caps != NULL) && (cap == MAC_CAPAB_HCKSUM)) {
548*13101SVenki.Rajagopalan@Sun.COM 		uint32_t *tx_flags = cap_data;
549*13101SVenki.Rajagopalan@Sun.COM 
550*13101SVenki.Rajagopalan@Sun.COM 		if (caps->cp_cksum_flags == 0) {
551*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_VERBOSE(ss->ei_instance,
552*13101SVenki.Rajagopalan@Sun.COM 			    "eib_m_getcapab: hw cksum disabled, cksum_flags=0");
553*13101SVenki.Rajagopalan@Sun.COM 			return (B_FALSE);
554*13101SVenki.Rajagopalan@Sun.COM 		}
555*13101SVenki.Rajagopalan@Sun.COM 
556*13101SVenki.Rajagopalan@Sun.COM 		*tx_flags = caps->cp_cksum_flags;
557*13101SVenki.Rajagopalan@Sun.COM 
558*13101SVenki.Rajagopalan@Sun.COM 		return (B_TRUE);
559*13101SVenki.Rajagopalan@Sun.COM 
560*13101SVenki.Rajagopalan@Sun.COM 	} else if ((caps != NULL) && (cap == MAC_CAPAB_LSO)) {
561*13101SVenki.Rajagopalan@Sun.COM 		mac_capab_lso_t *cap_lso = cap_data;
562*13101SVenki.Rajagopalan@Sun.COM 
563*13101SVenki.Rajagopalan@Sun.COM 		/*
564*13101SVenki.Rajagopalan@Sun.COM 		 * If the HCA supports LSO, it will advertise a non-zero
565*13101SVenki.Rajagopalan@Sun.COM 		 * "max lso size" parameter. Also, LSO relies on hw
566*13101SVenki.Rajagopalan@Sun.COM 		 * checksum being available.  Finally, if the HCA
567*13101SVenki.Rajagopalan@Sun.COM 		 * doesn't provide the reserved-lkey capability, LSO
568*13101SVenki.Rajagopalan@Sun.COM 		 * will adversely affect the performance.  So, we'll
569*13101SVenki.Rajagopalan@Sun.COM 		 * enable LSO only if we have a non-zero max lso size,
570*13101SVenki.Rajagopalan@Sun.COM 		 * support checksum offload and provide reserved lkey.
571*13101SVenki.Rajagopalan@Sun.COM 		 */
572*13101SVenki.Rajagopalan@Sun.COM 		if (caps->cp_lso_maxlen == 0 ||
573*13101SVenki.Rajagopalan@Sun.COM 		    caps->cp_cksum_flags == 0 ||
574*13101SVenki.Rajagopalan@Sun.COM 		    caps->cp_resv_lkey_capab == 0) {
575*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_VERBOSE(ss->ei_instance, "eib_m_getcapab: "
576*13101SVenki.Rajagopalan@Sun.COM 			    "LSO disabled, lso_maxlen=0x%lx, "
577*13101SVenki.Rajagopalan@Sun.COM 			    "cksum_flags=0x%lx, resv_lkey_capab=%d",
578*13101SVenki.Rajagopalan@Sun.COM 			    caps->cp_lso_maxlen,
579*13101SVenki.Rajagopalan@Sun.COM 			    caps->cp_cksum_flags,
580*13101SVenki.Rajagopalan@Sun.COM 			    caps->cp_resv_lkey_capab);
581*13101SVenki.Rajagopalan@Sun.COM 			return (B_FALSE);
582*13101SVenki.Rajagopalan@Sun.COM 		}
583*13101SVenki.Rajagopalan@Sun.COM 
584*13101SVenki.Rajagopalan@Sun.COM 		cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
585*13101SVenki.Rajagopalan@Sun.COM 		cap_lso->lso_basic_tcp_ipv4.lso_max = caps->cp_lso_maxlen - 1;
586*13101SVenki.Rajagopalan@Sun.COM 
587*13101SVenki.Rajagopalan@Sun.COM 		return (B_TRUE);
588*13101SVenki.Rajagopalan@Sun.COM 	}
589*13101SVenki.Rajagopalan@Sun.COM 
590*13101SVenki.Rajagopalan@Sun.COM 	return (B_FALSE);
591*13101SVenki.Rajagopalan@Sun.COM }
592*13101SVenki.Rajagopalan@Sun.COM 
593*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
594*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)595*13101SVenki.Rajagopalan@Sun.COM eib_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
596*13101SVenki.Rajagopalan@Sun.COM     uint_t pr_valsize, const void *pr_val)
597*13101SVenki.Rajagopalan@Sun.COM {
598*13101SVenki.Rajagopalan@Sun.COM 	return (ENOTSUP);
599*13101SVenki.Rajagopalan@Sun.COM }
600*13101SVenki.Rajagopalan@Sun.COM 
601*13101SVenki.Rajagopalan@Sun.COM static int
eib_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)602*13101SVenki.Rajagopalan@Sun.COM eib_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
603*13101SVenki.Rajagopalan@Sun.COM     uint_t pr_valsize, void *pr_val)
604*13101SVenki.Rajagopalan@Sun.COM {
605*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = arg;
606*13101SVenki.Rajagopalan@Sun.COM 	link_duplex_t duplex = LINK_DUPLEX_FULL;
607*13101SVenki.Rajagopalan@Sun.COM 	uint64_t speed = ss->ei_props->ep_ifspeed;
608*13101SVenki.Rajagopalan@Sun.COM 	int err = 0;
609*13101SVenki.Rajagopalan@Sun.COM 
610*13101SVenki.Rajagopalan@Sun.COM 	switch (pr_num) {
611*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_DUPLEX:
612*13101SVenki.Rajagopalan@Sun.COM 		ASSERT(pr_valsize >= sizeof (link_duplex_t));
613*13101SVenki.Rajagopalan@Sun.COM 		bcopy(&duplex, pr_val, sizeof (link_duplex_t));
614*13101SVenki.Rajagopalan@Sun.COM 		break;
615*13101SVenki.Rajagopalan@Sun.COM 
616*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_SPEED:
617*13101SVenki.Rajagopalan@Sun.COM 		ASSERT(pr_valsize >= sizeof (uint64_t));
618*13101SVenki.Rajagopalan@Sun.COM 		bcopy(&speed, pr_val, sizeof (speed));
619*13101SVenki.Rajagopalan@Sun.COM 		break;
620*13101SVenki.Rajagopalan@Sun.COM 
621*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_PRIVATE:
622*13101SVenki.Rajagopalan@Sun.COM 		if (strcmp(pr_name, EIB_DLPROP_GW_EPORT_STATE) == 0) {
623*13101SVenki.Rajagopalan@Sun.COM 			if (ss->ei_gw_eport_state == FIP_EPORT_UP) {
624*13101SVenki.Rajagopalan@Sun.COM 				(void) snprintf(pr_val, pr_valsize,
625*13101SVenki.Rajagopalan@Sun.COM 				    "%s", "up");
626*13101SVenki.Rajagopalan@Sun.COM 			} else {
627*13101SVenki.Rajagopalan@Sun.COM 				(void) snprintf(pr_val, pr_valsize,
628*13101SVenki.Rajagopalan@Sun.COM 				    "%s", "down");
629*13101SVenki.Rajagopalan@Sun.COM 			}
630*13101SVenki.Rajagopalan@Sun.COM 		} else if (strcmp(pr_name, EIB_DLPROP_HCA_GUID) == 0) {
631*13101SVenki.Rajagopalan@Sun.COM 			(void) snprintf(pr_val, pr_valsize, "%llX",
632*13101SVenki.Rajagopalan@Sun.COM 			    (u_longlong_t)ss->ei_props->ep_hca_guid);
633*13101SVenki.Rajagopalan@Sun.COM 
634*13101SVenki.Rajagopalan@Sun.COM 		} else if (strcmp(pr_name, EIB_DLPROP_PORT_GUID) == 0) {
635*13101SVenki.Rajagopalan@Sun.COM 			(void) snprintf(pr_val, pr_valsize, "%llX",
636*13101SVenki.Rajagopalan@Sun.COM 			    (u_longlong_t)((ss->ei_props->ep_sgid).gid_guid));
637*13101SVenki.Rajagopalan@Sun.COM 		}
638*13101SVenki.Rajagopalan@Sun.COM 		break;
639*13101SVenki.Rajagopalan@Sun.COM 
640*13101SVenki.Rajagopalan@Sun.COM 	default:
641*13101SVenki.Rajagopalan@Sun.COM 		err = ENOTSUP;
642*13101SVenki.Rajagopalan@Sun.COM 		break;
643*13101SVenki.Rajagopalan@Sun.COM 	}
644*13101SVenki.Rajagopalan@Sun.COM 
645*13101SVenki.Rajagopalan@Sun.COM 	return (err);
646*13101SVenki.Rajagopalan@Sun.COM }
647*13101SVenki.Rajagopalan@Sun.COM 
648*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
649*13101SVenki.Rajagopalan@Sun.COM static void
eib_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)650*13101SVenki.Rajagopalan@Sun.COM eib_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
651*13101SVenki.Rajagopalan@Sun.COM     mac_prop_info_handle_t prh)
652*13101SVenki.Rajagopalan@Sun.COM {
653*13101SVenki.Rajagopalan@Sun.COM 	switch (pr_num) {
654*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_DUPLEX:
655*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_SPEED:
656*13101SVenki.Rajagopalan@Sun.COM 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
657*13101SVenki.Rajagopalan@Sun.COM 		break;
658*13101SVenki.Rajagopalan@Sun.COM 
659*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_MTU:
660*13101SVenki.Rajagopalan@Sun.COM 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
661*13101SVenki.Rajagopalan@Sun.COM 		mac_prop_info_set_range_uint32(prh, ETHERMTU, ETHERMTU);
662*13101SVenki.Rajagopalan@Sun.COM 		break;
663*13101SVenki.Rajagopalan@Sun.COM 
664*13101SVenki.Rajagopalan@Sun.COM 	case MAC_PROP_PRIVATE:
665*13101SVenki.Rajagopalan@Sun.COM 		if (strcmp(pr_name, EIB_DLPROP_GW_EPORT_STATE) == 0) {
666*13101SVenki.Rajagopalan@Sun.COM 			mac_prop_info_set_default_str(prh, "up ");
667*13101SVenki.Rajagopalan@Sun.COM 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
668*13101SVenki.Rajagopalan@Sun.COM 		} else if (strcmp(pr_name, EIB_DLPROP_HCA_GUID) == 0) {
669*13101SVenki.Rajagopalan@Sun.COM 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
670*13101SVenki.Rajagopalan@Sun.COM 		} else if (strcmp(pr_name, EIB_DLPROP_PORT_GUID) == 0) {
671*13101SVenki.Rajagopalan@Sun.COM 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
672*13101SVenki.Rajagopalan@Sun.COM 		}
673*13101SVenki.Rajagopalan@Sun.COM 		break;
674*13101SVenki.Rajagopalan@Sun.COM 	}
675*13101SVenki.Rajagopalan@Sun.COM }
676*13101SVenki.Rajagopalan@Sun.COM 
677*13101SVenki.Rajagopalan@Sun.COM static int
eib_state_init(eib_t * ss)678*13101SVenki.Rajagopalan@Sun.COM eib_state_init(eib_t *ss)
679*13101SVenki.Rajagopalan@Sun.COM {
680*13101SVenki.Rajagopalan@Sun.COM 	kthread_t *kt;
681*13101SVenki.Rajagopalan@Sun.COM 
682*13101SVenki.Rajagopalan@Sun.COM 	/*
683*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize synchronization primitives
684*13101SVenki.Rajagopalan@Sun.COM 	 */
685*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_vnic_lock, NULL, MUTEX_DRIVER, NULL);
686*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_av_lock, NULL, MUTEX_DRIVER, NULL);
687*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_ev_lock, NULL, MUTEX_DRIVER, NULL);
688*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_rxpost_lock, NULL, MUTEX_DRIVER, NULL);
689*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_vnic_req_lock, NULL, MUTEX_DRIVER, NULL);
690*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_ka_vnics_lock, NULL, MUTEX_DRIVER, NULL);
691*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_vnic_cv, NULL, CV_DEFAULT, NULL);
692*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_ev_cv, NULL, CV_DEFAULT, NULL);
693*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_rxpost_cv, NULL, CV_DEFAULT, NULL);
694*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_vnic_req_cv, NULL, CV_DEFAULT, NULL);
695*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_ka_vnics_cv, NULL, CV_DEFAULT, NULL);
696*13101SVenki.Rajagopalan@Sun.COM 
697*13101SVenki.Rajagopalan@Sun.COM 	/*
698*13101SVenki.Rajagopalan@Sun.COM 	 * Create a node state structure and initialize
699*13101SVenki.Rajagopalan@Sun.COM 	 */
700*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_node_state = kmem_zalloc(sizeof (eib_node_state_t), KM_SLEEP);
701*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_node_state->ns_link_state = LINK_STATE_UNKNOWN;
702*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&ss->ei_node_state->ns_lock, NULL, MUTEX_DRIVER, NULL);
703*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&ss->ei_node_state->ns_cv, NULL, CV_DEFAULT, NULL);
704*13101SVenki.Rajagopalan@Sun.COM 
705*13101SVenki.Rajagopalan@Sun.COM 	/*
706*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate for gathering statistics
707*13101SVenki.Rajagopalan@Sun.COM 	 */
708*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_stats = kmem_zalloc(sizeof (eib_stats_t), KM_SLEEP);
709*13101SVenki.Rajagopalan@Sun.COM 
710*13101SVenki.Rajagopalan@Sun.COM 	/*
711*13101SVenki.Rajagopalan@Sun.COM 	 * Start up service threads
712*13101SVenki.Rajagopalan@Sun.COM 	 */
713*13101SVenki.Rajagopalan@Sun.COM 	kt = thread_create(NULL, 0, eib_events_handler, ss, 0,
714*13101SVenki.Rajagopalan@Sun.COM 	    &p0, TS_RUN, minclsyspri);
715*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_events_handler = kt->t_did;
716*13101SVenki.Rajagopalan@Sun.COM 
717*13101SVenki.Rajagopalan@Sun.COM 	kt = thread_create(NULL, 0, eib_refill_rwqes, ss, 0,
718*13101SVenki.Rajagopalan@Sun.COM 	    &p0, TS_RUN, minclsyspri);
719*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_rwqes_refiller = kt->t_did;
720*13101SVenki.Rajagopalan@Sun.COM 
721*13101SVenki.Rajagopalan@Sun.COM 	kt = thread_create(NULL, 0, eib_vnic_creator, ss, 0,
722*13101SVenki.Rajagopalan@Sun.COM 	    &p0, TS_RUN, minclsyspri);
723*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_creator = kt->t_did;
724*13101SVenki.Rajagopalan@Sun.COM 
725*13101SVenki.Rajagopalan@Sun.COM 	kt = thread_create(NULL, 0, eib_manage_keepalives, ss, 0,
726*13101SVenki.Rajagopalan@Sun.COM 	    &p0, TS_RUN, minclsyspri);
727*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_keepalives_manager = kt->t_did;
728*13101SVenki.Rajagopalan@Sun.COM 
729*13101SVenki.Rajagopalan@Sun.COM 	/*
730*13101SVenki.Rajagopalan@Sun.COM 	 * Set default state of gw eport
731*13101SVenki.Rajagopalan@Sun.COM 	 */
732*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_gw_eport_state = FIP_EPORT_UP;
733*13101SVenki.Rajagopalan@Sun.COM 
734*13101SVenki.Rajagopalan@Sun.COM 	/*
735*13101SVenki.Rajagopalan@Sun.COM 	 * Do static initializations of common structures
736*13101SVenki.Rajagopalan@Sun.COM 	 */
737*13101SVenki.Rajagopalan@Sun.COM 	eib_reserved_gid.gid_prefix = 0;
738*13101SVenki.Rajagopalan@Sun.COM 	eib_reserved_gid.gid_guid = 0;
739*13101SVenki.Rajagopalan@Sun.COM 
740*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
741*13101SVenki.Rajagopalan@Sun.COM }
742*13101SVenki.Rajagopalan@Sun.COM 
743*13101SVenki.Rajagopalan@Sun.COM static int
eib_add_event_callbacks(eib_t * ss)744*13101SVenki.Rajagopalan@Sun.COM eib_add_event_callbacks(eib_t *ss)
745*13101SVenki.Rajagopalan@Sun.COM {
746*13101SVenki.Rajagopalan@Sun.COM 	int ret;
747*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t login_ack_evc;
748*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t gw_alive_evc;
749*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t gw_info_evc;
750*13101SVenki.Rajagopalan@Sun.COM 
751*13101SVenki.Rajagopalan@Sun.COM 	/*
752*13101SVenki.Rajagopalan@Sun.COM 	 * Add callback for receiving vnic login acks from the gateway
753*13101SVenki.Rajagopalan@Sun.COM 	 */
754*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_LOGIN_ACK,
755*13101SVenki.Rajagopalan@Sun.COM 	    &login_ack_evc)) != DDI_SUCCESS) {
756*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
757*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_get_eventcookie(LOGIN_ACK) failed, ret=%d", ret);
758*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
759*13101SVenki.Rajagopalan@Sun.COM 	}
760*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_add_event_handler(ss->ei_dip, login_ack_evc,
761*13101SVenki.Rajagopalan@Sun.COM 	    eib_login_ack_cb, ss, &ss->ei_login_ack_cb)) != DDI_SUCCESS) {
762*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
763*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_add_event_handler(LOGIN_ACK) failed, ret=%d", ret);
764*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
765*13101SVenki.Rajagopalan@Sun.COM 	}
766*13101SVenki.Rajagopalan@Sun.COM 
767*13101SVenki.Rajagopalan@Sun.COM 	/*
768*13101SVenki.Rajagopalan@Sun.COM 	 * Add callback for receiving status on gateway transitioning from
769*13101SVenki.Rajagopalan@Sun.COM 	 * not-available to available
770*13101SVenki.Rajagopalan@Sun.COM 	 */
771*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_GW_AVAILABLE,
772*13101SVenki.Rajagopalan@Sun.COM 	    &gw_alive_evc)) != DDI_SUCCESS) {
773*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
774*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_get_eventcookie(GW_AVAILABLE) failed, ret=%d", ret);
775*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_login_ack_cb);
776*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
777*13101SVenki.Rajagopalan@Sun.COM 	}
778*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_add_event_handler(ss->ei_dip, gw_alive_evc,
779*13101SVenki.Rajagopalan@Sun.COM 	    eib_gw_alive_cb, ss, &ss->ei_gw_alive_cb)) != DDI_SUCCESS) {
780*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
781*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_add_event_handler(GW_AVAILABLE) failed, ret=%d", ret);
782*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_login_ack_cb);
783*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
784*13101SVenki.Rajagopalan@Sun.COM 	}
785*13101SVenki.Rajagopalan@Sun.COM 
786*13101SVenki.Rajagopalan@Sun.COM 	/*
787*13101SVenki.Rajagopalan@Sun.COM 	 * Add callback for receiving gateway info update
788*13101SVenki.Rajagopalan@Sun.COM 	 */
789*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_GW_INFO_UPDATE,
790*13101SVenki.Rajagopalan@Sun.COM 	    &gw_info_evc)) != DDI_SUCCESS) {
791*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
792*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_get_eventcookie(GW_INFO_UPDATE) failed, ret=%d", ret);
793*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_gw_alive_cb);
794*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_login_ack_cb);
795*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
796*13101SVenki.Rajagopalan@Sun.COM 	}
797*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = ddi_add_event_handler(ss->ei_dip, gw_info_evc,
798*13101SVenki.Rajagopalan@Sun.COM 	    eib_gw_info_cb, ss, &ss->ei_gw_info_cb)) != DDI_SUCCESS) {
799*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_add_event_callbacks: "
800*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_add_event_handler(GW_INFO) failed, ret=%d", ret);
801*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_gw_alive_cb);
802*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_login_ack_cb);
803*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
804*13101SVenki.Rajagopalan@Sun.COM 	}
805*13101SVenki.Rajagopalan@Sun.COM 
806*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
807*13101SVenki.Rajagopalan@Sun.COM }
808*13101SVenki.Rajagopalan@Sun.COM 
809*13101SVenki.Rajagopalan@Sun.COM static int
eib_register_with_mac(eib_t * ss,dev_info_t * dip)810*13101SVenki.Rajagopalan@Sun.COM eib_register_with_mac(eib_t *ss, dev_info_t *dip)
811*13101SVenki.Rajagopalan@Sun.COM {
812*13101SVenki.Rajagopalan@Sun.COM 	mac_register_t *macp;
813*13101SVenki.Rajagopalan@Sun.COM 	int ret;
814*13101SVenki.Rajagopalan@Sun.COM 
815*13101SVenki.Rajagopalan@Sun.COM 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
816*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_register_with_mac: "
817*13101SVenki.Rajagopalan@Sun.COM 		    "mac_alloc(MAC_VERSION=%d) failed", MAC_VERSION);
818*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
819*13101SVenki.Rajagopalan@Sun.COM 	}
820*13101SVenki.Rajagopalan@Sun.COM 
821*13101SVenki.Rajagopalan@Sun.COM 	/*
822*13101SVenki.Rajagopalan@Sun.COM 	 * Note that when we register with mac during attach, we don't
823*13101SVenki.Rajagopalan@Sun.COM 	 * have the mac address yet (we'll get that after we login into
824*13101SVenki.Rajagopalan@Sun.COM 	 * the gateway) so we'll simply register a zero macaddr that
825*13101SVenki.Rajagopalan@Sun.COM 	 * we'll overwrite later during plumb, in eib_m_start(). Likewise,
826*13101SVenki.Rajagopalan@Sun.COM 	 * we'll also update the max-sdu with the correct MTU after we
827*13101SVenki.Rajagopalan@Sun.COM 	 * figure it out when we login to the gateway during plumb.
828*13101SVenki.Rajagopalan@Sun.COM 	 */
829*13101SVenki.Rajagopalan@Sun.COM 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
830*13101SVenki.Rajagopalan@Sun.COM 	macp->m_driver = ss;
831*13101SVenki.Rajagopalan@Sun.COM 	macp->m_dip = dip;
832*13101SVenki.Rajagopalan@Sun.COM 	macp->m_src_addr = eib_zero_mac;
833*13101SVenki.Rajagopalan@Sun.COM 	macp->m_callbacks = &eib_m_callbacks;
834*13101SVenki.Rajagopalan@Sun.COM 	macp->m_min_sdu = 0;
835*13101SVenki.Rajagopalan@Sun.COM 	macp->m_max_sdu = ETHERMTU;
836*13101SVenki.Rajagopalan@Sun.COM 	macp->m_margin = VLAN_TAGSZ;
837*13101SVenki.Rajagopalan@Sun.COM 	macp->m_priv_props = eib_pvt_props;
838*13101SVenki.Rajagopalan@Sun.COM 
839*13101SVenki.Rajagopalan@Sun.COM 	ret = mac_register(macp, &ss->ei_mac_hdl);
840*13101SVenki.Rajagopalan@Sun.COM 	mac_free(macp);
841*13101SVenki.Rajagopalan@Sun.COM 
842*13101SVenki.Rajagopalan@Sun.COM 	if (ret != 0) {
843*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_register_with_mac: "
844*13101SVenki.Rajagopalan@Sun.COM 		    "mac_register() failed, ret=%d", ret);
845*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
846*13101SVenki.Rajagopalan@Sun.COM 	}
847*13101SVenki.Rajagopalan@Sun.COM 
848*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
849*13101SVenki.Rajagopalan@Sun.COM }
850*13101SVenki.Rajagopalan@Sun.COM 
851*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_attach(eib_t * ss,uint_t progress)852*13101SVenki.Rajagopalan@Sun.COM eib_rb_attach(eib_t *ss, uint_t progress)
853*13101SVenki.Rajagopalan@Sun.COM {
854*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
855*13101SVenki.Rajagopalan@Sun.COM 	int instance;
856*13101SVenki.Rajagopalan@Sun.COM 
857*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_REGISTER_MAC_DONE)
858*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_register_with_mac(ss);
859*13101SVenki.Rajagopalan@Sun.COM 
860*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_EV_CBS_ADDED)
861*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_add_event_callbacks(ss);
862*13101SVenki.Rajagopalan@Sun.COM 
863*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_IBT_ATT_DONE) {
864*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_detach(ss->ei_ibt_hdl);
865*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
866*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_rb_attach: "
867*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_detach() failed, ret=%d", ret);
868*13101SVenki.Rajagopalan@Sun.COM 		}
869*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_ibt_hdl = NULL;
870*13101SVenki.Rajagopalan@Sun.COM 	}
871*13101SVenki.Rajagopalan@Sun.COM 
872*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_STATE_INIT_DONE)
873*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_state_init(ss);
874*13101SVenki.Rajagopalan@Sun.COM 
875*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_PROPS_PARSED)
876*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_get_props(ss);
877*13101SVenki.Rajagopalan@Sun.COM 
878*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_ATTACH_STATE_ALLOCD) {
879*13101SVenki.Rajagopalan@Sun.COM 		instance = ddi_get_instance(ss->ei_dip);
880*13101SVenki.Rajagopalan@Sun.COM 		ddi_soft_state_free(eib_state, instance);
881*13101SVenki.Rajagopalan@Sun.COM 	}
882*13101SVenki.Rajagopalan@Sun.COM }
883*13101SVenki.Rajagopalan@Sun.COM 
884*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_state_init(eib_t * ss)885*13101SVenki.Rajagopalan@Sun.COM eib_rb_state_init(eib_t *ss)
886*13101SVenki.Rajagopalan@Sun.COM {
887*13101SVenki.Rajagopalan@Sun.COM 	/*
888*13101SVenki.Rajagopalan@Sun.COM 	 * Terminate service threads
889*13101SVenki.Rajagopalan@Sun.COM 	 */
890*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_keepalives_manager) {
891*13101SVenki.Rajagopalan@Sun.COM 		eib_stop_manage_keepalives(ss);
892*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_keepalives_manager = 0;
893*13101SVenki.Rajagopalan@Sun.COM 	}
894*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_vnic_creator) {
895*13101SVenki.Rajagopalan@Sun.COM 		eib_stop_vnic_creator(ss);
896*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_vnic_creator = 0;
897*13101SVenki.Rajagopalan@Sun.COM 	}
898*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_rwqes_refiller) {
899*13101SVenki.Rajagopalan@Sun.COM 		eib_stop_refill_rwqes(ss);
900*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_rwqes_refiller = 0;
901*13101SVenki.Rajagopalan@Sun.COM 	}
902*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_events_handler) {
903*13101SVenki.Rajagopalan@Sun.COM 		eib_stop_events_handler(ss);
904*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_events_handler = 0;
905*13101SVenki.Rajagopalan@Sun.COM 	}
906*13101SVenki.Rajagopalan@Sun.COM 
907*13101SVenki.Rajagopalan@Sun.COM 	/*
908*13101SVenki.Rajagopalan@Sun.COM 	 * Remove space allocated for gathering statistics
909*13101SVenki.Rajagopalan@Sun.COM 	 */
910*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_stats) {
911*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(ss->ei_stats, sizeof (eib_stats_t));
912*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_stats = NULL;
913*13101SVenki.Rajagopalan@Sun.COM 	}
914*13101SVenki.Rajagopalan@Sun.COM 
915*13101SVenki.Rajagopalan@Sun.COM 	/*
916*13101SVenki.Rajagopalan@Sun.COM 	 * Remove space allocated for keeping node state
917*13101SVenki.Rajagopalan@Sun.COM 	 */
918*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_node_state) {
919*13101SVenki.Rajagopalan@Sun.COM 		cv_destroy(&ss->ei_node_state->ns_cv);
920*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&ss->ei_node_state->ns_lock);
921*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(ss->ei_node_state, sizeof (eib_node_state_t));
922*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_node_state = NULL;
923*13101SVenki.Rajagopalan@Sun.COM 	}
924*13101SVenki.Rajagopalan@Sun.COM 
925*13101SVenki.Rajagopalan@Sun.COM 	/*
926*13101SVenki.Rajagopalan@Sun.COM 	 * Finally, destroy all synchronization resources
927*13101SVenki.Rajagopalan@Sun.COM 	 */
928*13101SVenki.Rajagopalan@Sun.COM 	cv_destroy(&ss->ei_ka_vnics_cv);
929*13101SVenki.Rajagopalan@Sun.COM 	cv_destroy(&ss->ei_vnic_req_cv);
930*13101SVenki.Rajagopalan@Sun.COM 	cv_destroy(&ss->ei_rxpost_cv);
931*13101SVenki.Rajagopalan@Sun.COM 	cv_destroy(&ss->ei_ev_cv);
932*13101SVenki.Rajagopalan@Sun.COM 	cv_destroy(&ss->ei_vnic_cv);
933*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_ka_vnics_lock);
934*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_vnic_req_lock);
935*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_rxpost_lock);
936*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_ev_lock);
937*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_av_lock);
938*13101SVenki.Rajagopalan@Sun.COM 	mutex_destroy(&ss->ei_vnic_lock);
939*13101SVenki.Rajagopalan@Sun.COM }
940*13101SVenki.Rajagopalan@Sun.COM 
941*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_add_event_callbacks(eib_t * ss)942*13101SVenki.Rajagopalan@Sun.COM eib_rb_add_event_callbacks(eib_t *ss)
943*13101SVenki.Rajagopalan@Sun.COM {
944*13101SVenki.Rajagopalan@Sun.COM 	ddi_eventcookie_t evc;
945*13101SVenki.Rajagopalan@Sun.COM 
946*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_GW_INFO_UPDATE,
947*13101SVenki.Rajagopalan@Sun.COM 	    &evc) == DDI_SUCCESS) {
948*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_gw_info_cb);
949*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_gw_info_cb = NULL;
950*13101SVenki.Rajagopalan@Sun.COM 	}
951*13101SVenki.Rajagopalan@Sun.COM 
952*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_GW_AVAILABLE,
953*13101SVenki.Rajagopalan@Sun.COM 	    &evc) == DDI_SUCCESS) {
954*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_gw_alive_cb);
955*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_gw_alive_cb = NULL;
956*13101SVenki.Rajagopalan@Sun.COM 	}
957*13101SVenki.Rajagopalan@Sun.COM 
958*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_get_eventcookie(ss->ei_dip, EIB_NDI_EVENT_LOGIN_ACK,
959*13101SVenki.Rajagopalan@Sun.COM 	    &evc) == DDI_SUCCESS) {
960*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_event_handler(ss->ei_login_ack_cb);
961*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_login_ack_cb = NULL;
962*13101SVenki.Rajagopalan@Sun.COM 	}
963*13101SVenki.Rajagopalan@Sun.COM }
964*13101SVenki.Rajagopalan@Sun.COM 
965*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_register_with_mac(eib_t * ss)966*13101SVenki.Rajagopalan@Sun.COM eib_rb_register_with_mac(eib_t *ss)
967*13101SVenki.Rajagopalan@Sun.COM {
968*13101SVenki.Rajagopalan@Sun.COM 	int ret;
969*13101SVenki.Rajagopalan@Sun.COM 
970*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = mac_unregister(ss->ei_mac_hdl)) != 0) {
971*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
972*13101SVenki.Rajagopalan@Sun.COM 		    "eib_rb_register_with_mac: "
973*13101SVenki.Rajagopalan@Sun.COM 		    "mac_unregister() failed, ret=%d", ret);
974*13101SVenki.Rajagopalan@Sun.COM 	}
975*13101SVenki.Rajagopalan@Sun.COM 
976*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_mac_hdl = NULL;
977*13101SVenki.Rajagopalan@Sun.COM }
978