xref: /illumos-gate/usr/src/uts/common/io/aggr/aggr_dev.c (revision 909c9a9f5171df17baed828a2889f1817ee87cfa)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * IEEE 802.3ad Link Aggregation.
28  */
29 
30 #include <sys/conf.h>
31 #include <sys/modctl.h>
32 #include <sys/aggr.h>
33 #include <sys/aggr_impl.h>
34 
35 /* module description */
36 #define	AGGR_LINKINFO	"Link Aggregation MAC"
37 
38 /* device info ptr, only one for instance 0 */
39 dev_info_t *aggr_dip = NULL;
40 
41 static int aggr_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
42 static int aggr_attach(dev_info_t *, ddi_attach_cmd_t);
43 static int aggr_detach(dev_info_t *, ddi_detach_cmd_t);
44 
45 static struct cb_ops aggr_cb_ops = {
46 	nulldev,		/* open */
47 	nulldev,		/* close */
48 	nulldev,		/* strategy */
49 	nulldev,		/* print */
50 	nodev,			/* dump */
51 	nodev,			/* read */
52 	nodev,			/* write */
53 	nodev,			/* ioctl */
54 	nodev,			/* devmap */
55 	nodev,			/* mmap */
56 	nodev,			/* segmap */
57 	nochpoll,		/* poll */
58 	ddi_prop_op,		/* cb_prop_op */
59 	0,			/* streamtab  */
60 	D_MP			/* Driver compatibility flag */
61 };
62 
63 static struct dev_ops aggr_dev_ops = {
64 	DEVO_REV,		/* devo_rev */
65 	0,			/* refcnt */
66 	aggr_getinfo,		/* get_dev_info */
67 	nulldev,		/* identify */
68 	nulldev,		/* probe */
69 	aggr_attach,		/* attach */
70 	aggr_detach,		/* detach */
71 	nodev,			/* reset */
72 	&aggr_cb_ops,		/* driver operations */
73 	NULL,			/* bus operations */
74 	nodev,			/* dev power */
75 	ddi_quiesce_not_supported,	/* dev quiesce */
76 };
77 
78 static struct modldrv aggr_modldrv = {
79 	&mod_driverops,		/* Type of module.  This one is a driver */
80 	AGGR_LINKINFO,		/* short description */
81 	&aggr_dev_ops		/* driver specific ops */
82 };
83 
84 static struct modlinkage modlinkage = {
85 	MODREV_1,
86 	&aggr_modldrv,
87 	NULL
88 };
89 
90 int
91 _init(void)
92 {
93 	int	err;
94 
95 	mac_init_ops(&aggr_dev_ops, "aggr");
96 	if ((err = mod_install(&modlinkage)) != 0)
97 		mac_fini_ops(&aggr_dev_ops);
98 	return (err);
99 }
100 
101 int
102 _fini(void)
103 {
104 	int	err;
105 
106 	if ((err = mod_remove(&modlinkage)) == 0)
107 		mac_fini_ops(&aggr_dev_ops);
108 	return (err);
109 }
110 
111 int
112 _info(struct modinfo *modinfop)
113 {
114 	return (mod_info(&modlinkage, modinfop));
115 }
116 
117 /*ARGSUSED*/
118 static int
119 aggr_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
120     void **result)
121 {
122 	switch (infocmd) {
123 	case DDI_INFO_DEVT2DEVINFO:
124 		*result = aggr_dip;
125 		return (DDI_SUCCESS);
126 	case DDI_INFO_DEVT2INSTANCE:
127 		*result = 0;
128 		return (DDI_SUCCESS);
129 	}
130 	return (DDI_FAILURE);
131 }
132 
133 static int
134 aggr_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
135 {
136 	switch (cmd) {
137 	case DDI_ATTACH:
138 		if (ddi_get_instance(dip) != 0) {
139 			/* we only allow instance 0 to attach */
140 			return (DDI_FAILURE);
141 		}
142 		if (aggr_ioc_init() != 0)
143 			return (DDI_FAILURE);
144 		aggr_dip = dip;
145 		aggr_port_init();
146 		aggr_grp_init();
147 		aggr_lacp_init();
148 		return (DDI_SUCCESS);
149 
150 	case DDI_RESUME:
151 		return (DDI_SUCCESS);
152 
153 	default:
154 		return (DDI_FAILURE);
155 	}
156 }
157 
158 /*ARGSUSED*/
159 static int
160 aggr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
161 {
162 	switch (cmd) {
163 	case DDI_DETACH:
164 		if (aggr_grp_count() > 0)
165 			return (DDI_FAILURE);
166 
167 		aggr_dip = NULL;
168 		aggr_port_fini();
169 		aggr_grp_fini();
170 		aggr_lacp_fini();
171 		aggr_ioc_fini();
172 		return (DDI_SUCCESS);
173 
174 	case DDI_SUSPEND:
175 		return (DDI_SUCCESS);
176 
177 	default:
178 		return (DDI_FAILURE);
179 	}
180 }
181