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 =