softmac_main.c revision 3ade6e843b7f9e2656892a172ecd9e302b0dee09
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The softmac driver is used to "unify" non-GLDv3 drivers to the GLDv3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * framework. It also creates the kernel datalink structure for each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * physical network device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Specifically, a softmac will be created for each physical network device
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (dip) during the device's post-attach process. When this softmac is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * created, the following will also be done:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * - create the device's <link name, linkid> mapping;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * - register the mac if this is a non-GLDv3 device and the media type is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * supported by the GLDv3 framework;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * - create the kernel data-link structure for this physical device;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This softmac will be destroyed during the device's pre-detach process,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and all the above will be undone.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Used as a parameter to the mod hash walk of softmac structures */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Softmac hash table including softmacs for both style-2 and style-1 devices.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void softmac_create_task(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int softmac_m_start(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void softmac_m_stop(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int softmac_m_open(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void softmac_m_close(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic boolean_t softmac_m_getcapab(void *, mac_capab_t, void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int softmac_m_setprop(void *, const char *, mac_prop_id_t,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint_t, const void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int softmac_m_getprop(void *, const char *, mac_prop_id_t,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (MC_IOCTL | MC_GETCAPAB | MC_OPEN | MC_CLOSE | MC_SETPROP | MC_GETPROP)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mutex_init(&softmac->smac_mutex, NULL, MUTEX_DEFAULT, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mutex_init(&softmac->smac_active_mutex, NULL, MUTEX_DEFAULT, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mutex_init(&softmac->smac_fp_mutex, NULL, MUTEX_DEFAULT, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw list_create(&softmac->smac_sup_list, sizeof (softmac_upper_t),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw SOFTMAC_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mutex_init(&smac_global_lock, NULL, MUTEX_DRIVER, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* ARGSUSED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsoftmac_exist(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * softmac_create() is called for each minor node during the post-attach of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * each DDI_NT_NET device instance. Note that it is possible that a device
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * instance has two minor nodes (DLPI style-1 and style-2), so that for that
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specific device, softmac_create() could be called twice.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * A softmac_t is used to track each DDI_NT_NET device, and a softmac_dev_t
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * is created to track each minor node.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * For each minor node of a legacy device, a taskq is started to finish
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * softmac_mac_register(), which will finish the rest of work (see comments
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * above softmac_mac_register()).
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * softmac state machine
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * --------------------------------------------------------------------------
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * OLD STATE EVENT NEW STATE
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * --------------------------------------------------------------------------
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * UNINIT attach of 1st minor node ATTACH_INPROG
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 0 net_postattach -> softmac_create okcnt = 1
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * ATTACH_INPROG attach of 2nd minor node (GLDv3) ATTACH_DONE
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 1 net_postattach -> softmac_create okcnt = 2
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * ATTACH_INPROG attach of 2nd minor node (legacy) ATTACH_INPROG
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 1 net_postattach -> softmac_create okcnt = 2
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * schedule softmac_mac_register
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * ATTACH_INPROG legacy device node ATTACH_DONE
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 2 softmac_mac_register okcnt = 2
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * ATTACH_DONE detach of 1st minor node DETACH_INPROG
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 2 (success) okcnt = 1
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * DETACH_INPROG detach of 2nd minor node UNINIT (or free)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 1 (success) okcnt = 0
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * ATTACH_DONE detach failure state unchanged
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * DETACH_INPROG left = okcnt
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * DETACH_INPROG reattach ATTACH_INPROG
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * okcnt = 0,1 net_postattach -> softmac_create
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ATTACH_DONE reattach ATTACH_DONE
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * left != 0 net_postattach -> softmac_create left = 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Abbreviation notes:
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States * states have SOFTMAC_ prefix,
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States * okcnt - softmac_attach_okcnt,
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States * left - softmac_attached_left
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States#ifdef DEBUG
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * There are at most 2 minor nodes, one per DLPI style
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(softmac->smac_cnt <= 2 && softmac->smac_attachok_cnt <= 2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The smac_attachok_cnt represents the number of attaches i.e. the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number of times net_postattach -> softmac_create() has been called
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * for a device instance.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(softmac->smac_attachok_cnt == SMAC_NONZERO_NODECNT(softmac));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * softmac_create (or softmac_mac_register) -> softmac_create_datalink
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * happens only after all minor nodes have been attached
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (softmac->smac_attachok_cnt < softmac->smac_cnt) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * In the stable condition the state whould be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SOFTMAC_ATTACH_DONE. But there is a small transient window
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in softmac_destroy where we change the state to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SOFTMAC_DETACH_INPROG and drop the lock before doing
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the link destroy
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(softmac->smac_attachok_cnt == softmac->smac_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(softmac->smac_attachok_cnt == softmac->smac_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define SOFTMAC_STATE_VERIFY(softmac) softmac_state_verify(softmac)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Force the softmac driver to be attached.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (i_ddi_attach_pseudo_node(SOFTMAC_DEV_NAME) == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cmn_err(CE_WARN, "softmac_create:softmac attach fails");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * For GLDv3, we don't care about the DLPI style 2
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * compatibility node. (We know that all such devices
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * have style 1 nodes.)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Likewise, we know that the minor number for DLPI style 1
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * nodes is constrained to a maximum value.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Otherwise we can decode the instance from the minor number,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * which allows for situations with multiple mac instances
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * for a single dev_info_t.
return (ENOTSUP);
static boolean_t
return (B_FALSE);
switch (cap) {
case MAC_CAPAB_HCKSUM: {
case MAC_CAPAB_LEGACY: {
case MAC_CAPAB_NO_ZCOPY:
case MAC_CAPAB_NO_NATIVEVLAN:
return (B_TRUE);
int err;
return (err);
int err;
return (err);
return (err);
if (err != 0) {
return (err);
int err;
goto done;
done:
if (err != 0)
int index;
int err;
goto done;
if (err == 0) {
int rval;
li) != 0) {
err = 0;
margin = 0;
&rval) == 0) {
if (native_vlan) {
case ENOTSUP:
err = 0;
if (err != 0)
goto done;
goto done;
if (err != 0) {
goto done;
goto done;
done:
int index;
(minor == 0)) {
return (ENOTSUP);
return (EBUSY);
return (EBUSY);
B_FALSE)) != 0) {
goto error;
goto error;
return (err);
static uint_t
int err;
return (MH_WALK_TERMINATE);
return (MH_WALK_CONTINUE);
return (MH_WALK_CONTINUE);
return (MH_WALK_CONTINUE);
if (err != 0) {
return (MH_WALK_CONTINUE);
int err;
if (err != 0)
return (err);
if (err != 0) {
return (err);
return (err);
return (err);
if (err != 0)
goto done;
goto done;
goto done;
goto done;
goto done;
done:
if (err != 0)
return (err);
int err;
return (err);
return (ENOTSUP);
return (EINVAL);
char *fpstr;
return (ENOTSUP);
return (ENOTSUP);
return (ENOTSUP);
const char *drvname;
if (inst < 0)
return (ENOENT);
return (ENOENT);
return (ENOENT);
return (ENOENT);
goto again;
return (err);
char *drv;
int err;
return (EINVAL);
return (err);