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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * gld - Generic LAN Driver Version 2, PSARC/1997/382 31 * 32 * This is a utility module that provides generic facilities for 33 * LAN drivers. The DLPI protocol and most STREAMS interfaces 34 * are handled here. 35 * 36 * It no longer provides compatibility with drivers 37 * implemented according to the GLD v0 documentation published 38 * in 1993. (See PSARC 2003/728) 39 */ 40 41 42 #include <sys/types.h> 43 #include <sys/errno.h> 44 #include <sys/stropts.h> 45 #include <sys/stream.h> 46 #include <sys/kmem.h> 47 #include <sys/stat.h> 48 #include <sys/modctl.h> 49 #include <sys/kstat.h> 50 #include <sys/debug.h> 51 #include <sys/note.h> 52 #include <sys/sysmacros.h> 53 54 #include <sys/byteorder.h> 55 #include <sys/strsun.h> 56 #include <sys/strsubr.h> 57 #include <sys/dlpi.h> 58 #include <sys/pattr.h> 59 #include <sys/ethernet.h> 60 #include <sys/ib/clients/ibd/ibd.h> 61 #include <sys/policy.h> 62 #include <sys/atomic.h> 63 64 #include <sys/multidata.h> 65 #include <sys/gld.h> 66 #include <sys/gldpriv.h> 67 68 #include <sys/ddi.h> 69 #include <sys/sunddi.h> 70 71 /* 72 * Macro to atomically increment counters of type uint32_t, uint64_t 73 * and ulong_t. 74 */ 75 #define BUMP(stat, delta) do { \ 76 _NOTE(CONSTANTCONDITION) \ 77 if (sizeof (stat) == sizeof (uint32_t)) { \ 78 atomic_add_32((uint32_t *)&stat, delta); \ 79 _NOTE(CONSTANTCONDITION) \ 80 } else if (sizeof (stat) == sizeof (uint64_t)) { \ 81 atomic_add_64((uint64_t *)&stat, delta); \ 82 } \ 83 _NOTE(CONSTANTCONDITION) \ 84 } while (0) 85 86 #define UPDATE_STATS(vlan, pktinfo, number) { \ 87 if ((pktinfo).isBroadcast) \ 88 (vlan)->gldv_stats->glds_brdcstxmt += (number); \ 89 else if ((pktinfo).isMulticast) \ 90 (vlan)->gldv_stats->glds_multixmt += (number); \ 91 (vlan)->gldv_stats->glds_bytexmt64 += (pktinfo).pktLen; \ 92 (vlan)->gldv_stats->glds_pktxmt64 += (number); \ 93 } 94 95 #ifdef GLD_DEBUG 96 int gld_debug = GLDERRS; 97 #endif 98 99 /* called from gld_register */ 100 static int gld_initstats(gld_mac_info_t *); 101 102 /* called from kstat mechanism, and from wsrv's get_statistics */ 103 static int gld_update_kstat(kstat_t *, int); 104 105 /* statistics for additional vlans */ 106 static int gld_init_vlan_stats(gld_vlan_t *); 107 static int gld_update_vlan_kstat(kstat_t *, int); 108 109 /* called from gld_getinfo */ 110 static dev_info_t *gld_finddevinfo(dev_t); 111 112 /* called from wput, wsrv, unidata, and v0_sched to send a packet */ 113 /* also from the source routing stuff for sending RDE protocol packets */ 114 static int gld_start(queue_t *, mblk_t *, int, uint32_t); 115 static int gld_start_mdt(queue_t *, mblk_t *, int); 116 117 /* called from gld_start[_mdt] to loopback packet(s) in promiscuous mode */ 118 static void gld_precv(gld_mac_info_t *, gld_vlan_t *, mblk_t *); 119 static void gld_precv_mdt(gld_mac_info_t *, gld_vlan_t *, mblk_t *, 120 pdesc_t *, pktinfo_t *); 121 122 /* receive group: called from gld_recv and gld_precv* with maclock held */ 123 static void gld_sendup(gld_mac_info_t *, gld_vlan_t *, pktinfo_t *, mblk_t *, 124 int (*)()); 125 static int gld_accept(gld_t *, pktinfo_t *); 126 static int gld_mcmatch(gld_t *, pktinfo_t *); 127 static int gld_multicast(unsigned char *, gld_t *); 128 static int gld_paccept(gld_t *, pktinfo_t *); 129 static void gld_passon(gld_t *, mblk_t *, pktinfo_t *, 130 void (*)(queue_t *, mblk_t *)); 131 static mblk_t *gld_addudind(gld_t *, mblk_t *, pktinfo_t *); 132 133 /* wsrv group: called from wsrv, single threaded per queue */ 134 static int gld_ioctl(queue_t *, mblk_t *); 135 static void gld_fastpath(gld_t *, queue_t *, mblk_t *); 136 static int gld_cmds(queue_t *, mblk_t *); 137 static mblk_t *gld_bindack(queue_t *, mblk_t *); 138 static int gld_notify_req(queue_t *, mblk_t *); 139 static int gld_udqos(queue_t *, mblk_t *); 140 static int gld_bind(queue_t *, mblk_t *); 141 static int gld_unbind(queue_t *, mblk_t *); 142 static int gld_inforeq(queue_t *, mblk_t *); 143 static int gld_unitdata(queue_t *, mblk_t *); 144 static int gldattach(queue_t *, mblk_t *); 145 static int gldunattach(queue_t *, mblk_t *); 146 static int gld_enable_multi(queue_t *, mblk_t *); 147 static int gld_disable_multi(queue_t *, mblk_t *); 148 static void gld_send_disable_multi(gld_mac_info_t *, gld_mcast_t *); 149 static int gld_promisc(queue_t *, mblk_t *, t_uscalar_t, boolean_t); 150 static int gld_physaddr(queue_t *, mblk_t *); 151 static int gld_setaddr(queue_t *, mblk_t *); 152 static int gld_get_statistics(queue_t *, mblk_t *); 153 static int gld_cap(queue_t *, mblk_t *); 154 static int gld_cap_ack(queue_t *, mblk_t *); 155 static int gld_cap_enable(queue_t *, mblk_t *); 156 157 /* misc utilities, some requiring various mutexes held */ 158 static int gld_start_mac(gld_mac_info_t *); 159 static void gld_stop_mac(gld_mac_info_t *); 160 static void gld_set_ipq(gld_t *); 161 static void gld_flushqueue(queue_t *); 162 static glddev_t *gld_devlookup(int); 163 static int gld_findminor(glddev_t *); 164 static void gldinsque(void *, void *); 165 static void gldremque(void *); 166 void gld_bitrevcopy(caddr_t, caddr_t, size_t); 167 void gld_bitreverse(uchar_t *, size_t); 168 char *gld_macaddr_sprintf(char *, unsigned char *, int); 169 static gld_vlan_t *gld_add_vlan(gld_mac_info_t *, uint32_t vid); 170 static void gld_rem_vlan(gld_vlan_t *); 171 gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t); 172 gld_vlan_t *gld_get_vlan(gld_mac_info_t *, uint32_t); 173 174 #ifdef GLD_DEBUG 175 static void gld_check_assertions(void); 176 extern void gld_sr_dump(gld_mac_info_t *); 177 #endif 178 179 /* 180 * Allocate and zero-out "number" structures each of type "structure" in 181 * kernel memory. 182 */ 183 #define GETSTRUCT(structure, number) \ 184 (kmem_zalloc((uint_t)(sizeof (structure) * (number)), KM_NOSLEEP)) 185 186 #define abs(a) ((a) < 0 ? -(a) : a) 187 188 uint32_t gld_global_options = GLD_OPT_NO_ETHRXSNAP; 189 190 /* 191 * VLANs are only supported on ethernet devices that manipulate VLAN headers 192 * themselves. 193 */ 194 #define VLAN_CAPABLE(macinfo) \ 195 ((macinfo)->gldm_type == DL_ETHER && \ 196 (macinfo)->gldm_send_tagged != NULL) 197 198 /* 199 * The set of notifications generatable by GLD itself, the additional 200 * set that can be generated if the MAC driver provide the link-state 201 * tracking callback capability, and the set supported by the GLD 202 * notification code below. 203 * 204 * PLEASE keep these in sync with what the code actually does! 205 */ 206 static const uint32_t gld_internal_notes = DL_NOTE_PROMISC_ON_PHYS | 207 DL_NOTE_PROMISC_OFF_PHYS | 208 DL_NOTE_PHYS_ADDR; 209 static const uint32_t gld_linkstate_notes = DL_NOTE_LINK_DOWN | 210 DL_NOTE_LINK_UP | 211 DL_NOTE_SPEED; 212 static const uint32_t gld_supported_notes = DL_NOTE_PROMISC_ON_PHYS | 213 DL_NOTE_PROMISC_OFF_PHYS | 214 DL_NOTE_PHYS_ADDR | 215 DL_NOTE_LINK_DOWN | 216 DL_NOTE_LINK_UP | 217 DL_NOTE_SPEED; 218 219 /* Media must correspond to #defines in gld.h */ 220 static char *gld_media[] = { 221 "unknown", /* GLDM_UNKNOWN - driver cannot determine media */ 222 "aui", /* GLDM_AUI */ 223 "bnc", /* GLDM_BNC */ 224 "twpair", /* GLDM_TP */ 225 "fiber", /* GLDM_FIBER */ 226 "100baseT", /* GLDM_100BT */ 227 "100vgAnyLan", /* GLDM_VGANYLAN */ 228 "10baseT", /* GLDM_10BT */ 229 "ring4", /* GLDM_RING4 */ 230 "ring16", /* GLDM_RING16 */ 231 "PHY/MII", /* GLDM_PHYMII */ 232 "100baseTX", /* GLDM_100BTX */ 233 "100baseT4", /* GLDM_100BT4 */ 234 "unknown", /* skip */ 235 "ipib", /* GLDM_IB */ 236 }; 237 238 /* Must correspond to #defines in gld.h */ 239 static char *gld_duplex[] = { 240 "unknown", /* GLD_DUPLEX_UNKNOWN - not known or not applicable */ 241 "half", /* GLD_DUPLEX_HALF */ 242 "full" /* GLD_DUPLEX_FULL */ 243 }; 244 245 extern int gld_interpret_ether(gld_mac_info_t *, mblk_t *, pktinfo_t *, int); 246 extern int gld_interpret_fddi(gld_mac_info_t *, mblk_t *, pktinfo_t *, int); 247 extern int gld_interpret_tr(gld_mac_info_t *, mblk_t *, pktinfo_t *, int); 248 extern int gld_interpret_ib(gld_mac_info_t *, mblk_t *, pktinfo_t *, int); 249 extern void gld_interpret_mdt_ib(gld_mac_info_t *, mblk_t *, pdescinfo_t *, 250 pktinfo_t *, int); 251 252 extern mblk_t *gld_fastpath_ether(gld_t *, mblk_t *); 253 extern mblk_t *gld_fastpath_fddi(gld_t *, mblk_t *); 254 extern mblk_t *gld_fastpath_tr(gld_t *, mblk_t *); 255 extern mblk_t *gld_fastpath_ib(gld_t *, mblk_t *); 256 257 extern mblk_t *gld_unitdata_ether(gld_t *, mblk_t *); 258 extern mblk_t *gld_unitdata_fddi(gld_t *, mblk_t *); 259 extern mblk_t *gld_unitdata_tr(gld_t *, mblk_t *); 260 extern mblk_t *gld_unitdata_ib(gld_t *, mblk_t *); 261 262 extern void gld_init_ether(gld_mac_info_t *); 263 extern void gld_init_fddi(gld_mac_info_t *); 264 extern void gld_init_tr(gld_mac_info_t *); 265 extern void gld_init_ib(gld_mac_info_t *); 266 267 extern void gld_uninit_ether(gld_mac_info_t *); 268 extern void gld_uninit_fddi(gld_mac_info_t *); 269 extern void gld_uninit_tr(gld_mac_info_t *); 270 extern void gld_uninit_ib(gld_mac_info_t *); 271 272 /* 273 * Interface types currently supported by GLD. 274 * If you add new types, you must check all "XXX" strings in the GLD source 275 * for implementation issues that may affect the support of your new type. 276 * In particular, any type with gldm_addrlen > 6, or gldm_saplen != -2, will 277 * require generalizing this GLD source to handle the new cases. In other 278 * words there are assumptions built into the code in a few places that must 279 * be fixed. Be sure to turn on DEBUG/ASSERT code when testing a new type. 280 */ 281 static gld_interface_t interfaces[] = { 282 283 /* Ethernet Bus */ 284 { 285 DL_ETHER, 286 (uint_t)-1, 287 sizeof (struct ether_mac_frm), 288 gld_interpret_ether, 289 NULL, 290 gld_fastpath_ether, 291 gld_unitdata_ether, 292 gld_init_ether, 293 gld_uninit_ether, 294 "ether" 295 }, 296 297 /* Fiber Distributed data interface */ 298 { 299 DL_FDDI, 300 4352, 301 sizeof (struct fddi_mac_frm), 302 gld_interpret_fddi, 303 NULL, 304 gld_fastpath_fddi, 305 gld_unitdata_fddi, 306 gld_init_fddi, 307 gld_uninit_fddi, 308 "fddi" 309 }, 310 311 /* Token Ring interface */ 312 { 313 DL_TPR, 314 17914, 315 -1, /* variable header size */ 316 gld_interpret_tr, 317 NULL, 318 gld_fastpath_tr, 319 gld_unitdata_tr, 320 gld_init_tr, 321 gld_uninit_tr, 322 "tpr" 323 }, 324 325 /* Infiniband */ 326 { 327 DL_IB, 328 4092, 329 sizeof (struct ipoib_header), 330 gld_interpret_ib, 331 gld_interpret_mdt_ib, 332 gld_fastpath_ib, 333 gld_unitdata_ib, 334 gld_init_ib, 335 gld_uninit_ib, 336 "ipib" 337 }, 338 }; 339 340 /* 341 * bit reversal lookup table. 342 */ 343 static uchar_t bit_rev[] = { 344 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 345 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 346 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 347 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 348 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 349 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 350 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 351 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 352 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 353 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 354 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 355 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 356 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 357 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 358 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 359 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 360 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 361 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 362 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 363 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 364 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 365 0x3f, 0xbf, 0x7f, 0xff, 366 }; 367 368 /* 369 * User priorities, mapped from b_band. 370 */ 371 static uint32_t user_priority[] = { 372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 374 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 375 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 376 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 377 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 378 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 379 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 380 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 381 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 382 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 383 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 384 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 385 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 386 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 387 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 388 }; 389 390 #define UPRI(gld, band) ((band != 0) ? user_priority[(band)] : (gld)->gld_upri) 391 392 static struct glddevice gld_device_list; /* Per-system root of GLD tables */ 393 394 /* 395 * Module linkage information for the kernel. 396 */ 397 398 static struct modldrv modlmisc = { 399 &mod_miscops, /* Type of module - a utility provider */ 400 "Generic LAN Driver (" GLD_VERSION_STRING ") %I%" 401 #ifdef GLD_DEBUG 402 " DEBUG" 403 #endif 404 }; 405 406 static struct modlinkage modlinkage = { 407 MODREV_1, &modlmisc, NULL 408 }; 409 410 int 411 _init(void) 412 { 413 int e; 414 415 /* initialize gld_device_list mutex */ 416 mutex_init(&gld_device_list.gld_devlock, NULL, MUTEX_DRIVER, NULL); 417 418 /* initialize device driver (per-major) list */ 419 gld_device_list.gld_next = 420 gld_device_list.gld_prev = &gld_device_list; 421 422 if ((e = mod_install(&modlinkage)) != 0) 423 mutex_destroy(&gld_device_list.gld_devlock); 424 425 return (e); 426 } 427 428 int 429 _fini(void) 430 { 431 int e; 432 433 if ((e = mod_remove(&modlinkage)) != 0) 434 return (e); 435 436 ASSERT(gld_device_list.gld_next == 437 (glddev_t *)&gld_device_list.gld_next); 438 ASSERT(gld_device_list.gld_prev == 439 (glddev_t *)&gld_device_list.gld_next); 440 mutex_destroy(&gld_device_list.gld_devlock); 441 442 return (e); 443 } 444 445 int 446 _info(struct modinfo *modinfop) 447 { 448 return (mod_info(&modlinkage, modinfop)); 449 } 450 451 /* 452 * GLD service routines 453 */ 454 455 /* So this gld binary maybe can be forward compatible with future v2 drivers */ 456 #define GLD_MAC_RESERVED (16 * sizeof (caddr_t)) 457 458 /*ARGSUSED*/ 459 gld_mac_info_t * 460 gld_mac_alloc(dev_info_t *devinfo) 461 { 462 gld_mac_info_t *macinfo; 463 464 macinfo = kmem_zalloc(sizeof (gld_mac_info_t) + GLD_MAC_RESERVED, 465 KM_SLEEP); 466 467 /* 468 * The setting of gldm_driver_version will not be documented or allowed 469 * until a future release. 470 */ 471 macinfo->gldm_driver_version = GLD_VERSION_200; 472 473 /* 474 * GLD's version. This also is undocumented for now, but will be 475 * available if needed in the future. 476 */ 477 macinfo->gldm_GLD_version = GLD_VERSION; 478 479 return (macinfo); 480 } 481 482 /* 483 * gld_mac_free must be called after the driver has removed interrupts 484 * and completely stopped calling gld_recv() and gld_sched(). At that 485 * point the interrupt routine is guaranteed by the system to have been 486 * exited and the maclock is no longer needed. Of course, it is 487 * expected (required) that (assuming gld_register() succeeded), 488 * gld_unregister() was called before gld_mac_free(). 489 */ 490 void 491 gld_mac_free(gld_mac_info_t *macinfo) 492 { 493 ASSERT(macinfo); 494 ASSERT(macinfo->gldm_GLD_version == GLD_VERSION); 495 496 /* 497 * Assert that if we made it through gld_register, then we must 498 * have unregistered. 499 */ 500 ASSERT(!GLDM_LOCK_INITED(macinfo) || 501 (macinfo->gldm_GLD_flags & GLD_UNREGISTERED)); 502 503 GLDM_LOCK_DESTROY(macinfo); 504 505 kmem_free(macinfo, sizeof (gld_mac_info_t) + GLD_MAC_RESERVED); 506 } 507 508 /* 509 * gld_register -- called once per device instance (PPA) 510 * 511 * During its attach routine, a real device driver will register with GLD 512 * so that later opens and dl_attach_reqs will work. The arguments are the 513 * devinfo pointer, the device name, and a macinfo structure describing the 514 * physical device instance. 515 */ 516 int 517 gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo) 518 { 519 int mediatype; 520 int major = ddi_name_to_major(devname), i; 521 glddev_t *glddev; 522 gld_mac_pvt_t *mac_pvt; 523 char minordev[32]; 524 char pbuf[3*GLD_MAX_ADDRLEN]; 525 gld_interface_t *ifp; 526 527 ASSERT(devinfo != NULL); 528 ASSERT(macinfo != NULL); 529 530 if (macinfo->gldm_driver_version != GLD_VERSION) 531 return (DDI_FAILURE); 532 533 mediatype = macinfo->gldm_type; 534 535 /* 536 * Entry points should be ready for us. 537 * ioctl is optional. 538 * set_multicast and get_stats are optional in v0. 539 * intr is only required if you add an interrupt. 540 */ 541 ASSERT(macinfo->gldm_reset != NULL); 542 ASSERT(macinfo->gldm_start != NULL); 543 ASSERT(macinfo->gldm_stop != NULL); 544 ASSERT(macinfo->gldm_set_mac_addr != NULL); 545 ASSERT(macinfo->gldm_set_promiscuous != NULL); 546 ASSERT(macinfo->gldm_send != NULL); 547 548 ASSERT(macinfo->gldm_maxpkt >= macinfo->gldm_minpkt); 549 ASSERT(macinfo->gldm_GLD_version == GLD_VERSION); 550 ASSERT(macinfo->gldm_broadcast_addr != NULL); 551 ASSERT(macinfo->gldm_vendor_addr != NULL); 552 ASSERT(macinfo->gldm_ident != NULL); 553 554 if (macinfo->gldm_addrlen > GLD_MAX_ADDRLEN) { 555 cmn_err(CE_WARN, "GLD: %s driver gldm_addrlen %d > %d not sup" 556 "ported", devname, macinfo->gldm_addrlen, GLD_MAX_ADDRLEN); 557 return (DDI_FAILURE); 558 } 559 560 /* 561 * GLD only functions properly with saplen == -2 562 */ 563 if (macinfo->gldm_saplen != -2) { 564 cmn_err(CE_WARN, "GLD: %s driver gldm_saplen %d != -2 " 565 "not supported", devname, macinfo->gldm_saplen); 566 return (DDI_FAILURE); 567 } 568 569 /* see gld_rsrv() */ 570 if (ddi_getprop(DDI_DEV_T_NONE, devinfo, 0, "fast_recv", 0)) 571 macinfo->gldm_options |= GLDOPT_FAST_RECV; 572 573 mutex_enter(&gld_device_list.gld_devlock); 574 glddev = gld_devlookup(major); 575 576 /* 577 * Allocate per-driver (major) data structure if necessary 578 */ 579 if (glddev == NULL) { 580 /* first occurrence of this device name (major number) */ 581 glddev = GETSTRUCT(glddev_t, 1); 582 if (glddev == NULL) { 583 mutex_exit(&gld_device_list.gld_devlock); 584 return (DDI_FAILURE); 585 } 586 (void) strncpy(glddev->gld_name, devname, 587 sizeof (glddev->gld_name) - 1); 588 glddev->gld_major = major; 589 glddev->gld_nextminor = GLD_MIN_CLONE_MINOR; 590 glddev->gld_mac_next = glddev->gld_mac_prev = 591 (gld_mac_info_t *)&glddev->gld_mac_next; 592 glddev->gld_str_next = glddev->gld_str_prev = 593 (gld_t *)&glddev->gld_str_next; 594 mutex_init(&glddev->gld_devlock, NULL, MUTEX_DRIVER, NULL); 595 596 /* allow increase of number of supported multicast addrs */ 597 glddev->gld_multisize = ddi_getprop(DDI_DEV_T_NONE, 598 devinfo, 0, "multisize", GLD_MAX_MULTICAST); 599 600 /* 601 * Optionally restrict DLPI provider style 602 * 603 * -1 - don't create style 1 nodes 604 * -2 - don't create style 2 nodes 605 */ 606 glddev->gld_styles = ddi_getprop(DDI_DEV_T_NONE, devinfo, 0, 607 "gld-provider-styles", 0); 608 609 /* Stuff that's needed before any PPA gets attached */ 610 glddev->gld_type = macinfo->gldm_type; 611 glddev->gld_minsdu = macinfo->gldm_minpkt; 612 glddev->gld_saplen = macinfo->gldm_saplen; 613 glddev->gld_addrlen = macinfo->gldm_addrlen; 614 glddev->gld_broadcast = kmem_zalloc(macinfo->gldm_addrlen, 615 KM_SLEEP); 616 bcopy(macinfo->gldm_broadcast_addr, 617 glddev->gld_broadcast, macinfo->gldm_addrlen); 618 glddev->gld_maxsdu = macinfo->gldm_maxpkt; 619 gldinsque(glddev, gld_device_list.gld_prev); 620 } 621 glddev->gld_ndevice++; 622 /* Now glddev can't go away until we unregister this mac (or fail) */ 623 mutex_exit(&gld_device_list.gld_devlock); 624 625 /* 626 * Per-instance initialization 627 */ 628 629 /* 630 * Initialize per-mac structure that is private to GLD. 631 * Set up interface pointer. These are device class specific pointers 632 * used to handle FDDI/TR/ETHER/IPoIB specific packets. 633 */ 634 for (i = 0; i < sizeof (interfaces)/sizeof (*interfaces); i++) { 635 if (mediatype != interfaces[i].mac_type) 636 continue; 637 638 macinfo->gldm_mac_pvt = kmem_zalloc(sizeof (gld_mac_pvt_t), 639 KM_SLEEP); 640 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep = ifp = 641 &interfaces[i]; 642 break; 643 } 644 645 if (ifp == NULL) { 646 cmn_err(CE_WARN, "GLD: this version does not support %s driver " 647 "of type %d", devname, mediatype); 648 goto failure; 649 } 650 651 /* 652 * Driver can only register MTU within legal media range. 653 */ 654 if (macinfo->gldm_maxpkt > ifp->mtu_size) { 655 cmn_err(CE_WARN, "GLD: oversize MTU is specified by driver %s", 656 devname); 657 goto failure; 658 } 659 660 /* 661 * For now, only Infiniband drivers can use MDT. Do not add 662 * support for Ethernet, FDDI or TR. 663 */ 664 if (macinfo->gldm_mdt_pre != NULL) { 665 if (mediatype != DL_IB) { 666 cmn_err(CE_WARN, "GLD: MDT not supported for %s " 667 "driver of type %d", devname, mediatype); 668 goto failure; 669 } 670 671 /* 672 * Validate entry points. 673 */ 674 if ((macinfo->gldm_mdt_send == NULL) || 675 (macinfo->gldm_mdt_post == NULL)) { 676 cmn_err(CE_WARN, "GLD: invalid MDT entry points for " 677 "%s driver of type %d", devname, mediatype); 678 goto failure; 679 } 680 macinfo->gldm_options |= GLDOPT_MDT; 681 } 682 683 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 684 mac_pvt->major_dev = glddev; 685 686 mac_pvt->curr_macaddr = kmem_zalloc(macinfo->gldm_addrlen, KM_SLEEP); 687 /* 688 * XXX Do bit-reversed devices store gldm_vendor in canonical 689 * format or in wire format? Also gldm_broadcast. For now 690 * we are assuming canonical, but I'm not sure that makes the 691 * most sense for ease of driver implementation. 692 */ 693 bcopy(macinfo->gldm_vendor_addr, mac_pvt->curr_macaddr, 694 macinfo->gldm_addrlen); 695 mac_pvt->statistics = kmem_zalloc(sizeof (struct gld_stats), KM_SLEEP); 696 697 /* 698 * The available set of notifications is those generatable by GLD 699 * itself, plus those corresponding to the capabilities of the MAC 700 * driver, intersected with those supported by gld_notify_ind() above. 701 */ 702 mac_pvt->notifications = gld_internal_notes; 703 if (macinfo->gldm_capabilities & GLD_CAP_LINKSTATE) 704 mac_pvt->notifications |= gld_linkstate_notes; 705 mac_pvt->notifications &= gld_supported_notes; 706 707 GLDM_LOCK_INIT(macinfo); 708 709 ddi_set_driver_private(devinfo, macinfo); 710 711 /* 712 * Now atomically get a PPA and put ourselves on the mac list. 713 */ 714 mutex_enter(&glddev->gld_devlock); 715 716 #ifdef DEBUG 717 if (macinfo->gldm_ppa != ddi_get_instance(devinfo)) 718 cmn_err(CE_WARN, "%s%d instance != ppa %d", 719 ddi_driver_name(devinfo), ddi_get_instance(devinfo), 720 macinfo->gldm_ppa); 721 #endif 722 723 /* 724 * Create style 2 node (gated by gld-provider-styles property). 725 * 726 * NOTE: When the CLONE_DEV flag is specified to 727 * ddi_create_minor_node() the minor number argument is 728 * immaterial. Opens of that node will go via the clone 729 * driver and gld_open() will always be passed a dev_t with 730 * minor of zero. 731 */ 732 if (glddev->gld_styles != -2) { 733 if (ddi_create_minor_node(devinfo, glddev->gld_name, S_IFCHR, 734 0, DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) { 735 mutex_exit(&glddev->gld_devlock); 736 goto late_failure; 737 } 738 } 739 740 /* 741 * Create style 1 node (gated by gld-provider-styles property) 742 */ 743 if (glddev->gld_styles != -1) { 744 (void) sprintf(minordev, "%s%d", glddev->gld_name, 745 macinfo->gldm_ppa); 746 if (ddi_create_minor_node(devinfo, minordev, S_IFCHR, 747 GLD_STYLE1_PPA_TO_MINOR(macinfo->gldm_ppa), DDI_NT_NET, 748 0) != DDI_SUCCESS) { 749 mutex_exit(&glddev->gld_devlock); 750 goto late_failure; 751 } 752 } 753 754 /* add ourselves to this major device's linked list of instances */ 755 gldinsque(macinfo, glddev->gld_mac_prev); 756 757 mutex_exit(&glddev->gld_devlock); 758 759 /* 760 * Unfortunately we need the ppa before we call gld_initstats(); 761 * otherwise we would like to do this just above the mutex_enter 762 * above. In which case we could have set MAC_READY inside the 763 * mutex and we wouldn't have needed to check it in open and 764 * DL_ATTACH. We wouldn't like to do the initstats/kstat_create 765 * inside the mutex because it might get taken in our kstat_update 766 * routine and cause a deadlock with kstat_chain_lock. 767 */ 768 769 /* gld_initstats() calls (*ifp->init)() */ 770 if (gld_initstats(macinfo) != GLD_SUCCESS) { 771 mutex_enter(&glddev->gld_devlock); 772 gldremque(macinfo); 773 mutex_exit(&glddev->gld_devlock); 774 goto late_failure; 775 } 776 777 /* 778 * Need to indicate we are NOW ready to process interrupts; 779 * any interrupt before this is set is for someone else. 780 * This flag is also now used to tell open, et. al. that this 781 * mac is now fully ready and available for use. 782 */ 783 GLDM_LOCK(macinfo, RW_WRITER); 784 macinfo->gldm_GLD_flags |= GLD_MAC_READY; 785 GLDM_UNLOCK(macinfo); 786 787 /* log local ethernet address -- XXX not DDI compliant */ 788 if (macinfo->gldm_addrlen == sizeof (struct ether_addr)) 789 (void) localetheraddr( 790 (struct ether_addr *)macinfo->gldm_vendor_addr, NULL); 791 792 /* now put announcement into the message buffer */ 793 cmn_err(CE_CONT, "!%s%d: %s: type \"%s\" mac address %s\n", 794 glddev->gld_name, 795 macinfo->gldm_ppa, macinfo->gldm_ident, 796 mac_pvt->interfacep->mac_string, 797 gld_macaddr_sprintf(pbuf, macinfo->gldm_vendor_addr, 798 macinfo->gldm_addrlen)); 799 800 ddi_report_dev(devinfo); 801 return (DDI_SUCCESS); 802 803 late_failure: 804 ddi_remove_minor_node(devinfo, NULL); 805 GLDM_LOCK_DESTROY(macinfo); 806 if (mac_pvt->curr_macaddr != NULL) 807 kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen); 808 if (mac_pvt->statistics != NULL) 809 kmem_free(mac_pvt->statistics, sizeof (struct gld_stats)); 810 kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t)); 811 macinfo->gldm_mac_pvt = NULL; 812 813 failure: 814 mutex_enter(&gld_device_list.gld_devlock); 815 glddev->gld_ndevice--; 816 /* 817 * Note that just because this goes to zero here does not necessarily 818 * mean that we were the one who added the glddev above. It's 819 * possible that the first mac unattached while were were in here 820 * failing to attach the second mac. But we're now the last. 821 */ 822 if (glddev->gld_ndevice == 0) { 823 /* There should be no macinfos left */ 824 ASSERT(glddev->gld_mac_next == 825 (gld_mac_info_t *)&glddev->gld_mac_next); 826 ASSERT(glddev->gld_mac_prev == 827 (gld_mac_info_t *)&glddev->gld_mac_next); 828 829 /* 830 * There should be no DL_UNATTACHED streams: the system 831 * should not have detached the "first" devinfo which has 832 * all the open style 2 streams. 833 * 834 * XXX This is not clear. See gld_getinfo and Bug 1165519 835 */ 836 ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next); 837 ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next); 838 839 gldremque(glddev); 840 mutex_destroy(&glddev->gld_devlock); 841 if (glddev->gld_broadcast != NULL) 842 kmem_free(glddev->gld_broadcast, glddev->gld_addrlen); 843 kmem_free(glddev, sizeof (glddev_t)); 844 } 845 mutex_exit(&gld_device_list.gld_devlock); 846 847 return (DDI_FAILURE); 848 } 849 850 /* 851 * gld_unregister (macinfo) 852 * remove the macinfo structure from local structures 853 * this is cleanup for a driver to be unloaded 854 */ 855 int 856 gld_unregister(gld_mac_info_t *macinfo) 857 { 858 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 859 glddev_t *glddev = mac_pvt->major_dev; 860 gld_interface_t *ifp; 861 int multisize = sizeof (gld_mcast_t) * glddev->gld_multisize; 862 863 mutex_enter(&glddev->gld_devlock); 864 GLDM_LOCK(macinfo, RW_WRITER); 865 866 if (mac_pvt->nvlan > 0) { 867 GLDM_UNLOCK(macinfo); 868 mutex_exit(&glddev->gld_devlock); 869 return (DDI_FAILURE); 870 } 871 872 #ifdef GLD_DEBUG 873 { 874 int i; 875 876 for (i = 0; i < VLAN_HASHSZ; i++) { 877 if ((mac_pvt->vlan_hash[i] != NULL)) 878 cmn_err(CE_PANIC, 879 "%s, line %d: " 880 "mac_pvt->vlan_hash[%d] != NULL", 881 __FILE__, __LINE__, i); 882 } 883 } 884 #endif 885 886 /* Delete this mac */ 887 gldremque(macinfo); 888 889 /* Disallow further entries to gld_recv() and gld_sched() */ 890 macinfo->gldm_GLD_flags |= GLD_UNREGISTERED; 891 892 GLDM_UNLOCK(macinfo); 893 mutex_exit(&glddev->gld_devlock); 894 895 ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep; 896 (*ifp->uninit)(macinfo); 897 898 ASSERT(mac_pvt->kstatp); 899 kstat_delete(mac_pvt->kstatp); 900 901 ASSERT(GLDM_LOCK_INITED(macinfo)); 902 kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen); 903 kmem_free(mac_pvt->statistics, sizeof (struct gld_stats)); 904 905 if (mac_pvt->mcast_table != NULL) 906 kmem_free(mac_pvt->mcast_table, multisize); 907 kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t)); 908 macinfo->gldm_mac_pvt = (caddr_t)NULL; 909 910 /* We now have one fewer instance for this major device */ 911 mutex_enter(&gld_device_list.gld_devlock); 912 glddev->gld_ndevice--; 913 if (glddev->gld_ndevice == 0) { 914 /* There should be no macinfos left */ 915 ASSERT(glddev->gld_mac_next == 916 (gld_mac_info_t *)&glddev->gld_mac_next); 917 ASSERT(glddev->gld_mac_prev == 918 (gld_mac_info_t *)&glddev->gld_mac_next); 919 920 /* 921 * There should be no DL_UNATTACHED streams: the system 922 * should not have detached the "first" devinfo which has 923 * all the open style 2 streams. 924 * 925 * XXX This is not clear. See gld_getinfo and Bug 1165519 926 */ 927 ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next); 928 ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next); 929 930 ddi_remove_minor_node(macinfo->gldm_devinfo, NULL); 931 gldremque(glddev); 932 mutex_destroy(&glddev->gld_devlock); 933 if (glddev->gld_broadcast != NULL) 934 kmem_free(glddev->gld_broadcast, glddev->gld_addrlen); 935 kmem_free(glddev, sizeof (glddev_t)); 936 } 937 mutex_exit(&gld_device_list.gld_devlock); 938 939 return (DDI_SUCCESS); 940 } 941 942 /* 943 * gld_initstats 944 * called from gld_register 945 */ 946 static int 947 gld_initstats(gld_mac_info_t *macinfo) 948 { 949 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 950 struct gldkstats *sp; 951 glddev_t *glddev; 952 kstat_t *ksp; 953 gld_interface_t *ifp; 954 955 glddev = mac_pvt->major_dev; 956 957 if ((ksp = kstat_create(glddev->gld_name, macinfo->gldm_ppa, 958 NULL, "net", KSTAT_TYPE_NAMED, 959 sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) { 960 cmn_err(CE_WARN, 961 "GLD: failed to create kstat structure for %s%d", 962 glddev->gld_name, macinfo->gldm_ppa); 963 return (GLD_FAILURE); 964 } 965 mac_pvt->kstatp = ksp; 966 967 ksp->ks_update = gld_update_kstat; 968 ksp->ks_private = (void *)macinfo; 969 970 sp = ksp->ks_data; 971 kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32); 972 kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32); 973 kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG); 974 kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG); 975 kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32); 976 kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32); 977 kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG); 978 kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG); 979 kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG); 980 kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG); 981 kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG); 982 kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG); 983 kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG); 984 kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG); 985 kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG); 986 kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64); 987 kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64); 988 kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64); 989 kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64); 990 kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG); 991 kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64); 992 kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR); 993 kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR); 994 995 kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG); 996 kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG); 997 kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG); 998 999 kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp", 1000 KSTAT_DATA_UINT32); 1001 kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp", 1002 KSTAT_DATA_UINT32); 1003 1004 ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep; 1005 1006 (*ifp->init)(macinfo); 1007 1008 kstat_install(ksp); 1009 1010 return (GLD_SUCCESS); 1011 } 1012 1013 /* called from kstat mechanism, and from wsrv's get_statistics_req */ 1014 static int 1015 gld_update_kstat(kstat_t *ksp, int rw) 1016 { 1017 gld_mac_info_t *macinfo; 1018 gld_mac_pvt_t *mac_pvt; 1019 struct gldkstats *gsp; 1020 struct gld_stats *stats; 1021 1022 if (rw == KSTAT_WRITE) 1023 return (EACCES); 1024 1025 macinfo = (gld_mac_info_t *)ksp->ks_private; 1026 ASSERT(macinfo != NULL); 1027 1028 GLDM_LOCK(macinfo, RW_WRITER); 1029 1030 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) { 1031 GLDM_UNLOCK(macinfo); 1032 return (EIO); /* this one's not ready yet */ 1033 } 1034 1035 if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) { 1036 GLDM_UNLOCK(macinfo); 1037 return (EIO); /* this one's not ready any more */ 1038 } 1039 1040 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 1041 gsp = mac_pvt->kstatp->ks_data; 1042 ASSERT(gsp); 1043 stats = mac_pvt->statistics; 1044 1045 if (macinfo->gldm_get_stats) 1046 (void) (*macinfo->gldm_get_stats)(macinfo, stats); 1047 1048 gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff; 1049 gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff; 1050 gsp->glds_multixmt.value.ul = stats->glds_multixmt; 1051 gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt; 1052 gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf; /* 0 for now */ 1053 gsp->glds_xmtretry.value.ul = stats->glds_xmtretry; 1054 1055 gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64; 1056 gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64; 1057 gsp->glds_xmtbadinterp.value.ui32 = stats->glds_xmtbadinterp; 1058 1059 gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff; 1060 gsp->glds_errxmt.value.ul = stats->glds_errxmt; 1061 gsp->glds_errrcv.value.ul = stats->glds_errrcv; 1062 gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff; 1063 gsp->glds_multircv.value.ul = stats->glds_multircv; 1064 gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv; 1065 gsp->glds_blocked.value.ul = stats->glds_blocked; 1066 gsp->glds_overflow.value.ul = stats->glds_overflow; 1067 gsp->glds_underflow.value.ul = stats->glds_underflow; 1068 gsp->glds_missed.value.ul = stats->glds_missed; 1069 gsp->glds_norcvbuf.value.ul = stats->glds_norcvbuf + 1070 stats->glds_gldnorcvbuf; 1071 gsp->glds_intr.value.ul = stats->glds_intr; 1072 1073 gsp->glds_speed.value.ui64 = stats->glds_speed; 1074 gsp->glds_unknowns.value.ul = stats->glds_unknowns; 1075 gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64; 1076 gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64; 1077 gsp->glds_rcvbadinterp.value.ui32 = stats->glds_rcvbadinterp; 1078 1079 if (mac_pvt->nprom) 1080 (void) strcpy(gsp->glds_prom.value.c, "phys"); 1081 else if (mac_pvt->nprom_multi) 1082 (void) strcpy(gsp->glds_prom.value.c, "multi"); 1083 else 1084 (void) strcpy(gsp->glds_prom.value.c, "off"); 1085 1086 (void) strcpy(gsp->glds_media.value.c, gld_media[ 1087 stats->glds_media < sizeof (gld_media) / sizeof (gld_media[0]) 1088 ? stats->glds_media : 0]); 1089 1090 switch (macinfo->gldm_type) { 1091 case DL_ETHER: 1092 gsp->glds_frame.value.ul = stats->glds_frame; 1093 gsp->glds_crc.value.ul = stats->glds_crc; 1094 gsp->glds_collisions.value.ul = stats->glds_collisions; 1095 gsp->glds_excoll.value.ul = stats->glds_excoll; 1096 gsp->glds_defer.value.ul = stats->glds_defer; 1097 gsp->glds_short.value.ul = stats->glds_short; 1098 gsp->glds_xmtlatecoll.value.ul = stats->glds_xmtlatecoll; 1099 gsp->glds_nocarrier.value.ul = stats->glds_nocarrier; 1100 gsp->glds_dot3_first_coll.value.ui32 = 1101 stats->glds_dot3_first_coll; 1102 gsp->glds_dot3_multi_coll.value.ui32 = 1103 stats->glds_dot3_multi_coll; 1104 gsp->glds_dot3_sqe_error.value.ui32 = 1105 stats->glds_dot3_sqe_error; 1106 gsp->glds_dot3_mac_xmt_error.value.ui32 = 1107 stats->glds_dot3_mac_xmt_error; 1108 gsp->glds_dot3_mac_rcv_error.value.ui32 = 1109 stats->glds_dot3_mac_rcv_error; 1110 gsp->glds_dot3_frame_too_long.value.ui32 = 1111 stats->glds_dot3_frame_too_long; 1112 (void) strcpy(gsp->glds_duplex.value.c, gld_duplex[ 1113 stats->glds_duplex < 1114 sizeof (gld_duplex) / sizeof (gld_duplex[0]) ? 1115 stats->glds_duplex : 0]); 1116 break; 1117 case DL_TPR: 1118 gsp->glds_dot5_line_error.value.ui32 = 1119 stats->glds_dot5_line_error; 1120 gsp->glds_dot5_burst_error.value.ui32 = 1121 stats->glds_dot5_burst_error; 1122 gsp->glds_dot5_signal_loss.value.ui32 = 1123 stats->glds_dot5_signal_loss; 1124 gsp->glds_dot5_ace_error.value.ui32 = 1125 stats->glds_dot5_ace_error; 1126 gsp->glds_dot5_internal_error.value.ui32 = 1127 stats->glds_dot5_internal_error; 1128 gsp->glds_dot5_lost_frame_error.value.ui32 = 1129 stats->glds_dot5_lost_frame_error; 1130 gsp->glds_dot5_frame_copied_error.value.ui32 = 1131 stats->glds_dot5_frame_copied_error; 1132 gsp->glds_dot5_token_error.value.ui32 = 1133 stats->glds_dot5_token_error; 1134 gsp->glds_dot5_freq_error.value.ui32 = 1135 stats->glds_dot5_freq_error; 1136 break; 1137 case DL_FDDI: 1138 gsp->glds_fddi_mac_error.value.ui32 = 1139 stats->glds_fddi_mac_error; 1140 gsp->glds_fddi_mac_lost.value.ui32 = 1141 stats->glds_fddi_mac_lost; 1142 gsp->glds_fddi_mac_token.value.ui32 = 1143 stats->glds_fddi_mac_token; 1144 gsp->glds_fddi_mac_tvx_expired.value.ui32 = 1145 stats->glds_fddi_mac_tvx_expired; 1146 gsp->glds_fddi_mac_late.value.ui32 = 1147 stats->glds_fddi_mac_late; 1148 gsp->glds_fddi_mac_ring_op.value.ui32 = 1149 stats->glds_fddi_mac_ring_op; 1150 break; 1151 case DL_IB: 1152 break; 1153 default: 1154 break; 1155 } 1156 1157 GLDM_UNLOCK(macinfo); 1158 1159 #ifdef GLD_DEBUG 1160 gld_check_assertions(); 1161 if (gld_debug & GLDRDE) 1162 gld_sr_dump(macinfo); 1163 #endif 1164 1165 return (0); 1166 } 1167 1168 static int 1169 gld_init_vlan_stats(gld_vlan_t *vlan) 1170 { 1171 gld_mac_info_t *mac = vlan->gldv_mac; 1172 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt; 1173 struct gldkstats *sp; 1174 glddev_t *glddev; 1175 kstat_t *ksp; 1176 char *name; 1177 int instance; 1178 1179 glddev = mac_pvt->major_dev; 1180 name = glddev->gld_name; 1181 instance = (vlan->gldv_id * GLD_VLAN_SCALE) + mac->gldm_ppa; 1182 1183 if ((ksp = kstat_create(name, instance, 1184 NULL, "net", KSTAT_TYPE_NAMED, 1185 sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) { 1186 cmn_err(CE_WARN, 1187 "GLD: failed to create kstat structure for %s%d", 1188 name, instance); 1189 return (GLD_FAILURE); 1190 } 1191 1192 vlan->gldv_kstatp = ksp; 1193 1194 ksp->ks_update = gld_update_vlan_kstat; 1195 ksp->ks_private = (void *)vlan; 1196 1197 sp = ksp->ks_data; 1198 kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32); 1199 kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32); 1200 kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG); 1201 kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG); 1202 kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32); 1203 kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32); 1204 kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG); 1205 kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG); 1206 kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG); 1207 kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG); 1208 kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG); 1209 kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG); 1210 kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG); 1211 kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG); 1212 kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG); 1213 kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64); 1214 kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64); 1215 kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64); 1216 kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64); 1217 kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG); 1218 kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64); 1219 kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR); 1220 kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR); 1221 1222 kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG); 1223 kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG); 1224 kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG); 1225 1226 kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp", 1227 KSTAT_DATA_UINT32); 1228 kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp", 1229 KSTAT_DATA_UINT32); 1230 1231 kstat_install(ksp); 1232 return (GLD_SUCCESS); 1233 } 1234 1235 static int 1236 gld_update_vlan_kstat(kstat_t *ksp, int rw) 1237 { 1238 gld_vlan_t *vlan; 1239 gld_mac_info_t *macinfo; 1240 struct gldkstats *gsp; 1241 struct gld_stats *stats; 1242 1243 if (rw == KSTAT_WRITE) 1244 return (EACCES); 1245 1246 vlan = (gld_vlan_t *)ksp->ks_private; 1247 ASSERT(vlan != NULL); 1248 1249 macinfo = vlan->gldv_mac; 1250 GLDM_LOCK(macinfo, RW_WRITER); 1251 1252 gsp = vlan->gldv_kstatp->ks_data; 1253 ASSERT(gsp); 1254 stats = vlan->gldv_stats; 1255 1256 gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff; 1257 gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff; 1258 gsp->glds_errxmt.value.ul = stats->glds_errxmt; 1259 gsp->glds_multixmt.value.ul = stats->glds_multixmt; 1260 gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt; 1261 gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf; 1262 gsp->glds_xmtretry.value.ul = stats->glds_xmtretry; 1263 gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64; 1264 gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64; 1265 1266 gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff; 1267 gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff; 1268 gsp->glds_errrcv.value.ul = stats->glds_errrcv; 1269 gsp->glds_multircv.value.ul = stats->glds_multircv; 1270 gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv; 1271 gsp->glds_blocked.value.ul = stats->glds_blocked; 1272 gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64; 1273 gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64; 1274 1275 GLDM_UNLOCK(macinfo); 1276 return (0); 1277 } 1278 1279 /* 1280 * The device dependent driver specifies gld_getinfo as its getinfo routine. 1281 */ 1282 /*ARGSUSED*/ 1283 int 1284 gld_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 1285 { 1286 dev_info_t *devinfo; 1287 minor_t minor = getminor((dev_t)arg); 1288 int rc = DDI_FAILURE; 1289 1290 switch (cmd) { 1291 case DDI_INFO_DEVT2DEVINFO: 1292 if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) { 1293 *(dev_info_t **)resultp = devinfo; 1294 rc = DDI_SUCCESS; 1295 } 1296 break; 1297 case DDI_INFO_DEVT2INSTANCE: 1298 /* Need static mapping for deferred attach */ 1299 if (minor == GLD_USE_STYLE2) { 1300 /* 1301 * Style 2: this minor number does not correspond to 1302 * any particular instance number. 1303 */ 1304 rc = DDI_FAILURE; 1305 } else if (minor <= GLD_MAX_STYLE1_MINOR) { 1306 /* Style 1: calculate the PPA from the minor */ 1307 *(int *)resultp = GLD_STYLE1_MINOR_TO_PPA(minor); 1308 rc = DDI_SUCCESS; 1309 } else { 1310 /* Clone: look for it. Not a static mapping */ 1311 if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) { 1312 *(int *)resultp = ddi_get_instance(devinfo); 1313 rc = DDI_SUCCESS; 1314 } 1315 } 1316 break; 1317 } 1318 1319 return (rc); 1320 } 1321 1322 /* called from gld_getinfo */ 1323 dev_info_t * 1324 gld_finddevinfo(dev_t dev) 1325 { 1326 minor_t minor = getminor(dev); 1327 glddev_t *device; 1328 gld_mac_info_t *mac; 1329 gld_vlan_t *vlan; 1330 gld_t *str; 1331 dev_info_t *devinfo = NULL; 1332 int i; 1333 1334 if (minor == GLD_USE_STYLE2) { 1335 /* 1336 * Style 2: this minor number does not correspond to 1337 * any particular instance number. 1338 * 1339 * XXX We don't know what to say. See Bug 1165519. 1340 */ 1341 return (NULL); 1342 } 1343 1344 mutex_enter(&gld_device_list.gld_devlock); /* hold the device */ 1345 1346 device = gld_devlookup(getmajor(dev)); 1347 if (device == NULL) { 1348 /* There are no attached instances of this device */ 1349 mutex_exit(&gld_device_list.gld_devlock); 1350 return (NULL); 1351 } 1352 1353 /* 1354 * Search all attached macs and streams. 1355 * 1356 * XXX We don't bother checking the DL_UNATTACHED streams since 1357 * we don't know what devinfo we should report back even if we 1358 * found the minor. Maybe we should associate streams that are 1359 * not currently attached to a PPA with the "first" devinfo node 1360 * of the major device to attach -- the one that created the 1361 * minor node for the generic device. 1362 */ 1363 mutex_enter(&device->gld_devlock); 1364 1365 for (mac = device->gld_mac_next; 1366 mac != (gld_mac_info_t *)&device->gld_mac_next; 1367 mac = mac->gldm_next) { 1368 gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt; 1369 1370 if (!(mac->gldm_GLD_flags & GLD_MAC_READY)) 1371 continue; /* this one's not ready yet */ 1372 if (minor <= GLD_MAX_STYLE1_MINOR) { 1373 /* Style 1 -- look for the corresponding PPA */ 1374 if (minor == GLD_STYLE1_PPA_TO_MINOR(mac->gldm_ppa)) { 1375 devinfo = mac->gldm_devinfo; 1376 goto out; /* found it! */ 1377 } else 1378 continue; /* not this PPA */ 1379 } 1380 1381 /* We are looking for a clone */ 1382 for (i = 0; i < VLAN_HASHSZ; i++) { 1383 for (vlan = pvt->vlan_hash[i]; 1384 vlan != NULL; vlan = vlan->gldv_next) { 1385 for (str = vlan->gldv_str_next; 1386 str != (gld_t *)&vlan->gldv_str_next; 1387 str = str->gld_next) { 1388 ASSERT(str->gld_mac_info == mac); 1389 if (minor == str->gld_minor) { 1390 devinfo = mac->gldm_devinfo; 1391 goto out; 1392 } 1393 } 1394 } 1395 } 1396 } 1397 out: 1398 mutex_exit(&device->gld_devlock); 1399 mutex_exit(&gld_device_list.gld_devlock); 1400 return (devinfo); 1401 } 1402 1403 /* 1404 * STREAMS open routine. The device dependent driver specifies this as its 1405 * open entry point. 1406 */ 1407 /*ARGSUSED2*/ 1408 int 1409 gld_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred) 1410 { 1411 gld_mac_pvt_t *mac_pvt; 1412 gld_t *gld; 1413 glddev_t *glddev; 1414 gld_mac_info_t *macinfo; 1415 minor_t minor = getminor(*dev); 1416 gld_vlan_t *vlan; 1417 t_uscalar_t ppa; 1418 1419 ASSERT(q != NULL); 1420 1421 if (minor > GLD_MAX_STYLE1_MINOR) 1422 return (ENXIO); 1423 1424 ASSERT(q->q_ptr == NULL); /* Clone device gives us a fresh Q */ 1425 1426 /* Find our per-major glddev_t structure */ 1427 mutex_enter(&gld_device_list.gld_devlock); 1428 glddev = gld_devlookup(getmajor(*dev)); 1429 1430 /* 1431 * This glddev will hang around since detach (and therefore 1432 * gld_unregister) can't run while we're here in the open routine. 1433 */ 1434 mutex_exit(&gld_device_list.gld_devlock); 1435 1436 if (glddev == NULL) 1437 return (ENXIO); 1438 1439 #ifdef GLD_DEBUG 1440 if (gld_debug & GLDPROT) { 1441 if (minor == GLD_USE_STYLE2) 1442 cmn_err(CE_NOTE, "gld_open(%p, Style 2)", (void *)q); 1443 else 1444 cmn_err(CE_NOTE, "gld_open(%p, Style 1, minor = %d)", 1445 (void *)q, minor); 1446 } 1447 #endif 1448 1449 /* 1450 * get a per-stream structure and link things together so we 1451 * can easily find them later. 1452 */ 1453 gld = kmem_zalloc(sizeof (gld_t), KM_SLEEP); 1454 1455 /* 1456 * fill in the structure and state info 1457 */ 1458 gld->gld_qptr = q; 1459 gld->gld_device = glddev; 1460 gld->gld_state = DL_UNATTACHED; 1461 1462 /* 1463 * we must atomically find a free minor number and add the stream 1464 * to a list, because gld_findminor has to traverse the lists to 1465 * determine which minor numbers are free. 1466 */ 1467 mutex_enter(&glddev->gld_devlock); 1468 1469 /* find a free minor device number for the clone */ 1470 gld->gld_minor = gld_findminor(glddev); 1471 if (gld->gld_minor == 0) { 1472 mutex_exit(&glddev->gld_devlock); 1473 kmem_free(gld, sizeof (gld_t)); 1474 return (ENOSR); 1475 } 1476 1477 #ifdef GLD_VERBOSE_DEBUG 1478 if (gld_debug & GLDPROT) 1479 cmn_err(CE_NOTE, "gld_open() gld ptr: %p minor: %d", 1480 (void *)gld, gld->gld_minor); 1481 #endif 1482 1483 if (minor == GLD_USE_STYLE2) { 1484 gld->gld_style = DL_STYLE2; 1485 *dev = makedevice(getmajor(*dev), gld->gld_minor); 1486 WR(q)->q_ptr = q->q_ptr = (caddr_t)gld; 1487 gldinsque(gld, glddev->gld_str_prev); 1488 #ifdef GLD_VERBOSE_DEBUG 1489 if (gld_debug & GLDPROT) 1490 cmn_err(CE_NOTE, "GLDstruct added to device list"); 1491 #endif 1492 (void) qassociate(q, -1); 1493 goto done; 1494 } 1495 1496 gld->gld_style = DL_STYLE1; 1497 1498 /* the PPA is actually 1 less than the minordev */ 1499 ppa = GLD_STYLE1_MINOR_TO_PPA(minor); 1500 1501 for (macinfo = glddev->gld_mac_next; 1502 macinfo != (gld_mac_info_t *)(&glddev->gld_mac_next); 1503 macinfo = macinfo->gldm_next) { 1504 ASSERT(macinfo != NULL); 1505 if (macinfo->gldm_ppa != ppa) 1506 continue; 1507 1508 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) 1509 continue; /* this one's not ready yet */ 1510 1511 /* 1512 * we found the correct PPA 1513 */ 1514 GLDM_LOCK(macinfo, RW_WRITER); 1515 1516 gld->gld_mac_info = macinfo; 1517 1518 if (macinfo->gldm_send_tagged != NULL) 1519 gld->gld_send = macinfo->gldm_send_tagged; 1520 else 1521 gld->gld_send = macinfo->gldm_send; 1522 1523 /* now ready for action */ 1524 gld->gld_state = DL_UNBOUND; 1525 1526 if ((vlan = gld_get_vlan(macinfo, VLAN_VID_NONE)) == NULL) { 1527 GLDM_UNLOCK(macinfo); 1528 mutex_exit(&glddev->gld_devlock); 1529 kmem_free(gld, sizeof (gld_t)); 1530 return (EIO); 1531 } 1532 1533 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 1534 if (!mac_pvt->started) { 1535 if (gld_start_mac(macinfo) != GLD_SUCCESS) { 1536 GLDM_UNLOCK(macinfo); 1537 mutex_exit(&glddev->gld_devlock); 1538 kmem_free(gld, sizeof (gld_t)); 1539 return (EIO); 1540 } 1541 } 1542 1543 gld->gld_vlan = vlan; 1544 vlan->gldv_nstreams++; 1545 gldinsque(gld, vlan->gldv_str_prev); 1546 *dev = makedevice(getmajor(*dev), gld->gld_minor); 1547 WR(q)->q_ptr = q->q_ptr = (caddr_t)gld; 1548 1549 GLDM_UNLOCK(macinfo); 1550 #ifdef GLD_VERBOSE_DEBUG 1551 if (gld_debug & GLDPROT) 1552 cmn_err(CE_NOTE, 1553 "GLDstruct added to instance list"); 1554 #endif 1555 break; 1556 } 1557 1558 if (gld->gld_state == DL_UNATTACHED) { 1559 mutex_exit(&glddev->gld_devlock); 1560 kmem_free(gld, sizeof (gld_t)); 1561 return (ENXIO); 1562 } 1563 1564 done: 1565 mutex_exit(&glddev->gld_devlock); 1566 noenable(WR(q)); /* We'll do the qenables manually */ 1567 qprocson(q); /* start the queues running */ 1568 qenable(WR(q)); 1569 return (0); 1570 } 1571 1572 /* 1573 * normal stream close call checks current status and cleans up 1574 * data structures that were dynamically allocated 1575 */ 1576 /*ARGSUSED1*/ 1577 int 1578 gld_close(queue_t *q, int flag, cred_t *cred) 1579 { 1580 gld_t *gld = (gld_t *)q->q_ptr; 1581 glddev_t *glddev = gld->gld_device; 1582 1583 ASSERT(q); 1584 ASSERT(gld); 1585 1586 #ifdef GLD_DEBUG 1587 if (gld_debug & GLDPROT) { 1588 cmn_err(CE_NOTE, "gld_close(%p, Style %d)", 1589 (void *)q, (gld->gld_style & 0x1) + 1); 1590 } 1591 #endif 1592 1593 /* Hold all device streams lists still while we check for a macinfo */ 1594 mutex_enter(&glddev->gld_devlock); 1595 1596 if (gld->gld_mac_info != NULL) { 1597 /* If there's a macinfo, block recv while we change state */ 1598 GLDM_LOCK(gld->gld_mac_info, RW_WRITER); 1599 gld->gld_flags |= GLD_STR_CLOSING; /* no more rcv putnexts */ 1600 GLDM_UNLOCK(gld->gld_mac_info); 1601 } else { 1602 /* no mac DL_ATTACHED right now */ 1603 gld->gld_flags |= GLD_STR_CLOSING; 1604 } 1605 1606 mutex_exit(&glddev->gld_devlock); 1607 1608 /* 1609 * qprocsoff before we call gld_unbind/gldunattach, so that 1610 * we know wsrv isn't in there trying to undo what we're doing. 1611 */ 1612 qprocsoff(q); 1613 1614 ASSERT(gld->gld_wput_count == 0); 1615 gld->gld_wput_count = 0; /* just in case */ 1616 1617 if (gld->gld_state == DL_IDLE) { 1618 /* Need to unbind */ 1619 ASSERT(gld->gld_mac_info != NULL); 1620 (void) gld_unbind(WR(q), NULL); 1621 } 1622 1623 if (gld->gld_state == DL_UNBOUND) { 1624 /* 1625 * Need to unattach 1626 * For style 2 stream, gldunattach also 1627 * associate queue with NULL dip 1628 */ 1629 ASSERT(gld->gld_mac_info != NULL); 1630 (void) gldunattach(WR(q), NULL); 1631 } 1632 1633 /* disassociate the stream from the device */ 1634 q->q_ptr = WR(q)->q_ptr = NULL; 1635 1636 /* 1637 * Since we unattached above (if necessary), we know that we're 1638 * on the per-major list of unattached streams, rather than a 1639 * per-PPA list. So we know we should hold the devlock. 1640 */ 1641 mutex_enter(&glddev->gld_devlock); 1642 gldremque(gld); /* remove from Style 2 list */ 1643 mutex_exit(&glddev->gld_devlock); 1644 1645 kmem_free(gld, sizeof (gld_t)); 1646 1647 return (0); 1648 } 1649 1650 /* 1651 * gld_rsrv (q) 1652 * simple read service procedure 1653 * purpose is to avoid the time it takes for packets 1654 * to move through IP so we can get them off the board 1655 * as fast as possible due to limited PC resources. 1656 * 1657 * This is not normally used in the current implementation. It 1658 * can be selected with the undocumented property "fast_recv". 1659 * If that property is set, gld_recv will send the packet 1660 * upstream with a putq() rather than a putnext(), thus causing 1661 * this routine to be scheduled. 1662 */ 1663 int 1664 gld_rsrv(queue_t *q) 1665 { 1666 mblk_t *mp; 1667 1668 while ((mp = getq(q)) != NULL) { 1669 if (canputnext(q)) { 1670 putnext(q, mp); 1671 } else { 1672 freemsg(mp); 1673 } 1674 } 1675 return (0); 1676 } 1677 1678 /* 1679 * gld_wput (q, mp) 1680 * general gld stream write put routine. Receives fastpath data from upper 1681 * modules and processes it immediately. ioctl and M_PROTO/M_PCPROTO are 1682 * queued for later processing by the service procedure. 1683 */ 1684 1685 int 1686 gld_wput(queue_t *q, mblk_t *mp) 1687 { 1688 gld_t *gld = (gld_t *)(q->q_ptr); 1689 int rc; 1690 boolean_t multidata = B_TRUE; 1691 1692 #ifdef GLD_DEBUG 1693 if (gld_debug & GLDTRACE) 1694 cmn_err(CE_NOTE, "gld_wput(%p %p): type %x", 1695 (void *)q, (void *)mp, DB_TYPE(mp)); 1696 #endif 1697 switch (DB_TYPE(mp)) { 1698 1699 case M_DATA: 1700 /* fast data / raw support */ 1701 /* we must be DL_ATTACHED and DL_BOUND to do this */ 1702 /* Tricky to access memory without taking the mutex */ 1703 if ((gld->gld_flags & (GLD_RAW | GLD_FAST)) == 0 || 1704 gld->gld_state != DL_IDLE) { 1705 merror(q, mp, EPROTO); 1706 break; 1707 } 1708 multidata = B_FALSE; 1709 /* LINTED: E_CASE_FALLTHRU */ 1710 case M_MULTIDATA: 1711 /* Only call gld_start() directly if nothing queued ahead */ 1712 /* No guarantees about ordering with different threads */ 1713 if (q->q_first) 1714 goto use_wsrv; 1715 1716 /* 1717 * This can happen if wsrv has taken off the last mblk but 1718 * is still processing it. 1719 */ 1720 membar_consumer(); 1721 if (gld->gld_in_wsrv) 1722 goto use_wsrv; 1723 1724 /* 1725 * Keep a count of current wput calls to start. 1726 * Nonzero count delays any attempted DL_UNBIND. 1727 * See comments above gld_start(). 1728 */ 1729 atomic_add_32((uint32_t *)&gld->gld_wput_count, 1); 1730 membar_enter(); 1731 1732 /* Recheck state now wput_count is set to prevent DL_UNBIND */ 1733 /* If this Q is in process of DL_UNBIND, don't call start */ 1734 if (gld->gld_state != DL_IDLE || gld->gld_in_unbind) { 1735 /* Extremely unlikely */ 1736 atomic_add_32((uint32_t *)&gld->gld_wput_count, -1); 1737 goto use_wsrv; 1738 } 1739 1740 rc = (multidata) ? gld_start_mdt(q, mp, GLD_WPUT) : 1741 gld_start(q, mp, GLD_WPUT, UPRI(gld, mp->b_band)); 1742 1743 /* Allow DL_UNBIND again */ 1744 membar_exit(); 1745 atomic_add_32((uint32_t *)&gld->gld_wput_count, -1); 1746 1747 if (rc == GLD_NORESOURCES) 1748 qenable(q); 1749 break; /* Done with this packet */ 1750 1751 use_wsrv: 1752 /* Q not empty, in DL_DETACH, or start gave NORESOURCES */ 1753 (void) putq(q, mp); 1754 qenable(q); 1755 break; 1756 1757 case M_IOCTL: 1758 /* ioctl relies on wsrv single threading per queue */ 1759 (void) putq(q, mp); 1760 qenable(q); 1761 break; 1762 1763 case M_CTL: 1764 (void) putq(q, mp); 1765 qenable(q); 1766 break; 1767 1768 case M_FLUSH: /* canonical flush handling */ 1769 /* XXX Should these be FLUSHALL? */ 1770 if (*mp->b_rptr & FLUSHW) 1771 flushq(q, 0); 1772 if (*mp->b_rptr & FLUSHR) { 1773 flushq(RD(q), 0); 1774 *mp->b_rptr &= ~FLUSHW; 1775 qreply(q, mp); 1776 } else 1777 freemsg(mp); 1778 break; 1779 1780 case M_PROTO: 1781 case M_PCPROTO: 1782 /* these rely on wsrv single threading per queue */ 1783 (void) putq(q, mp); 1784 qenable(q); 1785 break; 1786 1787 default: 1788 #ifdef GLD_DEBUG 1789 if (gld_debug & GLDETRACE) 1790 cmn_err(CE_WARN, 1791 "gld: Unexpected packet type from queue: 0x%x", 1792 DB_TYPE(mp)); 1793 #endif 1794 freemsg(mp); 1795 } 1796 return (0); 1797 } 1798 1799 /* 1800 * gld_wsrv - Incoming messages are processed according to the DLPI protocol 1801 * specification. 1802 * 1803 * wsrv is single-threaded per Q. We make use of this to avoid taking the 1804 * lock for reading data items that are only ever written by us. 1805 */ 1806 1807 int 1808 gld_wsrv(queue_t *q) 1809 { 1810 mblk_t *mp; 1811 gld_t *gld = (gld_t *)q->q_ptr; 1812 gld_mac_info_t *macinfo; 1813 union DL_primitives *prim; 1814 int err; 1815 boolean_t multidata; 1816 1817 #ifdef GLD_DEBUG 1818 if (gld_debug & GLDTRACE) 1819 cmn_err(CE_NOTE, "gld_wsrv(%p)", (void *)q); 1820 #endif 1821 1822 ASSERT(!gld->gld_in_wsrv); 1823 1824 gld->gld_xwait = B_FALSE; /* We are now going to process this Q */ 1825 1826 if (q->q_first == NULL) 1827 return (0); 1828 1829 macinfo = gld->gld_mac_info; 1830 1831 /* 1832 * Help wput avoid a call to gld_start if there might be a message 1833 * previously queued by that thread being processed here. 1834 */ 1835 gld->gld_in_wsrv = B_TRUE; 1836 membar_enter(); 1837 1838 while ((mp = getq(q)) != NULL) { 1839 switch (DB_TYPE(mp)) { 1840 case M_DATA: 1841 case M_MULTIDATA: 1842 multidata = (DB_TYPE(mp) == M_MULTIDATA); 1843 1844 /* 1845 * retry of a previously processed UNITDATA_REQ 1846 * or is a RAW or FAST message from above. 1847 */ 1848 if (macinfo == NULL) { 1849 /* No longer attached to a PPA, drop packet */ 1850 freemsg(mp); 1851 break; 1852 } 1853 1854 gld->gld_sched_ran = B_FALSE; 1855 membar_enter(); 1856 err = (multidata) ? gld_start_mdt(q, mp, GLD_WSRV) : 1857 gld_start(q, mp, GLD_WSRV, UPRI(gld, mp->b_band)); 1858 if (err == GLD_NORESOURCES) { 1859 /* gld_sched will qenable us later */ 1860 gld->gld_xwait = B_TRUE; /* want qenable */ 1861 membar_enter(); 1862 /* 1863 * v2: we're not holding the lock; it's 1864 * possible that the driver could have already 1865 * called gld_sched (following up on its 1866 * return of GLD_NORESOURCES), before we got a 1867 * chance to do the putbq() and set gld_xwait. 1868 * So if we saw a call to gld_sched that 1869 * examined this queue, since our call to 1870 * gld_start() above, then it's possible we've 1871 * already seen the only call to gld_sched() 1872 * we're ever going to see. So we better retry 1873 * transmitting this packet right now. 1874 */ 1875 if (gld->gld_sched_ran) { 1876 #ifdef GLD_DEBUG 1877 if (gld_debug & GLDTRACE) 1878 cmn_err(CE_NOTE, "gld_wsrv: " 1879 "sched was called"); 1880 #endif 1881 break; /* try again right now */ 1882 } 1883 gld->gld_in_wsrv = B_FALSE; 1884 return (0); 1885 } 1886 break; 1887 1888 case M_IOCTL: 1889 (void) gld_ioctl(q, mp); 1890 break; 1891 1892 case M_CTL: 1893 if (macinfo == NULL) { 1894 freemsg(mp); 1895 break; 1896 } 1897 1898 if (macinfo->gldm_mctl != NULL) { 1899 GLDM_LOCK(macinfo, RW_WRITER); 1900 (void) (*macinfo->gldm_mctl) (macinfo, q, mp); 1901 GLDM_UNLOCK(macinfo); 1902 } else { 1903 /* This driver doesn't recognize, just drop */ 1904 freemsg(mp); 1905 } 1906 break; 1907 1908 case M_PROTO: /* Will be an DLPI message of some type */ 1909 case M_PCPROTO: 1910 if ((err = gld_cmds(q, mp)) != GLDE_OK) { 1911 if (err == GLDE_RETRY) { 1912 gld->gld_in_wsrv = B_FALSE; 1913 return (0); /* quit while we're ahead */ 1914 } 1915 prim = (union DL_primitives *)mp->b_rptr; 1916 dlerrorack(q, mp, prim->dl_primitive, err, 0); 1917 } 1918 break; 1919 1920 default: 1921 /* This should never happen */ 1922 #ifdef GLD_DEBUG 1923 if (gld_debug & GLDERRS) 1924 cmn_err(CE_WARN, 1925 "gld_wsrv: db_type(%x) not supported", 1926 mp->b_datap->db_type); 1927 #endif 1928 freemsg(mp); /* unknown types are discarded */ 1929 break; 1930 } 1931 } 1932 1933 membar_exit(); 1934 gld->gld_in_wsrv = B_FALSE; 1935 return (0); 1936 } 1937 1938 /* 1939 * gld_start() can get called from gld_wput(), gld_wsrv(), or gld_unitdata(). 1940 * 1941 * We only come directly from wput() in the GLD_FAST (fastpath) or RAW case. 1942 * 1943 * In particular, we must avoid calling gld_precv*() if we came from wput(). 1944 * gld_precv*() is where we, on the transmit side, loop back our outgoing 1945 * packets to the receive side if we are in physical promiscuous mode. 1946 * Since the receive side holds a lock across its call to the upstream 1947 * putnext, and that upstream module could well have looped back to our 1948 * wput() routine on the same thread, we cannot call gld_precv* from here 1949 * for fear of causing a recursive lock entry in our receive code. 1950 * 1951 * There is a problem here when coming from gld_wput(). While wput 1952 * only comes here if the queue is attached to a PPA and bound to a SAP 1953 * and there are no messages on the queue ahead of the M_DATA that could 1954 * change that, it is theoretically possible that another thread could 1955 * now wput a DL_UNBIND and a DL_DETACH message, and the wsrv() routine 1956 * could wake up and process them, before we finish processing this 1957 * send of the M_DATA. This can only possibly happen on a Style 2 RAW or 1958 * FAST (fastpath) stream: non RAW/FAST streams always go through wsrv(), 1959 * and Style 1 streams only DL_DETACH in the close routine, where 1960 * qprocsoff() protects us. If this happens we could end up calling 1961 * gldm_send() after we have detached the stream and possibly called 1962 * gldm_stop(). Worse, once the number of attached streams goes to zero, 1963 * detach/unregister could be called, and the macinfo could go away entirely. 1964 * 1965 * No one has ever seen this happen. 1966 * 1967 * It is some trouble to fix this, and we would rather not add any mutex 1968 * logic into the wput() routine, which is supposed to be a "fast" 1969 * path. 1970 * 1971 * What I've done is use an atomic counter to keep a count of the number 1972 * of threads currently calling gld_start() from wput() on this stream. 1973 * If DL_DETACH sees this as nonzero, it putbqs the request back onto 1974 * the queue and qenables, hoping to have better luck next time. Since 1975 * people shouldn't be trying to send after they've asked to DL_DETACH, 1976 * hopefully very soon all the wput=>start threads should have returned 1977 * and the DL_DETACH will succeed. It's hard to test this since the odds 1978 * of the failure even trying to happen are so small. I probably could 1979 * have ignored the whole issue and never been the worse for it. 1980 */ 1981 static int 1982 gld_start(queue_t *q, mblk_t *mp, int caller, uint32_t upri) 1983 { 1984 mblk_t *nmp; 1985 gld_t *gld = (gld_t *)q->q_ptr; 1986 gld_mac_info_t *macinfo; 1987 gld_mac_pvt_t *mac_pvt; 1988 int rc; 1989 gld_interface_t *ifp; 1990 pktinfo_t pktinfo; 1991 uint32_t vtag; 1992 gld_vlan_t *vlan; 1993 1994 ASSERT(DB_TYPE(mp) == M_DATA); 1995 macinfo = gld->gld_mac_info; 1996 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 1997 ifp = mac_pvt->interfacep; 1998 vlan = (gld_vlan_t *)gld->gld_vlan; 1999 2000 if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_TX) != 0) { 2001 freemsg(mp); 2002 #ifdef GLD_DEBUG 2003 if (gld_debug & GLDERRS) 2004 cmn_err(CE_WARN, 2005 "gld_start: failed to interpret outbound packet"); 2006 #endif 2007 vlan->gldv_stats->glds_xmtbadinterp++; 2008 return (GLD_BADARG); 2009 } 2010 2011 /* 2012 * We're not holding the lock for this check. If the promiscuous 2013 * state is in flux it doesn't matter much if we get this wrong. 2014 */ 2015 if (mac_pvt->nprom > 0) { 2016 /* 2017 * We want to loopback to the receive side, but to avoid 2018 * recursive lock entry: if we came from wput(), which 2019 * could have looped back via IP from our own receive 2020 * interrupt thread, we decline this request. wput() 2021 * will then queue the packet for wsrv(). This means 2022 * that when snoop is running we don't get the advantage 2023 * of the wput() multithreaded direct entry to the 2024 * driver's send routine. 2025 */ 2026 if (caller == GLD_WPUT) { 2027 (void) putbq(q, mp); 2028 return (GLD_NORESOURCES); 2029 } 2030 if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY) 2031 nmp = dupmsg_noloan(mp); 2032 else 2033 nmp = dupmsg(mp); 2034 } else 2035 nmp = NULL; /* we need no loopback */ 2036 2037 vtag = GLD_MK_VTAG(vlan->gldv_ptag, upri); 2038 if (ifp->hdr_size > 0 && 2039 pktinfo.pktLen > ifp->hdr_size + (vtag == 0 ? 0 : VTAG_SIZE) + 2040 macinfo->gldm_maxpkt) { 2041 freemsg(mp); /* discard oversized outbound packet */ 2042 if (nmp) 2043 freemsg(nmp); /* free the duped message */ 2044 #ifdef GLD_DEBUG 2045 if (gld_debug & GLDERRS) 2046 cmn_err(CE_WARN, 2047 "gld_start: oversize outbound packet, size %d," 2048 "max %d", pktinfo.pktLen, 2049 ifp->hdr_size + macinfo->gldm_maxpkt); 2050 #endif 2051 vlan->gldv_stats->glds_xmtbadinterp++; 2052 return (GLD_BADARG); 2053 } 2054 2055 rc = (*gld->gld_send)(macinfo, mp, vtag); 2056 2057 if (rc != GLD_SUCCESS) { 2058 if (rc == GLD_NORESOURCES) { 2059 vlan->gldv_stats->glds_xmtretry++; 2060 (void) putbq(q, mp); 2061 } else { 2062 /* transmit error; drop the packet */ 2063 freemsg(mp); 2064 /* We're supposed to count failed attempts as well */ 2065 UPDATE_STATS(vlan, pktinfo, 1); 2066 #ifdef GLD_DEBUG 2067 if (gld_debug & GLDERRS) 2068 cmn_err(CE_WARN, 2069 "gld_start: gldm_send failed %d", rc); 2070 #endif 2071 } 2072 if (nmp) 2073 freemsg(nmp); /* free the dupped message */ 2074 return (rc); 2075 } 2076 2077 UPDATE_STATS(vlan, pktinfo, 1); 2078 2079 /* 2080 * Loopback case. The message needs to be returned back on 2081 * the read side. This would silently fail if the dumpmsg fails 2082 * above. This is probably OK, if there is no memory to dup the 2083 * block, then there isn't much we could do anyway. 2084 */ 2085 if (nmp) { 2086 GLDM_LOCK(macinfo, RW_WRITER); 2087 gld_precv(macinfo, vlan, nmp); 2088 GLDM_UNLOCK(macinfo); 2089 } 2090 2091 return (GLD_SUCCESS); 2092 } 2093 2094 /* 2095 * With MDT V.2 a single message mp can have one header area and multiple 2096 * payload areas. A packet is described by dl_pkt_info, and each packet can 2097 * span multiple payload areas (currently with TCP, each packet will have one 2098 * header and at the most two payload areas). MACs might have a limit on the 2099 * number of payload segments (i.e. per packet scatter-gather limit), and 2100 * MDT V.2 has a way of specifying that with mdt_span_limit; the MAC driver 2101 * might also have a limit on the total number of payloads in a message, and 2102 * that is specified by mdt_max_pld. 2103 */ 2104 static int 2105 gld_start_mdt(queue_t *q, mblk_t *mp, int caller) 2106 { 2107 mblk_t *nextmp; 2108 gld_t *gld = (gld_t *)q->q_ptr; 2109 gld_mac_info_t *macinfo = gld->gld_mac_info; 2110 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 2111 int numpacks, mdtpacks; 2112 gld_interface_t *ifp = mac_pvt->interfacep; 2113 pktinfo_t pktinfo; 2114 gld_vlan_t *vlan = (gld_vlan_t *)gld->gld_vlan; 2115 boolean_t doloop = B_FALSE; 2116 multidata_t *dlmdp; 2117 pdescinfo_t pinfo; 2118 pdesc_t *dl_pkt; 2119 void *cookie; 2120 uint_t totLen = 0; 2121 2122 ASSERT(DB_TYPE(mp) == M_MULTIDATA); 2123 2124 /* 2125 * We're not holding the lock for this check. If the promiscuous 2126 * state is in flux it doesn't matter much if we get this wrong. 2127 */ 2128 if (mac_pvt->nprom > 0) { 2129 /* 2130 * We want to loopback to the receive side, but to avoid 2131 * recursive lock entry: if we came from wput(), which 2132 * could have looped back via IP from our own receive 2133 * interrupt thread, we decline this request. wput() 2134 * will then queue the packet for wsrv(). This means 2135 * that when snoop is running we don't get the advantage 2136 * of the wput() multithreaded direct entry to the 2137 * driver's send routine. 2138 */ 2139 if (caller == GLD_WPUT) { 2140 (void) putbq(q, mp); 2141 return (GLD_NORESOURCES); 2142 } 2143 doloop = B_TRUE; 2144 2145 /* 2146 * unlike the M_DATA case, we don't have to call 2147 * dupmsg_noloan here because mmd_transform 2148 * (called by gld_precv_mdt) will make a copy of 2149 * each dblk. 2150 */ 2151 } 2152 2153 while (mp != NULL) { 2154 /* 2155 * The lower layer driver only gets a single multidata 2156 * message; this also makes it easier to handle noresources. 2157 */ 2158 nextmp = mp->b_cont; 2159 mp->b_cont = NULL; 2160 2161 /* 2162 * Get number of packets in this message; if nothing 2163 * to transmit, go to next message. 2164 */ 2165 dlmdp = mmd_getmultidata(mp); 2166 if ((mdtpacks = (int)mmd_getcnt(dlmdp, NULL, NULL)) == 0) { 2167 freemsg(mp); 2168 mp = nextmp; 2169 continue; 2170 } 2171 2172 /* 2173 * Run interpreter to populate media specific pktinfo fields. 2174 * This collects per MDT message information like sap, 2175 * broad/multicast etc. 2176 */ 2177 (void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, &pktinfo, 2178 GLD_MDT_TX); 2179 2180 numpacks = (*macinfo->gldm_mdt_pre)(macinfo, mp, &cookie); 2181 2182 if (numpacks > 0) { 2183 /* 2184 * Driver indicates it can transmit at least 1, and 2185 * possibly all, packets in MDT message. 2186 */ 2187 int count = numpacks; 2188 2189 for (dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo); 2190 (dl_pkt != NULL); 2191 dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo)) { 2192 /* 2193 * Format this packet by adding link header and 2194 * adjusting pdescinfo to include it; get 2195 * packet length. 2196 */ 2197 (void) (*ifp->interpreter_mdt)(macinfo, NULL, 2198 &pinfo, &pktinfo, GLD_MDT_TXPKT); 2199 2200 totLen += pktinfo.pktLen; 2201 2202 /* 2203 * Loop back packet before handing to the 2204 * driver. 2205 */ 2206 if (doloop && 2207 mmd_adjpdesc(dl_pkt, &pinfo) != NULL) { 2208 GLDM_LOCK(macinfo, RW_WRITER); 2209 gld_precv_mdt(macinfo, vlan, mp, 2210 dl_pkt, &pktinfo); 2211 GLDM_UNLOCK(macinfo); 2212 } 2213 2214 /* 2215 * And send off to driver. 2216 */ 2217 (*macinfo->gldm_mdt_send)(macinfo, cookie, 2218 &pinfo); 2219 2220 /* 2221 * Be careful not to invoke getnextpdesc if we 2222 * already sent the last packet, since driver 2223 * might have posted it to hardware causing a 2224 * completion and freemsg() so the MDT data 2225 * structures might not be valid anymore. 2226 */ 2227 if (--count == 0) 2228 break; 2229 } 2230 (*macinfo->gldm_mdt_post)(macinfo, mp, cookie); 2231 pktinfo.pktLen = totLen; 2232 UPDATE_STATS(vlan, pktinfo, numpacks); 2233 2234 /* 2235 * In the noresources case (when driver indicates it 2236 * can not transmit all packets in the MDT message), 2237 * adjust to skip the first few packets on retrial. 2238 */ 2239 if (numpacks != mdtpacks) { 2240 /* 2241 * Release already processed packet descriptors. 2242 */ 2243 for (count = 0; count < numpacks; count++) { 2244 dl_pkt = mmd_getfirstpdesc(dlmdp, 2245 &pinfo); 2246 mmd_rempdesc(dl_pkt); 2247 } 2248 vlan->gldv_stats->glds_xmtretry++; 2249 mp->b_cont = nextmp; 2250 (void) putbq(q, mp); 2251 return (GLD_NORESOURCES); 2252 } 2253 } else if (numpacks == 0) { 2254 /* 2255 * Driver indicates it can not transmit any packets 2256 * currently and will request retrial later. 2257 */ 2258 vlan->gldv_stats->glds_xmtretry++; 2259 mp->b_cont = nextmp; 2260 (void) putbq(q, mp); 2261 return (GLD_NORESOURCES); 2262 } else { 2263 ASSERT(numpacks == -1); 2264 /* 2265 * We're supposed to count failed attempts as well. 2266 */ 2267 dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo); 2268 while (dl_pkt != NULL) { 2269 /* 2270 * Call interpreter to determine total packet 2271 * bytes that are being dropped. 2272 */ 2273 (void) (*ifp->interpreter_mdt)(macinfo, NULL, 2274 &pinfo, &pktinfo, GLD_MDT_TXPKT); 2275 2276 totLen += pktinfo.pktLen; 2277 2278 dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo); 2279 } 2280 pktinfo.pktLen = totLen; 2281 UPDATE_STATS(vlan, pktinfo, mdtpacks); 2282 2283 /* 2284 * Transmit error; drop the message, move on 2285 * to the next one. 2286 */ 2287 freemsg(mp); 2288 } 2289 2290 /* 2291 * Process the next multidata block, if there is one. 2292 */ 2293 mp = nextmp; 2294 } 2295 2296 return (GLD_SUCCESS); 2297 } 2298 2299 /* 2300 * gld_intr (macinfo) 2301 */ 2302 uint_t 2303 gld_intr(gld_mac_info_t *macinfo) 2304 { 2305 ASSERT(macinfo != NULL); 2306 2307 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) 2308 return (DDI_INTR_UNCLAIMED); 2309 2310 return ((*macinfo->gldm_intr)(macinfo)); 2311 } 2312 2313 /* 2314 * gld_sched (macinfo) 2315 * 2316 * This routine scans the streams that refer to a specific macinfo 2317 * structure and causes the STREAMS scheduler to try to run them if 2318 * they are marked as waiting for the transmit buffer. 2319 */ 2320 void 2321 gld_sched(gld_mac_info_t *macinfo) 2322 { 2323 gld_mac_pvt_t *mac_pvt; 2324 gld_t *gld; 2325 gld_vlan_t *vlan; 2326 int i; 2327 2328 ASSERT(macinfo != NULL); 2329 2330 GLDM_LOCK(macinfo, RW_WRITER); 2331 2332 if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) { 2333 /* We're probably being called from a leftover interrupt */ 2334 GLDM_UNLOCK(macinfo); 2335 return; 2336 } 2337 2338 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 2339 2340 for (i = 0; i < VLAN_HASHSZ; i++) { 2341 for (vlan = mac_pvt->vlan_hash[i]; 2342 vlan != NULL; vlan = vlan->gldv_next) { 2343 for (gld = vlan->gldv_str_next; 2344 gld != (gld_t *)&vlan->gldv_str_next; 2345 gld = gld->gld_next) { 2346 ASSERT(gld->gld_mac_info == macinfo); 2347 gld->gld_sched_ran = B_TRUE; 2348 membar_enter(); 2349 if (gld->gld_xwait) { 2350 gld->gld_xwait = B_FALSE; 2351 qenable(WR(gld->gld_qptr)); 2352 } 2353 } 2354 } 2355 } 2356 2357 GLDM_UNLOCK(macinfo); 2358 } 2359 2360 /* 2361 * gld_precv (macinfo, mp) 2362 * called from gld_start to loopback a packet when in promiscuous mode 2363 */ 2364 static void 2365 gld_precv(gld_mac_info_t *macinfo, gld_vlan_t *vlan, mblk_t *mp) 2366 { 2367 gld_mac_pvt_t *mac_pvt; 2368 gld_interface_t *ifp; 2369 pktinfo_t pktinfo; 2370 2371 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 2372 2373 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 2374 ifp = mac_pvt->interfacep; 2375 2376 /* 2377 * call the media specific packet interpreter routine 2378 */ 2379 if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RXLOOP) != 0) { 2380 freemsg(mp); 2381 BUMP(vlan->gldv_stats->glds_rcvbadinterp, 1); 2382 #ifdef GLD_DEBUG 2383 if (gld_debug & GLDERRS) 2384 cmn_err(CE_WARN, 2385 "gld_precv: interpreter failed"); 2386 #endif 2387 return; 2388 } 2389 2390 gld_sendup(macinfo, vlan, &pktinfo, mp, gld_paccept); 2391 } 2392 2393 /* 2394 * called from gld_start_mdt to loopback packet(s) when in promiscuous mode 2395 */ 2396 static void 2397 gld_precv_mdt(gld_mac_info_t *macinfo, gld_vlan_t *vlan, mblk_t *mp, 2398 pdesc_t *dl_pkt, pktinfo_t *pktinfo) 2399 { 2400 mblk_t *adjmp; 2401 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 2402 gld_interface_t *ifp = mac_pvt->interfacep; 2403 2404 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 2405 2406 /* 2407 * Get source/destination. 2408 */ 2409 (void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, pktinfo, 2410 GLD_MDT_RXLOOP); 2411 if ((adjmp = mmd_transform(dl_pkt)) != NULL) 2412 gld_sendup(macinfo, vlan, pktinfo, adjmp, gld_paccept); 2413 } 2414 2415 /* 2416 * gld_recv (macinfo, mp) 2417 * called with an mac-level packet in a mblock; take the maclock, 2418 * try the ip4q and ip6q hack, and otherwise call gld_sendup. 2419 * 2420 * V0 drivers already are holding the mutex when they call us. 2421 */ 2422 void 2423 gld_recv(gld_mac_info_t *macinfo, mblk_t *mp) 2424 { 2425 gld_recv_tagged(macinfo, mp, VLAN_VTAG_NONE); 2426 } 2427 2428 void 2429 gld_recv_tagged(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag) 2430 { 2431 gld_mac_pvt_t *mac_pvt; 2432 char pbuf[3*GLD_MAX_ADDRLEN]; 2433 pktinfo_t pktinfo; 2434 gld_interface_t *ifp; 2435 queue_t *ipq = NULL; 2436 gld_vlan_t *vlan; 2437 uint32_t vid; 2438 2439 ASSERT(macinfo != NULL); 2440 ASSERT(mp->b_datap->db_ref); 2441 2442 GLDM_LOCK(macinfo, RW_READER); 2443 2444 if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) { 2445 /* We're probably being called from a leftover interrupt */ 2446 freemsg(mp); 2447 goto done; 2448 } 2449 2450 vid = GLD_VTAG_VID(vtag); 2451 if ((vlan = gld_find_vlan(macinfo, vid)) == NULL) { 2452 freemsg(mp); 2453 goto done; 2454 } 2455 2456 /* 2457 * Check whether underlying media code supports the IPQ hack, 2458 * and if so, whether the interpreter can quickly parse the 2459 * packet to get some relevant parameters. 2460 */ 2461 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 2462 ifp = mac_pvt->interfacep; 2463 if (((*ifp->interpreter)(macinfo, mp, &pktinfo, 2464 GLD_RXQUICK) == 0) && (vlan->gldv_ipq_flags == 0)) { 2465 switch (pktinfo.ethertype) { 2466 case ETHERTYPE_IP: 2467 ipq = vlan->gldv_ipq; 2468 break; 2469 case ETHERTYPE_IPV6: 2470 ipq = vlan->gldv_ipv6q; 2471 break; 2472 } 2473 } 2474 2475 BUMP(vlan->gldv_stats->glds_bytercv64, pktinfo.pktLen); 2476 BUMP(vlan->gldv_stats->glds_pktrcv64, 1); 2477 2478 /* 2479 * Special case for IP; we can simply do the putnext here, if: 2480 * o ipq != NULL, and therefore: 2481 * - the device type supports IPQ (ethernet and IPoIB); 2482 * - the interpreter could quickly parse the packet; 2483 * - there are no PROMISC_SAP streams (on this VLAN); 2484 * - there is one, and only one, IP stream bound (to this VLAN); 2485 * - that stream is a "fastpath" stream; 2486 * - the packet is of type ETHERTYPE_IP or ETHERTYPE_IPV6 2487 * 2488 * o the packet is specifically for me, and therefore: 2489 * - the packet is not multicast or broadcast (fastpath only 2490 * wants unicast packets). 2491 * 2492 * o the stream is not asserting flow control. 2493 */ 2494 if (ipq != NULL && 2495 pktinfo.isForMe && 2496 canputnext(ipq)) { 2497 /* 2498 * Skip the mac header. We know there is no LLC1/SNAP header 2499 * in this packet 2500 */ 2501 mp->b_rptr += pktinfo.macLen; 2502 putnext(ipq, mp); 2503 goto done; 2504 } 2505 2506 /* 2507 * call the media specific packet interpreter routine 2508 */ 2509 if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RX) != 0) { 2510 BUMP(vlan->gldv_stats->glds_rcvbadinterp, 1); 2511 #ifdef GLD_DEBUG 2512 if (gld_debug & GLDERRS) 2513 cmn_err(CE_WARN, 2514 "gld_recv_tagged: interpreter failed"); 2515 #endif 2516 freemsg(mp); 2517 goto done; 2518 } 2519 2520 /* 2521 * This is safe even if vtag is VLAN_VTAG_NONE 2522 */ 2523 2524 pktinfo.vid = vid; 2525 pktinfo.cfi = GLD_VTAG_CFI(vtag); 2526 #ifdef GLD_DEBUG 2527 if (pktinfo.cfi != VLAN_CFI_ETHER) 2528 cmn_err(CE_WARN, "gld_recv_tagged: non-ETHER CFI"); 2529 #endif 2530 pktinfo.user_pri = GLD_VTAG_PRI(vtag); 2531 2532 #ifdef GLD_DEBUG 2533 if ((gld_debug & GLDRECV) && 2534 (!(gld_debug & GLDNOBR) || 2535 (!pktinfo.isBroadcast && !pktinfo.isMulticast))) { 2536 char pbuf2[3*GLD_MAX_ADDRLEN]; 2537 2538 cmn_err(CE_CONT, "gld_recv_tagged: machdr=<%s -> %s>\n", 2539 gld_macaddr_sprintf(pbuf, pktinfo.shost, 2540 macinfo->gldm_addrlen), gld_macaddr_sprintf(pbuf2, 2541 pktinfo.dhost, macinfo->gldm_addrlen)); 2542 cmn_err(CE_CONT, "gld_recv_tagged: VlanId %d UserPri %d\n", 2543 pktinfo.vid, 2544 pktinfo.user_pri); 2545 cmn_err(CE_CONT, "gld_recv_tagged: ethertype: %4x Len: %4d " 2546 "Hdr: %d,%d isMulticast: %s\n", 2547 pktinfo.ethertype, 2548 pktinfo.pktLen, 2549 pktinfo.macLen, 2550 pktinfo.hdrLen, 2551 pktinfo.isMulticast ? "Y" : "N"); 2552 } 2553 #endif 2554 2555 gld_sendup(macinfo, vlan, &pktinfo, mp, gld_accept); 2556 2557 done: 2558 GLDM_UNLOCK(macinfo); 2559 } 2560 2561 /* =================================================================== */ 2562 /* receive group: called from gld_recv and gld_precv* with maclock held */ 2563 /* =================================================================== */ 2564 2565 /* 2566 * gld_sendup (macinfo, mp) 2567 * called with an ethernet packet in a mblock; must decide whether 2568 * packet is for us and which streams to queue it to. 2569 */ 2570 static void 2571 gld_sendup(gld_mac_info_t *macinfo, gld_vlan_t *vlan, pktinfo_t *pktinfo, 2572 mblk_t *mp, int (*acceptfunc)()) 2573 { 2574 gld_t *gld; 2575 gld_t *fgld = NULL; 2576 mblk_t *nmp; 2577 void (*send)(queue_t *qp, mblk_t *mp); 2578 int (*cansend)(queue_t *qp); 2579 2580 #ifdef GLD_DEBUG 2581 if (gld_debug & GLDTRACE) 2582 cmn_err(CE_NOTE, "gld_sendup(%p, %p)", (void *)mp, 2583 (void *)macinfo); 2584 #endif 2585 2586 ASSERT(mp != NULL); 2587 ASSERT(macinfo != NULL); 2588 ASSERT(vlan != NULL); 2589 ASSERT(pktinfo != NULL); 2590 ASSERT(GLDM_LOCK_HELD(macinfo)); 2591 2592 /* 2593 * The "fast" in "GLDOPT_FAST_RECV" refers to the speed at which 2594 * gld_recv returns to the caller's interrupt routine. The total 2595 * network throughput would normally be lower when selecting this 2596 * option, because we putq the messages and process them later, 2597 * instead of sending them with putnext now. Some time critical 2598 * device might need this, so it's here but undocumented. 2599 */ 2600 if (macinfo->gldm_options & GLDOPT_FAST_RECV) { 2601 send = (void (*)(queue_t *, mblk_t *))putq; 2602 cansend = canput; 2603 } else { 2604 send = (void (*)(queue_t *, mblk_t *))putnext; 2605 cansend = canputnext; 2606 } 2607 2608 /* 2609 * Search all the streams attached to this macinfo looking for 2610 * those eligible to receive the present packet. 2611 */ 2612 for (gld = vlan->gldv_str_next; 2613 gld != (gld_t *)&vlan->gldv_str_next; gld = gld->gld_next) { 2614 #ifdef GLD_VERBOSE_DEBUG 2615 cmn_err(CE_NOTE, "gld_sendup: SAP: %4x QPTR: %p QSTATE: %s", 2616 gld->gld_sap, (void *)gld->gld_qptr, 2617 gld->gld_state == DL_IDLE ? "IDLE": "NOT IDLE"); 2618 #endif 2619 ASSERT(gld->gld_qptr != NULL); 2620 ASSERT(gld->gld_state == DL_IDLE || 2621 gld->gld_state == DL_UNBOUND); 2622 ASSERT(gld->gld_mac_info == macinfo); 2623 ASSERT(gld->gld_vlan == vlan); 2624 2625 if (gld->gld_state != DL_IDLE) 2626 continue; /* not eligible to receive */ 2627 if (gld->gld_flags & GLD_STR_CLOSING) 2628 continue; /* not eligible to receive */ 2629 2630 #ifdef GLD_DEBUG 2631 if ((gld_debug & GLDRECV) && 2632 (!(gld_debug & GLDNOBR) || 2633 (!pktinfo->isBroadcast && !pktinfo->isMulticast))) 2634 cmn_err(CE_NOTE, 2635 "gld_sendup: queue sap: %4x promis: %s %s %s", 2636 gld->gld_sap, 2637 gld->gld_flags & GLD_PROM_PHYS ? "phys " : " ", 2638 gld->gld_flags & GLD_PROM_SAP ? "sap " : " ", 2639 gld->gld_flags & GLD_PROM_MULT ? "multi" : " "); 2640 #endif 2641 2642 /* 2643 * The accept function differs depending on whether this is 2644 * a packet that we received from the wire or a loopback. 2645 */ 2646 if ((*acceptfunc)(gld, pktinfo)) { 2647 /* sap matches */ 2648 pktinfo->wasAccepted = 1; /* known protocol */ 2649 2650 if (!(*cansend)(gld->gld_qptr)) { 2651 /* 2652 * Upper stream is not accepting messages, i.e. 2653 * it is flow controlled, therefore we will 2654 * forgo sending the message up this stream. 2655 */ 2656 #ifdef GLD_DEBUG 2657 if (gld_debug & GLDETRACE) 2658 cmn_err(CE_WARN, 2659 "gld_sendup: canput failed"); 2660 #endif 2661 BUMP(vlan->gldv_stats->glds_blocked, 1); 2662 qenable(gld->gld_qptr); 2663 continue; 2664 } 2665 2666 /* 2667 * we are trying to avoid an extra dumpmsg() here. 2668 * If this is the first eligible queue, remember the 2669 * queue and send up the message after the loop. 2670 */ 2671 if (!fgld) { 2672 fgld = gld; 2673 continue; 2674 } 2675 2676 /* duplicate the packet for this stream */ 2677 nmp = dupmsg(mp); 2678 if (nmp == NULL) { 2679 BUMP(vlan->gldv_stats->glds_gldnorcvbuf, 1); 2680 #ifdef GLD_DEBUG 2681 if (gld_debug & GLDERRS) 2682 cmn_err(CE_WARN, 2683 "gld_sendup: dupmsg failed"); 2684 #endif 2685 break; /* couldn't get resources; drop it */ 2686 } 2687 /* pass the message up the stream */ 2688 gld_passon(gld, nmp, pktinfo, send); 2689 } 2690 } 2691 2692 ASSERT(mp); 2693 /* send the original dup of the packet up the first stream found */ 2694 if (fgld) 2695 gld_passon(fgld, mp, pktinfo, send); 2696 else 2697 freemsg(mp); /* no streams matched */ 2698 2699 /* We do not count looped back packets */ 2700 if (acceptfunc == gld_paccept) 2701 return; /* transmit loopback case */ 2702 2703 if (pktinfo->isBroadcast) 2704 BUMP(vlan->gldv_stats->glds_brdcstrcv, 1); 2705 else if (pktinfo->isMulticast) 2706 BUMP(vlan->gldv_stats->glds_multircv, 1); 2707 2708 /* No stream accepted this packet */ 2709 if (!pktinfo->wasAccepted) 2710 BUMP(vlan->gldv_stats->glds_unknowns, 1); 2711 } 2712 2713 /* 2714 * A packet matches a stream if: 2715 * the stream accepts EtherType encoded packets and the type matches 2716 * or the stream accepts LLC packets and the packet is an LLC packet 2717 */ 2718 #define MATCH(stream, pktinfo) \ 2719 ((stream->gld_ethertype && stream->gld_sap == pktinfo->ethertype) || \ 2720 (!stream->gld_ethertype && pktinfo->isLLC)) 2721 2722 /* 2723 * This function validates a packet for sending up a particular 2724 * stream. The message header has been parsed and its characteristic 2725 * are recorded in the pktinfo data structure. The streams stack info 2726 * are presented in gld data structures. 2727 */ 2728 static int 2729 gld_accept(gld_t *gld, pktinfo_t *pktinfo) 2730 { 2731 /* 2732 * if there is no match do not bother checking further. 2733 */ 2734 if (!MATCH(gld, pktinfo) && !(gld->gld_flags & GLD_PROM_SAP)) 2735 return (0); 2736 2737 /* 2738 * We don't accept any packet from the hardware if we originated it. 2739 * (Contrast gld_paccept, the send-loopback accept function.) 2740 */ 2741 if (pktinfo->isLooped) 2742 return (0); 2743 2744 /* 2745 * If the packet is broadcast or sent to us directly we will accept it. 2746 * Also we will accept multicast packets requested by the stream. 2747 */ 2748 if (pktinfo->isForMe || pktinfo->isBroadcast || 2749 gld_mcmatch(gld, pktinfo)) 2750 return (1); 2751 2752 /* 2753 * Finally, accept anything else if we're in promiscuous mode 2754 */ 2755 if (gld->gld_flags & GLD_PROM_PHYS) 2756 return (1); 2757 2758 return (0); 2759 } 2760 2761 /* 2762 * Return TRUE if the given multicast address is one 2763 * of those that this particular Stream is interested in. 2764 */ 2765 static int 2766 gld_mcmatch(gld_t *gld, pktinfo_t *pktinfo) 2767 { 2768 /* 2769 * Return FALSE if not a multicast address. 2770 */ 2771 if (!pktinfo->isMulticast) 2772 return (0); 2773 2774 /* 2775 * Check if all multicasts have been enabled for this Stream 2776 */ 2777 if (gld->gld_flags & GLD_PROM_MULT) 2778 return (1); 2779 2780 /* 2781 * Return FALSE if no multicast addresses enabled for this Stream. 2782 */ 2783 if (!gld->gld_mcast) 2784 return (0); 2785 2786 /* 2787 * Otherwise, look for it in the table. 2788 */ 2789 return (gld_multicast(pktinfo->dhost, gld)); 2790 } 2791 2792 /* 2793 * gld_multicast determines if the address is a multicast address for 2794 * this stream. 2795 */ 2796 static int 2797 gld_multicast(unsigned char *macaddr, gld_t *gld) 2798 { 2799 int i; 2800 2801 ASSERT(GLDM_LOCK_HELD(gld->gld_mac_info)); 2802 2803 if (!gld->gld_mcast) 2804 return (0); 2805 2806 for (i = 0; i < gld->gld_multicnt; i++) { 2807 if (gld->gld_mcast[i]) { 2808 ASSERT(gld->gld_mcast[i]->gldm_refcnt); 2809 if (mac_eq(gld->gld_mcast[i]->gldm_addr, macaddr, 2810 gld->gld_mac_info->gldm_addrlen)) 2811 return (1); 2812 } 2813 } 2814 2815 return (0); 2816 } 2817 2818 /* 2819 * accept function for looped back packets 2820 */ 2821 static int 2822 gld_paccept(gld_t *gld, pktinfo_t *pktinfo) 2823 { 2824 return (gld->gld_flags & GLD_PROM_PHYS && 2825 (MATCH(gld, pktinfo) || gld->gld_flags & GLD_PROM_SAP)); 2826 } 2827 2828 static void 2829 gld_passon(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo, 2830 void (*send)(queue_t *qp, mblk_t *mp)) 2831 { 2832 int skiplen; 2833 2834 #ifdef GLD_DEBUG 2835 if (gld_debug & GLDTRACE) 2836 cmn_err(CE_NOTE, "gld_passon(%p, %p, %p)", (void *)gld, 2837 (void *)mp, (void *)pktinfo); 2838 2839 if ((gld_debug & GLDRECV) && (!(gld_debug & GLDNOBR) || 2840 (!pktinfo->isBroadcast && !pktinfo->isMulticast))) 2841 cmn_err(CE_NOTE, "gld_passon: q: %p mblk: %p minor: %d sap: %x", 2842 (void *)gld->gld_qptr->q_next, (void *)mp, gld->gld_minor, 2843 gld->gld_sap); 2844 #endif 2845 2846 /* 2847 * Figure out how much of the packet header to throw away. 2848 * 2849 * RAW streams expect to see the whole packet. 2850 * 2851 * Other streams expect to see the packet with the MAC header 2852 * removed. 2853 * 2854 * Normal DLPI (non RAW/FAST) streams also want the 2855 * DL_UNITDATA_IND M_PROTO message block prepended to the M_DATA. 2856 */ 2857 if (gld->gld_flags & GLD_RAW) { 2858 skiplen = 0; 2859 } else { 2860 skiplen = pktinfo->macLen; /* skip mac header */ 2861 if (gld->gld_ethertype) 2862 skiplen += pktinfo->hdrLen; /* skip any extra */ 2863 } 2864 2865 if (skiplen >= pktinfo->pktLen) { 2866 /* 2867 * If the interpreter did its job right, then it cannot be 2868 * asking us to skip more bytes than are in the packet! 2869 * However, there could be zero data bytes left after the 2870 * amount to skip. DLPI specifies that passed M_DATA blocks 2871 * should contain at least one byte of data, so if we have 2872 * none we just drop it. 2873 */ 2874 ASSERT(!(skiplen > pktinfo->pktLen)); 2875 freemsg(mp); 2876 return; 2877 } 2878 2879 /* 2880 * Skip over the header(s), taking care to possibly handle message 2881 * fragments shorter than the amount we need to skip. Hopefully 2882 * the driver will put the entire packet, or at least the entire 2883 * header, into a single message block. But we handle it if not. 2884 */ 2885 while (skiplen >= MBLKL(mp)) { 2886 mblk_t *tmp = mp; 2887 skiplen -= MBLKL(mp); 2888 mp = mp->b_cont; 2889 ASSERT(mp != NULL); /* because skiplen < pktinfo->pktLen */ 2890 freeb(tmp); 2891 } 2892 mp->b_rptr += skiplen; 2893 2894 /* Add M_PROTO if necessary, and pass upstream */ 2895 if (((gld->gld_flags & GLD_FAST) && !pktinfo->isMulticast && 2896 !pktinfo->isBroadcast) || (gld->gld_flags & GLD_RAW)) { 2897 /* RAW/FAST: just send up the M_DATA */ 2898 (*send)(gld->gld_qptr, mp); 2899 } else { 2900 /* everybody else wants to see a unitdata_ind structure */ 2901 mp = gld_addudind(gld, mp, pktinfo); 2902 if (mp) 2903 (*send)(gld->gld_qptr, mp); 2904 /* if it failed, gld_addudind already bumped statistic */ 2905 } 2906 } 2907 2908 /* 2909 * gld_addudind(gld, mp, pktinfo) 2910 * format a DL_UNITDATA_IND message to be sent upstream to the user 2911 */ 2912 static mblk_t * 2913 gld_addudind(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo) 2914 { 2915 gld_mac_info_t *macinfo = gld->gld_mac_info; 2916 gld_vlan_t *vlan = (gld_vlan_t *)gld->gld_vlan; 2917 dl_unitdata_ind_t *dludindp; 2918 mblk_t *nmp; 2919 int size; 2920 int type; 2921 2922 #ifdef GLD_DEBUG 2923 if (gld_debug & GLDTRACE) 2924 cmn_err(CE_NOTE, "gld_addudind(%p, %p, %p)", (void *)gld, 2925 (void *)mp, (void *)pktinfo); 2926 #endif 2927 ASSERT(macinfo != NULL); 2928 2929 /* 2930 * Allocate the DL_UNITDATA_IND M_PROTO header, if allocation fails 2931 * might as well discard since we can't go further 2932 */ 2933 size = sizeof (dl_unitdata_ind_t) + 2934 2 * (macinfo->gldm_addrlen + abs(macinfo->gldm_saplen)); 2935 if ((nmp = allocb(size, BPRI_MED)) == NULL) { 2936 freemsg(mp); 2937 BUMP(vlan->gldv_stats->glds_gldnorcvbuf, 1); 2938 #ifdef GLD_DEBUG 2939 if (gld_debug & GLDERRS) 2940 cmn_err(CE_WARN, 2941 "gld_addudind: allocb failed"); 2942 #endif 2943 return ((mblk_t *)NULL); 2944 } 2945 DB_TYPE(nmp) = M_PROTO; 2946 nmp->b_rptr = nmp->b_datap->db_lim - size; 2947 2948 type = (gld->gld_ethertype) ? pktinfo->ethertype : 0; 2949 2950 /* 2951 * now setup the DL_UNITDATA_IND header 2952 * 2953 * XXX This looks broken if the saps aren't two bytes. 2954 */ 2955 dludindp = (dl_unitdata_ind_t *)nmp->b_rptr; 2956 dludindp->dl_primitive = DL_UNITDATA_IND; 2957 dludindp->dl_src_addr_length = 2958 dludindp->dl_dest_addr_length = macinfo->gldm_addrlen + 2959 abs(macinfo->gldm_saplen); 2960 dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t); 2961 dludindp->dl_src_addr_offset = dludindp->dl_dest_addr_offset + 2962 dludindp->dl_dest_addr_length; 2963 2964 dludindp->dl_group_address = (pktinfo->isMulticast || 2965 pktinfo->isBroadcast); 2966 2967 nmp->b_wptr = nmp->b_rptr + dludindp->dl_dest_addr_offset; 2968 2969 mac_copy(pktinfo->dhost, nmp->b_wptr, macinfo->gldm_addrlen); 2970 nmp->b_wptr += macinfo->gldm_addrlen; 2971 2972 ASSERT(macinfo->gldm_saplen == -2); /* XXX following code assumes */ 2973 *(ushort_t *)(nmp->b_wptr) = type; 2974 nmp->b_wptr += abs(macinfo->gldm_saplen); 2975 2976 ASSERT(nmp->b_wptr == nmp->b_rptr + dludindp->dl_src_addr_offset); 2977 2978 mac_copy(pktinfo->shost, nmp->b_wptr, macinfo->gldm_addrlen); 2979 nmp->b_wptr += macinfo->gldm_addrlen; 2980 2981 *(ushort_t *)(nmp->b_wptr) = type; 2982 nmp->b_wptr += abs(macinfo->gldm_saplen); 2983 2984 if (pktinfo->nosource) 2985 dludindp->dl_src_addr_offset = dludindp->dl_src_addr_length = 0; 2986 linkb(nmp, mp); 2987 return (nmp); 2988 } 2989 2990 /* ======================================================= */ 2991 /* wsrv group: called from wsrv, single threaded per queue */ 2992 /* ======================================================= */ 2993 2994 /* 2995 * We go to some trouble to avoid taking the same lock during normal 2996 * transmit processing as we do during normal receive processing. 2997 * 2998 * Elements of the per-instance macinfo and per-stream gld_t structures 2999 * are for the most part protected by the GLDM_LOCK rwlock/mutex. 3000 * (Elements of the gld_mac_pvt_t structure are considered part of the 3001 * macinfo structure for purposes of this discussion). 3002 * 3003 * However, it is more complicated than that: 3004 * 3005 * Elements of the macinfo structure that are set before the macinfo 3006 * structure is added to its device list by gld_register(), and never 3007 * thereafter modified, are accessed without requiring taking the lock. 3008 * A similar rule applies to those elements of the gld_t structure that 3009 * are written by gld_open() before the stream is added to any list. 3010 * 3011 * Most other elements of the macinfo structure may only be read or 3012 * written while holding the maclock. 3013 * 3014 * Most writable elements of the gld_t structure are written only 3015 * within the single-threaded domain of wsrv() and subsidiaries. 3016 * (This domain includes open/close while qprocs are not on.) 3017 * The maclock need not be taken while within that domain 3018 * simply to read those elements. Writing to them, even within 3019 * that domain, or reading from it outside that domain, requires 3020 * holding the maclock. Exception: if the stream is not 3021 * presently attached to a PPA, there is no associated macinfo, 3022 * and no maclock need be taken. 3023 * 3024 * The curr_macaddr element of the mac private structure is also 3025 * protected by the GLDM_LOCK rwlock/mutex, like most other members 3026 * of that structure. However, there are a few instances in the 3027 * transmit path where we choose to forgo lock protection when 3028 * reading this variable. This is to avoid lock contention between 3029 * threads executing the DL_UNITDATA_REQ case and receive threads. 3030 * In doing so we will take a small risk or a few corrupted packets 3031 * during the short an rare times when someone is changing the interface's 3032 * physical address. We consider the small cost in this rare case to be 3033 * worth the benefit of reduced lock contention under normal operating 3034 * conditions. The risk/cost is small because: 3035 * 1. there is no guarantee at this layer of uncorrupted delivery. 3036 * 2. the physaddr doesn't change very often - no performance hit. 3037 * 3. if the physaddr changes, other stuff is going to be screwed 3038 * up for a while anyway, while other sites refigure ARP, etc., 3039 * so losing a couple of packets is the least of our worries. 3040 * 3041 * The list of streams associated with a macinfo is protected by 3042 * two locks: the per-macinfo maclock, and the per-major-device 3043 * gld_devlock. Both must be held to modify the list, but either 3044 * may be held to protect the list during reading/traversing. This 3045 * allows independent locking for multiple instances in the receive 3046 * path (using macinfo), while facilitating routines that must search 3047 * the entire set of streams associated with a major device, such as 3048 * gld_findminor(), gld_finddevinfo(), close(). The "nstreams" 3049 * macinfo element, and the gld_mac_info gld_t element, are similarly 3050 * protected, since they change at exactly the same time macinfo 3051 * streams list does. 3052 * 3053 * The list of macinfo structures associated with a major device 3054 * structure is protected by the gld_devlock, as is the per-major 3055 * list of Style 2 streams in the DL_UNATTACHED state. 3056 * 3057 * The list of major devices is kept on a module-global list 3058 * gld_device_list, which has its own lock to protect the list. 3059 * 3060 * When it is necessary to hold more than one lock at a time, they 3061 * are acquired in this "outside in" order: 3062 * gld_device_list.gld_devlock 3063 * glddev->gld_devlock 3064 * GLDM_LOCK(macinfo) 3065 * 3066 * Finally, there are some "volatile" elements of the gld_t structure 3067 * used for synchronization between various routines that don't share 3068 * the same mutexes. See the routines for details. These are: 3069 * gld_xwait between gld_wsrv() and gld_sched() 3070 * gld_sched_ran between gld_wsrv() and gld_sched() 3071 * gld_in_unbind between gld_wput() and wsrv's gld_unbind() 3072 * gld_wput_count between gld_wput() and wsrv's gld_unbind() 3073 * gld_in_wsrv between gld_wput() and gld_wsrv() 3074 * (used in conjunction with q->q_first) 3075 */ 3076 3077 /* 3078 * gld_ioctl (q, mp) 3079 * handles all ioctl requests passed downstream. This routine is 3080 * passed a pointer to the message block with the ioctl request in it, and a 3081 * pointer to the queue so it can respond to the ioctl request with an ack. 3082 */ 3083 int 3084 gld_ioctl(queue_t *q, mblk_t *mp) 3085 { 3086 struct iocblk *iocp; 3087 gld_t *gld; 3088 gld_mac_info_t *macinfo; 3089 3090 #ifdef GLD_DEBUG 3091 if (gld_debug & GLDTRACE) 3092 cmn_err(CE_NOTE, "gld_ioctl(%p %p)", (void *)q, (void *)mp); 3093 #endif 3094 gld = (gld_t *)q->q_ptr; 3095 iocp = (struct iocblk *)mp->b_rptr; 3096 switch (iocp->ioc_cmd) { 3097 case DLIOCRAW: /* raw M_DATA mode */ 3098 gld->gld_flags |= GLD_RAW; 3099 DB_TYPE(mp) = M_IOCACK; 3100 qreply(q, mp); 3101 break; 3102 3103 case DL_IOC_HDR_INFO: /* fastpath */ 3104 if (gld_global_options & GLD_OPT_NO_FASTPATH) { 3105 miocnak(q, mp, 0, EINVAL); 3106 break; 3107 } 3108 gld_fastpath(gld, q, mp); 3109 break; 3110 3111 default: 3112 macinfo = gld->gld_mac_info; 3113 if (macinfo == NULL || macinfo->gldm_ioctl == NULL) { 3114 miocnak(q, mp, 0, EINVAL); 3115 break; 3116 } 3117 3118 GLDM_LOCK(macinfo, RW_WRITER); 3119 (void) (*macinfo->gldm_ioctl) (macinfo, q, mp); 3120 GLDM_UNLOCK(macinfo); 3121 break; 3122 } 3123 return (0); 3124 } 3125 3126 /* 3127 * Since the rules for "fastpath" mode don't seem to be documented 3128 * anywhere, I will describe GLD's rules for fastpath users here: 3129 * 3130 * Once in this mode you remain there until close. 3131 * If you unbind/rebind you should get a new header using DL_IOC_HDR_INFO. 3132 * You must be bound (DL_IDLE) to transmit. 3133 * There are other rules not listed above. 3134 */ 3135 static void 3136 gld_fastpath(gld_t *gld, queue_t *q, mblk_t *mp) 3137 { 3138 gld_interface_t *ifp; 3139 gld_mac_info_t *macinfo; 3140 dl_unitdata_req_t *dludp; 3141 mblk_t *nmp; 3142 t_scalar_t off, len; 3143 uint_t maclen; 3144 int error; 3145 gld_vlan_t *vlan; 3146 3147 if (gld->gld_state != DL_IDLE) { 3148 miocnak(q, mp, 0, EINVAL); 3149 return; 3150 } 3151 3152 macinfo = gld->gld_mac_info; 3153 ASSERT(macinfo != NULL); 3154 maclen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen); 3155 3156 error = miocpullup(mp, sizeof (dl_unitdata_req_t) + maclen); 3157 if (error != 0) { 3158 miocnak(q, mp, 0, error); 3159 return; 3160 } 3161 3162 dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr; 3163 off = dludp->dl_dest_addr_offset; 3164 len = dludp->dl_dest_addr_length; 3165 if (dludp->dl_primitive != DL_UNITDATA_REQ || 3166 !MBLKIN(mp->b_cont, off, len) || len != maclen) { 3167 miocnak(q, mp, 0, EINVAL); 3168 return; 3169 } 3170 3171 /* 3172 * We take his fastpath request as a declaration that he will accept 3173 * M_DATA messages from us, whether or not we are willing to accept 3174 * them from him. This allows us to have fastpath in one direction 3175 * (flow upstream) even on media with Source Routing, where we are 3176 * unable to provide a fixed MAC header to be prepended to downstream 3177 * flowing packets. So we set GLD_FAST whether or not we decide to 3178 * allow him to send M_DATA down to us. 3179 */ 3180 GLDM_LOCK(macinfo, RW_WRITER); 3181 gld->gld_flags |= GLD_FAST; 3182 vlan = (gld_vlan_t *)gld->gld_vlan; 3183 vlan->gldv_ipq_flags &= ~IPQ_DISABLED; 3184 GLDM_UNLOCK(macinfo); 3185 3186 ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep; 3187 3188 /* This will fail for Source Routing media */ 3189 /* Also on Ethernet on 802.2 SAPs */ 3190 if ((nmp = (*ifp->mkfastpath)(gld, mp)) == NULL) { 3191 miocnak(q, mp, 0, ENOMEM); 3192 return; 3193 } 3194 3195 /* 3196 * Link new mblk in after the "request" mblks. 3197 */ 3198 linkb(mp, nmp); 3199 miocack(q, mp, msgdsize(mp->b_cont), 0); 3200 } 3201 3202 /* 3203 * gld_cmds (q, mp) 3204 * process the DL commands as defined in dlpi.h 3205 * note that the primitives return status which is passed back 3206 * to the service procedure. If the value is GLDE_RETRY, then 3207 * it is assumed that processing must stop and the primitive has 3208 * been put back onto the queue. If the value is any other error, 3209 * then an error ack is generated by the service procedure. 3210 */ 3211 static int 3212 gld_cmds(queue_t *q, mblk_t *mp) 3213 { 3214 union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr; 3215 gld_t *gld = (gld_t *)(q->q_ptr); 3216 int result = DL_BADPRIM; 3217 int mblkl = MBLKL(mp); 3218 t_uscalar_t dlreq; 3219 3220 /* Make sure we have at least dlp->dl_primitive */ 3221 if (mblkl < sizeof (dlp->dl_primitive)) 3222 return (DL_BADPRIM); 3223 3224 dlreq = dlp->dl_primitive; 3225 #ifdef GLD_DEBUG 3226 if (gld_debug & GLDTRACE) 3227 cmn_err(CE_NOTE, 3228 "gld_cmds(%p, %p):dlp=%p, dlp->dl_primitive=%d", 3229 (void *)q, (void *)mp, (void *)dlp, dlreq); 3230 #endif 3231 3232 switch (dlreq) { 3233 case DL_UDQOS_REQ: 3234 if (mblkl < DL_UDQOS_REQ_SIZE) 3235 break; 3236 result = gld_udqos(q, mp); 3237 break; 3238 3239 case DL_BIND_REQ: 3240 if (mblkl < DL_BIND_REQ_SIZE) 3241 break; 3242 result = gld_bind(q, mp); 3243 break; 3244 3245 case DL_UNBIND_REQ: 3246 if (mblkl < DL_UNBIND_REQ_SIZE) 3247 break; 3248 result = gld_unbind(q, mp); 3249 break; 3250 3251 case DL_UNITDATA_REQ: 3252 if (mblkl < DL_UNITDATA_REQ_SIZE) 3253 break; 3254 result = gld_unitdata(q, mp); 3255 break; 3256 3257 case DL_INFO_REQ: 3258 if (mblkl < DL_INFO_REQ_SIZE) 3259 break; 3260 result = gld_inforeq(q, mp); 3261 break; 3262 3263 case DL_ATTACH_REQ: 3264 if (mblkl < DL_ATTACH_REQ_SIZE) 3265 break; 3266 if (gld->gld_style == DL_STYLE2) 3267 result = gldattach(q, mp); 3268 else 3269 result = DL_NOTSUPPORTED; 3270 break; 3271 3272 case DL_DETACH_REQ: 3273 if (mblkl < DL_DETACH_REQ_SIZE) 3274 break; 3275 if (gld->gld_style == DL_STYLE2) 3276 result = gldunattach(q, mp); 3277 else 3278 result = DL_NOTSUPPORTED; 3279 break; 3280 3281 case DL_ENABMULTI_REQ: 3282 if (mblkl < DL_ENABMULTI_REQ_SIZE) 3283 break; 3284 result = gld_enable_multi(q, mp); 3285 break; 3286 3287 case DL_DISABMULTI_REQ: 3288 if (mblkl < DL_DISABMULTI_REQ_SIZE) 3289 break; 3290 result = gld_disable_multi(q, mp); 3291 break; 3292 3293 case DL_PHYS_ADDR_REQ: 3294 if (mblkl < DL_PHYS_ADDR_REQ_SIZE) 3295 break; 3296 result = gld_physaddr(q, mp); 3297 break; 3298 3299 case DL_SET_PHYS_ADDR_REQ: 3300 if (mblkl < DL_SET_PHYS_ADDR_REQ_SIZE) 3301 break; 3302 result = gld_setaddr(q, mp); 3303 break; 3304 3305 case DL_PROMISCON_REQ: 3306 if (mblkl < DL_PROMISCON_REQ_SIZE) 3307 break; 3308 result = gld_promisc(q, mp, dlreq, B_TRUE); 3309 break; 3310 3311 case DL_PROMISCOFF_REQ: 3312 if (mblkl < DL_PROMISCOFF_REQ_SIZE) 3313 break; 3314 result = gld_promisc(q, mp, dlreq, B_FALSE); 3315 break; 3316 3317 case DL_GET_STATISTICS_REQ: 3318 if (mblkl < DL_GET_STATISTICS_REQ_SIZE) 3319 break; 3320 result = gld_get_statistics(q, mp); 3321 break; 3322 3323 case DL_CAPABILITY_REQ: 3324 if (mblkl < DL_CAPABILITY_REQ_SIZE) 3325 break; 3326 result = gld_cap(q, mp); 3327 break; 3328 3329 case DL_NOTIFY_REQ: 3330 if (mblkl < DL_NOTIFY_REQ_SIZE) 3331 break; 3332 result = gld_notify_req(q, mp); 3333 break; 3334 3335 case DL_XID_REQ: 3336 case DL_XID_RES: 3337 case DL_TEST_REQ: 3338 case DL_TEST_RES: 3339 case DL_CONTROL_REQ: 3340 case DL_PASSIVE_REQ: 3341 result = DL_NOTSUPPORTED; 3342 break; 3343 3344 default: 3345 #ifdef GLD_DEBUG 3346 if (gld_debug & GLDERRS) 3347 cmn_err(CE_WARN, 3348 "gld_cmds: unknown M_PROTO message: %d", 3349 dlreq); 3350 #endif 3351 result = DL_BADPRIM; 3352 } 3353 3354 return (result); 3355 } 3356 3357 static int 3358 gld_cap(queue_t *q, mblk_t *mp) 3359 { 3360 gld_t *gld = (gld_t *)q->q_ptr; 3361 dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr; 3362 3363 if (gld->gld_state == DL_UNATTACHED) 3364 return (DL_OUTSTATE); 3365 3366 if (dlp->dl_sub_length == 0) 3367 return (gld_cap_ack(q, mp)); 3368 3369 return (gld_cap_enable(q, mp)); 3370 } 3371 3372 static int 3373 gld_cap_ack(queue_t *q, mblk_t *mp) 3374 { 3375 gld_t *gld = (gld_t *)q->q_ptr; 3376 gld_mac_info_t *macinfo = gld->gld_mac_info; 3377 gld_interface_t *ifp; 3378 dl_capability_ack_t *dlap; 3379 dl_capability_sub_t *dlsp; 3380 size_t size = sizeof (dl_capability_ack_t); 3381 size_t subsize = 0; 3382 3383 ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep; 3384 3385 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY) 3386 subsize += sizeof (dl_capability_sub_t) + 3387 sizeof (dl_capab_hcksum_t); 3388 if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY) 3389 subsize += sizeof (dl_capability_sub_t) + 3390 sizeof (dl_capab_zerocopy_t); 3391 if (macinfo->gldm_options & GLDOPT_MDT) 3392 subsize += (sizeof (dl_capability_sub_t) + 3393 sizeof (dl_capab_mdt_t)); 3394 3395 if ((mp = mexchange(q, mp, size + subsize, M_PROTO, 3396 DL_CAPABILITY_ACK)) == NULL) 3397 return (GLDE_OK); 3398 3399 dlap = (dl_capability_ack_t *)mp->b_rptr; 3400 dlap->dl_sub_offset = 0; 3401 if ((dlap->dl_sub_length = subsize) != 0) 3402 dlap->dl_sub_offset = sizeof (dl_capability_ack_t); 3403 dlsp = (dl_capability_sub_t *)&dlap[1]; 3404 3405 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY) { 3406 dl_capab_hcksum_t *dlhp = (dl_capab_hcksum_t *)&dlsp[1]; 3407 3408 dlsp->dl_cap = DL_CAPAB_HCKSUM; 3409 dlsp->dl_length = sizeof (dl_capab_hcksum_t); 3410 3411 dlhp->hcksum_version = HCKSUM_VERSION_1; 3412 3413 dlhp->hcksum_txflags = 0; 3414 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_PARTIAL) 3415 dlhp->hcksum_txflags |= HCKSUM_INET_PARTIAL; 3416 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V4) 3417 dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V4; 3418 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V6) 3419 dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V6; 3420 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_IPHDR) 3421 dlhp->hcksum_txflags |= HCKSUM_IPHDRCKSUM; 3422 3423 dlcapabsetqid(&(dlhp->hcksum_mid), RD(q)); 3424 dlsp = (dl_capability_sub_t *)&dlhp[1]; 3425 } 3426 3427 if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY) { 3428 dl_capab_zerocopy_t *dlzp = (dl_capab_zerocopy_t *)&dlsp[1]; 3429 3430 dlsp->dl_cap = DL_CAPAB_ZEROCOPY; 3431 dlsp->dl_length = sizeof (dl_capab_zerocopy_t); 3432 dlzp->zerocopy_version = ZEROCOPY_VERSION_1; 3433 dlzp->zerocopy_flags = DL_CAPAB_VMSAFE_MEM; 3434 3435 dlcapabsetqid(&(dlzp->zerocopy_mid), RD(q)); 3436 dlsp = (dl_capability_sub_t *)&dlzp[1]; 3437 } 3438 3439 if (macinfo->gldm_options & GLDOPT_MDT) { 3440 dl_capab_mdt_t *dlmp = (dl_capab_mdt_t *)&dlsp[1]; 3441 3442 dlsp->dl_cap = DL_CAPAB_MDT; 3443 dlsp->dl_length = sizeof (dl_capab_mdt_t); 3444 3445 dlmp->mdt_version = MDT_VERSION_2; 3446 dlmp->mdt_max_pld = macinfo->gldm_mdt_segs; 3447 dlmp->mdt_span_limit = macinfo->gldm_mdt_sgl; 3448 dlcapabsetqid(&dlmp->mdt_mid, OTHERQ(q)); 3449 dlmp->mdt_flags = DL_CAPAB_MDT_ENABLE; 3450 dlmp->mdt_hdr_head = ifp->hdr_size; 3451 dlmp->mdt_hdr_tail = 0; 3452 } 3453 3454 qreply(q, mp); 3455 return (GLDE_OK); 3456 } 3457 3458 static int 3459 gld_cap_enable(queue_t *q, mblk_t *mp) 3460 { 3461 dl_capability_req_t *dlp; 3462 dl_capability_sub_t *dlsp; 3463 dl_capab_hcksum_t *dlhp; 3464 offset_t off; 3465 size_t len; 3466 size_t size; 3467 offset_t end; 3468 3469 dlp = (dl_capability_req_t *)mp->b_rptr; 3470 dlp->dl_primitive = DL_CAPABILITY_ACK; 3471 3472 off = dlp->dl_sub_offset; 3473 len = dlp->dl_sub_length; 3474 3475 if (!MBLKIN(mp, off, len)) 3476 return (DL_BADPRIM); 3477 3478 end = off + len; 3479 while (off < end) { 3480 dlsp = (dl_capability_sub_t *)(mp->b_rptr + off); 3481 size = sizeof (dl_capability_sub_t) + dlsp->dl_length; 3482 if (off + size > end) 3483 return (DL_BADPRIM); 3484 3485 switch (dlsp->dl_cap) { 3486 case DL_CAPAB_HCKSUM: 3487 dlhp = (dl_capab_hcksum_t *)&dlsp[1]; 3488 /* nothing useful we can do with the contents */ 3489 dlcapabsetqid(&(dlhp->hcksum_mid), RD(q)); 3490 break; 3491 default: 3492 break; 3493 } 3494 3495 off += size; 3496 } 3497 3498 qreply(q, mp); 3499 return (GLDE_OK); 3500 } 3501 3502 /* 3503 * Send a copy of the DL_NOTIFY_IND message <mp> to each stream that has 3504 * requested the specific <notification> that the message carries AND is 3505 * eligible and ready to receive the notification immediately. 3506 * 3507 * This routine ignores flow control. Notifications will be sent regardless. 3508 * 3509 * In all cases, the original message passed in is freed at the end of 3510 * the routine. 3511 */ 3512 static void 3513 gld_notify_qs(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t notification) 3514 { 3515 gld_mac_pvt_t *mac_pvt; 3516 gld_vlan_t *vlan; 3517 gld_t *gld; 3518 mblk_t *nmp; 3519 int i; 3520 3521 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 3522 3523 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 3524 3525 /* 3526 * Search all the streams attached to this macinfo looking 3527 * for those eligible to receive the present notification. 3528 */ 3529 for (i = 0; i < VLAN_HASHSZ; i++) { 3530 for (vlan = mac_pvt->vlan_hash[i]; 3531 vlan != NULL; vlan = vlan->gldv_next) { 3532 for (gld = vlan->gldv_str_next; 3533 gld != (gld_t *)&vlan->gldv_str_next; 3534 gld = gld->gld_next) { 3535 ASSERT(gld->gld_qptr != NULL); 3536 ASSERT(gld->gld_state == DL_IDLE || 3537 gld->gld_state == DL_UNBOUND); 3538 ASSERT(gld->gld_mac_info == macinfo); 3539 3540 if (gld->gld_flags & GLD_STR_CLOSING) 3541 continue; /* not eligible - skip */ 3542 if (!(notification & gld->gld_notifications)) 3543 continue; /* not wanted - skip */ 3544 if ((nmp = dupmsg(mp)) == NULL) 3545 continue; /* can't copy - skip */ 3546 3547 /* 3548 * All OK; send dup'd notification up this 3549 * stream 3550 */ 3551 qreply(WR(gld->gld_qptr), nmp); 3552 } 3553 } 3554 } 3555 3556 /* 3557 * Drop the original message block now 3558 */ 3559 freemsg(mp); 3560 } 3561 3562 /* 3563 * For each (understood) bit in the <notifications> argument, contruct 3564 * a DL_NOTIFY_IND message and send it to the specified <q>, or to all 3565 * eligible queues if <q> is NULL. 3566 */ 3567 static void 3568 gld_notify_ind(gld_mac_info_t *macinfo, uint32_t notifications, queue_t *q) 3569 { 3570 gld_mac_pvt_t *mac_pvt; 3571 dl_notify_ind_t *dlnip; 3572 struct gld_stats *stats; 3573 mblk_t *mp; 3574 size_t size; 3575 uint32_t bit; 3576 3577 GLDM_LOCK(macinfo, RW_WRITER); 3578 3579 /* 3580 * The following cases shouldn't happen, but just in case the 3581 * MAC driver calls gld_linkstate() at an inappropriate time, we 3582 * check anyway ... 3583 */ 3584 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) { 3585 GLDM_UNLOCK(macinfo); 3586 return; /* not ready yet */ 3587 } 3588 3589 if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) { 3590 GLDM_UNLOCK(macinfo); 3591 return; /* not ready anymore */ 3592 } 3593 3594 /* 3595 * Make sure the kstats are up to date, 'cos we use some of 3596 * the kstat values below, specifically the link speed ... 3597 */ 3598 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 3599 stats = mac_pvt->statistics; 3600 if (macinfo->gldm_get_stats) 3601 (void) (*macinfo->gldm_get_stats)(macinfo, stats); 3602 3603 for (bit = 1; notifications != 0; bit <<= 1) { 3604 if ((notifications & bit) == 0) 3605 continue; 3606 notifications &= ~bit; 3607 3608 size = DL_NOTIFY_IND_SIZE; 3609 if (bit == DL_NOTE_PHYS_ADDR) 3610 size += macinfo->gldm_addrlen; 3611 if ((mp = allocb(size, BPRI_MED)) == NULL) 3612 continue; 3613 3614 mp->b_datap->db_type = M_PROTO; 3615 mp->b_wptr = mp->b_rptr + size; 3616 dlnip = (dl_notify_ind_t *)mp->b_rptr; 3617 dlnip->dl_primitive = DL_NOTIFY_IND; 3618 dlnip->dl_notification = 0; 3619 dlnip->dl_data = 0; 3620 dlnip->dl_addr_length = 0; 3621 dlnip->dl_addr_offset = 0; 3622 3623 switch (bit) { 3624 case DL_NOTE_PROMISC_ON_PHYS: 3625 case DL_NOTE_PROMISC_OFF_PHYS: 3626 if (mac_pvt->nprom != 0) 3627 dlnip->dl_notification = bit; 3628 break; 3629 3630 case DL_NOTE_LINK_DOWN: 3631 if (macinfo->gldm_linkstate == GLD_LINKSTATE_DOWN) 3632 dlnip->dl_notification = bit; 3633 break; 3634 3635 case DL_NOTE_LINK_UP: 3636 if (macinfo->gldm_linkstate == GLD_LINKSTATE_UP) 3637 dlnip->dl_notification = bit; 3638 break; 3639 3640 case DL_NOTE_SPEED: 3641 /* 3642 * Conversion required here: 3643 * GLD keeps the speed in bit/s in a uint64 3644 * DLPI wants it in kb/s in a uint32 3645 * Fortunately this is still big enough for 10Gb/s! 3646 */ 3647 dlnip->dl_notification = bit; 3648 dlnip->dl_data = stats->glds_speed/1000ULL; 3649 break; 3650 3651 case DL_NOTE_PHYS_ADDR: 3652 dlnip->dl_notification = bit; 3653 dlnip->dl_data = DL_CURR_PHYS_ADDR; 3654 dlnip->dl_addr_offset = sizeof (dl_notify_ind_t); 3655 dlnip->dl_addr_length = macinfo->gldm_addrlen + 3656 abs(macinfo->gldm_saplen); 3657 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 3658 mac_copy(mac_pvt->curr_macaddr, 3659 mp->b_rptr + sizeof (dl_notify_ind_t), 3660 macinfo->gldm_addrlen); 3661 break; 3662 3663 default: 3664 break; 3665 } 3666 3667 if (dlnip->dl_notification == 0) 3668 freemsg(mp); 3669 else if (q != NULL) 3670 qreply(q, mp); 3671 else 3672 gld_notify_qs(macinfo, mp, bit); 3673 } 3674 3675 GLDM_UNLOCK(macinfo); 3676 } 3677 3678 /* 3679 * gld_notify_req - handle a DL_NOTIFY_REQ message 3680 */ 3681 static int 3682 gld_notify_req(queue_t *q, mblk_t *mp) 3683 { 3684 gld_t *gld = (gld_t *)q->q_ptr; 3685 gld_mac_info_t *macinfo; 3686 gld_mac_pvt_t *pvt; 3687 dl_notify_req_t *dlnrp; 3688 dl_notify_ack_t *dlnap; 3689 3690 ASSERT(gld != NULL); 3691 ASSERT(gld->gld_qptr == RD(q)); 3692 3693 dlnrp = (dl_notify_req_t *)mp->b_rptr; 3694 3695 #ifdef GLD_DEBUG 3696 if (gld_debug & GLDTRACE) 3697 cmn_err(CE_NOTE, "gld_notify_req(%p %p)", 3698 (void *)q, (void *)mp); 3699 #endif 3700 3701 if (gld->gld_state == DL_UNATTACHED) { 3702 #ifdef GLD_DEBUG 3703 if (gld_debug & GLDERRS) 3704 cmn_err(CE_NOTE, "gld_notify_req: wrong state (%d)", 3705 gld->gld_state); 3706 #endif 3707 return (DL_OUTSTATE); 3708 } 3709 3710 /* 3711 * Remember what notifications are required by this stream 3712 */ 3713 macinfo = gld->gld_mac_info; 3714 pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 3715 3716 gld->gld_notifications = dlnrp->dl_notifications & pvt->notifications; 3717 3718 /* 3719 * The return DL_NOTIFY_ACK carries the bitset of notifications 3720 * that this driver can provide, independently of which ones have 3721 * previously been or are now being requested. 3722 */ 3723 if ((mp = mexchange(q, mp, sizeof (dl_notify_ack_t), M_PCPROTO, 3724 DL_NOTIFY_ACK)) == NULL) 3725 return (DL_SYSERR); 3726 3727 dlnap = (dl_notify_ack_t *)mp->b_rptr; 3728 dlnap->dl_notifications = pvt->notifications; 3729 qreply(q, mp); 3730 3731 /* 3732 * A side effect of a DL_NOTIFY_REQ is that after the DL_NOTIFY_ACK 3733 * reply, the the requestor gets zero or more DL_NOTIFY_IND messages 3734 * that provide the current status. 3735 */ 3736 gld_notify_ind(macinfo, gld->gld_notifications, q); 3737 3738 return (GLDE_OK); 3739 } 3740 3741 /* 3742 * gld_linkstate() 3743 * Called by driver to tell GLD the state of the physical link. 3744 * As a side effect, sends a DL_NOTE_LINK_UP or DL_NOTE_LINK_DOWN 3745 * notification to each client that has previously requested such 3746 * notifications 3747 */ 3748 void 3749 gld_linkstate(gld_mac_info_t *macinfo, int32_t newstate) 3750 { 3751 uint32_t notification; 3752 3753 switch (newstate) { 3754 default: 3755 return; 3756 3757 case GLD_LINKSTATE_DOWN: 3758 notification = DL_NOTE_LINK_DOWN; 3759 break; 3760 3761 case GLD_LINKSTATE_UP: 3762 notification = DL_NOTE_LINK_UP | DL_NOTE_SPEED; 3763 break; 3764 3765 case GLD_LINKSTATE_UNKNOWN: 3766 notification = 0; 3767 break; 3768 } 3769 3770 GLDM_LOCK(macinfo, RW_WRITER); 3771 if (macinfo->gldm_linkstate == newstate) 3772 notification = 0; 3773 else 3774 macinfo->gldm_linkstate = newstate; 3775 GLDM_UNLOCK(macinfo); 3776 3777 if (notification) 3778 gld_notify_ind(macinfo, notification, NULL); 3779 } 3780 3781 /* 3782 * gld_udqos - set the current QoS parameters (priority only at the moment). 3783 */ 3784 static int 3785 gld_udqos(queue_t *q, mblk_t *mp) 3786 { 3787 dl_udqos_req_t *dlp; 3788 gld_t *gld = (gld_t *)q->q_ptr; 3789 int off; 3790 int len; 3791 dl_qos_cl_sel1_t *selp; 3792 3793 ASSERT(gld); 3794 ASSERT(gld->gld_qptr == RD(q)); 3795 3796 #ifdef GLD_DEBUG 3797 if (gld_debug & GLDTRACE) 3798 cmn_err(CE_NOTE, "gld_udqos(%p %p)", (void *)q, (void *)mp); 3799 #endif 3800 3801 if (gld->gld_state != DL_IDLE) { 3802 #ifdef GLD_DEBUG 3803 if (gld_debug & GLDERRS) 3804 cmn_err(CE_NOTE, "gld_udqos: wrong state (%d)", 3805 gld->gld_state); 3806 #endif 3807 return (DL_OUTSTATE); 3808 } 3809 3810 dlp = (dl_udqos_req_t *)mp->b_rptr; 3811 off = dlp->dl_qos_offset; 3812 len = dlp->dl_qos_length; 3813 3814 if (len != sizeof (dl_qos_cl_sel1_t) || !MBLKIN(mp, off, len)) 3815 return (DL_BADQOSTYPE); 3816 3817 selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off); 3818 if (selp->dl_qos_type != DL_QOS_CL_SEL1) 3819 return (DL_BADQOSTYPE); 3820 3821 if (selp->dl_trans_delay != 0 && 3822 selp->dl_trans_delay != DL_QOS_DONT_CARE) 3823 return (DL_BADQOSPARAM); 3824 if (selp->dl_protection != 0 && 3825 selp->dl_protection != DL_QOS_DONT_CARE) 3826 return (DL_BADQOSPARAM); 3827 if (selp->dl_residual_error != 0 && 3828 selp->dl_residual_error != DL_QOS_DONT_CARE) 3829 return (DL_BADQOSPARAM); 3830 if (selp->dl_priority < 0 || selp->dl_priority > 7) 3831 return (DL_BADQOSPARAM); 3832 3833 gld->gld_upri = selp->dl_priority; 3834 3835 dlokack(q, mp, DL_UDQOS_REQ); 3836 return (GLDE_OK); 3837 } 3838 3839 static mblk_t * 3840 gld_bindack(queue_t *q, mblk_t *mp) 3841 { 3842 gld_t *gld = (gld_t *)q->q_ptr; 3843 gld_mac_info_t *macinfo = gld->gld_mac_info; 3844 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 3845 dl_bind_ack_t *dlp; 3846 size_t size; 3847 t_uscalar_t addrlen; 3848 uchar_t *sapp; 3849 3850 addrlen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen); 3851 size = sizeof (dl_bind_ack_t) + addrlen; 3852 if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL) 3853 return (NULL); 3854 3855 dlp = (dl_bind_ack_t *)mp->b_rptr; 3856 dlp->dl_sap = gld->gld_sap; 3857 dlp->dl_addr_length = addrlen; 3858 dlp->dl_addr_offset = sizeof (dl_bind_ack_t); 3859 dlp->dl_max_conind = 0; 3860 dlp->dl_xidtest_flg = 0; 3861 3862 mac_copy(mac_pvt->curr_macaddr, (uchar_t *)&dlp[1], 3863 macinfo->gldm_addrlen); 3864 sapp = mp->b_rptr + dlp->dl_addr_offset + macinfo->gldm_addrlen; 3865 *(ushort_t *)sapp = gld->gld_sap; 3866 3867 return (mp); 3868 } 3869 3870 /* 3871 * gld_bind - determine if a SAP is already allocated and whether it is legal 3872 * to do the bind at this time 3873 */ 3874 static int 3875 gld_bind(queue_t *q, mblk_t *mp) 3876 { 3877 ulong_t sap; 3878 dl_bind_req_t *dlp; 3879 gld_t *gld = (gld_t *)q->q_ptr; 3880 gld_mac_info_t *macinfo = gld->gld_mac_info; 3881 3882 ASSERT(gld); 3883 ASSERT(gld->gld_qptr == RD(q)); 3884 3885 #ifdef GLD_DEBUG 3886 if (gld_debug & GLDTRACE) 3887 cmn_err(CE_NOTE, "gld_bind(%p %p)", (void *)q, (void *)mp); 3888 #endif 3889 3890 dlp = (dl_bind_req_t *)mp->b_rptr; 3891 sap = dlp->dl_sap; 3892 3893 #ifdef GLD_DEBUG 3894 if (gld_debug & GLDPROT) 3895 cmn_err(CE_NOTE, "gld_bind: lsap=%lx", sap); 3896 #endif 3897 3898 if (gld->gld_state != DL_UNBOUND) { 3899 #ifdef GLD_DEBUG 3900 if (gld_debug & GLDERRS) 3901 cmn_err(CE_NOTE, "gld_bind: bound or not attached (%d)", 3902 gld->gld_state); 3903 #endif 3904 return (DL_OUTSTATE); 3905 } 3906 ASSERT(macinfo); 3907 3908 if (dlp->dl_service_mode != DL_CLDLS) { 3909 return (DL_UNSUPPORTED); 3910 } 3911 if (dlp->dl_xidtest_flg & (DL_AUTO_XID | DL_AUTO_TEST)) { 3912 return (DL_NOAUTO); 3913 } 3914 3915 /* 3916 * Check sap validity and decide whether this stream accepts 3917 * IEEE 802.2 (LLC) packets. 3918 */ 3919 if (sap > ETHERTYPE_MAX) 3920 return (DL_BADSAP); 3921 3922 /* 3923 * Decide whether the SAP value selects EtherType encoding/decoding. 3924 * For compatibility with monolithic ethernet drivers, the range of 3925 * SAP values is different for DL_ETHER media. 3926 */ 3927 switch (macinfo->gldm_type) { 3928 case DL_ETHER: 3929 gld->gld_ethertype = (sap > ETHERMTU); 3930 break; 3931 default: 3932 gld->gld_ethertype = (sap > GLD_MAX_802_SAP); 3933 break; 3934 } 3935 3936 /* if we get to here, then the SAP is legal enough */ 3937 GLDM_LOCK(macinfo, RW_WRITER); 3938 gld->gld_state = DL_IDLE; /* bound and ready */ 3939 gld->gld_sap = sap; 3940 gld_set_ipq(gld); 3941 3942 #ifdef GLD_DEBUG 3943 if (gld_debug & GLDPROT) 3944 cmn_err(CE_NOTE, "gld_bind: ok - sap = %d", gld->gld_sap); 3945 #endif 3946 3947 /* ACK the BIND */ 3948 mp = gld_bindack(q, mp); 3949 GLDM_UNLOCK(macinfo); 3950 3951 if (mp != NULL) { 3952 qreply(q, mp); 3953 return (GLDE_OK); 3954 } 3955 3956 return (DL_SYSERR); 3957 } 3958 3959 /* 3960 * gld_unbind - perform an unbind of an LSAP or ether type on the stream. 3961 * The stream is still open and can be re-bound. 3962 */ 3963 static int 3964 gld_unbind(queue_t *q, mblk_t *mp) 3965 { 3966 gld_t *gld = (gld_t *)q->q_ptr; 3967 gld_mac_info_t *macinfo = gld->gld_mac_info; 3968 3969 ASSERT(gld); 3970 3971 #ifdef GLD_DEBUG 3972 if (gld_debug & GLDTRACE) 3973 cmn_err(CE_NOTE, "gld_unbind(%p %p)", (void *)q, (void *)mp); 3974 #endif 3975 3976 if (gld->gld_state != DL_IDLE) { 3977 #ifdef GLD_DEBUG 3978 if (gld_debug & GLDERRS) 3979 cmn_err(CE_NOTE, "gld_unbind: wrong state (%d)", 3980 gld->gld_state); 3981 #endif 3982 return (DL_OUTSTATE); 3983 } 3984 ASSERT(macinfo); 3985 3986 /* 3987 * Avoid unbinding (DL_UNBIND_REQ) while FAST/RAW is inside wput. 3988 * See comments above gld_start(). 3989 */ 3990 gld->gld_in_unbind = B_TRUE; /* disallow wput=>start */ 3991 membar_enter(); 3992 if (gld->gld_wput_count != 0) { 3993 gld->gld_in_unbind = B_FALSE; 3994 ASSERT(mp); /* we didn't come from close */ 3995 #ifdef GLD_DEBUG 3996 if (gld_debug & GLDETRACE) 3997 cmn_err(CE_NOTE, "gld_unbind: defer for wput"); 3998 #endif 3999 (void) putbq(q, mp); 4000 qenable(q); /* try again soon */ 4001 return (GLDE_RETRY); 4002 } 4003 4004 GLDM_LOCK(macinfo, RW_WRITER); 4005 gld->gld_state = DL_UNBOUND; 4006 gld->gld_sap = 0; 4007 gld_set_ipq(gld); 4008 GLDM_UNLOCK(macinfo); 4009 4010 membar_exit(); 4011 gld->gld_in_unbind = B_FALSE; 4012 4013 /* mp is NULL if we came from close */ 4014 if (mp) { 4015 gld_flushqueue(q); /* flush the queues */ 4016 dlokack(q, mp, DL_UNBIND_REQ); 4017 } 4018 return (GLDE_OK); 4019 } 4020 4021 /* 4022 * gld_inforeq - generate the response to an info request 4023 */ 4024 static int 4025 gld_inforeq(queue_t *q, mblk_t *mp) 4026 { 4027 gld_t *gld; 4028 dl_info_ack_t *dlp; 4029 int bufsize; 4030 glddev_t *glddev; 4031 gld_mac_info_t *macinfo; 4032 gld_mac_pvt_t *mac_pvt; 4033 int sel_offset = 0; 4034 int range_offset = 0; 4035 int addr_offset; 4036 int addr_length; 4037 int sap_length; 4038 int brdcst_offset; 4039 int brdcst_length; 4040 gld_vlan_t *vlan; 4041 uchar_t *sapp; 4042 4043 #ifdef GLD_DEBUG 4044 if (gld_debug & GLDTRACE) 4045 cmn_err(CE_NOTE, "gld_inforeq(%p %p)", (void *)q, (void *)mp); 4046 #endif 4047 gld = (gld_t *)q->q_ptr; 4048 ASSERT(gld); 4049 glddev = gld->gld_device; 4050 ASSERT(glddev); 4051 4052 if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) { 4053 macinfo = gld->gld_mac_info; 4054 ASSERT(macinfo != NULL); 4055 4056 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 4057 4058 addr_length = macinfo->gldm_addrlen; 4059 sap_length = macinfo->gldm_saplen; 4060 brdcst_length = macinfo->gldm_addrlen; 4061 } else { 4062 addr_length = glddev->gld_addrlen; 4063 sap_length = glddev->gld_saplen; 4064 brdcst_length = glddev->gld_addrlen; 4065 } 4066 4067 bufsize = sizeof (dl_info_ack_t); 4068 4069 addr_offset = bufsize; 4070 bufsize += addr_length; 4071 bufsize += abs(sap_length); 4072 4073 brdcst_offset = bufsize; 4074 bufsize += brdcst_length; 4075 4076 if ((vlan = (gld_vlan_t *)gld->gld_vlan) != NULL && 4077 vlan->gldv_id != VLAN_VID_NONE) { 4078 sel_offset = P2ROUNDUP(bufsize, sizeof (int64_t)); 4079 bufsize = sel_offset + sizeof (dl_qos_cl_sel1_t); 4080 4081 range_offset = P2ROUNDUP(bufsize, sizeof (int64_t)); 4082 bufsize = range_offset + sizeof (dl_qos_cl_range1_t); 4083 } 4084 4085 if ((mp = mexchange(q, mp, bufsize, M_PCPROTO, DL_INFO_ACK)) == NULL) 4086 return (GLDE_OK); /* nothing more to be done */ 4087 4088 bzero(mp->b_rptr, bufsize); 4089 4090 dlp = (dl_info_ack_t *)mp->b_rptr; 4091 dlp->dl_primitive = DL_INFO_ACK; 4092 dlp->dl_version = DL_VERSION_2; 4093 dlp->dl_service_mode = DL_CLDLS; 4094 dlp->dl_current_state = gld->gld_state; 4095 dlp->dl_provider_style = gld->gld_style; 4096 4097 if (sel_offset != 0) { 4098 dl_qos_cl_sel1_t *selp; 4099 dl_qos_cl_range1_t *rangep; 4100 4101 ASSERT(range_offset != 0); 4102 4103 dlp->dl_qos_offset = sel_offset; 4104 dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t); 4105 dlp->dl_qos_range_offset = range_offset; 4106 dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t); 4107 4108 selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + sel_offset); 4109 selp->dl_qos_type = DL_QOS_CL_SEL1; 4110 selp->dl_priority = gld->gld_upri; 4111 4112 rangep = (dl_qos_cl_range1_t *)(mp->b_rptr + range_offset); 4113 rangep->dl_qos_type = DL_QOS_CL_RANGE1; 4114 rangep->dl_priority.dl_min = 0; 4115 rangep->dl_priority.dl_max = 7; 4116 } 4117 4118 if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) { 4119 dlp->dl_min_sdu = macinfo->gldm_minpkt; 4120 dlp->dl_max_sdu = macinfo->gldm_maxpkt; 4121 dlp->dl_mac_type = macinfo->gldm_type; 4122 dlp->dl_addr_length = addr_length + abs(sap_length); 4123 dlp->dl_sap_length = sap_length; 4124 4125 if (gld->gld_state == DL_IDLE) { 4126 /* 4127 * If we are bound to a non-LLC SAP on any medium 4128 * other than Ethernet, then we need room for a 4129 * SNAP header. So we have to adjust the MTU size 4130 * accordingly. XXX I suppose this should be done 4131 * in gldutil.c, but it seems likely that this will 4132 * always be true for everything GLD supports but 4133 * Ethernet. Check this if you add another medium. 4134 */ 4135 if ((macinfo->gldm_type == DL_TPR || 4136 macinfo->gldm_type == DL_FDDI) && 4137 gld->gld_ethertype) 4138 dlp->dl_max_sdu -= LLC_SNAP_HDR_LEN; 4139 4140 /* copy macaddr and sap */ 4141 dlp->dl_addr_offset = addr_offset; 4142 4143 mac_copy(mac_pvt->curr_macaddr, mp->b_rptr + 4144 addr_offset, macinfo->gldm_addrlen); 4145 sapp = mp->b_rptr + addr_offset + 4146 macinfo->gldm_addrlen; 4147 *(ushort_t *)sapp = gld->gld_sap; 4148 } else { 4149 dlp->dl_addr_offset = 0; 4150 } 4151 4152 /* copy broadcast addr */ 4153 dlp->dl_brdcst_addr_length = macinfo->gldm_addrlen; 4154 dlp->dl_brdcst_addr_offset = brdcst_offset; 4155 mac_copy((caddr_t)macinfo->gldm_broadcast_addr, 4156 mp->b_rptr + brdcst_offset, brdcst_length); 4157 } else { 4158 /* 4159 * No PPA is attached. 4160 * The best we can do is use the values provided 4161 * by the first mac that called gld_register. 4162 */ 4163 dlp->dl_min_sdu = glddev->gld_minsdu; 4164 dlp->dl_max_sdu = glddev->gld_maxsdu; 4165 dlp->dl_mac_type = glddev->gld_type; 4166 dlp->dl_addr_length = addr_length + abs(sap_length); 4167 dlp->dl_sap_length = sap_length; 4168 dlp->dl_addr_offset = 0; 4169 dlp->dl_brdcst_addr_offset = brdcst_offset; 4170 dlp->dl_brdcst_addr_length = brdcst_length; 4171 mac_copy((caddr_t)glddev->gld_broadcast, 4172 mp->b_rptr + brdcst_offset, brdcst_length); 4173 } 4174 qreply(q, mp); 4175 return (GLDE_OK); 4176 } 4177 4178 /* 4179 * gld_unitdata (q, mp) 4180 * send a datagram. Destination address/lsap is in M_PROTO 4181 * message (first mblock), data is in remainder of message. 4182 * 4183 */ 4184 static int 4185 gld_unitdata(queue_t *q, mblk_t *mp) 4186 { 4187 gld_t *gld = (gld_t *)q->q_ptr; 4188 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr; 4189 gld_mac_info_t *macinfo = gld->gld_mac_info; 4190 size_t msglen; 4191 mblk_t *nmp; 4192 gld_interface_t *ifp; 4193 uint32_t start; 4194 uint32_t stuff; 4195 uint32_t end; 4196 uint32_t value; 4197 uint32_t flags; 4198 uint32_t upri; 4199 4200 #ifdef GLD_DEBUG 4201 if (gld_debug & GLDTRACE) 4202 cmn_err(CE_NOTE, "gld_unitdata(%p %p)", (void *)q, (void *)mp); 4203 #endif 4204 4205 if (gld->gld_state != DL_IDLE) { 4206 #ifdef GLD_DEBUG 4207 if (gld_debug & GLDERRS) 4208 cmn_err(CE_NOTE, "gld_unitdata: wrong state (%d)", 4209 gld->gld_state); 4210 #endif 4211 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset, 4212 dlp->dl_dest_addr_length, DL_OUTSTATE, 0); 4213 return (GLDE_OK); 4214 } 4215 ASSERT(macinfo != NULL); 4216 4217 if (!MBLKIN(mp, dlp->dl_dest_addr_offset, dlp->dl_dest_addr_length) || 4218 dlp->dl_dest_addr_length != 4219 macinfo->gldm_addrlen + abs(macinfo->gldm_saplen)) { 4220 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset, 4221 dlp->dl_dest_addr_length, DL_BADADDR, 0); 4222 return (GLDE_OK); 4223 } 4224 4225 upri = dlp->dl_priority.dl_max; 4226 4227 msglen = msgdsize(mp); 4228 if (msglen == 0 || msglen > macinfo->gldm_maxpkt) { 4229 #ifdef GLD_DEBUG 4230 if (gld_debug & GLDERRS) 4231 cmn_err(CE_NOTE, "gld_unitdata: bad msglen (%d)", 4232 (int)msglen); 4233 #endif 4234 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset, 4235 dlp->dl_dest_addr_length, DL_BADDATA, 0); 4236 return (GLDE_OK); 4237 } 4238 4239 ASSERT(mp->b_cont != NULL); /* because msgdsize(mp) is nonzero */ 4240 4241 ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep; 4242 4243 /* grab any checksum information that may be present */ 4244 hcksum_retrieve(mp->b_cont, NULL, NULL, &start, &stuff, &end, 4245 &value, &flags); 4246 4247 /* 4248 * Prepend a valid header for transmission 4249 */ 4250 if ((nmp = (*ifp->mkunitdata)(gld, mp)) == NULL) { 4251 #ifdef GLD_DEBUG 4252 if (gld_debug & GLDERRS) 4253 cmn_err(CE_NOTE, "gld_unitdata: mkunitdata failed."); 4254 #endif 4255 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset, 4256 dlp->dl_dest_addr_length, DL_SYSERR, ENOSR); 4257 return (GLDE_OK); 4258 } 4259 4260 /* apply any checksum information to the first block in the chain */ 4261 (void) hcksum_assoc(nmp, NULL, NULL, start, stuff, end, value, 4262 flags, 0); 4263 4264 if (gld_start(q, nmp, GLD_WSRV, upri) == GLD_NORESOURCES) { 4265 qenable(q); 4266 return (GLDE_RETRY); 4267 } 4268 4269 return (GLDE_OK); 4270 } 4271 4272 /* 4273 * gldattach(q, mp) 4274 * DLPI DL_ATTACH_REQ 4275 * this attaches the stream to a PPA 4276 */ 4277 static int 4278 gldattach(queue_t *q, mblk_t *mp) 4279 { 4280 dl_attach_req_t *at; 4281 gld_mac_info_t *macinfo; 4282 gld_t *gld = (gld_t *)q->q_ptr; 4283 glddev_t *glddev; 4284 gld_mac_pvt_t *mac_pvt; 4285 uint32_t ppa; 4286 uint32_t vid; 4287 gld_vlan_t *vlan; 4288 4289 at = (dl_attach_req_t *)mp->b_rptr; 4290 4291 if (gld->gld_state != DL_UNATTACHED) 4292 return (DL_OUTSTATE); 4293 4294 ASSERT(!gld->gld_mac_info); 4295 4296 ppa = at->dl_ppa % GLD_VLAN_SCALE; /* 0 .. 999 */ 4297 vid = at->dl_ppa / GLD_VLAN_SCALE; /* 0 .. 4094 */ 4298 if (vid > VLAN_VID_MAX) 4299 return (DL_BADPPA); 4300 4301 glddev = gld->gld_device; 4302 mutex_enter(&glddev->gld_devlock); 4303 for (macinfo = glddev->gld_mac_next; 4304 macinfo != (gld_mac_info_t *)&glddev->gld_mac_next; 4305 macinfo = macinfo->gldm_next) { 4306 int inst; 4307 4308 ASSERT(macinfo != NULL); 4309 if (macinfo->gldm_ppa != ppa) 4310 continue; 4311 4312 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) 4313 continue; /* this one's not ready yet */ 4314 4315 /* 4316 * VLAN sanity check 4317 */ 4318 if (vid != VLAN_VID_NONE && !VLAN_CAPABLE(macinfo)) { 4319 mutex_exit(&glddev->gld_devlock); 4320 return (DL_BADPPA); 4321 } 4322 4323 /* 4324 * We found the correct PPA, hold the instance 4325 */ 4326 inst = ddi_get_instance(macinfo->gldm_devinfo); 4327 if (inst == -1 || qassociate(q, inst) != 0) { 4328 mutex_exit(&glddev->gld_devlock); 4329 return (DL_BADPPA); 4330 } 4331 4332 /* Take the stream off the per-driver-class list */ 4333 gldremque(gld); 4334 4335 /* 4336 * We must hold the lock to prevent multiple calls 4337 * to the reset and start routines. 4338 */ 4339 GLDM_LOCK(macinfo, RW_WRITER); 4340 4341 gld->gld_mac_info = macinfo; 4342 4343 if (macinfo->gldm_send_tagged != NULL) 4344 gld->gld_send = macinfo->gldm_send_tagged; 4345 else 4346 gld->gld_send = macinfo->gldm_send; 4347 4348 if ((vlan = gld_get_vlan(macinfo, vid)) == NULL) { 4349 GLDM_UNLOCK(macinfo); 4350 gldinsque(gld, glddev->gld_str_prev); 4351 mutex_exit(&glddev->gld_devlock); 4352 (void) qassociate(q, -1); 4353 return (DL_BADPPA); 4354 } 4355 4356 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 4357 if (!mac_pvt->started) { 4358 if (gld_start_mac(macinfo) != GLD_SUCCESS) { 4359 gld_rem_vlan(vlan); 4360 GLDM_UNLOCK(macinfo); 4361 gldinsque(gld, glddev->gld_str_prev); 4362 mutex_exit(&glddev->gld_devlock); 4363 dlerrorack(q, mp, DL_ATTACH_REQ, DL_SYSERR, 4364 EIO); 4365 (void) qassociate(q, -1); 4366 return (GLDE_OK); 4367 } 4368 } 4369 4370 gld->gld_vlan = vlan; 4371 vlan->gldv_nstreams++; 4372 gldinsque(gld, vlan->gldv_str_prev); 4373 gld->gld_state = DL_UNBOUND; 4374 GLDM_UNLOCK(macinfo); 4375 4376 #ifdef GLD_DEBUG 4377 if (gld_debug & GLDPROT) { 4378 cmn_err(CE_NOTE, "gldattach(%p, %p, PPA = %d)", 4379 (void *)q, (void *)mp, macinfo->gldm_ppa); 4380 } 4381 #endif 4382 mutex_exit(&glddev->gld_devlock); 4383 dlokack(q, mp, DL_ATTACH_REQ); 4384 return (GLDE_OK); 4385 } 4386 mutex_exit(&glddev->gld_devlock); 4387 return (DL_BADPPA); 4388 } 4389 4390 /* 4391 * gldunattach(q, mp) 4392 * DLPI DL_DETACH_REQ 4393 * detaches the mac layer from the stream 4394 */ 4395 int 4396 gldunattach(queue_t *q, mblk_t *mp) 4397 { 4398 gld_t *gld = (gld_t *)q->q_ptr; 4399 glddev_t *glddev = gld->gld_device; 4400 gld_mac_info_t *macinfo = gld->gld_mac_info; 4401 int state = gld->gld_state; 4402 int i; 4403 gld_mac_pvt_t *mac_pvt; 4404 gld_vlan_t *vlan; 4405 boolean_t phys_off; 4406 boolean_t mult_off; 4407 int op = GLD_MAC_PROMISC_NOOP; 4408 4409 if (state != DL_UNBOUND) 4410 return (DL_OUTSTATE); 4411 4412 ASSERT(macinfo != NULL); 4413 ASSERT(gld->gld_sap == 0); 4414 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 4415 4416 #ifdef GLD_DEBUG 4417 if (gld_debug & GLDPROT) { 4418 cmn_err(CE_NOTE, "gldunattach(%p, %p, PPA = %d)", 4419 (void *)q, (void *)mp, macinfo->gldm_ppa); 4420 } 4421 #endif 4422 4423 GLDM_LOCK(macinfo, RW_WRITER); 4424 4425 if (gld->gld_mcast) { 4426 for (i = 0; i < gld->gld_multicnt; i++) { 4427 gld_mcast_t *mcast; 4428 4429 if ((mcast = gld->gld_mcast[i]) != NULL) { 4430 ASSERT(mcast->gldm_refcnt); 4431 gld_send_disable_multi(macinfo, mcast); 4432 } 4433 } 4434 kmem_free(gld->gld_mcast, 4435 sizeof (gld_mcast_t *) * gld->gld_multicnt); 4436 gld->gld_mcast = NULL; 4437 gld->gld_multicnt = 0; 4438 } 4439 4440 /* decide if we need to turn off any promiscuity */ 4441 phys_off = (gld->gld_flags & GLD_PROM_PHYS && 4442 --mac_pvt->nprom == 0); 4443 mult_off = (gld->gld_flags & GLD_PROM_MULT && 4444 --mac_pvt->nprom_multi == 0); 4445 4446 gld->gld_flags &= ~(GLD_PROM_PHYS | GLD_PROM_SAP | GLD_PROM_MULT); 4447 4448 if (phys_off) { 4449 op = (mac_pvt->nprom_multi == 0) ? GLD_MAC_PROMISC_NONE : 4450 GLD_MAC_PROMISC_MULTI; 4451 } else if (mult_off) { 4452 op = (mac_pvt->nprom == 0) ? GLD_MAC_PROMISC_NONE : 4453 GLD_MAC_PROMISC_NOOP; /* phys overrides multi */ 4454 } 4455 4456 if (op != GLD_MAC_PROMISC_NOOP) 4457 (void) (*macinfo->gldm_set_promiscuous)(macinfo, op); 4458 4459 GLDM_UNLOCK(macinfo); 4460 4461 if (phys_off) 4462 gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL); 4463 4464 /* 4465 * We need to hold both locks when modifying the mac stream list 4466 * to protect findminor as well as everyone else. 4467 */ 4468 mutex_enter(&glddev->gld_devlock); 4469 GLDM_LOCK(macinfo, RW_WRITER); 4470 4471 /* disassociate this stream with its vlan and underlying mac */ 4472 gldremque(gld); 4473 4474 vlan = (gld_vlan_t *)gld->gld_vlan; 4475 if (--vlan->gldv_nstreams == 0) { 4476 gld_rem_vlan(vlan); 4477 gld->gld_vlan = NULL; 4478 } 4479 4480 gld->gld_mac_info = NULL; 4481 gld->gld_state = DL_UNATTACHED; 4482 4483 /* cleanup mac layer if last vlan */ 4484 if (mac_pvt->nvlan == 0) { 4485 gld_stop_mac(macinfo); 4486 macinfo->gldm_GLD_flags &= ~GLD_INTR_WAIT; 4487 } 4488 4489 /* make sure no references to this gld for gld_v0_sched */ 4490 if (mac_pvt->last_sched == gld) 4491 mac_pvt->last_sched = NULL; 4492 4493 GLDM_UNLOCK(macinfo); 4494 4495 /* put the stream on the unattached Style 2 list */ 4496 gldinsque(gld, glddev->gld_str_prev); 4497 4498 mutex_exit(&glddev->gld_devlock); 4499 4500 /* There will be no mp if we were called from close */ 4501 if (mp) { 4502 dlokack(q, mp, DL_DETACH_REQ); 4503 } 4504 if (gld->gld_style == DL_STYLE2) 4505 (void) qassociate(q, -1); 4506 return (GLDE_OK); 4507 } 4508 4509 /* 4510 * gld_enable_multi (q, mp) 4511 * Enables multicast address on the stream. If the mac layer 4512 * isn't enabled for this address, enable at that level as well. 4513 */ 4514 static int 4515 gld_enable_multi(queue_t *q, mblk_t *mp) 4516 { 4517 gld_t *gld = (gld_t *)q->q_ptr; 4518 glddev_t *glddev; 4519 gld_mac_info_t *macinfo = gld->gld_mac_info; 4520 unsigned char *maddr; 4521 dl_enabmulti_req_t *multi; 4522 gld_mcast_t *mcast; 4523 int i, rc; 4524 gld_mac_pvt_t *mac_pvt; 4525 4526 #ifdef GLD_DEBUG 4527 if (gld_debug & GLDPROT) { 4528 cmn_err(CE_NOTE, "gld_enable_multi(%p, %p)", (void *)q, 4529 (void *)mp); 4530 } 4531 #endif 4532 4533 if (gld->gld_state == DL_UNATTACHED) 4534 return (DL_OUTSTATE); 4535 4536 ASSERT(macinfo != NULL); 4537 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 4538 4539 if (macinfo->gldm_set_multicast == NULL) { 4540 return (DL_UNSUPPORTED); 4541 } 4542 4543 multi = (dl_enabmulti_req_t *)mp->b_rptr; 4544 4545 if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) || 4546 multi->dl_addr_length != macinfo->gldm_addrlen) 4547 return (DL_BADADDR); 4548 4549 /* request appears to be valid */ 4550 4551 glddev = mac_pvt->major_dev; 4552 ASSERT(glddev == gld->gld_device); 4553 4554 maddr = mp->b_rptr + multi->dl_addr_offset; 4555 4556 /* 4557 * The multicast addresses live in a per-device table, along 4558 * with a reference count. Each stream has a table that 4559 * points to entries in the device table, with the reference 4560 * count reflecting the number of streams pointing at it. If 4561 * this multicast address is already in the per-device table, 4562 * all we have to do is point at it. 4563 */ 4564 GLDM_LOCK(macinfo, RW_WRITER); 4565 4566 /* does this address appear in current table? */ 4567 if (gld->gld_mcast == NULL) { 4568 /* no mcast addresses -- allocate table */ 4569 gld->gld_mcast = GETSTRUCT(gld_mcast_t *, 4570 glddev->gld_multisize); 4571 if (gld->gld_mcast == NULL) { 4572 GLDM_UNLOCK(macinfo); 4573 dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR); 4574 return (GLDE_OK); 4575 } 4576 gld->gld_multicnt = glddev->gld_multisize; 4577 } else { 4578 for (i = 0; i < gld->gld_multicnt; i++) { 4579 if (gld->gld_mcast[i] && 4580 mac_eq(gld->gld_mcast[i]->gldm_addr, 4581 maddr, macinfo->gldm_addrlen)) { 4582 /* this is a match -- just succeed */ 4583 ASSERT(gld->gld_mcast[i]->gldm_refcnt); 4584 GLDM_UNLOCK(macinfo); 4585 dlokack(q, mp, DL_ENABMULTI_REQ); 4586 return (GLDE_OK); 4587 } 4588 } 4589 } 4590 4591 /* 4592 * it wasn't in the stream so check to see if the mac layer has it 4593 */ 4594 mcast = NULL; 4595 if (mac_pvt->mcast_table == NULL) { 4596 mac_pvt->mcast_table = GETSTRUCT(gld_mcast_t, 4597 glddev->gld_multisize); 4598 if (mac_pvt->mcast_table == NULL) { 4599 GLDM_UNLOCK(macinfo); 4600 dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR); 4601 return (GLDE_OK); 4602 } 4603 } else { 4604 for (i = 0; i < glddev->gld_multisize; i++) { 4605 if (mac_pvt->mcast_table[i].gldm_refcnt && 4606 mac_eq(mac_pvt->mcast_table[i].gldm_addr, 4607 maddr, macinfo->gldm_addrlen)) { 4608 mcast = &mac_pvt->mcast_table[i]; 4609 break; 4610 } 4611 } 4612 } 4613 if (mcast == NULL) { 4614 /* not in mac layer -- find an empty mac slot to fill in */ 4615 for (i = 0; i < glddev->gld_multisize; i++) { 4616 if (mac_pvt->mcast_table[i].gldm_refcnt == 0) { 4617 mcast = &mac_pvt->mcast_table[i]; 4618 mac_copy(maddr, mcast->gldm_addr, 4619 macinfo->gldm_addrlen); 4620 break; 4621 } 4622 } 4623 } 4624 if (mcast == NULL) { 4625 /* couldn't get a mac layer slot */ 4626 GLDM_UNLOCK(macinfo); 4627 return (DL_TOOMANY); 4628 } 4629 4630 /* now we have a mac layer slot in mcast -- get a stream slot */ 4631 for (i = 0; i < gld->gld_multicnt; i++) { 4632 if (gld->gld_mcast[i] != NULL) 4633 continue; 4634 /* found an empty slot */ 4635 if (!mcast->gldm_refcnt) { 4636 /* set mcast in hardware */ 4637 unsigned char cmaddr[GLD_MAX_ADDRLEN]; 4638 4639 ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen); 4640 cmac_copy(maddr, cmaddr, 4641 macinfo->gldm_addrlen, macinfo); 4642 4643 rc = (*macinfo->gldm_set_multicast) 4644 (macinfo, cmaddr, GLD_MULTI_ENABLE); 4645 if (rc == GLD_NOTSUPPORTED) { 4646 GLDM_UNLOCK(macinfo); 4647 return (DL_NOTSUPPORTED); 4648 } else if (rc == GLD_NORESOURCES) { 4649 GLDM_UNLOCK(macinfo); 4650 return (DL_TOOMANY); 4651 } else if (rc == GLD_BADARG) { 4652 GLDM_UNLOCK(macinfo); 4653 return (DL_BADADDR); 4654 } else if (rc == GLD_RETRY) { 4655 /* 4656 * The putbq and gld_xwait must be 4657 * within the lock to prevent races 4658 * with gld_sched. 4659 */ 4660 (void) putbq(q, mp); 4661 gld->gld_xwait = B_TRUE; 4662 GLDM_UNLOCK(macinfo); 4663 return (GLDE_RETRY); 4664 } else if (rc != GLD_SUCCESS) { 4665 GLDM_UNLOCK(macinfo); 4666 dlerrorack(q, mp, DL_ENABMULTI_REQ, 4667 DL_SYSERR, EIO); 4668 return (GLDE_OK); 4669 } 4670 } 4671 gld->gld_mcast[i] = mcast; 4672 mcast->gldm_refcnt++; 4673 GLDM_UNLOCK(macinfo); 4674 dlokack(q, mp, DL_ENABMULTI_REQ); 4675 return (GLDE_OK); 4676 } 4677 4678 /* couldn't get a stream slot */ 4679 GLDM_UNLOCK(macinfo); 4680 return (DL_TOOMANY); 4681 } 4682 4683 4684 /* 4685 * gld_disable_multi (q, mp) 4686 * Disable the multicast address on the stream. If last 4687 * reference for the mac layer, disable there as well. 4688 */ 4689 static int 4690 gld_disable_multi(queue_t *q, mblk_t *mp) 4691 { 4692 gld_t *gld; 4693 gld_mac_info_t *macinfo; 4694 unsigned char *maddr; 4695 dl_disabmulti_req_t *multi; 4696 int i; 4697 gld_mcast_t *mcast; 4698 4699 #ifdef GLD_DEBUG 4700 if (gld_debug & GLDPROT) { 4701 cmn_err(CE_NOTE, "gld_disable_multi(%p, %p)", (void *)q, 4702 (void *)mp); 4703 } 4704 #endif 4705 4706 gld = (gld_t *)q->q_ptr; 4707 if (gld->gld_state == DL_UNATTACHED) 4708 return (DL_OUTSTATE); 4709 4710 macinfo = gld->gld_mac_info; 4711 ASSERT(macinfo != NULL); 4712 if (macinfo->gldm_set_multicast == NULL) { 4713 return (DL_UNSUPPORTED); 4714 } 4715 4716 multi = (dl_disabmulti_req_t *)mp->b_rptr; 4717 4718 if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) || 4719 multi->dl_addr_length != macinfo->gldm_addrlen) 4720 return (DL_BADADDR); 4721 4722 maddr = mp->b_rptr + multi->dl_addr_offset; 4723 4724 /* request appears to be valid */ 4725 /* does this address appear in current table? */ 4726 GLDM_LOCK(macinfo, RW_WRITER); 4727 if (gld->gld_mcast != NULL) { 4728 for (i = 0; i < gld->gld_multicnt; i++) 4729 if (((mcast = gld->gld_mcast[i]) != NULL) && 4730 mac_eq(mcast->gldm_addr, 4731 maddr, macinfo->gldm_addrlen)) { 4732 ASSERT(mcast->gldm_refcnt); 4733 gld_send_disable_multi(macinfo, mcast); 4734 gld->gld_mcast[i] = NULL; 4735 GLDM_UNLOCK(macinfo); 4736 dlokack(q, mp, DL_DISABMULTI_REQ); 4737 return (GLDE_OK); 4738 } 4739 } 4740 GLDM_UNLOCK(macinfo); 4741 return (DL_NOTENAB); /* not an enabled address */ 4742 } 4743 4744 /* 4745 * gld_send_disable_multi(macinfo, mcast) 4746 * this function is used to disable a multicast address if the reference 4747 * count goes to zero. The disable request will then be forwarded to the 4748 * lower stream. 4749 */ 4750 static void 4751 gld_send_disable_multi(gld_mac_info_t *macinfo, gld_mcast_t *mcast) 4752 { 4753 ASSERT(macinfo != NULL); 4754 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 4755 ASSERT(mcast != NULL); 4756 ASSERT(mcast->gldm_refcnt); 4757 4758 if (!mcast->gldm_refcnt) { 4759 return; /* "cannot happen" */ 4760 } 4761 4762 if (--mcast->gldm_refcnt > 0) { 4763 return; 4764 } 4765 4766 /* 4767 * This must be converted from canonical form to device form. 4768 * The refcnt is now zero so we can trash the data. 4769 */ 4770 if (macinfo->gldm_options & GLDOPT_CANONICAL_ADDR) 4771 gld_bitreverse(mcast->gldm_addr, macinfo->gldm_addrlen); 4772 4773 /* XXX Ought to check for GLD_NORESOURCES or GLD_FAILURE */ 4774 (void) (*macinfo->gldm_set_multicast) 4775 (macinfo, mcast->gldm_addr, GLD_MULTI_DISABLE); 4776 } 4777 4778 /* 4779 * gld_promisc (q, mp, req, on) 4780 * enable or disable the use of promiscuous mode with the hardware 4781 */ 4782 static int 4783 gld_promisc(queue_t *q, mblk_t *mp, t_uscalar_t req, boolean_t on) 4784 { 4785 gld_t *gld; 4786 gld_mac_info_t *macinfo; 4787 gld_mac_pvt_t *mac_pvt; 4788 gld_vlan_t *vlan; 4789 union DL_primitives *prim; 4790 int macrc = GLD_SUCCESS; 4791 int dlerr = GLDE_OK; 4792 int op = GLD_MAC_PROMISC_NOOP; 4793 4794 #ifdef GLD_DEBUG 4795 if (gld_debug & GLDTRACE) 4796 cmn_err(CE_NOTE, "gld_promisc(%p, %p, %d, %d)", 4797 (void *)q, (void *)mp, req, on); 4798 #endif 4799 4800 ASSERT(mp != NULL); 4801 prim = (union DL_primitives *)mp->b_rptr; 4802 4803 /* XXX I think spec allows promisc in unattached state */ 4804 gld = (gld_t *)q->q_ptr; 4805 if (gld->gld_state == DL_UNATTACHED) 4806 return (DL_OUTSTATE); 4807 4808 macinfo = gld->gld_mac_info; 4809 ASSERT(macinfo != NULL); 4810 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 4811 4812 vlan = (gld_vlan_t *)gld->gld_vlan; 4813 ASSERT(vlan != NULL); 4814 4815 GLDM_LOCK(macinfo, RW_WRITER); 4816 4817 /* 4818 * Work out what request (if any) has to be made to the MAC layer 4819 */ 4820 if (on) { 4821 switch (prim->promiscon_req.dl_level) { 4822 default: 4823 dlerr = DL_UNSUPPORTED; /* this is an error */ 4824 break; 4825 4826 case DL_PROMISC_PHYS: 4827 if (mac_pvt->nprom == 0) 4828 op = GLD_MAC_PROMISC_PHYS; 4829 break; 4830 4831 case DL_PROMISC_MULTI: 4832 if (mac_pvt->nprom_multi == 0) 4833 if (mac_pvt->nprom == 0) 4834 op = GLD_MAC_PROMISC_MULTI; 4835 break; 4836 4837 case DL_PROMISC_SAP: 4838 /* We can do this without reference to the MAC */ 4839 break; 4840 } 4841 } else { 4842 switch (prim->promiscoff_req.dl_level) { 4843 default: 4844 dlerr = DL_UNSUPPORTED; /* this is an error */ 4845 break; 4846 4847 case DL_PROMISC_PHYS: 4848 if (!(gld->gld_flags & GLD_PROM_PHYS)) 4849 dlerr = DL_NOTENAB; 4850 else if (mac_pvt->nprom == 1) 4851 if (mac_pvt->nprom_multi) 4852 op = GLD_MAC_PROMISC_MULTI; 4853 else 4854 op = GLD_MAC_PROMISC_NONE; 4855 break; 4856 4857 case DL_PROMISC_MULTI: 4858 if (!(gld->gld_flags & GLD_PROM_MULT)) 4859 dlerr = DL_NOTENAB; 4860 else if (mac_pvt->nprom_multi == 1) 4861 if (mac_pvt->nprom == 0) 4862 op = GLD_MAC_PROMISC_NONE; 4863 break; 4864 4865 case DL_PROMISC_SAP: 4866 if (!(gld->gld_flags & GLD_PROM_SAP)) 4867 dlerr = DL_NOTENAB; 4868 4869 /* We can do this without reference to the MAC */ 4870 break; 4871 } 4872 } 4873 4874 /* 4875 * The request was invalid in some way so no need to continue. 4876 */ 4877 if (dlerr != GLDE_OK) { 4878 GLDM_UNLOCK(macinfo); 4879 return (dlerr); 4880 } 4881 4882 /* 4883 * Issue the request to the MAC layer, if required 4884 */ 4885 if (op != GLD_MAC_PROMISC_NOOP) { 4886 macrc = (*macinfo->gldm_set_promiscuous)(macinfo, op); 4887 } 4888 4889 /* 4890 * On success, update the appropriate flags & refcounts 4891 */ 4892 if (macrc == GLD_SUCCESS) { 4893 if (on) { 4894 switch (prim->promiscon_req.dl_level) { 4895 case DL_PROMISC_PHYS: 4896 mac_pvt->nprom++; 4897 gld->gld_flags |= GLD_PROM_PHYS; 4898 break; 4899 4900 case DL_PROMISC_MULTI: 4901 mac_pvt->nprom_multi++; 4902 gld->gld_flags |= GLD_PROM_MULT; 4903 break; 4904 4905 case DL_PROMISC_SAP: 4906 gld->gld_flags |= GLD_PROM_SAP; 4907 break; 4908 4909 default: 4910 break; 4911 } 4912 } else { 4913 switch (prim->promiscoff_req.dl_level) { 4914 case DL_PROMISC_PHYS: 4915 mac_pvt->nprom--; 4916 gld->gld_flags &= ~GLD_PROM_PHYS; 4917 break; 4918 4919 case DL_PROMISC_MULTI: 4920 mac_pvt->nprom_multi--; 4921 gld->gld_flags &= ~GLD_PROM_MULT; 4922 break; 4923 4924 case DL_PROMISC_SAP: 4925 gld->gld_flags &= ~GLD_PROM_SAP; 4926 break; 4927 4928 default: 4929 break; 4930 } 4931 } 4932 } else if (macrc == GLD_RETRY) { 4933 /* 4934 * The putbq and gld_xwait must be within the lock to 4935 * prevent races with gld_sched. 4936 */ 4937 (void) putbq(q, mp); 4938 gld->gld_xwait = B_TRUE; 4939 } 4940 4941 /* 4942 * Update VLAN IPQ status -- it may have changed 4943 */ 4944 if (gld->gld_flags & (GLD_PROM_SAP | GLD_PROM_MULT | GLD_PROM_PHYS)) 4945 vlan->gldv_ipq_flags |= IPQ_FORBIDDEN; 4946 else 4947 vlan->gldv_ipq_flags &= ~IPQ_FORBIDDEN; 4948 4949 GLDM_UNLOCK(macinfo); 4950 4951 /* 4952 * Finally, decide how to reply. 4953 * 4954 * If <macrc> is not GLD_SUCCESS, the request was put to the MAC 4955 * layer but failed. In such cases, we can return a DL_* error 4956 * code and let the caller send an error-ack reply upstream, or 4957 * we can send a reply here and then return GLDE_OK so that the 4958 * caller doesn't also respond. 4959 * 4960 * If physical-promiscuous mode was (successfully) switched on or 4961 * off, send a notification (DL_NOTIFY_IND) to anyone interested. 4962 */ 4963 switch (macrc) { 4964 case GLD_NOTSUPPORTED: 4965 return (DL_NOTSUPPORTED); 4966 4967 case GLD_NORESOURCES: 4968 dlerrorack(q, mp, req, DL_SYSERR, ENOSR); 4969 return (GLDE_OK); 4970 4971 case GLD_RETRY: 4972 return (GLDE_RETRY); 4973 4974 default: 4975 dlerrorack(q, mp, req, DL_SYSERR, EIO); 4976 return (GLDE_OK); 4977 4978 case GLD_SUCCESS: 4979 dlokack(q, mp, req); 4980 break; 4981 } 4982 4983 switch (op) { 4984 case GLD_MAC_PROMISC_NOOP: 4985 break; 4986 4987 case GLD_MAC_PROMISC_PHYS: 4988 gld_notify_ind(macinfo, DL_NOTE_PROMISC_ON_PHYS, NULL); 4989 break; 4990 4991 default: 4992 gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL); 4993 break; 4994 } 4995 4996 return (GLDE_OK); 4997 } 4998 4999 /* 5000 * gld_physaddr() 5001 * get the current or factory physical address value 5002 */ 5003 static int 5004 gld_physaddr(queue_t *q, mblk_t *mp) 5005 { 5006 gld_t *gld = (gld_t *)q->q_ptr; 5007 gld_mac_info_t *macinfo; 5008 union DL_primitives *prim = (union DL_primitives *)mp->b_rptr; 5009 unsigned char addr[GLD_MAX_ADDRLEN]; 5010 5011 if (gld->gld_state == DL_UNATTACHED) 5012 return (DL_OUTSTATE); 5013 5014 macinfo = (gld_mac_info_t *)gld->gld_mac_info; 5015 ASSERT(macinfo != NULL); 5016 ASSERT(macinfo->gldm_addrlen <= GLD_MAX_ADDRLEN); 5017 5018 switch (prim->physaddr_req.dl_addr_type) { 5019 case DL_FACT_PHYS_ADDR: 5020 mac_copy((caddr_t)macinfo->gldm_vendor_addr, 5021 (caddr_t)addr, macinfo->gldm_addrlen); 5022 break; 5023 case DL_CURR_PHYS_ADDR: 5024 /* make a copy so we don't hold the lock across qreply */ 5025 GLDM_LOCK(macinfo, RW_WRITER); 5026 mac_copy((caddr_t) 5027 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr, 5028 (caddr_t)addr, macinfo->gldm_addrlen); 5029 GLDM_UNLOCK(macinfo); 5030 break; 5031 default: 5032 return (DL_BADPRIM); 5033 } 5034 dlphysaddrack(q, mp, (caddr_t)addr, macinfo->gldm_addrlen); 5035 return (GLDE_OK); 5036 } 5037 5038 /* 5039 * gld_setaddr() 5040 * change the hardware's physical address to a user specified value 5041 */ 5042 static int 5043 gld_setaddr(queue_t *q, mblk_t *mp) 5044 { 5045 gld_t *gld = (gld_t *)q->q_ptr; 5046 gld_mac_info_t *macinfo; 5047 gld_mac_pvt_t *mac_pvt; 5048 union DL_primitives *prim = (union DL_primitives *)mp->b_rptr; 5049 unsigned char *addr; 5050 unsigned char cmaddr[GLD_MAX_ADDRLEN]; 5051 int rc; 5052 gld_vlan_t *vlan; 5053 5054 if (gld->gld_state == DL_UNATTACHED) 5055 return (DL_OUTSTATE); 5056 5057 vlan = (gld_vlan_t *)gld->gld_vlan; 5058 ASSERT(vlan != NULL); 5059 5060 if (vlan->gldv_id != VLAN_VID_NONE) 5061 return (DL_NOTSUPPORTED); 5062 5063 macinfo = (gld_mac_info_t *)gld->gld_mac_info; 5064 ASSERT(macinfo != NULL); 5065 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5066 5067 if (!MBLKIN(mp, prim->set_physaddr_req.dl_addr_offset, 5068 prim->set_physaddr_req.dl_addr_length) || 5069 prim->set_physaddr_req.dl_addr_length != macinfo->gldm_addrlen) 5070 return (DL_BADADDR); 5071 5072 GLDM_LOCK(macinfo, RW_WRITER); 5073 5074 /* now do the set at the hardware level */ 5075 addr = mp->b_rptr + prim->set_physaddr_req.dl_addr_offset; 5076 ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen); 5077 cmac_copy(addr, cmaddr, macinfo->gldm_addrlen, macinfo); 5078 5079 rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr); 5080 if (rc == GLD_SUCCESS) 5081 mac_copy(addr, mac_pvt->curr_macaddr, 5082 macinfo->gldm_addrlen); 5083 5084 GLDM_UNLOCK(macinfo); 5085 5086 switch (rc) { 5087 case GLD_SUCCESS: 5088 break; 5089 case GLD_NOTSUPPORTED: 5090 return (DL_NOTSUPPORTED); 5091 case GLD_BADARG: 5092 return (DL_BADADDR); 5093 case GLD_NORESOURCES: 5094 dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOSR); 5095 return (GLDE_OK); 5096 default: 5097 dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, EIO); 5098 return (GLDE_OK); 5099 } 5100 5101 gld_notify_ind(macinfo, DL_NOTE_PHYS_ADDR, NULL); 5102 5103 dlokack(q, mp, DL_SET_PHYS_ADDR_REQ); 5104 return (GLDE_OK); 5105 } 5106 5107 int 5108 gld_get_statistics(queue_t *q, mblk_t *mp) 5109 { 5110 dl_get_statistics_ack_t *dlsp; 5111 gld_t *gld = (gld_t *)q->q_ptr; 5112 gld_mac_info_t *macinfo = gld->gld_mac_info; 5113 gld_mac_pvt_t *mac_pvt; 5114 5115 if (gld->gld_state == DL_UNATTACHED) 5116 return (DL_OUTSTATE); 5117 5118 ASSERT(macinfo != NULL); 5119 5120 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5121 (void) gld_update_kstat(mac_pvt->kstatp, KSTAT_READ); 5122 5123 mp = mexchange(q, mp, DL_GET_STATISTICS_ACK_SIZE + 5124 sizeof (struct gldkstats), M_PCPROTO, DL_GET_STATISTICS_ACK); 5125 5126 if (mp == NULL) 5127 return (GLDE_OK); /* mexchange already sent merror */ 5128 5129 dlsp = (dl_get_statistics_ack_t *)mp->b_rptr; 5130 dlsp->dl_primitive = DL_GET_STATISTICS_ACK; 5131 dlsp->dl_stat_length = sizeof (struct gldkstats); 5132 dlsp->dl_stat_offset = DL_GET_STATISTICS_ACK_SIZE; 5133 5134 GLDM_LOCK(macinfo, RW_WRITER); 5135 bcopy(mac_pvt->kstatp->ks_data, 5136 (mp->b_rptr + DL_GET_STATISTICS_ACK_SIZE), 5137 sizeof (struct gldkstats)); 5138 GLDM_UNLOCK(macinfo); 5139 5140 qreply(q, mp); 5141 return (GLDE_OK); 5142 } 5143 5144 /* =================================================== */ 5145 /* misc utilities, some requiring various mutexes held */ 5146 /* =================================================== */ 5147 5148 /* 5149 * Initialize and start the driver. 5150 */ 5151 static int 5152 gld_start_mac(gld_mac_info_t *macinfo) 5153 { 5154 int rc; 5155 unsigned char cmaddr[GLD_MAX_ADDRLEN]; 5156 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5157 5158 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 5159 ASSERT(!mac_pvt->started); 5160 5161 rc = (*macinfo->gldm_reset)(macinfo); 5162 if (rc != GLD_SUCCESS) 5163 return (GLD_FAILURE); 5164 5165 /* set the addr after we reset the device */ 5166 ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen); 5167 cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt) 5168 ->curr_macaddr, cmaddr, macinfo->gldm_addrlen, macinfo); 5169 5170 rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr); 5171 ASSERT(rc != GLD_BADARG); /* this address was good before */ 5172 if (rc != GLD_SUCCESS && rc != GLD_NOTSUPPORTED) 5173 return (GLD_FAILURE); 5174 5175 rc = (*macinfo->gldm_start)(macinfo); 5176 if (rc != GLD_SUCCESS) 5177 return (GLD_FAILURE); 5178 5179 mac_pvt->started = B_TRUE; 5180 return (GLD_SUCCESS); 5181 } 5182 5183 /* 5184 * Stop the driver. 5185 */ 5186 static void 5187 gld_stop_mac(gld_mac_info_t *macinfo) 5188 { 5189 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5190 5191 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 5192 ASSERT(mac_pvt->started); 5193 5194 (void) (*macinfo->gldm_stop)(macinfo); 5195 5196 mac_pvt->started = B_FALSE; 5197 } 5198 5199 5200 /* 5201 * gld_set_ipq will set a pointer to the queue which is bound to the 5202 * IP sap if: 5203 * o the device type is ethernet or IPoIB. 5204 * o there is no stream in SAP promiscuous mode. 5205 * o there is exactly one stream bound to the IP sap. 5206 * o the stream is in "fastpath" mode. 5207 */ 5208 static void 5209 gld_set_ipq(gld_t *gld) 5210 { 5211 gld_vlan_t *vlan; 5212 gld_mac_info_t *macinfo = gld->gld_mac_info; 5213 gld_t *ip_gld = NULL; 5214 uint_t ipq_candidates = 0; 5215 gld_t *ipv6_gld = NULL; 5216 uint_t ipv6q_candidates = 0; 5217 5218 ASSERT(GLDM_LOCK_HELD_WRITE(macinfo)); 5219 5220 /* The ipq code in gld_recv() is intimate with ethernet/IPoIB */ 5221 if (((macinfo->gldm_type != DL_ETHER) && 5222 (macinfo->gldm_type != DL_IB)) || 5223 (gld_global_options & GLD_OPT_NO_IPQ)) 5224 return; 5225 5226 vlan = (gld_vlan_t *)gld->gld_vlan; 5227 ASSERT(vlan != NULL); 5228 5229 /* clear down any previously defined ipqs */ 5230 vlan->gldv_ipq = NULL; 5231 vlan->gldv_ipv6q = NULL; 5232 5233 /* Try to find a single stream eligible to receive IP packets */ 5234 for (gld = vlan->gldv_str_next; 5235 gld != (gld_t *)&vlan->gldv_str_next; gld = gld->gld_next) { 5236 if (gld->gld_state != DL_IDLE) 5237 continue; /* not eligible to receive */ 5238 if (gld->gld_flags & GLD_STR_CLOSING) 5239 continue; /* not eligible to receive */ 5240 5241 if (gld->gld_sap == ETHERTYPE_IP) { 5242 ip_gld = gld; 5243 ipq_candidates++; 5244 } 5245 5246 if (gld->gld_sap == ETHERTYPE_IPV6) { 5247 ipv6_gld = gld; 5248 ipv6q_candidates++; 5249 } 5250 } 5251 5252 if (ipq_candidates == 1) { 5253 ASSERT(ip_gld != NULL); 5254 5255 if (ip_gld->gld_flags & GLD_FAST) /* eligible for ipq */ 5256 vlan->gldv_ipq = ip_gld->gld_qptr; 5257 } 5258 5259 if (ipv6q_candidates == 1) { 5260 ASSERT(ipv6_gld != NULL); 5261 5262 if (ipv6_gld->gld_flags & GLD_FAST) /* eligible for ipq */ 5263 vlan->gldv_ipv6q = ipv6_gld->gld_qptr; 5264 } 5265 } 5266 5267 /* 5268 * gld_flushqueue (q) 5269 * used by DLPI primitives that require flushing the queues. 5270 * essentially, this is DL_UNBIND_REQ. 5271 */ 5272 static void 5273 gld_flushqueue(queue_t *q) 5274 { 5275 /* flush all data in both queues */ 5276 /* XXX Should these be FLUSHALL? */ 5277 flushq(q, FLUSHDATA); 5278 flushq(WR(q), FLUSHDATA); 5279 /* flush all the queues upstream */ 5280 (void) putctl1(q, M_FLUSH, FLUSHRW); 5281 } 5282 5283 /* 5284 * gld_devlookup (major) 5285 * search the device table for the device with specified 5286 * major number and return a pointer to it if it exists 5287 */ 5288 static glddev_t * 5289 gld_devlookup(int major) 5290 { 5291 struct glddevice *dev; 5292 5293 ASSERT(mutex_owned(&gld_device_list.gld_devlock)); 5294 5295 for (dev = gld_device_list.gld_next; 5296 dev != &gld_device_list; 5297 dev = dev->gld_next) { 5298 ASSERT(dev); 5299 if (dev->gld_major == major) 5300 return (dev); 5301 } 5302 return (NULL); 5303 } 5304 5305 /* 5306 * gld_findminor(device) 5307 * Returns a minor number currently unused by any stream in the current 5308 * device class (major) list. 5309 */ 5310 static int 5311 gld_findminor(glddev_t *device) 5312 { 5313 gld_t *next; 5314 gld_mac_info_t *nextmac; 5315 gld_vlan_t *nextvlan; 5316 int minor; 5317 int i; 5318 5319 ASSERT(mutex_owned(&device->gld_devlock)); 5320 5321 /* The fast way */ 5322 if (device->gld_nextminor >= GLD_MIN_CLONE_MINOR && 5323 device->gld_nextminor <= GLD_MAX_CLONE_MINOR) 5324 return (device->gld_nextminor++); 5325 5326 /* The steady way */ 5327 for (minor = GLD_MIN_CLONE_MINOR; minor <= GLD_MAX_CLONE_MINOR; 5328 minor++) { 5329 /* Search all unattached streams */ 5330 for (next = device->gld_str_next; 5331 next != (gld_t *)&device->gld_str_next; 5332 next = next->gld_next) { 5333 if (minor == next->gld_minor) 5334 goto nextminor; 5335 } 5336 /* Search all attached streams; we don't need maclock because */ 5337 /* mac stream list is protected by devlock as well as maclock */ 5338 for (nextmac = device->gld_mac_next; 5339 nextmac != (gld_mac_info_t *)&device->gld_mac_next; 5340 nextmac = nextmac->gldm_next) { 5341 gld_mac_pvt_t *pvt = 5342 (gld_mac_pvt_t *)nextmac->gldm_mac_pvt; 5343 5344 if (!(nextmac->gldm_GLD_flags & GLD_MAC_READY)) 5345 continue; /* this one's not ready yet */ 5346 5347 for (i = 0; i < VLAN_HASHSZ; i++) { 5348 for (nextvlan = pvt->vlan_hash[i]; 5349 nextvlan != NULL; 5350 nextvlan = nextvlan->gldv_next) { 5351 for (next = nextvlan->gldv_str_next; 5352 next != 5353 (gld_t *)&nextvlan->gldv_str_next; 5354 next = next->gld_next) { 5355 if (minor == next->gld_minor) 5356 goto nextminor; 5357 } 5358 } 5359 } 5360 } 5361 5362 return (minor); 5363 nextminor: 5364 /* don't need to do anything */ 5365 ; 5366 } 5367 cmn_err(CE_WARN, "GLD ran out of minor numbers for %s", 5368 device->gld_name); 5369 return (0); 5370 } 5371 5372 /* 5373 * version of insque/remque for use by this driver 5374 */ 5375 struct qelem { 5376 struct qelem *q_forw; 5377 struct qelem *q_back; 5378 /* rest of structure */ 5379 }; 5380 5381 static void 5382 gldinsque(void *elem, void *pred) 5383 { 5384 struct qelem *pelem = elem; 5385 struct qelem *ppred = pred; 5386 struct qelem *pnext = ppred->q_forw; 5387 5388 pelem->q_forw = pnext; 5389 pelem->q_back = ppred; 5390 ppred->q_forw = pelem; 5391 pnext->q_back = pelem; 5392 } 5393 5394 static void 5395 gldremque(void *arg) 5396 { 5397 struct qelem *pelem = arg; 5398 struct qelem *elem = arg; 5399 5400 pelem->q_forw->q_back = pelem->q_back; 5401 pelem->q_back->q_forw = pelem->q_forw; 5402 elem->q_back = elem->q_forw = NULL; 5403 } 5404 5405 static gld_vlan_t * 5406 gld_add_vlan(gld_mac_info_t *macinfo, uint32_t vid) 5407 { 5408 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5409 gld_vlan_t **pp; 5410 gld_vlan_t *p; 5411 5412 pp = &(mac_pvt->vlan_hash[vid % VLAN_HASHSZ]); 5413 while ((p = *pp) != NULL) { 5414 ASSERT(p->gldv_id != vid); 5415 pp = &(p->gldv_next); 5416 } 5417 5418 if ((p = kmem_zalloc(sizeof (gld_vlan_t), KM_NOSLEEP)) == NULL) 5419 return (NULL); 5420 5421 p->gldv_mac = macinfo; 5422 p->gldv_id = vid; 5423 5424 if (vid == VLAN_VID_NONE) { 5425 p->gldv_ptag = VLAN_VTAG_NONE; 5426 p->gldv_stats = mac_pvt->statistics; 5427 p->gldv_kstatp = NULL; 5428 } else { 5429 p->gldv_ptag = GLD_MK_PTAG(VLAN_CFI_ETHER, vid); 5430 p->gldv_stats = kmem_zalloc(sizeof (struct gld_stats), 5431 KM_SLEEP); 5432 5433 if (gld_init_vlan_stats(p) != GLD_SUCCESS) { 5434 kmem_free(p->gldv_stats, sizeof (struct gld_stats)); 5435 kmem_free(p, sizeof (gld_vlan_t)); 5436 return (NULL); 5437 } 5438 } 5439 5440 p->gldv_str_next = p->gldv_str_prev = (gld_t *)&p->gldv_str_next; 5441 mac_pvt->nvlan++; 5442 *pp = p; 5443 5444 return (p); 5445 } 5446 5447 static void 5448 gld_rem_vlan(gld_vlan_t *vlan) 5449 { 5450 gld_mac_info_t *macinfo = vlan->gldv_mac; 5451 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5452 gld_vlan_t **pp; 5453 gld_vlan_t *p; 5454 5455 pp = &(mac_pvt->vlan_hash[vlan->gldv_id % VLAN_HASHSZ]); 5456 while ((p = *pp) != NULL) { 5457 if (p->gldv_id == vlan->gldv_id) 5458 break; 5459 pp = &(p->gldv_next); 5460 } 5461 ASSERT(p != NULL); 5462 5463 *pp = p->gldv_next; 5464 mac_pvt->nvlan--; 5465 if (p->gldv_id != VLAN_VID_NONE) { 5466 ASSERT(p->gldv_kstatp != NULL); 5467 kstat_delete(p->gldv_kstatp); 5468 kmem_free(p->gldv_stats, sizeof (struct gld_stats)); 5469 } 5470 kmem_free(p, sizeof (gld_vlan_t)); 5471 } 5472 5473 gld_vlan_t * 5474 gld_find_vlan(gld_mac_info_t *macinfo, uint32_t vid) 5475 { 5476 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt; 5477 gld_vlan_t *p; 5478 5479 p = mac_pvt->vlan_hash[vid % VLAN_HASHSZ]; 5480 while (p != NULL) { 5481 if (p->gldv_id == vid) 5482 return (p); 5483 p = p->gldv_next; 5484 } 5485 return (NULL); 5486 } 5487 5488 gld_vlan_t * 5489 gld_get_vlan(gld_mac_info_t *macinfo, uint32_t vid) 5490 { 5491 gld_vlan_t *vlan; 5492 5493 if ((vlan = gld_find_vlan(macinfo, vid)) == NULL) 5494 vlan = gld_add_vlan(macinfo, vid); 5495 5496 return (vlan); 5497 } 5498 5499 /* 5500 * gld_bitrevcopy() 5501 * This is essentially bcopy, with the ability to bit reverse the 5502 * the source bytes. The MAC addresses bytes as transmitted by FDDI 5503 * interfaces are bit reversed. 5504 */ 5505 void 5506 gld_bitrevcopy(caddr_t src, caddr_t target, size_t n) 5507 { 5508 while (n--) 5509 *target++ = bit_rev[(uchar_t)*src++]; 5510 } 5511 5512 /* 5513 * gld_bitreverse() 5514 * Convert the bit order by swaping all the bits, using a 5515 * lookup table. 5516 */ 5517 void 5518 gld_bitreverse(uchar_t *rptr, size_t n) 5519 { 5520 while (n--) { 5521 *rptr = bit_rev[*rptr]; 5522 rptr++; 5523 } 5524 } 5525 5526 char * 5527 gld_macaddr_sprintf(char *etherbuf, unsigned char *ap, int len) 5528 { 5529 int i; 5530 char *cp = etherbuf; 5531 static char digits[] = "0123456789abcdef"; 5532 5533 for (i = 0; i < len; i++) { 5534 *cp++ = digits[*ap >> 4]; 5535 *cp++ = digits[*ap++ & 0xf]; 5536 *cp++ = ':'; 5537 } 5538 *--cp = 0; 5539 return (etherbuf); 5540 } 5541 5542 #ifdef GLD_DEBUG 5543 static void 5544 gld_check_assertions() 5545 { 5546 glddev_t *dev; 5547 gld_mac_info_t *mac; 5548 gld_t *str; 5549 gld_vlan_t *vlan; 5550 int i; 5551 5552 mutex_enter(&gld_device_list.gld_devlock); 5553 5554 for (dev = gld_device_list.gld_next; 5555 dev != (glddev_t *)&gld_device_list.gld_next; 5556 dev = dev->gld_next) { 5557 mutex_enter(&dev->gld_devlock); 5558 ASSERT(dev->gld_broadcast != NULL); 5559 for (str = dev->gld_str_next; 5560 str != (gld_t *)&dev->gld_str_next; 5561 str = str->gld_next) { 5562 ASSERT(str->gld_device == dev); 5563 ASSERT(str->gld_mac_info == NULL); 5564 ASSERT(str->gld_qptr != NULL); 5565 ASSERT(str->gld_minor >= GLD_MIN_CLONE_MINOR); 5566 ASSERT(str->gld_multicnt == 0); 5567 ASSERT(str->gld_mcast == NULL); 5568 ASSERT(!(str->gld_flags & 5569 (GLD_PROM_PHYS|GLD_PROM_MULT|GLD_PROM_SAP))); 5570 ASSERT(str->gld_sap == 0); 5571 ASSERT(str->gld_state == DL_UNATTACHED); 5572 } 5573 for (mac = dev->gld_mac_next; 5574 mac != (gld_mac_info_t *)&dev->gld_mac_next; 5575 mac = mac->gldm_next) { 5576 int nvlan = 0; 5577 gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt; 5578 5579 if (!(mac->gldm_GLD_flags & GLD_MAC_READY)) 5580 continue; /* this one's not ready yet */ 5581 5582 GLDM_LOCK(mac, RW_WRITER); 5583 ASSERT(mac->gldm_devinfo != NULL); 5584 ASSERT(mac->gldm_mac_pvt != NULL); 5585 ASSERT(pvt->interfacep != NULL); 5586 ASSERT(pvt->kstatp != NULL); 5587 ASSERT(pvt->statistics != NULL); 5588 ASSERT(pvt->major_dev == dev); 5589 5590 for (i = 0; i < VLAN_HASHSZ; i++) { 5591 for (vlan = pvt->vlan_hash[i]; 5592 vlan != NULL; vlan = vlan->gldv_next) { 5593 int nstr = 0; 5594 5595 ASSERT(vlan->gldv_mac == mac); 5596 5597 for (str = vlan->gldv_str_next; 5598 str != 5599 (gld_t *)&vlan->gldv_str_next; 5600 str = str->gld_next) { 5601 ASSERT(str->gld_device == dev); 5602 ASSERT(str->gld_mac_info == 5603 mac); 5604 ASSERT(str->gld_qptr != NULL); 5605 ASSERT(str->gld_minor >= 5606 GLD_MIN_CLONE_MINOR); 5607 ASSERT( 5608 str->gld_multicnt == 0 || 5609 str->gld_mcast); 5610 nstr++; 5611 } 5612 ASSERT(vlan->gldv_nstreams == nstr); 5613 nvlan++; 5614 } 5615 } 5616 ASSERT(pvt->nvlan == nvlan); 5617 GLDM_UNLOCK(mac); 5618 } 5619 mutex_exit(&dev->gld_devlock); 5620 } 5621 mutex_exit(&gld_device_list.gld_devlock); 5622 } 5623 #endif 5624