xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/enx_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 Nexus driver is a bus nexus driver
28*13101SVenki.Rajagopalan@Sun.COM  * that enumerates all the EoIB nodes.
29*13101SVenki.Rajagopalan@Sun.COM  */
30*13101SVenki.Rajagopalan@Sun.COM 
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/devops.h>
34*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
35*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
36*13101SVenki.Rajagopalan@Sun.COM #include <sys/modctl.h>
37*13101SVenki.Rajagopalan@Sun.COM #include <sys/stat.h>
38*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
39*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
40*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunndi.h>
41*13101SVenki.Rajagopalan@Sun.COM 
42*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/enx_impl.h>
43*13101SVenki.Rajagopalan@Sun.COM 
44*13101SVenki.Rajagopalan@Sun.COM /*
45*13101SVenki.Rajagopalan@Sun.COM  * Global per-instance EoIB Nexus data.  Only one instance
46*13101SVenki.Rajagopalan@Sun.COM  * of EoIB Nexus is supported
47*13101SVenki.Rajagopalan@Sun.COM  */
48*13101SVenki.Rajagopalan@Sun.COM eibnx_t *enx_global_ss = NULL;
49*13101SVenki.Rajagopalan@Sun.COM 
50*13101SVenki.Rajagopalan@Sun.COM /*
51*13101SVenki.Rajagopalan@Sun.COM  * Static function declarations
52*13101SVenki.Rajagopalan@Sun.COM  */
53*13101SVenki.Rajagopalan@Sun.COM static int eibnx_attach(dev_info_t *, ddi_attach_cmd_t);
54*13101SVenki.Rajagopalan@Sun.COM static int eibnx_detach(dev_info_t *, ddi_detach_cmd_t);
55*13101SVenki.Rajagopalan@Sun.COM static int eibnx_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
56*13101SVenki.Rajagopalan@Sun.COM static int eibnx_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
57*13101SVenki.Rajagopalan@Sun.COM     void *, void *);
58*13101SVenki.Rajagopalan@Sun.COM 
59*13101SVenki.Rajagopalan@Sun.COM static int eibnx_get_eventcookie(dev_info_t *, dev_info_t *, char *,
60*13101SVenki.Rajagopalan@Sun.COM     ddi_eventcookie_t *);
61*13101SVenki.Rajagopalan@Sun.COM static int eibnx_add_eventcall(dev_info_t *, dev_info_t *, ddi_eventcookie_t,
62*13101SVenki.Rajagopalan@Sun.COM     void (*)(dev_info_t *, ddi_eventcookie_t, void *, void *),
63*13101SVenki.Rajagopalan@Sun.COM     void *, ddi_callback_id_t *);
64*13101SVenki.Rajagopalan@Sun.COM static int eibnx_remove_eventcall(dev_info_t *, ddi_callback_id_t);
65*13101SVenki.Rajagopalan@Sun.COM static int eibnx_post_event(dev_info_t *, dev_info_t *,
66*13101SVenki.Rajagopalan@Sun.COM     ddi_eventcookie_t, void *);
67*13101SVenki.Rajagopalan@Sun.COM 
68*13101SVenki.Rajagopalan@Sun.COM static int eibnx_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
69*13101SVenki.Rajagopalan@Sun.COM     void *, dev_info_t **);
70*13101SVenki.Rajagopalan@Sun.COM static int eibnx_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
71*13101SVenki.Rajagopalan@Sun.COM     void *);
72*13101SVenki.Rajagopalan@Sun.COM static int eibnx_config_all_children(dev_info_t *);
73*13101SVenki.Rajagopalan@Sun.COM static void eibnx_unconfig_all_children(dev_info_t *);
74*13101SVenki.Rajagopalan@Sun.COM static int eibnx_config_child(char *, dev_info_t **);
75*13101SVenki.Rajagopalan@Sun.COM static int eibnx_unconfig_child(char *);
76*13101SVenki.Rajagopalan@Sun.COM 
77*13101SVenki.Rajagopalan@Sun.COM /*
78*13101SVenki.Rajagopalan@Sun.COM  * Cbops
79*13101SVenki.Rajagopalan@Sun.COM  */
80*13101SVenki.Rajagopalan@Sun.COM static struct cb_ops enx_cb_ops = {
81*13101SVenki.Rajagopalan@Sun.COM 	eibnx_devctl_open,	/* cb_open */
82*13101SVenki.Rajagopalan@Sun.COM 	eibnx_devctl_close,	/* cb_close */
83*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_strategy */
84*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_print */
85*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_dump */
86*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_read */
87*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_write */
88*13101SVenki.Rajagopalan@Sun.COM 	eibnx_devctl_ioctl,	/* cb_ioctl */
89*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_devmap */
90*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_mmap */
91*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_segmap */
92*13101SVenki.Rajagopalan@Sun.COM 	nochpoll,		/* cb_chpoll */
93*13101SVenki.Rajagopalan@Sun.COM 	ddi_prop_op,		/* cb_prop_op */
94*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* cb_str */
95*13101SVenki.Rajagopalan@Sun.COM 	D_MP,			/* cb_flag */
96*13101SVenki.Rajagopalan@Sun.COM 	CB_REV, 		/* cb_rev */
97*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* cb_aread */
98*13101SVenki.Rajagopalan@Sun.COM 	nodev			/* cb_awrite */
99*13101SVenki.Rajagopalan@Sun.COM };
100*13101SVenki.Rajagopalan@Sun.COM 
101*13101SVenki.Rajagopalan@Sun.COM /*
102*13101SVenki.Rajagopalan@Sun.COM  * Busops
103*13101SVenki.Rajagopalan@Sun.COM  */
104*13101SVenki.Rajagopalan@Sun.COM static struct bus_ops enx_bus_ops = {
105*13101SVenki.Rajagopalan@Sun.COM 	BUSO_REV,
106*13101SVenki.Rajagopalan@Sun.COM 	nullbusmap,		/* bus_map */
107*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_get_intrspec */
108*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_add_intrspec */
109*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_remove_intrspec */
110*13101SVenki.Rajagopalan@Sun.COM 	i_ddi_map_fault,	/* bus_map_fault */
111*13101SVenki.Rajagopalan@Sun.COM 	ddi_no_dma_map,		/* bus_dma_map */
112*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_allochdl */
113*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_freehdl */
114*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_bindhdl */
115*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_unbindhdl */
116*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_flush */
117*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_win */
118*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_dma_ctl */
119*13101SVenki.Rajagopalan@Sun.COM 	eibnx_bus_ctl,		/* bus_ctl */
120*13101SVenki.Rajagopalan@Sun.COM 	ddi_bus_prop_op,	/* bus_prop_op */
121*13101SVenki.Rajagopalan@Sun.COM 	eibnx_get_eventcookie,	/* bus_get_eventcookie */
122*13101SVenki.Rajagopalan@Sun.COM 	eibnx_add_eventcall,	/* bus_add_eventcall */
123*13101SVenki.Rajagopalan@Sun.COM 	eibnx_remove_eventcall,	/* bus_remove_eventcall */
124*13101SVenki.Rajagopalan@Sun.COM 	eibnx_post_event,	/* bus_post_event */
125*13101SVenki.Rajagopalan@Sun.COM 	NULL,			/* bus_intr_ctl */
126*13101SVenki.Rajagopalan@Sun.COM 	eibnx_bus_config,	/* bus_config */
127*13101SVenki.Rajagopalan@Sun.COM 	eibnx_bus_unconfig,	/* bus_unconfig */
128*13101SVenki.Rajagopalan@Sun.COM };
129*13101SVenki.Rajagopalan@Sun.COM 
130*13101SVenki.Rajagopalan@Sun.COM /*
131*13101SVenki.Rajagopalan@Sun.COM  * Nexus ops
132*13101SVenki.Rajagopalan@Sun.COM  */
133*13101SVenki.Rajagopalan@Sun.COM static struct dev_ops enx_ops = {
134*13101SVenki.Rajagopalan@Sun.COM 	DEVO_REV,		/* devo_rev, */
135*13101SVenki.Rajagopalan@Sun.COM 	0,			/* devo_refcnt  */
136*13101SVenki.Rajagopalan@Sun.COM 	eibnx_getinfo,		/* devo_info */
137*13101SVenki.Rajagopalan@Sun.COM 	nulldev,		/* devo_identify */
138*13101SVenki.Rajagopalan@Sun.COM 	nulldev,		/* devo_probe */
139*13101SVenki.Rajagopalan@Sun.COM 	eibnx_attach,		/* devo_attach */
140*13101SVenki.Rajagopalan@Sun.COM 	eibnx_detach,		/* devo_detach */
141*13101SVenki.Rajagopalan@Sun.COM 	nodev,			/* devo_reset */
142*13101SVenki.Rajagopalan@Sun.COM 	&enx_cb_ops,		/* devo_cb_ops */
143*13101SVenki.Rajagopalan@Sun.COM 	&enx_bus_ops,		/* devo_bus_ops */
144*13101SVenki.Rajagopalan@Sun.COM 	nulldev,		/* devo_power */
145*13101SVenki.Rajagopalan@Sun.COM 	ddi_quiesce_not_needed	/* devo_quiesce */
146*13101SVenki.Rajagopalan@Sun.COM };
147*13101SVenki.Rajagopalan@Sun.COM 
148*13101SVenki.Rajagopalan@Sun.COM /*
149*13101SVenki.Rajagopalan@Sun.COM  * Module linkage information for the kernel
150*13101SVenki.Rajagopalan@Sun.COM  */
151*13101SVenki.Rajagopalan@Sun.COM static struct modldrv enx_modldrv = {
152*13101SVenki.Rajagopalan@Sun.COM 	&mod_driverops,		/* Driver module */
153*13101SVenki.Rajagopalan@Sun.COM 	"EoIB Nexus",		/* Driver name and version */
154*13101SVenki.Rajagopalan@Sun.COM 	&enx_ops,		/* Driver ops */
155*13101SVenki.Rajagopalan@Sun.COM };
156*13101SVenki.Rajagopalan@Sun.COM 
157*13101SVenki.Rajagopalan@Sun.COM static struct modlinkage enx_modlinkage = {
158*13101SVenki.Rajagopalan@Sun.COM 	MODREV_1, (void *)&enx_modldrv, NULL
159*13101SVenki.Rajagopalan@Sun.COM };
160*13101SVenki.Rajagopalan@Sun.COM 
161*13101SVenki.Rajagopalan@Sun.COM /*
162*13101SVenki.Rajagopalan@Sun.COM  * EoIB NDI events
163*13101SVenki.Rajagopalan@Sun.COM  */
164*13101SVenki.Rajagopalan@Sun.COM static ndi_event_definition_t enx_ndi_event_defs[] = {
165*13101SVenki.Rajagopalan@Sun.COM 	{ ENX_EVENT_TAG_GW_INFO_UPDATE, EIB_NDI_EVENT_GW_INFO_UPDATE,
166*13101SVenki.Rajagopalan@Sun.COM 		EPL_KERNEL, NDI_EVENT_POST_TO_TGT },
167*13101SVenki.Rajagopalan@Sun.COM 	{ ENX_EVENT_TAG_GW_AVAILABLE, EIB_NDI_EVENT_GW_AVAILABLE,
168*13101SVenki.Rajagopalan@Sun.COM 		EPL_KERNEL, NDI_EVENT_POST_TO_TGT },
169*13101SVenki.Rajagopalan@Sun.COM 	{ ENX_EVENT_TAG_LOGIN_ACK, EIB_NDI_EVENT_LOGIN_ACK,
170*13101SVenki.Rajagopalan@Sun.COM 		EPL_KERNEL, NDI_EVENT_POST_TO_TGT }
171*13101SVenki.Rajagopalan@Sun.COM };
172*13101SVenki.Rajagopalan@Sun.COM #define	ENX_NUM_NDI_EVENTS		\
173*13101SVenki.Rajagopalan@Sun.COM 	(sizeof (enx_ndi_event_defs) / sizeof (enx_ndi_event_defs[0]))
174*13101SVenki.Rajagopalan@Sun.COM 
175*13101SVenki.Rajagopalan@Sun.COM static ndi_event_set_t enx_ndi_events = {
176*13101SVenki.Rajagopalan@Sun.COM 	NDI_EVENTS_REV1,
177*13101SVenki.Rajagopalan@Sun.COM 	ENX_NUM_NDI_EVENTS,
178*13101SVenki.Rajagopalan@Sun.COM 	enx_ndi_event_defs
179*13101SVenki.Rajagopalan@Sun.COM };
180*13101SVenki.Rajagopalan@Sun.COM ndi_event_hdl_t enx_ndi_event_hdl;
181*13101SVenki.Rajagopalan@Sun.COM 
182*13101SVenki.Rajagopalan@Sun.COM 
183*13101SVenki.Rajagopalan@Sun.COM /*
184*13101SVenki.Rajagopalan@Sun.COM  * Common loadable module entry points _init, _fini, _info
185*13101SVenki.Rajagopalan@Sun.COM  */
186*13101SVenki.Rajagopalan@Sun.COM 
187*13101SVenki.Rajagopalan@Sun.COM int
_init(void)188*13101SVenki.Rajagopalan@Sun.COM _init(void)
189*13101SVenki.Rajagopalan@Sun.COM {
190*13101SVenki.Rajagopalan@Sun.COM 	int ret;
191*13101SVenki.Rajagopalan@Sun.COM 
192*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = mod_install(&enx_modlinkage)) == 0)
193*13101SVenki.Rajagopalan@Sun.COM 		eibnx_debug_init();
194*13101SVenki.Rajagopalan@Sun.COM 
195*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
196*13101SVenki.Rajagopalan@Sun.COM }
197*13101SVenki.Rajagopalan@Sun.COM 
198*13101SVenki.Rajagopalan@Sun.COM int
_fini(void)199*13101SVenki.Rajagopalan@Sun.COM _fini(void)
200*13101SVenki.Rajagopalan@Sun.COM {
201*13101SVenki.Rajagopalan@Sun.COM 	int ret;
202*13101SVenki.Rajagopalan@Sun.COM 
203*13101SVenki.Rajagopalan@Sun.COM 	if ((ret = mod_remove(&enx_modlinkage)) == 0)
204*13101SVenki.Rajagopalan@Sun.COM 		eibnx_debug_fini();
205*13101SVenki.Rajagopalan@Sun.COM 
206*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
207*13101SVenki.Rajagopalan@Sun.COM }
208*13101SVenki.Rajagopalan@Sun.COM 
209*13101SVenki.Rajagopalan@Sun.COM int
_info(struct modinfo * modinfop)210*13101SVenki.Rajagopalan@Sun.COM _info(struct modinfo *modinfop)
211*13101SVenki.Rajagopalan@Sun.COM {
212*13101SVenki.Rajagopalan@Sun.COM 	return (mod_info(&enx_modlinkage, modinfop));
213*13101SVenki.Rajagopalan@Sun.COM }
214*13101SVenki.Rajagopalan@Sun.COM 
215*13101SVenki.Rajagopalan@Sun.COM /*
216*13101SVenki.Rajagopalan@Sun.COM  * Autoconfiguration entry points: attach, detach, getinfo
217*13101SVenki.Rajagopalan@Sun.COM  */
218*13101SVenki.Rajagopalan@Sun.COM 
219*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)220*13101SVenki.Rajagopalan@Sun.COM eibnx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
221*13101SVenki.Rajagopalan@Sun.COM {
222*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss;
223*13101SVenki.Rajagopalan@Sun.COM 	int instance;
224*13101SVenki.Rajagopalan@Sun.COM 
225*13101SVenki.Rajagopalan@Sun.COM 	if (cmd == DDI_RESUME)
226*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_SUCCESS);
227*13101SVenki.Rajagopalan@Sun.COM 	else if (cmd != DDI_ATTACH)
228*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
229*13101SVenki.Rajagopalan@Sun.COM 
230*13101SVenki.Rajagopalan@Sun.COM 	/*
231*13101SVenki.Rajagopalan@Sun.COM 	 * Don't allow more than one instance to attach
232*13101SVenki.Rajagopalan@Sun.COM 	 */
233*13101SVenki.Rajagopalan@Sun.COM 	if (enx_global_ss)
234*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
235*13101SVenki.Rajagopalan@Sun.COM 
236*13101SVenki.Rajagopalan@Sun.COM 	/*
237*13101SVenki.Rajagopalan@Sun.COM 	 * Alloc this instance's softstate
238*13101SVenki.Rajagopalan@Sun.COM 	 */
239*13101SVenki.Rajagopalan@Sun.COM 	ss = kmem_zalloc(sizeof (eibnx_t), KM_SLEEP);
240*13101SVenki.Rajagopalan@Sun.COM 	ss->nx_dip = dip;
241*13101SVenki.Rajagopalan@Sun.COM 
242*13101SVenki.Rajagopalan@Sun.COM 	enx_global_ss = ss;
243*13101SVenki.Rajagopalan@Sun.COM 
244*13101SVenki.Rajagopalan@Sun.COM 	/*
245*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate our NDI event handle and bind our event set
246*13101SVenki.Rajagopalan@Sun.COM 	 */
247*13101SVenki.Rajagopalan@Sun.COM 	if (ndi_event_alloc_hdl(dip, 0, &enx_ndi_event_hdl,
248*13101SVenki.Rajagopalan@Sun.COM 	    NDI_SLEEP) != NDI_SUCCESS) {
249*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("ndi_event_alloc_hdl(dip=0x%llx) "
250*13101SVenki.Rajagopalan@Sun.COM 		    "failed", dip);
251*13101SVenki.Rajagopalan@Sun.COM 
252*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(enx_global_ss, sizeof (eibnx_t));
253*13101SVenki.Rajagopalan@Sun.COM 		enx_global_ss = NULL;
254*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
255*13101SVenki.Rajagopalan@Sun.COM 	}
256*13101SVenki.Rajagopalan@Sun.COM 	if (ndi_event_bind_set(enx_ndi_event_hdl, &enx_ndi_events,
257*13101SVenki.Rajagopalan@Sun.COM 	    NDI_SLEEP) != NDI_SUCCESS) {
258*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_ERR("ndi_event_bind_set(ndi_event_hdl=0x%llx) "
259*13101SVenki.Rajagopalan@Sun.COM 		    "failed", enx_ndi_event_hdl);
260*13101SVenki.Rajagopalan@Sun.COM 
261*13101SVenki.Rajagopalan@Sun.COM 		(void) ndi_event_free_hdl(enx_ndi_event_hdl);
262*13101SVenki.Rajagopalan@Sun.COM 		enx_ndi_event_hdl = NULL;
263*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(enx_global_ss, sizeof (eibnx_t));
264*13101SVenki.Rajagopalan@Sun.COM 		enx_global_ss = NULL;
265*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
266*13101SVenki.Rajagopalan@Sun.COM 	}
267*13101SVenki.Rajagopalan@Sun.COM 
268*13101SVenki.Rajagopalan@Sun.COM 	/*
269*13101SVenki.Rajagopalan@Sun.COM 	 * Create "devctl" minor node for general ioctl interface to the
270*13101SVenki.Rajagopalan@Sun.COM 	 * eoib nexus. If we cannot, it isn't fatal - we'll operate without
271*13101SVenki.Rajagopalan@Sun.COM 	 * the support for devctl (but issue a warning).
272*13101SVenki.Rajagopalan@Sun.COM 	 */
273*13101SVenki.Rajagopalan@Sun.COM 	instance = ddi_get_instance(dip);
274*13101SVenki.Rajagopalan@Sun.COM 	if (ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
275*13101SVenki.Rajagopalan@Sun.COM 	    DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
276*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_WARN("could not create devctl minor node "
277*13101SVenki.Rajagopalan@Sun.COM 		    "for instance %d", instance);
278*13101SVenki.Rajagopalan@Sun.COM 	}
279*13101SVenki.Rajagopalan@Sun.COM 
280*13101SVenki.Rajagopalan@Sun.COM 	/*
281*13101SVenki.Rajagopalan@Sun.COM 	 * Do IBTF related initializations. If we fail, we cannot operate,
282*13101SVenki.Rajagopalan@Sun.COM 	 * so fail the attach.
283*13101SVenki.Rajagopalan@Sun.COM 	 */
284*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_ibt_init(ss) != ENX_E_SUCCESS) {
285*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_remove_minor_node(dip, NULL);
286*13101SVenki.Rajagopalan@Sun.COM 		(void) ndi_event_unbind_set(enx_ndi_event_hdl,
287*13101SVenki.Rajagopalan@Sun.COM 		    &enx_ndi_events, NDI_SLEEP);
288*13101SVenki.Rajagopalan@Sun.COM 		(void) ndi_event_free_hdl(enx_ndi_event_hdl);
289*13101SVenki.Rajagopalan@Sun.COM 		enx_ndi_event_hdl = NULL;
290*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(enx_global_ss, sizeof (eibnx_t));
291*13101SVenki.Rajagopalan@Sun.COM 		enx_global_ss = NULL;
292*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
293*13101SVenki.Rajagopalan@Sun.COM 	}
294*13101SVenki.Rajagopalan@Sun.COM 
295*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_SUCCESS);
296*13101SVenki.Rajagopalan@Sun.COM }
297*13101SVenki.Rajagopalan@Sun.COM 
298*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)299*13101SVenki.Rajagopalan@Sun.COM eibnx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
300*13101SVenki.Rajagopalan@Sun.COM {
301*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
302*13101SVenki.Rajagopalan@Sun.COM 
303*13101SVenki.Rajagopalan@Sun.COM 	if (cmd == DDI_SUSPEND)
304*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_SUCCESS);
305*13101SVenki.Rajagopalan@Sun.COM 	else if (cmd != DDI_DETACH)
306*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
307*13101SVenki.Rajagopalan@Sun.COM 
308*13101SVenki.Rajagopalan@Sun.COM 	/*
309*13101SVenki.Rajagopalan@Sun.COM 	 * If there's no instance of eibnx attached, fail
310*13101SVenki.Rajagopalan@Sun.COM 	 */
311*13101SVenki.Rajagopalan@Sun.COM 	if (ss == NULL)
312*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
313*13101SVenki.Rajagopalan@Sun.COM 
314*13101SVenki.Rajagopalan@Sun.COM 	/*
315*13101SVenki.Rajagopalan@Sun.COM 	 * Before we do anything, we need to stop the port monitors
316*13101SVenki.Rajagopalan@Sun.COM 	 * we may have started earlier.
317*13101SVenki.Rajagopalan@Sun.COM 	 */
318*13101SVenki.Rajagopalan@Sun.COM 	eibnx_terminate_monitors();
319*13101SVenki.Rajagopalan@Sun.COM 
320*13101SVenki.Rajagopalan@Sun.COM 	/*
321*13101SVenki.Rajagopalan@Sun.COM 	 * If eibnx_ibt_fini() fails, it could be because one of the
322*13101SVenki.Rajagopalan@Sun.COM 	 * HCA's pd could not be freed, the hca could not be closed
323*13101SVenki.Rajagopalan@Sun.COM 	 * or the IBTF detach wasn't successful.  If this is the case,
324*13101SVenki.Rajagopalan@Sun.COM 	 * we have to return failure, but cannot do much about the
325*13101SVenki.Rajagopalan@Sun.COM 	 * port monitors we've already terminated.
326*13101SVenki.Rajagopalan@Sun.COM 	 */
327*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_ibt_fini(ss) == ENX_E_FAILURE)
328*13101SVenki.Rajagopalan@Sun.COM 		return (DDI_FAILURE);
329*13101SVenki.Rajagopalan@Sun.COM 
330*13101SVenki.Rajagopalan@Sun.COM 	/*
331*13101SVenki.Rajagopalan@Sun.COM 	 * Cleanup any devctl minor node we may have created, unbind and
332*13101SVenki.Rajagopalan@Sun.COM 	 * free ndi event handle and free the instance softstate.
333*13101SVenki.Rajagopalan@Sun.COM 	 */
334*13101SVenki.Rajagopalan@Sun.COM 	(void) ddi_remove_minor_node(dip, NULL);
335*13101SVenki.Rajagopalan@Sun.COM 	(void) ndi_event_unbind_set(enx_ndi_event_hdl,
336*13101SVenki.Rajagopalan@Sun.COM 	    &enx_ndi_events, NDI_SLEEP);
337*13101SVenki.Rajagopalan@Sun.COM 	(void) ndi_event_free_hdl(enx_ndi_event_hdl);
338*13101SVenki.Rajagopalan@Sun.COM 	enx_ndi_event_hdl = NULL;
339*13101SVenki.Rajagopalan@Sun.COM 	kmem_free(enx_global_ss, sizeof (eibnx_t));
340*13101SVenki.Rajagopalan@Sun.COM 	enx_global_ss = NULL;
341*13101SVenki.Rajagopalan@Sun.COM 
342*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_SUCCESS);
343*13101SVenki.Rajagopalan@Sun.COM }
344*13101SVenki.Rajagopalan@Sun.COM 
345*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
346*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)347*13101SVenki.Rajagopalan@Sun.COM eibnx_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
348*13101SVenki.Rajagopalan@Sun.COM {
349*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
350*13101SVenki.Rajagopalan@Sun.COM 	int ret;
351*13101SVenki.Rajagopalan@Sun.COM 
352*13101SVenki.Rajagopalan@Sun.COM 	if (cmd == DDI_INFO_DEVT2DEVINFO) {
353*13101SVenki.Rajagopalan@Sun.COM 		*resultp = (ss) ? ss->nx_dip : NULL;
354*13101SVenki.Rajagopalan@Sun.COM 		ret = (ss) ? DDI_SUCCESS : DDI_FAILURE;
355*13101SVenki.Rajagopalan@Sun.COM 	} else if (cmd == DDI_INFO_DEVT2INSTANCE) {
356*13101SVenki.Rajagopalan@Sun.COM 		*resultp = 0;
357*13101SVenki.Rajagopalan@Sun.COM 		ret = DDI_SUCCESS;
358*13101SVenki.Rajagopalan@Sun.COM 	} else {
359*13101SVenki.Rajagopalan@Sun.COM 		ret = DDI_FAILURE;
360*13101SVenki.Rajagopalan@Sun.COM 	}
361*13101SVenki.Rajagopalan@Sun.COM 
362*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
363*13101SVenki.Rajagopalan@Sun.COM }
364*13101SVenki.Rajagopalan@Sun.COM 
365*13101SVenki.Rajagopalan@Sun.COM /*
366*13101SVenki.Rajagopalan@Sun.COM  * Busops: bus_ctl, bus_config, bus_unconfig
367*13101SVenki.Rajagopalan@Sun.COM  */
368*13101SVenki.Rajagopalan@Sun.COM 
369*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
370*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_bus_ctl(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)371*13101SVenki.Rajagopalan@Sun.COM eibnx_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
372*13101SVenki.Rajagopalan@Sun.COM     void *arg, void *result)
373*13101SVenki.Rajagopalan@Sun.COM {
374*13101SVenki.Rajagopalan@Sun.COM 	dev_info_t *child = arg;
375*13101SVenki.Rajagopalan@Sun.COM 	int ret;
376*13101SVenki.Rajagopalan@Sun.COM 	char name[MAXNAMELEN];
377*13101SVenki.Rajagopalan@Sun.COM 
378*13101SVenki.Rajagopalan@Sun.COM 	switch (ctlop) {
379*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_REPORTDEV:
380*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("EoIB device: %s@%s, %s%d",
381*13101SVenki.Rajagopalan@Sun.COM 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
382*13101SVenki.Rajagopalan@Sun.COM 		    ddi_driver_name(rdip), ddi_get_instance(rdip));
383*13101SVenki.Rajagopalan@Sun.COM 		/*FALLTHROUGH*/
384*13101SVenki.Rajagopalan@Sun.COM 
385*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_ATTACH:
386*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_DETACH:
387*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_POWER:
388*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_SIDDEV:
389*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_IOMIN:
390*13101SVenki.Rajagopalan@Sun.COM 		ret = DDI_SUCCESS;
391*13101SVenki.Rajagopalan@Sun.COM 		break;
392*13101SVenki.Rajagopalan@Sun.COM 
393*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_INITCHILD:
394*13101SVenki.Rajagopalan@Sun.COM 		if ((ret = eibnx_name_child(child, name,
395*13101SVenki.Rajagopalan@Sun.COM 		    sizeof (name))) == DDI_SUCCESS) {
396*13101SVenki.Rajagopalan@Sun.COM 			ddi_set_name_addr(child, name);
397*13101SVenki.Rajagopalan@Sun.COM 		}
398*13101SVenki.Rajagopalan@Sun.COM 		break;
399*13101SVenki.Rajagopalan@Sun.COM 
400*13101SVenki.Rajagopalan@Sun.COM 	case DDI_CTLOPS_UNINITCHILD:
401*13101SVenki.Rajagopalan@Sun.COM 		ddi_set_name_addr(child, NULL);
402*13101SVenki.Rajagopalan@Sun.COM 		ret = DDI_SUCCESS;
403*13101SVenki.Rajagopalan@Sun.COM 		break;
404*13101SVenki.Rajagopalan@Sun.COM 
405*13101SVenki.Rajagopalan@Sun.COM 	default:
406*13101SVenki.Rajagopalan@Sun.COM 		ret = ddi_ctlops(dip, rdip, ctlop, arg, result);
407*13101SVenki.Rajagopalan@Sun.COM 		break;
408*13101SVenki.Rajagopalan@Sun.COM 	}
409*13101SVenki.Rajagopalan@Sun.COM 
410*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
411*13101SVenki.Rajagopalan@Sun.COM }
412*13101SVenki.Rajagopalan@Sun.COM 
413*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
414*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_bus_config(dev_info_t * parent,uint_t flags,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)415*13101SVenki.Rajagopalan@Sun.COM eibnx_bus_config(dev_info_t *parent, uint_t flags,
416*13101SVenki.Rajagopalan@Sun.COM     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
417*13101SVenki.Rajagopalan@Sun.COM {
418*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
419*13101SVenki.Rajagopalan@Sun.COM 	int ret = NDI_SUCCESS;
420*13101SVenki.Rajagopalan@Sun.COM 
421*13101SVenki.Rajagopalan@Sun.COM 	switch (op) {
422*13101SVenki.Rajagopalan@Sun.COM 	case BUS_CONFIG_ONE:
423*13101SVenki.Rajagopalan@Sun.COM 		eibnx_busop_inprog_enter(ss);
424*13101SVenki.Rajagopalan@Sun.COM 		ret = eibnx_config_child(arg, childp);
425*13101SVenki.Rajagopalan@Sun.COM 		eibnx_busop_inprog_exit(ss);
426*13101SVenki.Rajagopalan@Sun.COM 		break;
427*13101SVenki.Rajagopalan@Sun.COM 
428*13101SVenki.Rajagopalan@Sun.COM 	case BUS_CONFIG_ALL:
429*13101SVenki.Rajagopalan@Sun.COM 	case BUS_CONFIG_DRIVER:
430*13101SVenki.Rajagopalan@Sun.COM 		eibnx_busop_inprog_enter(ss);
431*13101SVenki.Rajagopalan@Sun.COM 		if ((ss->nx_busop_flags & NX_FL_BUSCFG_COMPLETE) == 0) {
432*13101SVenki.Rajagopalan@Sun.COM 			ret = eibnx_config_all_children(parent);
433*13101SVenki.Rajagopalan@Sun.COM 			if (ret == NDI_SUCCESS)
434*13101SVenki.Rajagopalan@Sun.COM 				ss->nx_busop_flags |= NX_FL_BUSCFG_COMPLETE;
435*13101SVenki.Rajagopalan@Sun.COM 		}
436*13101SVenki.Rajagopalan@Sun.COM 		eibnx_busop_inprog_exit(ss);
437*13101SVenki.Rajagopalan@Sun.COM 		break;
438*13101SVenki.Rajagopalan@Sun.COM 
439*13101SVenki.Rajagopalan@Sun.COM 	default:
440*13101SVenki.Rajagopalan@Sun.COM 		ret = NDI_FAILURE;
441*13101SVenki.Rajagopalan@Sun.COM 	}
442*13101SVenki.Rajagopalan@Sun.COM 
443*13101SVenki.Rajagopalan@Sun.COM 	if (ret == NDI_SUCCESS)
444*13101SVenki.Rajagopalan@Sun.COM 		ret = ndi_busop_bus_config(parent, flags, op, arg, childp, 0);
445*13101SVenki.Rajagopalan@Sun.COM 
446*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
447*13101SVenki.Rajagopalan@Sun.COM }
448*13101SVenki.Rajagopalan@Sun.COM 
449*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_bus_unconfig(dev_info_t * parent,uint_t flags,ddi_bus_config_op_t op,void * arg)450*13101SVenki.Rajagopalan@Sun.COM eibnx_bus_unconfig(dev_info_t *parent, uint_t flags,
451*13101SVenki.Rajagopalan@Sun.COM     ddi_bus_config_op_t op, void *arg)
452*13101SVenki.Rajagopalan@Sun.COM {
453*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
454*13101SVenki.Rajagopalan@Sun.COM 	int ret;
455*13101SVenki.Rajagopalan@Sun.COM 
456*13101SVenki.Rajagopalan@Sun.COM 	ret = ndi_busop_bus_unconfig(parent, flags, op, arg);
457*13101SVenki.Rajagopalan@Sun.COM 	if (ret != NDI_SUCCESS)
458*13101SVenki.Rajagopalan@Sun.COM 		return (ret);
459*13101SVenki.Rajagopalan@Sun.COM 
460*13101SVenki.Rajagopalan@Sun.COM 	switch (op) {
461*13101SVenki.Rajagopalan@Sun.COM 	case BUS_UNCONFIG_ONE:
462*13101SVenki.Rajagopalan@Sun.COM 		if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
463*13101SVenki.Rajagopalan@Sun.COM 			eibnx_busop_inprog_enter(ss);
464*13101SVenki.Rajagopalan@Sun.COM 
465*13101SVenki.Rajagopalan@Sun.COM 			if ((ret = eibnx_unconfig_child(arg)) == ENX_E_SUCCESS)
466*13101SVenki.Rajagopalan@Sun.COM 				ss->nx_busop_flags &= (~NX_FL_BUSCFG_COMPLETE);
467*13101SVenki.Rajagopalan@Sun.COM 			else {
468*13101SVenki.Rajagopalan@Sun.COM 				ENX_DPRINTF_DEBUG("eibnx_bus_config: "
469*13101SVenki.Rajagopalan@Sun.COM 				    "unconfig child %s failed", (char *)arg);
470*13101SVenki.Rajagopalan@Sun.COM 			}
471*13101SVenki.Rajagopalan@Sun.COM 
472*13101SVenki.Rajagopalan@Sun.COM 			eibnx_busop_inprog_exit(ss);
473*13101SVenki.Rajagopalan@Sun.COM 		}
474*13101SVenki.Rajagopalan@Sun.COM 		break;
475*13101SVenki.Rajagopalan@Sun.COM 
476*13101SVenki.Rajagopalan@Sun.COM 	case BUS_UNCONFIG_ALL:
477*13101SVenki.Rajagopalan@Sun.COM 	case BUS_UNCONFIG_DRIVER:
478*13101SVenki.Rajagopalan@Sun.COM 		if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
479*13101SVenki.Rajagopalan@Sun.COM 			eibnx_busop_inprog_enter(ss);
480*13101SVenki.Rajagopalan@Sun.COM 
481*13101SVenki.Rajagopalan@Sun.COM 			eibnx_unconfig_all_children(parent);
482*13101SVenki.Rajagopalan@Sun.COM 			ss->nx_busop_flags &= (~NX_FL_BUSCFG_COMPLETE);
483*13101SVenki.Rajagopalan@Sun.COM 
484*13101SVenki.Rajagopalan@Sun.COM 			eibnx_busop_inprog_exit(ss);
485*13101SVenki.Rajagopalan@Sun.COM 		}
486*13101SVenki.Rajagopalan@Sun.COM 		break;
487*13101SVenki.Rajagopalan@Sun.COM 
488*13101SVenki.Rajagopalan@Sun.COM 	default:
489*13101SVenki.Rajagopalan@Sun.COM 		break;
490*13101SVenki.Rajagopalan@Sun.COM 	}
491*13101SVenki.Rajagopalan@Sun.COM 
492*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
493*13101SVenki.Rajagopalan@Sun.COM }
494*13101SVenki.Rajagopalan@Sun.COM 
495*13101SVenki.Rajagopalan@Sun.COM /*
496*13101SVenki.Rajagopalan@Sun.COM  * Event Handling: bus_get_eventcookie, bus_add_eventcall, bus_remove_eventcall
497*13101SVenki.Rajagopalan@Sun.COM  * and bus_post_event
498*13101SVenki.Rajagopalan@Sun.COM  */
499*13101SVenki.Rajagopalan@Sun.COM 
500*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
501*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_get_eventcookie(dev_info_t * dip,dev_info_t * rdip,char * name,ddi_eventcookie_t * cookiep)502*13101SVenki.Rajagopalan@Sun.COM eibnx_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
503*13101SVenki.Rajagopalan@Sun.COM     char *name, ddi_eventcookie_t *cookiep)
504*13101SVenki.Rajagopalan@Sun.COM {
505*13101SVenki.Rajagopalan@Sun.COM 	return (ndi_event_retrieve_cookie(enx_ndi_event_hdl, rdip, name,
506*13101SVenki.Rajagopalan@Sun.COM 	    cookiep, NDI_EVENT_NOPASS));
507*13101SVenki.Rajagopalan@Sun.COM }
508*13101SVenki.Rajagopalan@Sun.COM 
509*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
510*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_add_eventcall(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void (* callback)(dev_info_t * cb_dip,ddi_eventcookie_t cb_cookie,void * cb_arg,void * cb_impl_data),void * arg,ddi_callback_id_t * cb_id)511*13101SVenki.Rajagopalan@Sun.COM eibnx_add_eventcall(dev_info_t *dip, dev_info_t *rdip, ddi_eventcookie_t cookie,
512*13101SVenki.Rajagopalan@Sun.COM     void (*callback)(dev_info_t *cb_dip, ddi_eventcookie_t cb_cookie,
513*13101SVenki.Rajagopalan@Sun.COM     void *cb_arg, void *cb_impl_data),
514*13101SVenki.Rajagopalan@Sun.COM     void *arg, ddi_callback_id_t *cb_id)
515*13101SVenki.Rajagopalan@Sun.COM {
516*13101SVenki.Rajagopalan@Sun.COM 	return (ndi_event_add_callback(enx_ndi_event_hdl, rdip, cookie,
517*13101SVenki.Rajagopalan@Sun.COM 	    callback, arg, NDI_SLEEP, cb_id));
518*13101SVenki.Rajagopalan@Sun.COM }
519*13101SVenki.Rajagopalan@Sun.COM 
520*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
521*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_remove_eventcall(dev_info_t * dip,ddi_callback_id_t cb_id)522*13101SVenki.Rajagopalan@Sun.COM eibnx_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
523*13101SVenki.Rajagopalan@Sun.COM {
524*13101SVenki.Rajagopalan@Sun.COM 	return (ndi_event_remove_callback(enx_ndi_event_hdl, cb_id));
525*13101SVenki.Rajagopalan@Sun.COM }
526*13101SVenki.Rajagopalan@Sun.COM 
527*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
528*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_post_event(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void * impl_data)529*13101SVenki.Rajagopalan@Sun.COM eibnx_post_event(dev_info_t *dip, dev_info_t *rdip,
530*13101SVenki.Rajagopalan@Sun.COM     ddi_eventcookie_t cookie, void *impl_data)
531*13101SVenki.Rajagopalan@Sun.COM {
532*13101SVenki.Rajagopalan@Sun.COM 	return (ndi_event_run_callbacks(enx_ndi_event_hdl, rdip, cookie,
533*13101SVenki.Rajagopalan@Sun.COM 	    impl_data));
534*13101SVenki.Rajagopalan@Sun.COM }
535*13101SVenki.Rajagopalan@Sun.COM 
536*13101SVenki.Rajagopalan@Sun.COM /*
537*13101SVenki.Rajagopalan@Sun.COM  * Routines to configure/unconfigure EoIB node(s) on a system.
538*13101SVenki.Rajagopalan@Sun.COM  */
539*13101SVenki.Rajagopalan@Sun.COM 
540*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
541*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_config_all_children(dev_info_t * parent)542*13101SVenki.Rajagopalan@Sun.COM eibnx_config_all_children(dev_info_t *parent)
543*13101SVenki.Rajagopalan@Sun.COM {
544*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
545*13101SVenki.Rajagopalan@Sun.COM 	eibnx_hca_t *hca;
546*13101SVenki.Rajagopalan@Sun.COM 	eibnx_port_t *port;
547*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
548*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti_tail;
549*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *gwi;
550*13101SVenki.Rajagopalan@Sun.COM 
551*13101SVenki.Rajagopalan@Sun.COM 	/*
552*13101SVenki.Rajagopalan@Sun.COM 	 * Go through each port of each hca and create a thread to solicit,
553*13101SVenki.Rajagopalan@Sun.COM 	 * monitor, receive advertisements, create eoib nodes and attach eoib
554*13101SVenki.Rajagopalan@Sun.COM 	 * driver instances.
555*13101SVenki.Rajagopalan@Sun.COM 	 */
556*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
557*13101SVenki.Rajagopalan@Sun.COM 	if (!ss->nx_monitors_up) {
558*13101SVenki.Rajagopalan@Sun.COM 		ss->nx_thr_info = ti_tail = NULL;
559*13101SVenki.Rajagopalan@Sun.COM 		for (hca = ss->nx_hca; hca; hca = hca->hc_next) {
560*13101SVenki.Rajagopalan@Sun.COM 			for (port = hca->hc_port; port; port = port->po_next) {
561*13101SVenki.Rajagopalan@Sun.COM 				ti = eibnx_start_port_monitor(hca, port);
562*13101SVenki.Rajagopalan@Sun.COM 				if (ti_tail) {
563*13101SVenki.Rajagopalan@Sun.COM 					ti_tail->ti_next = ti;
564*13101SVenki.Rajagopalan@Sun.COM 				} else {
565*13101SVenki.Rajagopalan@Sun.COM 					ss->nx_thr_info = ti;
566*13101SVenki.Rajagopalan@Sun.COM 				}
567*13101SVenki.Rajagopalan@Sun.COM 				ti_tail = ti;
568*13101SVenki.Rajagopalan@Sun.COM 			}
569*13101SVenki.Rajagopalan@Sun.COM 		}
570*13101SVenki.Rajagopalan@Sun.COM 
571*13101SVenki.Rajagopalan@Sun.COM 		ss->nx_monitors_up = B_TRUE;
572*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->nx_lock);
573*13101SVenki.Rajagopalan@Sun.COM 
574*13101SVenki.Rajagopalan@Sun.COM 		return (NDI_SUCCESS);
575*13101SVenki.Rajagopalan@Sun.COM 	}
576*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
577*13101SVenki.Rajagopalan@Sun.COM 
578*13101SVenki.Rajagopalan@Sun.COM 	while (eibnx_locate_unconfigured_node(&ti, &gwi) == ENX_E_SUCCESS)
579*13101SVenki.Rajagopalan@Sun.COM 		(void) eibnx_configure_node(ti, gwi, NULL);
580*13101SVenki.Rajagopalan@Sun.COM 
581*13101SVenki.Rajagopalan@Sun.COM 	return (NDI_SUCCESS);
582*13101SVenki.Rajagopalan@Sun.COM }
583*13101SVenki.Rajagopalan@Sun.COM 
584*13101SVenki.Rajagopalan@Sun.COM /*
585*13101SVenki.Rajagopalan@Sun.COM  * Routine to unconfigure all the EoIB nodes on a system. This terminates
586*13101SVenki.Rajagopalan@Sun.COM  * all the per-port monitor threads and releases any resources allocated.
587*13101SVenki.Rajagopalan@Sun.COM  */
588*13101SVenki.Rajagopalan@Sun.COM 
589*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
590*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_unconfig_all_children(dev_info_t * parent)591*13101SVenki.Rajagopalan@Sun.COM eibnx_unconfig_all_children(dev_info_t *parent)
592*13101SVenki.Rajagopalan@Sun.COM {
593*13101SVenki.Rajagopalan@Sun.COM 	eibnx_t *ss = enx_global_ss;
594*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
595*13101SVenki.Rajagopalan@Sun.COM 	eibnx_child_t *ch;
596*13101SVenki.Rajagopalan@Sun.COM 
597*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->nx_lock);
598*13101SVenki.Rajagopalan@Sun.COM 	for (ti = ss->nx_thr_info; ti; ti = ti->ti_next) {
599*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ti->ti_child_lock);
600*13101SVenki.Rajagopalan@Sun.COM 		for (ch = ti->ti_child; ch; ch = ch->ch_next) {
601*13101SVenki.Rajagopalan@Sun.COM 			ch->ch_dip = NULL;
602*13101SVenki.Rajagopalan@Sun.COM 		}
603*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ti->ti_child_lock);
604*13101SVenki.Rajagopalan@Sun.COM 	}
605*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->nx_lock);
606*13101SVenki.Rajagopalan@Sun.COM }
607*13101SVenki.Rajagopalan@Sun.COM 
608*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
609*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_config_child(char * devname,dev_info_t ** childp)610*13101SVenki.Rajagopalan@Sun.COM eibnx_config_child(char *devname, dev_info_t **childp)
611*13101SVenki.Rajagopalan@Sun.COM {
612*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
613*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *gwi;
614*13101SVenki.Rajagopalan@Sun.COM 
615*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_locate_node_name(devname, &ti, &gwi) == ENX_E_FAILURE) {
616*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("eibnx_config_child: invalid eoib "
617*13101SVenki.Rajagopalan@Sun.COM 		    "nodename %s, no such address", devname);
618*13101SVenki.Rajagopalan@Sun.COM 		return (ENX_E_FAILURE);
619*13101SVenki.Rajagopalan@Sun.COM 	}
620*13101SVenki.Rajagopalan@Sun.COM 
621*13101SVenki.Rajagopalan@Sun.COM 	return (eibnx_configure_node(ti, gwi, childp));
622*13101SVenki.Rajagopalan@Sun.COM }
623*13101SVenki.Rajagopalan@Sun.COM 
624*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
625*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_unconfig_child(char * devname)626*13101SVenki.Rajagopalan@Sun.COM eibnx_unconfig_child(char *devname)
627*13101SVenki.Rajagopalan@Sun.COM {
628*13101SVenki.Rajagopalan@Sun.COM 	eibnx_thr_info_t *ti;
629*13101SVenki.Rajagopalan@Sun.COM 	eibnx_gw_info_t *gwi;
630*13101SVenki.Rajagopalan@Sun.COM 
631*13101SVenki.Rajagopalan@Sun.COM 	if (eibnx_locate_node_name(devname, &ti, &gwi) == ENX_E_FAILURE) {
632*13101SVenki.Rajagopalan@Sun.COM 		ENX_DPRINTF_DEBUG("eibnx_unconfig_child: invalid eoib "
633*13101SVenki.Rajagopalan@Sun.COM 		    "nodename %s, no such address", devname);
634*13101SVenki.Rajagopalan@Sun.COM 		return (ENX_E_FAILURE);
635*13101SVenki.Rajagopalan@Sun.COM 	}
636*13101SVenki.Rajagopalan@Sun.COM 
637*13101SVenki.Rajagopalan@Sun.COM 	return (eibnx_unconfigure_node(ti, gwi));
638*13101SVenki.Rajagopalan@Sun.COM }
639