xref: /titanic_51/usr/src/uts/common/io/aggr/aggr_dev.c (revision 1a7c1b724419d3cb5fa6eea75123c6b2060ba31b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * IEEE 802.3ad Link Aggregation.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/sysmacros.h>
35 #include <sys/conf.h>
36 #include <sys/cmn_err.h>
37 #include <sys/list.h>
38 #include <sys/ksynch.h>
39 #include <sys/kmem.h>
40 #include <sys/stream.h>
41 #include <sys/modctl.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/atomic.h>
45 #include <sys/stat.h>
46 
47 #include <sys/aggr.h>
48 #include <sys/aggr_impl.h>
49 
50 /* module description */
51 #define	AGGR_LINKINFO	"Link Aggregation MAC"
52 
53 /* device info ptr, only one for instance 0 */
54 dev_info_t *aggr_dip;
55 
56 static void aggr_dev_init(void);
57 static int aggr_dev_fini(void);
58 static int aggr_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
59 static int aggr_attach(dev_info_t *, ddi_attach_cmd_t);
60 static int aggr_detach(dev_info_t *, ddi_detach_cmd_t);
61 
62 static struct cb_ops aggr_cb_ops = {
63 	aggr_open,		/* open */
64 	aggr_close,		/* close */
65 	nulldev,		/* strategy */
66 	nulldev,		/* print */
67 	nodev,			/* dump */
68 	nodev,			/* read */
69 	nodev,			/* write */
70 	aggr_ioctl,		/* ioctl */
71 	nodev,			/* devmap */
72 	nodev,			/* mmap */
73 	nodev,			/* segmap */
74 	nochpoll,		/* poll */
75 	ddi_prop_op,		/* cb_prop_op */
76 	0,			/* streamtab  */
77 	D_NEW | D_MP		/* driver compatibility flag */
78 };
79 
80 static struct dev_ops aggr_ops = {
81 	DEVO_REV,		/* devo_rev */
82 	0,			/* refcnt */
83 	aggr_getinfo,		/* getinfo */
84 	nulldev,		/* identify */
85 	nulldev,		/* probe */
86 	aggr_attach,		/* attach */
87 	aggr_detach,		/* detach */
88 	nodev,			/* reset */
89 	&aggr_cb_ops,		/* driver operations */
90 	NULL,			/* bus operations */
91 	nodev			/* dev power */
92 };
93 
94 static struct modldrv modldrv = {
95 	&mod_driverops,
96 	AGGR_LINKINFO,
97 	&aggr_ops
98 };
99 
100 static struct modlinkage	modlinkage = {
101 	MODREV_1,
102 	&modldrv,
103 	NULL
104 };
105 
106 int
107 _init(void)
108 {
109 	int err;
110 
111 	aggr_dev_init();
112 
113 	if ((err = mod_install(&modlinkage)) != 0) {
114 		(void) aggr_dev_fini();
115 		return (err);
116 	}
117 
118 	aggr_dip = NULL;
119 
120 	return (0);
121 }
122 
123 int
124 _fini(void)
125 {
126 	int err;
127 
128 	if ((err = aggr_dev_fini()) != 0)
129 		return (err);
130 
131 	if ((err = mod_remove(&modlinkage)) != 0) {
132 		aggr_dev_init();
133 		return (err);
134 	}
135 
136 	return (0);
137 }
138 
139 int
140 _info(struct modinfo *modinfop)
141 {
142 	return (mod_info(&modlinkage, modinfop));
143 }
144 
145 static void
146 aggr_dev_init(void)
147 {
148 	aggr_port_init();
149 	aggr_grp_init();
150 }
151 
152 static int
153 aggr_dev_fini(void)
154 {
155 	int err;
156 
157 	if ((err = aggr_grp_fini()) != 0)
158 		return (err);
159 	if ((err = aggr_port_fini()) != 0) {
160 		/*
161 		 * re-initialize the groups to keep a consistent
162 		 * state.
163 		 */
164 		aggr_grp_init();
165 	}
166 
167 	return (err);
168 }
169 
170 /*ARGSUSED*/
171 static int
172 aggr_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
173     void **result)
174 {
175 	switch (infocmd) {
176 	case DDI_INFO_DEVT2DEVINFO:
177 		*result = aggr_dip;
178 		return (DDI_SUCCESS);
179 	case DDI_INFO_DEVT2INSTANCE:
180 		*result = NULL;
181 		return (DDI_SUCCESS);
182 	}
183 	return (DDI_FAILURE);
184 }
185 
186 static int
187 aggr_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
188 {
189 	switch (cmd) {
190 	case DDI_ATTACH:
191 		if (ddi_get_instance(dip) != 0) {
192 			/* we only allow instance 0 to attach */
193 			return (DDI_FAILURE);
194 		}
195 
196 		/* create minor node for control interface */
197 		if (ddi_create_minor_node(dip, AGGR_DEVNAME_CTL, S_IFCHR,
198 		    AGGR_MINOR_CTL, DDI_PSEUDO, 0) != DDI_SUCCESS) {
199 			return (DDI_FAILURE);
200 		}
201 
202 		aggr_dip = dip;
203 		return (DDI_SUCCESS);
204 
205 	case DDI_RESUME:
206 		return (DDI_SUCCESS);
207 
208 	default:
209 		return (DDI_FAILURE);
210 	}
211 }
212 
213 /*ARGSUSED*/
214 static int
215 aggr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
216 {
217 	switch (cmd) {
218 	case DDI_DETACH:
219 		aggr_dip = NULL;
220 		ddi_remove_minor_node(dip, NULL);
221 
222 		return (DDI_SUCCESS);
223 
224 	case DDI_SUSPEND:
225 		return (DDI_SUCCESS);
226 
227 	default:
228 		return (DDI_FAILURE);
229 	}
230 }
231