Home | History | Annotate | Download | only in io
      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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 /*
     29  * gld - Generic LAN Driver Version 2, PSARC/1997/382
     30  *
     31  * This is a utility module that provides generic facilities for
     32  * LAN	drivers.  The DLPI protocol and most STREAMS interfaces
     33  * are handled here.
     34  *
     35  * It no longer provides compatibility with drivers
     36  * implemented according to the GLD v0 documentation published
     37  * in 1993. (See PSARC 2003/728)
     38  */
     39 
     40 
     41 #include <sys/types.h>
     42 #include <sys/errno.h>
     43 #include <sys/stropts.h>
     44 #include <sys/stream.h>
     45 #include <sys/kmem.h>
     46 #include <sys/stat.h>
     47 #include <sys/modctl.h>
     48 #include <sys/kstat.h>
     49 #include <sys/debug.h>
     50 #include <sys/note.h>
     51 #include <sys/sysmacros.h>
     52 
     53 #include <sys/byteorder.h>
     54 #include <sys/strsun.h>
     55 #include <sys/strsubr.h>
     56 #include <sys/dlpi.h>
     57 #include <sys/pattr.h>
     58 #include <sys/ethernet.h>
     59 #include <sys/ib/clients/ibd/ibd.h>
     60 #include <sys/policy.h>
     61 #include <sys/atomic.h>
     62 
     63 #include <sys/multidata.h>
     64 #include <sys/gld.h>
     65 #include <sys/gldpriv.h>
     66 
     67 #include <sys/ddi.h>
     68 #include <sys/sunddi.h>
     69 
     70 /*
     71  * Macros to increment statistics.
     72  */
     73 
     74 /*
     75  * Increase kstats. Note this operation is not atomic. It can be used when
     76  * GLDM_LOCK_HELD_WRITE(macinfo).
     77  */
     78 #define	BUMP(stats, vstats, stat, delta)	do {			\
     79 	((stats)->stat) += (delta);					\
     80 	_NOTE(CONSTANTCONDITION)					\
     81 	if ((vstats) != NULL)						\
     82 		((struct gld_stats *)(vstats))->stat += (delta);	\
     83 	_NOTE(CONSTANTCONDITION)					\
     84 } while (0)
     85 
     86 #define	ATOMIC_BUMP_STAT(stat, delta)	do {			\
     87 	_NOTE(CONSTANTCONDITION)				\
     88 	if (sizeof ((stat)) == sizeof (uint32_t)) {		\
     89 		atomic_add_32((uint32_t *)&(stat), (delta));	\
     90 	_NOTE(CONSTANTCONDITION)				\
     91 	} else if (sizeof ((stat)) == sizeof (uint64_t)) {	\
     92 		atomic_add_64((uint64_t *)&(stat), (delta));	\
     93 	}							\
     94 	_NOTE(CONSTANTCONDITION)				\
     95 } while (0)
     96 
     97 #define	ATOMIC_BUMP(stats, vstats, stat, delta)	do {			\
     98 	ATOMIC_BUMP_STAT((stats)->stat, (delta));			\
     99 	_NOTE(CONSTANTCONDITION)					\
    100 	if ((vstats) != NULL) {						\
    101 		ATOMIC_BUMP_STAT(((struct gld_stats *)(vstats))->stat,	\
    102 		    (delta));						\
    103 	}								\
    104 	_NOTE(CONSTANTCONDITION)					\
    105 } while (0)
    106 
    107 #define	UPDATE_STATS(stats, vstats, pktinfo, delta) {			\
    108 	if ((pktinfo).isBroadcast) {					\
    109 		ATOMIC_BUMP((stats), (vstats),				\
    110 		    glds_brdcstxmt, (delta));				\
    111 	} else if ((pktinfo).isMulticast) {				\
    112 		ATOMIC_BUMP((stats), (vstats), glds_multixmt, (delta));	\
    113 	}								\
    114 	ATOMIC_BUMP((stats), (vstats), glds_bytexmt64,			\
    115 	    ((pktinfo).pktLen));					\
    116 	ATOMIC_BUMP((stats), (vstats), glds_pktxmt64, (delta));		\
    117 }
    118 
    119 #ifdef GLD_DEBUG
    120 int gld_debug = GLDERRS;
    121 #endif
    122 
    123 /* called from gld_register */
    124 static int gld_initstats(gld_mac_info_t *);
    125 
    126 /* called from kstat mechanism, and from wsrv's get_statistics */
    127 static int gld_update_kstat(kstat_t *, int);
    128 
    129 /* statistics for additional vlans */
    130 static int gld_init_vlan_stats(gld_vlan_t *);
    131 static int gld_update_vlan_kstat(kstat_t *, int);
    132 
    133 /* called from gld_getinfo */
    134 static dev_info_t *gld_finddevinfo(dev_t);
    135 
    136 /* called from wput, wsrv, unidata, and v0_sched to send a packet */
    137 /* also from the source routing stuff for sending RDE protocol packets */
    138 static int gld_start(queue_t *, mblk_t *, int, uint32_t);
    139 static int gld_start_mdt(queue_t *, mblk_t *, int);
    140 
    141 /* called from gld_start[_mdt] to loopback packet(s) in promiscuous mode */
    142 static void gld_precv(gld_mac_info_t *, mblk_t *, uint32_t, struct gld_stats *);
    143 static void gld_precv_mdt(gld_mac_info_t *, gld_vlan_t *, mblk_t *,
    144     pdesc_t *, pktinfo_t *);
    145 
    146 /* receive group: called from gld_recv and gld_precv* with maclock held */
    147 static void gld_sendup(gld_mac_info_t *, pktinfo_t *, mblk_t *,
    148     int (*)());
    149 static int gld_accept(gld_t *, pktinfo_t *);
    150 static int gld_mcmatch(gld_t *, pktinfo_t *);
    151 static int gld_multicast(unsigned char *, gld_t *);
    152 static int gld_paccept(gld_t *, pktinfo_t *);
    153 static void gld_passon(gld_t *, mblk_t *, pktinfo_t *,
    154     void (*)(queue_t *, mblk_t *));
    155 static mblk_t *gld_addudind(gld_t *, mblk_t *, pktinfo_t *, boolean_t);
    156 
    157 /* wsrv group: called from wsrv, single threaded per queue */
    158 static int gld_ioctl(queue_t *, mblk_t *);
    159 static void gld_fastpath(gld_t *, queue_t *, mblk_t *);
    160 static int gld_cmds(queue_t *, mblk_t *);
    161 static mblk_t *gld_bindack(queue_t *, mblk_t *);
    162 static int gld_notify_req(queue_t *, mblk_t *);
    163 static int gld_udqos(queue_t *, mblk_t *);
    164 static int gld_bind(queue_t *, mblk_t *);
    165 static int gld_unbind(queue_t *, mblk_t *);
    166 static int gld_inforeq(queue_t *, mblk_t *);
    167 static int gld_unitdata(queue_t *, mblk_t *);
    168 static int gldattach(queue_t *, mblk_t *);
    169 static int gldunattach(queue_t *, mblk_t *);
    170 static int gld_enable_multi(queue_t *, mblk_t *);
    171 static int gld_disable_multi(queue_t *, mblk_t *);
    172 static void gld_send_disable_multi(gld_mac_info_t *, gld_mcast_t *);
    173 static int gld_promisc(queue_t *, mblk_t *, t_uscalar_t, boolean_t);
    174 static int gld_physaddr(queue_t *, mblk_t *);
    175 static int gld_setaddr(queue_t *, mblk_t *);
    176 static int gld_get_statistics(queue_t *, mblk_t *);
    177 static int gld_cap(queue_t *, mblk_t *);
    178 static int gld_cap_ack(queue_t *, mblk_t *);
    179 static int gld_cap_enable(queue_t *, mblk_t *);
    180 
    181 /* misc utilities, some requiring various mutexes held */
    182 static int gld_start_mac(gld_mac_info_t *);
    183 static void gld_stop_mac(gld_mac_info_t *);
    184 static void gld_set_ipq(gld_t *);
    185 static void gld_flushqueue(queue_t *);
    186 static glddev_t *gld_devlookup(int);
    187 static int gld_findminor(glddev_t *);
    188 static void gldinsque(void *, void *);
    189 static void gldremque(void *);
    190 void gld_bitrevcopy(caddr_t, caddr_t, size_t);
    191 void gld_bitreverse(uchar_t *, size_t);
    192 char *gld_macaddr_sprintf(char *, unsigned char *, int);
    193 static gld_vlan_t *gld_add_vlan(gld_mac_info_t *, uint32_t vid);
    194 static void gld_rem_vlan(gld_vlan_t *);
    195 gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
    196 gld_vlan_t *gld_get_vlan(gld_mac_info_t *, uint32_t);
    197 
    198 #ifdef GLD_DEBUG
    199 static void gld_check_assertions(void);
    200 extern void gld_sr_dump(gld_mac_info_t *);
    201 #endif
    202 
    203 /*
    204  * Allocate and zero-out "number" structures each of type "structure" in
    205  * kernel memory.
    206  */
    207 #define	GLD_GETSTRUCT(structure, number)   \
    208 	(kmem_zalloc((uint_t)(sizeof (structure) * (number)), KM_NOSLEEP))
    209 
    210 #define	abs(a) ((a) < 0 ? -(a) : a)
    211 
    212 uint32_t gld_global_options = GLD_OPT_NO_ETHRXSNAP;
    213 
    214 /*
    215  * The device is of DL_ETHER type and is able to support VLAN by itself.
    216  */
    217 #define	VLAN_CAPABLE(macinfo) \
    218 	((macinfo)->gldm_type == DL_ETHER && \
    219 	(macinfo)->gldm_send_tagged != NULL)
    220 
    221 /*
    222  * The set of notifications generatable by GLD itself, the additional
    223  * set that can be generated if the MAC driver provide the link-state
    224  * tracking callback capability, and the set supported by the GLD
    225  * notification code below.
    226  *
    227  * PLEASE keep these in sync with what the code actually does!
    228  */
    229 static const uint32_t gld_internal_notes =	DL_NOTE_PROMISC_ON_PHYS |
    230 						DL_NOTE_PROMISC_OFF_PHYS |
    231 						DL_NOTE_PHYS_ADDR;
    232 static const uint32_t gld_linkstate_notes =	DL_NOTE_LINK_DOWN |
    233 						DL_NOTE_LINK_UP |
    234 						DL_NOTE_SPEED;
    235 static const uint32_t gld_supported_notes =	DL_NOTE_PROMISC_ON_PHYS |
    236 						DL_NOTE_PROMISC_OFF_PHYS |
    237 						DL_NOTE_PHYS_ADDR |
    238 						DL_NOTE_LINK_DOWN |
    239 						DL_NOTE_LINK_UP |
    240 						DL_NOTE_SPEED;
    241 
    242 /* Media must correspond to #defines in gld.h */
    243 static char *gld_media[] = {
    244 	"unknown",	/* GLDM_UNKNOWN - driver cannot determine media */
    245 	"aui",		/* GLDM_AUI */
    246 	"bnc",		/* GLDM_BNC */
    247 	"twpair",	/* GLDM_TP */
    248 	"fiber",	/* GLDM_FIBER */
    249 	"100baseT",	/* GLDM_100BT */
    250 	"100vgAnyLan",	/* GLDM_VGANYLAN */
    251 	"10baseT",	/* GLDM_10BT */
    252 	"ring4",	/* GLDM_RING4 */
    253 	"ring16",	/* GLDM_RING16 */
    254 	"PHY/MII",	/* GLDM_PHYMII */
    255 	"100baseTX",	/* GLDM_100BTX */
    256 	"100baseT4",	/* GLDM_100BT4 */
    257 	"unknown",	/* skip */
    258 	"ipib",		/* GLDM_IB */
    259 };
    260 
    261 /* Must correspond to #defines in gld.h */
    262 static char *gld_duplex[] = {
    263 	"unknown",	/* GLD_DUPLEX_UNKNOWN - not known or not applicable */
    264 	"half",		/* GLD_DUPLEX_HALF */
    265 	"full"		/* GLD_DUPLEX_FULL */
    266 };
    267 
    268 /*
    269  * Interface types currently supported by GLD.
    270  * If you add new types, you must check all "XXX" strings in the GLD source
    271  * for implementation issues that may affect the support of your new type.
    272  * In particular, any type with gldm_addrlen > 6, or gldm_saplen != -2, will
    273  * require generalizing this GLD source to handle the new cases.  In other
    274  * words there are assumptions built into the code in a few places that must
    275  * be fixed.  Be sure to turn on DEBUG/ASSERT code when testing a new type.
    276  */
    277 static gld_interface_t interfaces[] = {
    278 
    279 	/* Ethernet Bus */
    280 	{
    281 		DL_ETHER,
    282 		(uint_t)-1,
    283 		sizeof (struct ether_header),
    284 		gld_interpret_ether,
    285 		NULL,
    286 		gld_fastpath_ether,
    287 		gld_unitdata_ether,
    288 		gld_init_ether,
    289 		gld_uninit_ether,
    290 		"ether"
    291 	},
    292 
    293 	/* Fiber Distributed data interface */
    294 	{
    295 		DL_FDDI,
    296 		4352,
    297 		sizeof (struct fddi_mac_frm),
    298 		gld_interpret_fddi,
    299 		NULL,
    300 		gld_fastpath_fddi,
    301 		gld_unitdata_fddi,
    302 		gld_init_fddi,
    303 		gld_uninit_fddi,
    304 		"fddi"
    305 	},
    306 
    307 	/* Token Ring interface */
    308 	{
    309 		DL_TPR,
    310 		17914,
    311 		-1,			/* variable header size */
    312 		gld_interpret_tr,
    313 		NULL,
    314 		gld_fastpath_tr,
    315 		gld_unitdata_tr,
    316 		gld_init_tr,
    317 		gld_uninit_tr,
    318 		"tpr"
    319 	},
    320 
    321 	/* Infiniband */
    322 	{
    323 		DL_IB,
    324 		4092,
    325 		sizeof (struct ipoib_header),
    326 		gld_interpret_ib,
    327 		gld_interpret_mdt_ib,
    328 		gld_fastpath_ib,
    329 		gld_unitdata_ib,
    330 		gld_init_ib,
    331 		gld_uninit_ib,
    332 		"ipib"
    333 	},
    334 };
    335 
    336 /*
    337  * bit reversal lookup table.
    338  */
    339 static	uchar_t bit_rev[] = {
    340 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
    341 	0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    342 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
    343 	0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    344 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
    345 	0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    346 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
    347 	0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    348 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
    349 	0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    350 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
    351 	0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    352 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
    353 	0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    354 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
    355 	0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    356 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
    357 	0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    358 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
    359 	0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    360 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
    361 	0x3f, 0xbf, 0x7f, 0xff,
    362 };
    363 
    364 /*
    365  * User priorities, mapped from b_band.
    366  */
    367 static uint32_t user_priority[] = {
    368 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    369 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    370 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    371 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    372 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    373 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    374 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    375 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    376 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    377 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    378 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    379 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    380 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    381 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    382 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    383 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
    384 };
    385 
    386 #define	UPRI(gld, band)	((band != 0) ? user_priority[(band)] : (gld)->gld_upri)
    387 
    388 static struct glddevice gld_device_list;  /* Per-system root of GLD tables */
    389 
    390 /*
    391  * Module linkage information for the kernel.
    392  */
    393 
    394 static struct modldrv modlmisc = {
    395 	&mod_miscops,		/* Type of module - a utility provider */
    396 	"Generic LAN Driver (" GLD_VERSION_STRING ") %I%"
    397 #ifdef GLD_DEBUG
    398 	" DEBUG"
    399 #endif
    400 };
    401 
    402 static struct modlinkage modlinkage = {
    403 	MODREV_1, &modlmisc, NULL
    404 };
    405 
    406 int
    407 _init(void)
    408 {
    409 	int e;
    410 
    411 	/* initialize gld_device_list mutex */
    412 	mutex_init(&gld_device_list.gld_devlock, NULL, MUTEX_DRIVER, NULL);
    413 
    414 	/* initialize device driver (per-major) list */
    415 	gld_device_list.gld_next =
    416 	    gld_device_list.gld_prev = &gld_device_list;
    417 
    418 	if ((e = mod_install(&modlinkage)) != 0)
    419 		mutex_destroy(&gld_device_list.gld_devlock);
    420 
    421 	return (e);
    422 }
    423 
    424 int
    425 _fini(void)
    426 {
    427 	int e;
    428 
    429 	if ((e = mod_remove(&modlinkage)) != 0)
    430 		return (e);
    431 
    432 	ASSERT(gld_device_list.gld_next ==
    433 	    (glddev_t *)&gld_device_list.gld_next);
    434 	ASSERT(gld_device_list.gld_prev ==
    435 	    (glddev_t *)&gld_device_list.gld_next);
    436 	mutex_destroy(&gld_device_list.gld_devlock);
    437 
    438 	return (e);
    439 }
    440 
    441 int
    442 _info(struct modinfo *modinfop)
    443 {
    444 	return (mod_info(&modlinkage, modinfop));
    445 }
    446 
    447 /*
    448  * GLD service routines
    449  */
    450 
    451 /* So this gld binary maybe can be forward compatible with future v2 drivers */
    452 #define	GLD_MAC_RESERVED (16 * sizeof (caddr_t))
    453 
    454 /*ARGSUSED*/
    455 gld_mac_info_t *
    456 gld_mac_alloc(dev_info_t *devinfo)
    457 {
    458 	gld_mac_info_t *macinfo;
    459 
    460 	macinfo = kmem_zalloc(sizeof (gld_mac_info_t) + GLD_MAC_RESERVED,
    461 	    KM_SLEEP);
    462 
    463 	/*
    464 	 * The setting of gldm_driver_version will not be documented or allowed
    465 	 * until a future release.
    466 	 */
    467 	macinfo->gldm_driver_version = GLD_VERSION_200;
    468 
    469 	/*
    470 	 * GLD's version.  This also is undocumented for now, but will be
    471 	 * available if needed in the future.
    472 	 */
    473 	macinfo->gldm_GLD_version = GLD_VERSION;
    474 
    475 	return (macinfo);
    476 }
    477 
    478 /*
    479  * gld_mac_free must be called after the driver has removed interrupts
    480  * and completely stopped calling gld_recv() and gld_sched().  At that
    481  * point the interrupt routine is guaranteed by the system to have been
    482  * exited and the maclock is no longer needed.  Of course, it is
    483  * expected (required) that (assuming gld_register() succeeded),
    484  * gld_unregister() was called before gld_mac_free().
    485  */
    486 void
    487 gld_mac_free(gld_mac_info_t *macinfo)
    488 {
    489 	ASSERT(macinfo);
    490 	ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
    491 
    492 	/*
    493 	 * Assert that if we made it through gld_register, then we must
    494 	 * have unregistered.
    495 	 */
    496 	ASSERT(!GLDM_LOCK_INITED(macinfo) ||
    497 	    (macinfo->gldm_GLD_flags & GLD_UNREGISTERED));
    498 
    499 	GLDM_LOCK_DESTROY(macinfo);
    500 
    501 	kmem_free(macinfo, sizeof (gld_mac_info_t) + GLD_MAC_RESERVED);
    502 }
    503 
    504 /*
    505  * gld_register -- called once per device instance (PPA)
    506  *
    507  * During its attach routine, a real device driver will register with GLD
    508  * so that later opens and dl_attach_reqs will work.  The arguments are the
    509  * devinfo pointer, the device name, and a macinfo structure describing the
    510  * physical device instance.
    511  */
    512 int
    513 gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo)
    514 {
    515 	int mediatype;
    516 	int major = ddi_name_to_major(devname), i;
    517 	glddev_t *glddev;
    518 	gld_mac_pvt_t *mac_pvt;
    519 	char minordev[32];
    520 	char pbuf[3*GLD_MAX_ADDRLEN];
    521 	gld_interface_t *ifp;
    522 
    523 	ASSERT(devinfo != NULL);
    524 	ASSERT(macinfo != NULL);
    525 
    526 	if (macinfo->gldm_driver_version != GLD_VERSION)
    527 		return (DDI_FAILURE);
    528 
    529 	mediatype = macinfo->gldm_type;
    530 
    531 	/*
    532 	 * Entry points should be ready for us.
    533 	 * ioctl is optional.
    534 	 * set_multicast and get_stats are optional in v0.
    535 	 * intr is only required if you add an interrupt.
    536 	 */
    537 	ASSERT(macinfo->gldm_reset != NULL);
    538 	ASSERT(macinfo->gldm_start != NULL);
    539 	ASSERT(macinfo->gldm_stop != NULL);
    540 	ASSERT(macinfo->gldm_set_mac_addr != NULL);
    541 	ASSERT(macinfo->gldm_set_promiscuous != NULL);
    542 	ASSERT(macinfo->gldm_send != NULL);
    543 
    544 	ASSERT(macinfo->gldm_maxpkt >= macinfo->gldm_minpkt);
    545 	ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
    546 	ASSERT(macinfo->gldm_broadcast_addr != NULL);
    547 	ASSERT(macinfo->gldm_vendor_addr != NULL);
    548 	ASSERT(macinfo->gldm_ident != NULL);
    549 
    550 	if (macinfo->gldm_addrlen > GLD_MAX_ADDRLEN) {
    551 		cmn_err(CE_WARN, "GLD: %s driver gldm_addrlen %d > %d not sup"
    552 		    "ported", devname, macinfo->gldm_addrlen, GLD_MAX_ADDRLEN);
    553 		return (DDI_FAILURE);
    554 	}
    555 
    556 	/*
    557 	 * GLD only functions properly with saplen == -2
    558 	 */
    559 	if (macinfo->gldm_saplen != -2) {
    560 		cmn_err(CE_WARN, "GLD: %s driver gldm_saplen %d != -2 "
    561 		    "not supported", devname, macinfo->gldm_saplen);
    562 		return (DDI_FAILURE);
    563 	}
    564 
    565 	/* see gld_rsrv() */
    566 	if (ddi_getprop(DDI_DEV_T_NONE, devinfo, 0, "fast_recv", 0))
    567 		macinfo->gldm_options |= GLDOPT_FAST_RECV;
    568 
    569 	mutex_enter(&gld_device_list.gld_devlock);
    570 	glddev = gld_devlookup(major);
    571 
    572 	/*
    573 	 *  Allocate per-driver (major) data structure if necessary
    574 	 */
    575 	if (glddev == NULL) {
    576 		/* first occurrence of this device name (major number) */
    577 		glddev = GLD_GETSTRUCT(glddev_t, 1);
    578 		if (glddev == NULL) {
    579 			mutex_exit(&gld_device_list.gld_devlock);
    580 			return (DDI_FAILURE);
    581 		}
    582 		(void) strncpy(glddev->gld_name, devname,
    583 		    sizeof (glddev->gld_name) - 1);
    584 		glddev->gld_major = major;
    585 		glddev->gld_nextminor = GLD_MIN_CLONE_MINOR;
    586 		glddev->gld_mac_next = glddev->gld_mac_prev =
    587 		    (gld_mac_info_t *)&glddev->gld_mac_next;
    588 		glddev->gld_str_next = glddev->gld_str_prev =
    589 		    (gld_t *)&glddev->gld_str_next;
    590 		mutex_init(&glddev->gld_devlock, NULL, MUTEX_DRIVER, NULL);
    591 
    592 		/* allow increase of number of supported multicast addrs */
    593 		glddev->gld_multisize = ddi_getprop(DDI_DEV_T_NONE,
    594 		    devinfo, 0, "multisize", GLD_MAX_MULTICAST);
    595 
    596 		/*
    597 		 * Optionally restrict DLPI provider style
    598 		 *
    599 		 * -1 - don't create style 1 nodes
    600 		 * -2 - don't create style 2 nodes
    601 		 */
    602 		glddev->gld_styles = ddi_getprop(DDI_DEV_T_NONE, devinfo, 0,
    603 		    "gld-provider-styles", 0);
    604 
    605 		/* Stuff that's needed before any PPA gets attached */
    606 		glddev->gld_type = macinfo->gldm_type;
    607 		glddev->gld_minsdu = macinfo->gldm_minpkt;
    608 		glddev->gld_saplen = macinfo->gldm_saplen;
    609 		glddev->gld_addrlen = macinfo->gldm_addrlen;
    610 		glddev->gld_broadcast = kmem_zalloc(macinfo->gldm_addrlen,
    611 		    KM_SLEEP);
    612 		bcopy(macinfo->gldm_broadcast_addr,
    613 		    glddev->gld_broadcast, macinfo->gldm_addrlen);
    614 		glddev->gld_maxsdu = macinfo->gldm_maxpkt;
    615 		gldinsque(glddev, gld_device_list.gld_prev);
    616 	}
    617 	glddev->gld_ndevice++;
    618 	/* Now glddev can't go away until we unregister this mac (or fail) */
    619 	mutex_exit(&gld_device_list.gld_devlock);
    620 
    621 	/*
    622 	 *  Per-instance initialization
    623 	 */
    624 
    625 	/*
    626 	 * Initialize per-mac structure that is private to GLD.
    627 	 * Set up interface pointer. These are device class specific pointers
    628 	 * used to handle FDDI/TR/ETHER/IPoIB specific packets.
    629 	 */
    630 	for (i = 0; i < sizeof (interfaces)/sizeof (*interfaces); i++) {
    631 		if (mediatype != interfaces[i].mac_type)
    632 			continue;
    633 
    634 		macinfo->gldm_mac_pvt = kmem_zalloc(sizeof (gld_mac_pvt_t),
    635 		    KM_SLEEP);
    636 		((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep = ifp =
    637 		    &interfaces[i];
    638 		break;
    639 	}
    640 
    641 	if (ifp == NULL) {
    642 		cmn_err(CE_WARN, "GLD: this version does not support %s driver "
    643 		    "of type %d", devname, mediatype);
    644 		goto failure;
    645 	}
    646 
    647 	/*
    648 	 * Driver can only register MTU within legal media range.
    649 	 */
    650 	if (macinfo->gldm_maxpkt > ifp->mtu_size) {
    651 		cmn_err(CE_WARN, "GLD: oversize MTU is specified by driver %s",
    652 		    devname);
    653 		goto failure;
    654 	}
    655 
    656 	/*
    657 	 * Correct margin size if it is not set.
    658 	 */
    659 	if (VLAN_CAPABLE(macinfo) && (macinfo->gldm_margin == 0))
    660 		macinfo->gldm_margin = VTAG_SIZE;
    661 
    662 	/*
    663 	 * For now, only Infiniband drivers can use MDT. Do not add
    664 	 * support for Ethernet, FDDI or TR.
    665 	 */
    666 	if (macinfo->gldm_mdt_pre != NULL) {
    667 		if (mediatype != DL_IB) {
    668 			cmn_err(CE_WARN, "GLD: MDT not supported for %s "
    669 			    "driver of type %d", devname, mediatype);
    670 			goto failure;
    671 		}
    672 
    673 		/*
    674 		 * Validate entry points.
    675 		 */
    676 		if ((macinfo->gldm_mdt_send == NULL) ||
    677 		    (macinfo->gldm_mdt_post == NULL)) {
    678 			cmn_err(CE_WARN, "GLD: invalid MDT entry points for "
    679 			    "%s driver of type %d", devname, mediatype);
    680 			goto failure;
    681 		}
    682 		macinfo->gldm_options |= GLDOPT_MDT;
    683 	}
    684 
    685 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    686 	mac_pvt->major_dev = glddev;
    687 
    688 	mac_pvt->curr_macaddr = kmem_zalloc(macinfo->gldm_addrlen, KM_SLEEP);
    689 	/*
    690 	 * XXX Do bit-reversed devices store gldm_vendor in canonical
    691 	 * format or in wire format?  Also gldm_broadcast.  For now
    692 	 * we are assuming canonical, but I'm not sure that makes the
    693 	 * most sense for ease of driver implementation.
    694 	 */
    695 	bcopy(macinfo->gldm_vendor_addr, mac_pvt->curr_macaddr,
    696 	    macinfo->gldm_addrlen);
    697 	mac_pvt->statistics = kmem_zalloc(sizeof (struct gld_stats), KM_SLEEP);
    698 
    699 	/*
    700 	 * The available set of notifications is those generatable by GLD
    701 	 * itself, plus those corresponding to the capabilities of the MAC
    702 	 * driver, intersected with those supported by gld_notify_ind() above.
    703 	 */
    704 	mac_pvt->notifications = gld_internal_notes;
    705 	if (macinfo->gldm_capabilities & GLD_CAP_LINKSTATE)
    706 		mac_pvt->notifications |= gld_linkstate_notes;
    707 	mac_pvt->notifications &= gld_supported_notes;
    708 
    709 	GLDM_LOCK_INIT(macinfo);
    710 
    711 	ddi_set_driver_private(devinfo, macinfo);
    712 
    713 	/*
    714 	 * Now atomically get a PPA and put ourselves on the mac list.
    715 	 */
    716 	mutex_enter(&glddev->gld_devlock);
    717 
    718 #ifdef DEBUG
    719 	if (macinfo->gldm_ppa != ddi_get_instance(devinfo))
    720 		cmn_err(CE_WARN, "%s%d instance != ppa %d",
    721 		    ddi_driver_name(devinfo), ddi_get_instance(devinfo),
    722 		    macinfo->gldm_ppa);
    723 #endif
    724 
    725 	/*
    726 	 * Create style 2 node (gated by gld-provider-styles property).
    727 	 *
    728 	 * NOTE: When the CLONE_DEV flag is specified to
    729 	 *	 ddi_create_minor_node() the minor number argument is
    730 	 *	 immaterial. Opens of that node will go via the clone
    731 	 *	 driver and gld_open() will always be passed a dev_t with
    732 	 *	 minor of zero.
    733 	 */
    734 	if (glddev->gld_styles != -2) {
    735 		if (ddi_create_minor_node(devinfo, glddev->gld_name, S_IFCHR,
    736 		    0, DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) {
    737 			mutex_exit(&glddev->gld_devlock);
    738 			goto late_failure;
    739 		}
    740 	}
    741 
    742 	/*
    743 	 * Create style 1 node (gated by gld-provider-styles property)
    744 	 */
    745 	if (glddev->gld_styles != -1) {
    746 		(void) sprintf(minordev, "%s%d", glddev->gld_name,
    747 		    macinfo->gldm_ppa);
    748 		if (ddi_create_minor_node(devinfo, minordev, S_IFCHR,
    749 		    GLD_STYLE1_PPA_TO_MINOR(macinfo->gldm_ppa), DDI_NT_NET,
    750 		    0) != DDI_SUCCESS) {
    751 			mutex_exit(&glddev->gld_devlock);
    752 			goto late_failure;
    753 		}
    754 	}
    755 
    756 	/* add ourselves to this major device's linked list of instances */
    757 	gldinsque(macinfo, glddev->gld_mac_prev);
    758 
    759 	mutex_exit(&glddev->gld_devlock);
    760 
    761 	/*
    762 	 * Unfortunately we need the ppa before we call gld_initstats();
    763 	 * otherwise we would like to do this just above the mutex_enter
    764 	 * above.  In which case we could have set MAC_READY inside the
    765 	 * mutex and we wouldn't have needed to check it in open and
    766 	 * DL_ATTACH.  We wouldn't like to do the initstats/kstat_create
    767 	 * inside the mutex because it might get taken in our kstat_update
    768 	 * routine and cause a deadlock with kstat_chain_lock.
    769 	 */
    770 
    771 	/* gld_initstats() calls (*ifp->init)() */
    772 	if (gld_initstats(macinfo) != GLD_SUCCESS) {
    773 		mutex_enter(&glddev->gld_devlock);
    774 		gldremque(macinfo);
    775 		mutex_exit(&glddev->gld_devlock);
    776 		goto late_failure;
    777 	}
    778 
    779 	/*
    780 	 * Need to indicate we are NOW ready to process interrupts;
    781 	 * any interrupt before this is set is for someone else.
    782 	 * This flag is also now used to tell open, et. al. that this
    783 	 * mac is now fully ready and available for use.
    784 	 */
    785 	GLDM_LOCK(macinfo, RW_WRITER);
    786 	macinfo->gldm_GLD_flags |= GLD_MAC_READY;
    787 	GLDM_UNLOCK(macinfo);
    788 
    789 	/* log local ethernet address -- XXX not DDI compliant */
    790 	if (macinfo->gldm_addrlen == sizeof (struct ether_addr))
    791 		(void) localetheraddr(
    792 		    (struct ether_addr *)macinfo->gldm_vendor_addr, NULL);
    793 
    794 	/* now put announcement into the message buffer */
    795 	cmn_err(CE_CONT, "!%s%d: %s: type \"%s\" mac address %s\n",
    796 	    glddev->gld_name,
    797 	    macinfo->gldm_ppa, macinfo->gldm_ident,
    798 	    mac_pvt->interfacep->mac_string,
    799 	    gld_macaddr_sprintf(pbuf, macinfo->gldm_vendor_addr,
    800 	    macinfo->gldm_addrlen));
    801 
    802 	ddi_report_dev(devinfo);
    803 	return (DDI_SUCCESS);
    804 
    805 late_failure:
    806 	ddi_remove_minor_node(devinfo, NULL);
    807 	GLDM_LOCK_DESTROY(macinfo);
    808 	if (mac_pvt->curr_macaddr != NULL)
    809 		kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
    810 	if (mac_pvt->statistics != NULL)
    811 		kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
    812 	kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
    813 	macinfo->gldm_mac_pvt = NULL;
    814 
    815 failure:
    816 	mutex_enter(&gld_device_list.gld_devlock);
    817 	glddev->gld_ndevice--;
    818 	/*
    819 	 * Note that just because this goes to zero here does not necessarily
    820 	 * mean that we were the one who added the glddev above.  It's
    821 	 * possible that the first mac unattached while were were in here
    822 	 * failing to attach the second mac.  But we're now the last.
    823 	 */
    824 	if (glddev->gld_ndevice == 0) {
    825 		/* There should be no macinfos left */
    826 		ASSERT(glddev->gld_mac_next ==
    827 		    (gld_mac_info_t *)&glddev->gld_mac_next);
    828 		ASSERT(glddev->gld_mac_prev ==
    829 		    (gld_mac_info_t *)&glddev->gld_mac_next);
    830 
    831 		/*
    832 		 * There should be no DL_UNATTACHED streams: the system
    833 		 * should not have detached the "first" devinfo which has
    834 		 * all the open style 2 streams.
    835 		 *
    836 		 * XXX This is not clear.  See gld_getinfo and Bug 1165519
    837 		 */
    838 		ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
    839 		ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
    840 
    841 		gldremque(glddev);
    842 		mutex_destroy(&glddev->gld_devlock);
    843 		if (glddev->gld_broadcast != NULL)
    844 			kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
    845 		kmem_free(glddev, sizeof (glddev_t));
    846 	}
    847 	mutex_exit(&gld_device_list.gld_devlock);
    848 
    849 	return (DDI_FAILURE);
    850 }
    851 
    852 /*
    853  * gld_unregister (macinfo)
    854  * remove the macinfo structure from local structures
    855  * this is cleanup for a driver to be unloaded
    856  */
    857 int
    858 gld_unregister(gld_mac_info_t *macinfo)
    859 {
    860 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    861 	glddev_t *glddev = mac_pvt->major_dev;
    862 	gld_interface_t *ifp;
    863 	int multisize = sizeof (gld_mcast_t) * glddev->gld_multisize;
    864 
    865 	mutex_enter(&glddev->gld_devlock);
    866 	GLDM_LOCK(macinfo, RW_WRITER);
    867 
    868 	if (mac_pvt->nvlan > 0) {
    869 		GLDM_UNLOCK(macinfo);
    870 		mutex_exit(&glddev->gld_devlock);
    871 		return (DDI_FAILURE);
    872 	}
    873 
    874 #ifdef	GLD_DEBUG
    875 	{
    876 		int i;
    877 
    878 		for (i = 0; i < VLAN_HASHSZ; i++) {
    879 			if ((mac_pvt->vlan_hash[i] != NULL))
    880 				cmn_err(CE_PANIC,
    881 				    "%s, line %d: "
    882 				    "mac_pvt->vlan_hash[%d] != NULL",
    883 				    __FILE__, __LINE__, i);
    884 		}
    885 	}
    886 #endif
    887 
    888 	/* Delete this mac */
    889 	gldremque(macinfo);
    890 
    891 	/* Disallow further entries to gld_recv() and gld_sched() */
    892 	macinfo->gldm_GLD_flags |= GLD_UNREGISTERED;
    893 
    894 	GLDM_UNLOCK(macinfo);
    895 	mutex_exit(&glddev->gld_devlock);
    896 
    897 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
    898 	(*ifp->uninit)(macinfo);
    899 
    900 	ASSERT(mac_pvt->kstatp);
    901 	kstat_delete(mac_pvt->kstatp);
    902 
    903 	ASSERT(GLDM_LOCK_INITED(macinfo));
    904 	kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
    905 	kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
    906 
    907 	if (mac_pvt->mcast_table != NULL)
    908 		kmem_free(mac_pvt->mcast_table, multisize);
    909 	kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
    910 	macinfo->gldm_mac_pvt = (caddr_t)NULL;
    911 
    912 	/* We now have one fewer instance for this major device */
    913 	mutex_enter(&gld_device_list.gld_devlock);
    914 	glddev->gld_ndevice--;
    915 	if (glddev->gld_ndevice == 0) {
    916 		/* There should be no macinfos left */
    917 		ASSERT(glddev->gld_mac_next ==
    918 		    (gld_mac_info_t *)&glddev->gld_mac_next);
    919 		ASSERT(glddev->gld_mac_prev ==
    920 		    (gld_mac_info_t *)&glddev->gld_mac_next);
    921 
    922 		/*
    923 		 * There should be no DL_UNATTACHED streams: the system
    924 		 * should not have detached the "first" devinfo which has
    925 		 * all the open style 2 streams.
    926 		 *
    927 		 * XXX This is not clear.  See gld_getinfo and Bug 1165519
    928 		 */
    929 		ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
    930 		ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
    931 
    932 		ddi_remove_minor_node(macinfo->gldm_devinfo, NULL);
    933 		gldremque(glddev);
    934 		mutex_destroy(&glddev->gld_devlock);
    935 		if (glddev->gld_broadcast != NULL)
    936 			kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
    937 		kmem_free(glddev, sizeof (glddev_t));
    938 	}
    939 	mutex_exit(&gld_device_list.gld_devlock);
    940 
    941 	return (DDI_SUCCESS);
    942 }
    943 
    944 /*
    945  * gld_initstats
    946  * called from gld_register
    947  */
    948 static int
    949 gld_initstats(gld_mac_info_t *macinfo)
    950 {
    951 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    952 	struct gldkstats *sp;
    953 	glddev_t *glddev;
    954 	kstat_t *ksp;
    955 	gld_interface_t *ifp;
    956 
    957 	glddev = mac_pvt->major_dev;
    958 
    959 	if ((ksp = kstat_create(glddev->gld_name, macinfo->gldm_ppa,
    960 	    NULL, "net", KSTAT_TYPE_NAMED,
    961 	    sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) {
    962 		cmn_err(CE_WARN,
    963 		    "GLD: failed to create kstat structure for %s%d",
    964 		    glddev->gld_name, macinfo->gldm_ppa);
    965 		return (GLD_FAILURE);
    966 	}
    967 	mac_pvt->kstatp =