Home | History | Annotate | Download | only in aggr
      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