xref: /titanic_44/usr/src/uts/common/io/mac/mac.c (revision e5ba14ff435beeefdaa2e6649e175c74afe02c76)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 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  * MAC Services Module
31  */
32 
33 #include <sys/types.h>
34 #include <sys/conf.h>
35 #include <sys/stat.h>
36 #include <sys/stream.h>
37 #include <sys/strsun.h>
38 #include <sys/strsubr.h>
39 #include <sys/dlpi.h>
40 #include <sys/modhash.h>
41 #include <sys/mac.h>
42 #include <sys/mac_impl.h>
43 #include <sys/dls.h>
44 #include <sys/dld.h>
45 #include <sys/modctl.h>
46 #include <sys/fs/dv_node.h>
47 #include <sys/thread.h>
48 #include <sys/proc.h>
49 #include <sys/callb.h>
50 #include <sys/cpuvar.h>
51 #include <sys/atomic.h>
52 #include <sys/sdt.h>
53 
54 #define	IMPL_HASHSZ	67	/* prime */
55 
56 static kmem_cache_t	*i_mac_impl_cachep;
57 static mod_hash_t	*i_mac_impl_hash;
58 krwlock_t		i_mac_impl_lock;
59 uint_t			i_mac_impl_count;
60 static kmem_cache_t	*mac_vnic_tx_cache;
61 
62 #define	MACTYPE_KMODDIR	"mac"
63 #define	MACTYPE_HASHSZ	67
64 static mod_hash_t	*i_mactype_hash;
65 /*
66  * i_mactype_lock synchronizes threads that obtain references to mactype_t
67  * structures through i_mactype_getplugin().
68  */
69 static kmutex_t		i_mactype_lock;
70 
71 static void i_mac_notify_thread(void *);
72 static mblk_t *mac_vnic_tx(void *, mblk_t *);
73 static mblk_t *mac_vnic_txloop(void *, mblk_t *);
74 
75 /*
76  * Private functions.
77  */
78 
79 /*ARGSUSED*/
80 static int
81 i_mac_constructor(void *buf, void *arg, int kmflag)
82 {
83 	mac_impl_t	*mip = buf;
84 
85 	bzero(buf, sizeof (mac_impl_t));
86 
87 	mip->mi_linkstate = LINK_STATE_UNKNOWN;
88 
89 	rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL);
90 	rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL);
91 	rw_init(&mip->mi_notify_lock, NULL, RW_DRIVER, NULL);
92 	rw_init(&mip->mi_rx_lock, NULL, RW_DRIVER, NULL);
93 	rw_init(&mip->mi_tx_lock, NULL, RW_DRIVER, NULL);
94 	rw_init(&mip->mi_resource_lock, NULL, RW_DRIVER, NULL);
95 	mutex_init(&mip->mi_activelink_lock, NULL, MUTEX_DEFAULT, NULL);
96 	mutex_init(&mip->mi_notify_bits_lock, NULL, MUTEX_DRIVER, NULL);
97 	cv_init(&mip->mi_notify_cv, NULL, CV_DRIVER, NULL);
98 	mutex_init(&mip->mi_lock, NULL, MUTEX_DRIVER, NULL);
99 	cv_init(&mip->mi_rx_cv, NULL, CV_DRIVER, NULL);
100 	return (0);
101 }
102 
103 /*ARGSUSED*/
104 static void
105 i_mac_destructor(void *buf, void *arg)
106 {
107 	mac_impl_t	*mip = buf;
108 
109 	ASSERT(mip->mi_ref == 0);
110 	ASSERT(mip->mi_active == 0);
111 	ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN);
112 	ASSERT(mip->mi_devpromisc == 0);
113 	ASSERT(mip->mi_promisc == 0);
114 	ASSERT(mip->mi_mmap == NULL);
115 	ASSERT(mip->mi_mnfp == NULL);
116 	ASSERT(mip->mi_resource_add == NULL);
117 	ASSERT(mip->mi_ksp == NULL);
118 	ASSERT(mip->mi_kstat_count == 0);
119 	ASSERT(mip->mi_notify_bits == 0);
120 	ASSERT(mip->mi_notify_thread == NULL);
121 
122 	rw_destroy(&mip->mi_state_lock);
123 	rw_destroy(&mip->mi_data_lock);
124 	rw_destroy(&mip->mi_notify_lock);
125 	rw_destroy(&mip->mi_rx_lock);
126 	rw_destroy(&mip->mi_tx_lock);
127 	rw_destroy(&mip->mi_resource_lock);
128 	mutex_destroy(&mip->mi_activelink_lock);
129 	mutex_destroy(&mip->mi_notify_bits_lock);
130 	cv_destroy(&mip->mi_notify_cv);
131 	mutex_destroy(&mip->mi_lock);
132 	cv_destroy(&mip->mi_rx_cv);
133 }
134 
135 /*
136  * mac_vnic_tx_t kmem cache support functions.
137  */
138 
139 /* ARGSUSED */
140 static int
141 i_mac_vnic_tx_ctor(void *buf, void *arg, int mkflag)
142 {
143 	mac_vnic_tx_t *vnic_tx = buf;
144 
145 	bzero(buf, sizeof (mac_vnic_tx_t));
146 	mutex_init(&vnic_tx->mv_lock, NULL, MUTEX_DRIVER, NULL);
147 	cv_init(&vnic_tx->mv_cv, NULL, CV_DRIVER, NULL);
148 	return (0);
149 }
150 
151 /* ARGSUSED */
152 static void
153 i_mac_vnic_tx_dtor(void *buf, void *arg)
154 {
155 	mac_vnic_tx_t *vnic_tx = buf;
156 
157 	ASSERT(vnic_tx->mv_refs == 0);
158 	mutex_destroy(&vnic_tx->mv_lock);
159 	cv_destroy(&vnic_tx->mv_cv);
160 }
161 
162 static void
163 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type)
164 {
165 	rw_enter(&i_mac_impl_lock, RW_READER);
166 	if (mip->mi_disabled)
167 		goto exit;
168 
169 	/*
170 	 * Guard against incorrect notifications.  (Running a newer
171 	 * mac client against an older implementation?)
172 	 */
173 	if (type >= MAC_NNOTE)
174 		goto exit;
175 
176 	mutex_enter(&mip->mi_notify_bits_lock);
177 	mip->mi_notify_bits |= (1 << type);
178 	cv_broadcast(&mip->mi_notify_cv);
179 	mutex_exit(&mip->mi_notify_bits_lock);
180 
181 exit:
182 	rw_exit(&i_mac_impl_lock);
183 }
184 
185 static void
186 i_mac_log_link_state(mac_impl_t *mip)
187 {
188 	/*
189 	 * If no change, then it is not interesting.
190 	 */
191 	if (mip->mi_lastlinkstate == mip->mi_linkstate)
192 		return;
193 
194 	switch (mip->mi_linkstate) {
195 	case LINK_STATE_UP:
196 		if (mip->mi_type->mt_ops.mtops_ops & MTOPS_LINK_DETAILS) {
197 			char det[200];
198 
199 			mip->mi_type->mt_ops.mtops_link_details(det,
200 			    sizeof (det), (mac_handle_t)mip, mip->mi_pdata);
201 
202 			cmn_err(CE_NOTE, "!%s link up, %s", mip->mi_name, det);
203 		} else {
204 			cmn_err(CE_NOTE, "!%s link up", mip->mi_name);
205 		}
206 		break;
207 
208 	case LINK_STATE_DOWN:
209 		/*
210 		 * Only transitions from UP to DOWN are interesting
211 		 */
212 		if (mip->mi_lastlinkstate != LINK_STATE_UNKNOWN)
213 			cmn_err(CE_NOTE, "!%s link down", mip->mi_name);
214 		break;
215 
216 	case LINK_STATE_UNKNOWN:
217 		/*
218 		 * This case is normally not interesting.
219 		 */
220 		break;
221 	}
222 	mip->mi_lastlinkstate = mip->mi_linkstate;
223 }
224 
225 static void
226 i_mac_notify_thread(void *arg)
227 {
228 	mac_impl_t	*mip = arg;
229 	callb_cpr_t	cprinfo;
230 
231 	CALLB_CPR_INIT(&cprinfo, &mip->mi_notify_bits_lock, callb_generic_cpr,
232 	    "i_mac_notify_thread");
233 
234 	mutex_enter(&mip->mi_notify_bits_lock);
235 	for (;;) {
236 		uint32_t	bits;
237 		uint32_t	type;
238 
239 		bits = mip->mi_notify_bits;
240 		if (bits == 0) {
241 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
242 			cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock);
243 			CALLB_CPR_SAFE_END(&cprinfo, &mip->mi_notify_bits_lock);
244 			continue;
245 		}
246 		mip->mi_notify_bits = 0;
247 
248 		if ((bits & (1 << MAC_NNOTE)) != 0) {
249 			/* request to quit */
250 			ASSERT(mip->mi_disabled);
251 			break;
252 		}
253 
254 		mutex_exit(&mip->mi_notify_bits_lock);
255 
256 		/*
257 		 * Log link changes.
258 		 */
259 		if ((bits & (1 << MAC_NOTE_LINK)) != 0)
260 			i_mac_log_link_state(mip);
261 
262 		/*
263 		 * Do notification callbacks for each notification type.
264 		 */
265 		for (type = 0; type < MAC_NNOTE; type++) {
266 			mac_notify_fn_t	*mnfp;
267 
268 			if ((bits & (1 << type)) == 0) {
269 				continue;
270 			}
271 
272 			/*
273 			 * Walk the list of notifications.
274 			 */
275 			rw_enter(&mip->mi_notify_lock, RW_READER);
276 			for (mnfp = mip->mi_mnfp; mnfp != NULL;
277 			    mnfp = mnfp->mnf_nextp) {
278 
279 				mnfp->mnf_fn(mnfp->mnf_arg, type);
280 			}
281 			rw_exit(&mip->mi_notify_lock);
282 		}
283 
284 		mutex_enter(&mip->mi_notify_bits_lock);
285 	}
286 
287 	mip->mi_notify_thread = NULL;
288 	cv_broadcast(&mip->mi_notify_cv);
289 
290 	CALLB_CPR_EXIT(&cprinfo);
291 
292 	thread_exit();
293 }
294 
295 static mactype_t *
296 i_mactype_getplugin(const char *pname)
297 {
298 	mactype_t	*mtype = NULL;
299 	boolean_t	tried_modload = B_FALSE;
300 
301 	mutex_enter(&i_mactype_lock);
302 
303 find_registered_mactype:
304 	if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)pname,
305 	    (mod_hash_val_t *)&mtype) != 0) {
306 		if (!tried_modload) {
307 			/*
308 			 * If the plugin has not yet been loaded, then
309 			 * attempt to load it now.  If modload() succeeds,
310 			 * the plugin should have registered using
311 			 * mactype_register(), in which case we can go back
312 			 * and attempt to find it again.
313 			 */
314 			if (modload(MACTYPE_KMODDIR, (char *)pname) != -1) {
315 				tried_modload = B_TRUE;
316 				goto find_registered_mactype;
317 			}
318 		}
319 	} else {
320 		/*
321 		 * Note that there's no danger that the plugin we've loaded
322 		 * could be unloaded between the modload() step and the
323 		 * reference count bump here, as we're holding
324 		 * i_mactype_lock, which mactype_unregister() also holds.
325 		 */
326 		atomic_inc_32(&mtype->mt_ref);
327 	}
328 
329 	mutex_exit(&i_mactype_lock);
330 	return (mtype);
331 }
332 
333 /*
334  * Module initialization functions.
335  */
336 
337 void
338 mac_init(void)
339 {
340 	i_mac_impl_cachep = kmem_cache_create("mac_impl_cache",
341 	    sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor,
342 	    NULL, NULL, NULL, 0);
343 	ASSERT(i_mac_impl_cachep != NULL);
344 
345 	mac_vnic_tx_cache = kmem_cache_create("mac_vnic_tx_cache",
346 	    sizeof (mac_vnic_tx_t), 0, i_mac_vnic_tx_ctor, i_mac_vnic_tx_dtor,
347 	    NULL, NULL, NULL, 0);
348 	ASSERT(mac_vnic_tx_cache != NULL);
349 
350 	i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash",
351 	    IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
352 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
353 	rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL);
354 	i_mac_impl_count = 0;
355 
356 	i_mactype_hash = mod_hash_create_extended("mactype_hash",
357 	    MACTYPE_HASHSZ,
358 	    mod_hash_null_keydtor, mod_hash_null_valdtor,
359 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
360 }
361 
362 int
363 mac_fini(void)
364 {
365 	if (i_mac_impl_count > 0)
366 		return (EBUSY);
367 
368 	mod_hash_destroy_hash(i_mac_impl_hash);
369 	rw_destroy(&i_mac_impl_lock);
370 
371 	kmem_cache_destroy(i_mac_impl_cachep);
372 	kmem_cache_destroy(mac_vnic_tx_cache);
373 
374 	mod_hash_destroy_hash(i_mactype_hash);
375 	return (0);
376 }
377 
378 /*
379  * Client functions.
380  */
381 
382 int
383 mac_open(const char *macname, uint_t ddi_instance, mac_handle_t *mhp)
384 {
385 	char		driver[MAXNAMELEN];
386 	uint_t		instance;
387 	major_t		major;
388 	dev_info_t	*dip;
389 	mac_impl_t	*mip;
390 	int		err;
391 
392 	/*
393 	 * Check the device name length to make sure it won't overflow our
394 	 * buffer.
395 	 */
396 	if (strlen(macname) >= MAXNAMELEN)
397 		return (EINVAL);
398 
399 	/*
400 	 * Split the device name into driver and instance components.
401 	 */
402 	if (ddi_parse(macname, driver, &instance) != DDI_SUCCESS)
403 		return (EINVAL);
404 
405 	if ((strcmp(driver, "aggr") == 0) || (strcmp(driver, "vnic") == 0))
406 		ddi_instance = 0;
407 
408 	/*
409 	 * Get the major number of the driver.
410 	 */
411 	if ((major = ddi_name_to_major(driver)) == (major_t)-1)
412 		return (EINVAL);
413 
414 	/*
415 	 * Hold the given instance to prevent it from being detached.
416 	 * This will also attach the instance if it is not currently attached.
417 	 * Currently we ensure that mac_register() (called by the driver's
418 	 * attach entry point) and all code paths under it cannot possibly
419 	 * call mac_open() because this would lead to a recursive attach
420 	 * panic.
421 	 */
422 	if ((dip = ddi_hold_devi_by_instance(major, ddi_instance, 0)) == NULL)
423 		return (EINVAL);
424 
425 	/*
426 	 * Look up its entry in the global hash table.
427 	 */
428 again:
429 	rw_enter(&i_mac_impl_lock, RW_WRITER);
430 	err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname,
431 	    (mod_hash_val_t *)&mip);
432 	if (err != 0) {
433 		err = ENOENT;
434 		goto failed;
435 	}
436 
437 	if (mip->mi_disabled) {
438 		rw_exit(&i_mac_impl_lock);
439 		goto again;
440 	}
441 
442 	mip->mi_ref++;
443 	rw_exit(&i_mac_impl_lock);
444 
445 	*mhp = (mac_handle_t)mip;
446 	return (0);
447 
448 failed:
449 	rw_exit(&i_mac_impl_lock);
450 	ddi_release_devi(dip);
451 	return (err);
452 }
453 
454 void
455 mac_close(mac_handle_t mh)
456 {
457 	mac_impl_t	*mip = (mac_impl_t *)mh;
458 	dev_info_t	*dip = mip->mi_dip;
459 
460 	rw_enter(&i_mac_impl_lock, RW_WRITER);
461 
462 	ASSERT(mip->mi_ref != 0);
463 	if (--mip->mi_ref == 0) {
464 		ASSERT(!mip->mi_activelink);
465 	}
466 	ddi_release_devi(dip);
467 	rw_exit(&i_mac_impl_lock);
468 }
469 
470 const mac_info_t *
471 mac_info(mac_handle_t mh)
472 {
473 	return (&((mac_impl_t *)mh)->mi_info);
474 }
475 
476 dev_info_t *
477 mac_devinfo_get(mac_handle_t mh)
478 {
479 	return (((mac_impl_t *)mh)->mi_dip);
480 }
481 
482 uint64_t
483 mac_stat_get(mac_handle_t mh, uint_t stat)
484 {
485 	mac_impl_t	*mip = (mac_impl_t *)mh;
486 	uint64_t	val;
487 	int		ret;
488 
489 	/*
490 	 * The range of stat determines where it is maintained.  Stat
491 	 * values from 0 up to (but not including) MAC_STAT_MIN are
492 	 * mainteined by the mac module itself.  Everything else is
493 	 * maintained by the driver.
494 	 */
495 	if (stat < MAC_STAT_MIN) {
496 		/* These stats are maintained by the mac module itself. */
497 		switch (stat) {
498 		case MAC_STAT_LINK_STATE:
499 			return (mip->mi_linkstate);
500 		case MAC_STAT_LINK_UP:
501 			return (mip->mi_linkstate == LINK_STATE_UP);
502 		case MAC_STAT_PROMISC:
503 			return (mip->mi_devpromisc != 0);
504 		default:
505 			ASSERT(B_FALSE);
506 		}
507 	}
508 
509 	/*
510 	 * Call the driver to get the given statistic.
511 	 */
512 	ret = mip->mi_getstat(mip->mi_driver, stat, &val);
513 	if (ret != 0) {
514 		/*
515 		 * The driver doesn't support this statistic.  Get the
516 		 * statistic's default value.
517 		 */
518 		val = mac_stat_default(mip, stat);
519 	}
520 	return (val);
521 }
522 
523 int
524 mac_start(mac_handle_t mh)
525 {
526 	mac_impl_t	*mip = (mac_impl_t *)mh;
527 	int		err;
528 
529 	ASSERT(mip->mi_start != NULL);
530 
531 	rw_enter(&(mip->mi_state_lock), RW_WRITER);
532 
533 	/*
534 	 * Check whether the device is already started.
535 	 */
536 	if (mip->mi_active++ != 0) {
537 		/*
538 		 * It's already started so there's nothing more to do.
539 		 */
540 		err = 0;
541 		goto done;
542 	}
543 
544 	/*
545 	 * Start the device.
546 	 */
547 	if ((err = mip->mi_start(mip->mi_driver)) != 0)
548 		--mip->mi_active;
549 
550 done:
551 	rw_exit(&(mip->mi_state_lock));
552 	return (err);
553 }
554 
555 void
556 mac_stop(mac_handle_t mh)
557 {
558 	mac_impl_t	*mip = (mac_impl_t *)mh;
559 
560 	ASSERT(mip->mi_stop != NULL);
561 
562 	rw_enter(&(mip->mi_state_lock), RW_WRITER);
563 
564 	/*
565 	 * Check whether the device is still needed.
566 	 */
567 	ASSERT(mip->mi_active != 0);
568 	if (--mip->mi_active != 0) {
569 		/*
570 		 * It's still needed so there's nothing more to do.
571 		 */
572 		goto done;
573 	}
574 
575 	/*
576 	 * Stop the device.
577 	 */
578 	mip->mi_stop(mip->mi_driver);
579 
580 done:
581 	rw_exit(&(mip->mi_state_lock));
582 }
583 
584 int
585 mac_multicst_add(mac_handle_t mh, const uint8_t *addr)
586 {
587 	mac_impl_t		*mip = (mac_impl_t *)mh;
588 	mac_multicst_addr_t	**pp;
589 	mac_multicst_addr_t	*p;
590 	int			err;
591 
592 	ASSERT(mip->mi_multicst != NULL);
593 
594 	/*
595 	 * Verify the address.
596 	 */
597 	if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr,
598 	    mip->mi_pdata)) != 0) {
599 		return (err);
600 	}
601 
602 	/*
603 	 * Check whether the given address is already enabled.
604 	 */
605 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
606 	for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
607 		if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
608 		    0) {
609 			/*
610 			 * The address is already enabled so just bump the
611 			 * reference count.
612 			 */
613 			p->mma_ref++;
614 			err = 0;
615 			goto done;
616 		}
617 	}
618 
619 	/*
620 	 * Allocate a new list entry.
621 	 */
622 	if ((p = kmem_zalloc(sizeof (mac_multicst_addr_t),
623 	    KM_NOSLEEP)) == NULL) {
624 		err = ENOMEM;
625 		goto done;
626 	}
627 
628 	/*
629 	 * Enable a new multicast address.
630 	 */
631 	if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) {
632 		kmem_free(p, sizeof (mac_multicst_addr_t));
633 		goto done;
634 	}
635 
636 	/*
637 	 * Add the address to the list of enabled addresses.
638 	 */
639 	bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length);
640 	p->mma_ref++;
641 	*pp = p;
642 
643 done:
644 	rw_exit(&(mip->mi_data_lock));
645 	return (err);
646 }
647 
648 int
649 mac_multicst_remove(mac_handle_t mh, const uint8_t *addr)
650 {
651 	mac_impl_t		*mip = (mac_impl_t *)mh;
652 	mac_multicst_addr_t	**pp;
653 	mac_multicst_addr_t	*p;
654 	int			err;
655 
656 	ASSERT(mip->mi_multicst != NULL);
657 
658 	/*
659 	 * Find the entry in the list for the given address.
660 	 */
661 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
662 	for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
663 		if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
664 		    0) {
665 			if (--p->mma_ref == 0)
666 				break;
667 
668 			/*
669 			 * There is still a reference to this address so
670 			 * there's nothing more to do.
671 			 */
672 			err = 0;
673 			goto done;
674 		}
675 	}
676 
677 	/*
678 	 * We did not find an entry for the given address so it is not
679 	 * currently enabled.
680 	 */
681 	if (p == NULL) {
682 		err = ENOENT;
683 		goto done;
684 	}
685 	ASSERT(p->mma_ref == 0);
686 
687 	/*
688 	 * Disable the multicast address.
689 	 */
690 	if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) {
691 		p->mma_ref++;
692 		goto done;
693 	}
694 
695 	/*
696 	 * Remove it from the list.
697 	 */
698 	*pp = p->mma_nextp;
699 	kmem_free(p, sizeof (mac_multicst_addr_t));
700 
701 done:
702 	rw_exit(&(mip->mi_data_lock));
703 	return (err);
704 }
705 
706 /*
707  * mac_unicst_verify: Verifies the passed address. It fails
708  * if the passed address is a group address or has incorrect length.
709  */
710 boolean_t
711 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len)
712 {
713 	mac_impl_t	*mip = (mac_impl_t *)mh;
714 
715 	/*
716 	 * Verify the address.
717 	 */
718 	if ((len != mip->mi_type->mt_addr_length) ||
719 	    (mip->mi_type->mt_ops.mtops_unicst_verify(addr,
720 	    mip->mi_pdata)) != 0) {
721 		return (B_FALSE);
722 	} else {
723 		return (B_TRUE);
724 	}
725 }
726 
727 int
728 mac_unicst_set(mac_handle_t mh, const uint8_t *addr)
729 {
730 	mac_impl_t	*mip = (mac_impl_t *)mh;
731 	int		err;
732 	boolean_t	notify = B_FALSE;
733 
734 	ASSERT(mip->mi_unicst != NULL);
735 
736 	/*
737 	 * Verify the address.
738 	 */
739 	if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr,
740 	    mip->mi_pdata)) != 0) {
741 		return (err);
742 	}
743 
744 	/*
745 	 * Program the new unicast address.
746 	 */
747 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
748 
749 	/*
750 	 * If address doesn't change, do nothing.
751 	 * This check is necessary otherwise it may call into mac_unicst_set
752 	 * recursively.
753 	 */
754 	if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
755 		err = 0;
756 		goto done;
757 	}
758 
759 	if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0)
760 		goto done;
761 
762 	/*
763 	 * Save the address and flag that we need to send a notification.
764 	 */
765 	bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
766 	notify = B_TRUE;
767 
768 done:
769 	rw_exit(&(mip->mi_data_lock));
770 
771 	if (notify)
772 		i_mac_notify(mip, MAC_NOTE_UNICST);
773 
774 	return (err);
775 }
776 
777 void
778 mac_unicst_get(mac_handle_t mh, uint8_t *addr)
779 {
780 	mac_impl_t	*mip = (mac_impl_t *)mh;
781 
782 	/*
783 	 * Copy out the current unicast source address.
784 	 */
785 	rw_enter(&(mip->mi_data_lock), RW_READER);
786 	bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length);
787 	rw_exit(&(mip->mi_data_lock));
788 }
789 
790 void
791 mac_dest_get(mac_handle_t mh, uint8_t *addr)
792 {
793 	mac_impl_t	*mip = (mac_impl_t *)mh;
794 
795 	/*
796 	 * Copy out the current destination address.
797 	 */
798 	rw_enter(&(mip->mi_data_lock), RW_READER);
799 	bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length);
800 	rw_exit(&(mip->mi_data_lock));
801 }
802 
803 int
804 mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype)
805 {
806 	mac_impl_t	*mip = (mac_impl_t *)mh;
807 	int		err = 0;
808 
809 	ASSERT(mip->mi_setpromisc != NULL);
810 	ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC);
811 
812 	/*
813 	 * Determine whether we should enable or disable promiscuous mode.
814 	 * For details on the distinction between "device promiscuous mode"
815 	 * and "MAC promiscuous mode", see PSARC/2005/289.
816 	 */
817 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
818 	if (on) {
819 		/*
820 		 * Enable promiscuous mode on the device if not yet enabled.
821 		 */
822 		if (mip->mi_devpromisc++ == 0) {
823 			err = mip->mi_setpromisc(mip->mi_driver, B_TRUE);
824 			if (err != 0) {
825 				mip->mi_devpromisc--;
826 				goto done;
827 			}
828 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
829 		}
830 
831 		/*
832 		 * Enable promiscuous mode on the MAC if not yet enabled.
833 		 */
834 		if (ptype == MAC_PROMISC && mip->mi_promisc++ == 0)
835 			i_mac_notify(mip, MAC_NOTE_PROMISC);
836 	} else {
837 		if (mip->mi_devpromisc == 0) {
838 			err = EPROTO;
839 			goto done;
840 		}
841 
842 		/*
843 		 * Disable promiscuous mode on the device if this is the last
844 		 * enabling.
845 		 */
846 		if (--mip->mi_devpromisc == 0) {
847 			err = mip->mi_setpromisc(mip->mi_driver, B_FALSE);
848 			if (err != 0) {
849 				mip->mi_devpromisc++;
850 				goto done;
851 			}
852 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
853 		}
854 
855 		/*
856 		 * Disable promiscuous mode on the MAC if this is the last
857 		 * enabling.
858 		 */
859 		if (ptype == MAC_PROMISC && --mip->mi_promisc == 0)
860 			i_mac_notify(mip, MAC_NOTE_PROMISC);
861 	}
862 
863 done:
864 	rw_exit(&(mip->mi_data_lock));
865 	return (err);
866 }
867 
868 boolean_t
869 mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype)
870 {
871 	mac_impl_t		*mip = (mac_impl_t *)mh;
872 
873 	ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC);
874 
875 	/*
876 	 * Return the current promiscuity.
877 	 */
878 	if (ptype == MAC_DEVPROMISC)
879 		return (mip->mi_devpromisc != 0);
880 	else
881 		return (mip->mi_promisc != 0);
882 }
883 
884 void
885 mac_resources(mac_handle_t mh)
886 {
887 	mac_impl_t	*mip = (mac_impl_t *)mh;
888 
889 	/*
890 	 * If the driver supports resource registration, call the driver to
891 	 * ask it to register its resources.
892 	 */
893 	if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES)
894 		mip->mi_resources(mip->mi_driver);
895 }
896 
897 void
898 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp)
899 {
900 	mac_impl_t	*mip = (mac_impl_t *)mh;
901 
902 	/*
903 	 * Call the driver to handle the ioctl.  The driver may not support
904 	 * any ioctls, in which case we reply with a NAK on its behalf.
905 	 */
906 	if (mip->mi_callbacks->mc_callbacks & MC_IOCTL)
907 		mip->mi_ioctl(mip->mi_driver, wq, bp);
908 	else
909 		miocnak(wq, bp, 0, EINVAL);
910 }
911 
912 const mac_txinfo_t *
913 mac_do_tx_get(mac_handle_t mh, boolean_t is_vnic)
914 {
915 	mac_impl_t	*mip = (mac_impl_t *)mh;
916 	mac_txinfo_t	*mtp;
917 
918 	/*
919 	 * Grab the lock to prevent us from racing with MAC_PROMISC being
920 	 * changed.  This is sufficient since MAC clients are careful to always
921 	 * call mac_txloop_add() prior to enabling MAC_PROMISC, and to disable
922 	 * MAC_PROMISC prior to calling mac_txloop_remove().
923 	 */
924 	rw_enter(&mip->mi_tx_lock, RW_READER);
925 
926 	if (mac_promisc_get(mh, MAC_PROMISC)) {
927 		ASSERT(mip->mi_mtfp != NULL);
928 		if (mip->mi_vnic_present && !is_vnic) {
929 			mtp = &mip->mi_vnic_txloopinfo;
930 		} else {
931 			mtp = &mip->mi_txloopinfo;
932 		}
933 	} else {
934 		if (mip->mi_vnic_present && !is_vnic) {
935 			mtp = &mip->mi_vnic_txinfo;
936 		} else {
937 			/*
938 			 * Note that we cannot ASSERT() that mip->mi_mtfp is
939 			 * NULL, because to satisfy the above ASSERT(), we
940 			 * have to disable MAC_PROMISC prior to calling
941 			 * mac_txloop_remove().
942 			 */
943 			mtp = &mip->mi_txinfo;
944 		}
945 	}
946 
947 	rw_exit(&mip->mi_tx_lock);
948 	return (mtp);
949 }
950 
951 /*
952  * Invoked by VNIC to obtain the transmit entry point.
953  */
954 const mac_txinfo_t *
955 mac_vnic_tx_get(mac_handle_t mh)
956 {
957 	return (mac_do_tx_get(mh, B_TRUE));
958 }
959 
960 /*
961  * Invoked by any non-VNIC client to obtain the transmit entry point.
962  * If a VNIC is present, the VNIC transmit function provided by the VNIC
963  * will be returned to the MAC client.
964  */
965 const mac_txinfo_t *
966 mac_tx_get(mac_handle_t mh)
967 {
968 	return (mac_do_tx_get(mh, B_FALSE));
969 }
970 
971 link_state_t
972 mac_link_get(mac_handle_t mh)
973 {
974 	return (((mac_impl_t *)mh)->mi_linkstate);
975 }
976 
977 mac_notify_handle_t
978 mac_notify_add(mac_handle_t mh, mac_notify_t notify, void *arg)
979 {
980 	mac_impl_t		*mip = (mac_impl_t *)mh;
981 	mac_notify_fn_t		*mnfp;
982 
983 	mnfp = kmem_zalloc(sizeof (mac_notify_fn_t), KM_SLEEP);
984 	mnfp->mnf_fn = notify;
985 	mnfp->mnf_arg = arg;
986 
987 	/*
988 	 * Add it to the head of the 'notify' callback list.
989 	 */
990 	rw_enter(&mip->mi_notify_lock, RW_WRITER);
991 	mnfp->mnf_nextp = mip->mi_mnfp;
992 	mip->mi_mnfp = mnfp;
993 	rw_exit(&mip->mi_notify_lock);
994 
995 	return ((mac_notify_handle_t)mnfp);
996 }
997 
998 void
999 mac_notify_remove(mac_handle_t mh, mac_notify_handle_t mnh)
1000 {
1001 	mac_impl_t		*mip = (mac_impl_t *)mh;
1002 	mac_notify_fn_t		*mnfp = (mac_notify_fn_t *)mnh;
1003 	mac_notify_fn_t		**pp;
1004 	mac_notify_fn_t		*p;
1005 
1006 	/*
1007 	 * Search the 'notify' callback list for the function closure.
1008 	 */
1009 	rw_enter(&mip->mi_notify_lock, RW_WRITER);
1010 	for (pp = &(mip->mi_mnfp); (p = *pp) != NULL;
1011 	    pp = &(p->mnf_nextp)) {
1012 		if (p == mnfp)
1013 			break;
1014 	}
1015 	ASSERT(p != NULL);
1016 
1017 	/*
1018 	 * Remove it from the list.
1019 	 */
1020 	*pp = p->mnf_nextp;
1021 	rw_exit(&mip->mi_notify_lock);
1022 
1023 	/*
1024 	 * Free it.
1025 	 */
1026 	kmem_free(mnfp, sizeof (mac_notify_fn_t));
1027 }
1028 
1029 void
1030 mac_notify(mac_handle_t mh)
1031 {
1032 	mac_impl_t		*mip = (mac_impl_t *)mh;
1033 	mac_notify_type_t	type;
1034 
1035 	for (type = 0; type < MAC_NNOTE; type++)
1036 		i_mac_notify(mip, type);
1037 }
1038 
1039 /*
1040  * Register a receive function for this mac.
1041  * More information on this function's interaction with mac_rx()
1042  * can be found atop mac_rx().
1043  */
1044 mac_rx_handle_t
1045 mac_do_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg, boolean_t is_active)
1046 {
1047 	mac_impl_t	*mip = (mac_impl_t *)mh;
1048 	mac_rx_fn_t	*mrfp;
1049 
1050 	mrfp = kmem_zalloc(sizeof (mac_rx_fn_t), KM_SLEEP);
1051 	mrfp->mrf_fn = rx;
1052 	mrfp->mrf_arg = arg;
1053 	mrfp->mrf_active = is_active;
1054 
1055 	/*
1056 	 * Add it to the head of the 'rx' callback list.
1057 	 */
1058 	rw_enter(&(mip->mi_rx_lock), RW_WRITER);
1059 
1060 	/*
1061 	 * mac_rx() will only call callbacks that are marked inuse.
1062 	 */
1063 	mrfp->mrf_inuse = B_TRUE;
1064 	mrfp->mrf_nextp = mip->mi_mrfp;
1065 
1066 	/*
1067 	 * mac_rx() could be traversing the remainder of the list
1068 	 * and miss the new callback we're adding here. This is not a problem
1069 	 * because we do not guarantee the callback to take effect immediately
1070 	 * after mac_rx_add() returns.
1071 	 */
1072 	mip->mi_mrfp = mrfp;
1073 	rw_exit(&(mip->mi_rx_lock));
1074 
1075 	return ((mac_rx_handle_t)mrfp);
1076 }
1077 
1078 mac_rx_handle_t
1079 mac_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg)
1080 {
1081 	return (mac_do_rx_add(mh, rx, arg, B_FALSE));
1082 }
1083 
1084 mac_rx_handle_t
1085 mac_active_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg)
1086 {
1087 	return (mac_do_rx_add(mh, rx, arg, B_TRUE));
1088 }
1089 
1090 /*
1091  * Unregister a receive function for this mac.
1092  * This function does not block if wait is B_FALSE. This is useful
1093  * for clients who call mac_rx_remove() from a non-blockable context.
1094  * More information on this function's interaction with mac_rx()
1095  * can be found atop mac_rx().
1096  */
1097 void
1098 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh, boolean_t wait)
1099 {
1100 	mac_impl_t		*mip = (mac_impl_t *)mh;
1101 	mac_rx_fn_t		*mrfp = (mac_rx_fn_t *)mrh;
1102 	mac_rx_fn_t		**pp;
1103 	mac_rx_fn_t		*p;
1104 
1105 	/*
1106 	 * Search the 'rx' callback list for the function closure.
1107 	 */
1108 	rw_enter(&mip->mi_rx_lock, RW_WRITER);
1109 	for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) {
1110 		if (p == mrfp)
1111 			break;
1112 	}
1113 	ASSERT(p != NULL);
1114 
1115 	/*
1116 	 * If mac_rx() is running, mark callback for deletion
1117 	 * and return (if wait is false), or wait until mac_rx()
1118 	 * exits (if wait is true).
1119 	 */
1120 	if (mip->mi_rx_ref > 0) {
1121 		DTRACE_PROBE1(defer_delete, mac_impl_t *, mip);
1122 		p->mrf_inuse = B_FALSE;
1123 		mutex_enter(&mip->mi_lock);
1124 		mip->mi_rx_removed++;
1125 		mutex_exit(&mip->mi_lock);
1126 
1127 		rw_exit(&mip->mi_rx_lock);
1128 		if (wait)
1129 			mac_rx_remove_wait(mh);
1130 		return;
1131 	}
1132 
1133 	/* Remove it from the list. */
1134 	*pp = p->mrf_nextp;
1135 	kmem_free(mrfp, sizeof (mac_rx_fn_t));
1136 	rw_exit(&mip->mi_rx_lock);
1137 }
1138 
1139 /*
1140  * Wait for all pending callback removals to be completed by mac_rx().
1141  * Note that if we call mac_rx_remove() immediately before this, there is no
1142  * guarantee we would wait *only* on the callback that we specified.
1143  * mac_rx_remove() could have been called by other threads and we would have
1144  * to wait for other marked callbacks to be removed as well.
1145  */
1146 void
1147 mac_rx_remove_wait(mac_handle_t mh)
1148 {
1149 	mac_impl_t	*mip = (mac_impl_t *)mh;
1150 
1151 	mutex_enter(&mip->mi_lock);
1152 	while (mip->mi_rx_removed > 0) {
1153 		DTRACE_PROBE1(need_wait, mac_impl_t *, mip);
1154 		cv_wait(&mip->mi_rx_cv, &mip->mi_lock);
1155 	}
1156 	mutex_exit(&mip->mi_lock);
1157 }
1158 
1159 mac_txloop_handle_t
1160 mac_txloop_add(mac_handle_t mh, mac_txloop_t tx, void *arg)
1161 {
1162 	mac_impl_t	*mip = (mac_impl_t *)mh;
1163 	mac_txloop_fn_t	*mtfp;
1164 
1165 	mtfp = kmem_zalloc(sizeof (mac_txloop_fn_t), KM_SLEEP);
1166 	mtfp->mtf_fn = tx;
1167 	mtfp->mtf_arg = arg;
1168 
1169 	/*
1170 	 * Add it to the head of the 'tx' callback list.
1171 	 */
1172 	rw_enter(&(mip->mi_tx_lock), RW_WRITER);
1173 	mtfp->mtf_nextp = mip->mi_mtfp;
1174 	mip->mi_mtfp = mtfp;
1175 	rw_exit(&(mip->mi_tx_lock));
1176 
1177 	return ((mac_txloop_handle_t)mtfp);
1178 }
1179 
1180 /*
1181  * Unregister a transmit function for this mac.  This removes the function
1182  * from the list of transmit functions for this mac.
1183  */
1184 void
1185 mac_txloop_remove(mac_handle_t mh, mac_txloop_handle_t mth)
1186 {
1187 	mac_impl_t		*mip = (mac_impl_t *)mh;
1188 	mac_txloop_fn_t		*mtfp = (mac_txloop_fn_t *)mth;
1189 	mac_txloop_fn_t		**pp;
1190 	mac_txloop_fn_t		*p;
1191 
1192 	/*
1193 	 * Search the 'tx' callback list for the function.
1194 	 */
1195 	rw_enter(&(mip->mi_tx_lock), RW_WRITER);
1196 	for (pp = &(mip->mi_mtfp); (p = *pp) != NULL; pp = &(p->mtf_nextp)) {
1197 		if (p == mtfp)
1198 			break;
1199 	}
1200 	ASSERT(p != NULL);
1201 
1202 	/* Remove it from the list. */
1203 	*pp = p->mtf_nextp;
1204 	kmem_free(mtfp, sizeof (mac_txloop_fn_t));
1205 	rw_exit(&(mip->mi_tx_lock));
1206 }
1207 
1208 void
1209 mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg)
1210 {
1211 	mac_impl_t		*mip = (mac_impl_t *)mh;
1212 
1213 	/*
1214 	 * Update the 'resource_add' callbacks.
1215 	 */
1216 	rw_enter(&(mip->mi_resource_lock), RW_WRITER);
1217 	mip->mi_resource_add = add;
1218 	mip->mi_resource_add_arg = arg;
1219 	rw_exit(&(mip->mi_resource_lock));
1220 }
1221 
1222 /*
1223  * Driver support functions.
1224  */
1225 
1226 mac_register_t *
1227 mac_alloc(uint_t mac_version)
1228 {
1229 	mac_register_t *mregp;
1230 
1231 	/*
1232 	 * Make sure there isn't a version mismatch between the driver and
1233 	 * the framework.  In the future, if multiple versions are
1234 	 * supported, this check could become more sophisticated.
1235 	 */
1236 	if (mac_version != MAC_VERSION)
1237 		return (NULL);
1238 
1239 	mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP);
1240 	mregp->m_version = mac_version;
1241 	return (mregp);
1242 }
1243 
1244 void
1245 mac_free(mac_register_t *mregp)
1246 {
1247 	kmem_free(mregp, sizeof (mac_register_t));
1248 }
1249 
1250 /*
1251  * mac_register() is how drivers register new MACs with the GLDv3
1252  * framework.  The mregp argument is allocated by drivers using the
1253  * mac_alloc() function, and can be freed using mac_free() immediately upon
1254  * return from mac_register().  Upon success (0 return value), the mhp
1255  * opaque pointer becomes the driver's handle to its MAC interface, and is
1256  * the argument to all other mac module entry points.
1257  */
1258 int
1259 mac_register(mac_register_t *mregp, mac_handle_t *mhp)
1260 {
1261 	mac_impl_t	*mip;
1262 	mactype_t	*mtype;
1263 	int		err = EINVAL;
1264 	struct devnames *dnp;
1265 	minor_t		minor;
1266 	boolean_t	style1_created = B_FALSE, style2_created = B_FALSE;
1267 
1268 	/* Find the required MAC-Type plugin. */
1269 	if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL)
1270 		return (EINVAL);
1271 
1272 	/* Create a mac_impl_t to represent this MAC. */
1273 	mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP);
1274 
1275 	/*
1276 	 * The mac is not ready for open yet.
1277 	 */
1278 	mip->mi_disabled = B_TRUE;
1279 
1280 	mip->mi_drvname = ddi_driver_name(mregp->m_dip);
1281 	/*
1282 	 * Some drivers such as aggr need to register multiple MACs.  Such
1283 	 * drivers must supply a non-zero "instance" argument so that each
1284 	 * MAC can be assigned a unique MAC name and can have unique
1285 	 * kstats.
1286 	 */
1287 	mip->mi_instance = ((mregp->m_instance == 0) ?
1288 	    ddi_get_instance(mregp->m_dip) : mregp->m_instance);
1289 
1290 	/* Construct the MAC name as <drvname><instance> */
1291 	(void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d",
1292 	    mip->mi_drvname, mip->mi_instance);
1293 
1294 	mip->mi_driver = mregp->m_driver;
1295 
1296 	mip->mi_type = mtype;
1297 	mip->mi_info.mi_media = mtype->mt_type;
1298 	mip->mi_info.mi_nativemedia = mtype->mt_nativetype;
1299 	mip->mi_info.mi_sdu_min = mregp->m_min_sdu;
1300 	if (mregp->m_max_sdu <= mregp->m_min_sdu)
1301 		goto fail;
1302 	mip->mi_info.mi_sdu_max = mregp->m_max_sdu;
1303 	mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length;
1304 	/*
1305 	 * If the media supports a broadcast address, cache a pointer to it
1306 	 * in the mac_info_t so that upper layers can use it.
1307 	 */
1308 	mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr;
1309 
1310 	/*
1311 	 * Copy the unicast source address into the mac_info_t, but only if
1312 	 * the MAC-Type defines a non-zero address length.  We need to
1313 	 * handle MAC-Types that have an address length of 0
1314 	 * (point-to-point protocol MACs for example).
1315 	 */
1316 	if (mip->mi_type->mt_addr_length > 0) {
1317 		if (mregp->m_src_addr == NULL)
1318 			goto fail;
1319 		mip->mi_info.mi_unicst_addr =
1320 		    kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP);
1321 		bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr,
1322 		    mip->mi_type->mt_addr_length);
1323 
1324 		/*
1325 		 * Copy the fixed 'factory' MAC address from the immutable
1326 		 * info.  This is taken to be the MAC address currently in
1327 		 * use.
1328 		 */
1329 		bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr,
1330 		    mip->mi_type->mt_addr_length);
1331 		/* Copy the destination address if one is provided. */
1332 		if (mregp->m_dst_addr != NULL) {
1333 			bcopy(mregp->m_dst_addr, mip->mi_dstaddr,
1334 			    mip->mi_type->mt_addr_length);
1335 		}
1336 	} else if (mregp->m_src_addr != NULL) {
1337 		goto fail;
1338 	}
1339 
1340 	/*
1341 	 * The format of the m_pdata is specific to the plugin.  It is
1342 	 * passed in as an argument to all of the plugin callbacks.  The
1343 	 * driver can update this information by calling
1344 	 * mac_pdata_update().
1345 	 */
1346 	if (mregp->m_pdata != NULL) {
1347 		/*
1348 		 * Verify that the plugin supports MAC plugin data and that
1349 		 * the supplied data is valid.
1350 		 */
1351 		if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY))
1352 			goto fail;
1353 		if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata,
1354 		    mregp->m_pdata_size)) {
1355 			goto fail;
1356 		}
1357 		mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP);
1358 		bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size);
1359 		mip->mi_pdata_size = mregp->m_pdata_size;
1360 	}
1361 
1362 	/*
1363 	 * Stash the driver callbacks into the mac_impl_t, but first sanity
1364 	 * check to make sure all mandatory callbacks are set.
1365 	 */
1366 	if (mregp->m_callbacks->mc_getstat == NULL ||
1367 	    mregp->m_callbacks->mc_start == NULL ||
1368 	    mregp->m_callbacks->mc_stop == NULL ||
1369 	    mregp->m_callbacks->mc_setpromisc == NULL ||
1370 	    mregp->m_callbacks->mc_multicst == NULL ||
1371 	    mregp->m_callbacks->mc_unicst == NULL ||
1372 	    mregp->m_callbacks->mc_tx == NULL) {
1373 		goto fail;
1374 	}
1375 	mip->mi_callbacks = mregp->m_callbacks;
1376 
1377 	mip->mi_dip = mregp->m_dip;
1378 
1379 	/*
1380 	 * Set up the possible transmit routines.
1381 	 */
1382 	mip->mi_txinfo.mt_fn = mip->mi_tx;
1383 	mip->mi_txinfo.mt_arg = mip->mi_driver;
1384 
1385 	mip->mi_vnic_txinfo.mt_fn = mac_vnic_tx;
1386 	mip->mi_vnic_txinfo.mt_arg = mip;
1387 
1388 	mip->mi_txloopinfo.mt_fn = mac_txloop;
1389 	mip->mi_txloopinfo.mt_arg = mip;
1390 
1391 	mip->mi_vnic_txloopinfo.mt_fn = mac_vnic_txloop;
1392 	mip->mi_vnic_txloopinfo.mt_arg = mip;
1393 
1394 	/*
1395 	 * Allocate a notification thread.
1396 	 */
1397 	mip->mi_notify_thread = thread_create(NULL, 0, i_mac_notify_thread,
1398 	    mip, 0, &p0, TS_RUN, minclsyspri);
1399 	if (mip->mi_notify_thread == NULL)
1400 		goto fail;
1401 
1402 	/*
1403 	 * Initialize the kstats for this device.
1404 	 */
1405 	mac_stat_create(mip);
1406 
1407 	err = EEXIST;
1408 	/* Create a style-2 DLPI device */
1409 	if (ddi_create_minor_node(mip->mi_dip, (char *)mip->mi_drvname,
1410 	    S_IFCHR, 0, DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
1411 		goto fail;
1412 	style2_created = B_TRUE;
1413 
1414 	/* Create a style-1 DLPI device */
1415 	minor = (minor_t)mip->mi_instance + 1;
1416 	if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, minor,
1417 	    DDI_NT_NET, 0) != DDI_SUCCESS)
1418 		goto fail;
1419 	style1_created = B_TRUE;
1420 
1421 	/*
1422 	 * Create a link for this MAC.  The link name will be the same as
1423 	 * the MAC name.
1424 	 */
1425 	err = dls_create(mip->mi_name, mip->mi_name,
1426 	    ddi_get_instance(mip->mi_dip));
1427 	if (err != 0)
1428 		goto fail;
1429 
1430 	/* set the gldv3 flag in dn_flags */
1431 	dnp = &devnamesp[ddi_driver_major(mip->mi_dip)];
1432 	LOCK_DEV_OPS(&dnp->dn_lock);
1433 	dnp->dn_flags |= DN_GLDV3_DRIVER;
1434 	UNLOCK_DEV_OPS(&dnp->dn_lock);
1435 
1436 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1437 	if (mod_hash_insert(i_mac_impl_hash,
1438 	    (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) {
1439 		rw_exit(&i_mac_impl_lock);
1440 		VERIFY(dls_destroy(mip->mi_name) == 0);
1441 		err = EEXIST;
1442 		goto fail;
1443 	}
1444 
1445 	/*
1446 	 * Mark the MAC to be ready for open.
1447 	 */
1448 	mip->mi_disabled = B_FALSE;
1449 
1450 	cmn_err(CE_NOTE, "!%s registered", mip->mi_name);
1451 
1452 	rw_exit(&i_mac_impl_lock);
1453 
1454 	atomic_inc_32(&i_mac_impl_count);
1455 	*mhp = (mac_handle_t)mip;
1456 	return (0);
1457 
1458 fail:
1459 	/* clean up notification thread */
1460 	if (mip->mi_notify_thread != NULL) {
1461 		mutex_enter(&mip->mi_notify_bits_lock);
1462 		mip->mi_notify_bits = (1 << MAC_NNOTE);
1463 		cv_broadcast(&mip->mi_notify_cv);
1464 		while (mip->mi_notify_bits != 0)
1465 			cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock);
1466 		mutex_exit(&mip->mi_notify_bits_lock);
1467 	}
1468 
1469 	if (mip->mi_info.mi_unicst_addr != NULL) {
1470 		kmem_free(mip->mi_info.mi_unicst_addr,
1471 		    mip->mi_type->mt_addr_length);
1472 		mip->mi_info.mi_unicst_addr = NULL;
1473 	}
1474 	if (style1_created)
1475 		ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
1476 	if (style2_created)
1477 		ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
1478 
1479 	mac_stat_destroy(mip);
1480 
1481 	if (mip->mi_type != NULL) {
1482 		atomic_dec_32(&mip->mi_type->mt_ref);
1483 		mip->mi_type = NULL;
1484 	}
1485 
1486 	if (mip->mi_pdata != NULL) {
1487 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1488 		mip->mi_pdata = NULL;
1489 		mip->mi_pdata_size = 0;
1490 	}
1491 
1492 	kmem_cache_free(i_mac_impl_cachep, mip);
1493 	return (err);
1494 }
1495 
1496 int
1497 mac_disable(mac_handle_t mh)
1498 {
1499 	int			err;
1500 	mac_impl_t		*mip = (mac_impl_t *)mh;
1501 
1502 	/*
1503 	 * See if there are any other references to this mac_t (e.g., VLAN's).
1504 	 * If not, set mi_disabled to prevent any new VLAN's from being
1505 	 * created while we're destroying this mac.
1506 	 */
1507 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1508 	if (mip->mi_ref > 0) {
1509 		rw_exit(&i_mac_impl_lock);
1510 		return (EBUSY);
1511 	}
1512 	mip->mi_disabled = B_TRUE;
1513 	rw_exit(&i_mac_impl_lock);
1514 
1515 	if ((err = dls_destroy(mip->mi_name)) != 0) {
1516 		rw_enter(&i_mac_impl_lock, RW_WRITER);
1517 		mip->mi_disabled = B_FALSE;
1518 		rw_exit(&i_mac_impl_lock);
1519 		return (err);
1520 	}
1521 
1522 	return (0);
1523 }
1524 
1525 int
1526 mac_unregister(mac_handle_t mh)
1527 {
1528 	int			err;
1529 	mac_impl_t		*mip = (mac_impl_t *)mh;
1530 	mod_hash_val_t		val;
1531 	mac_multicst_addr_t	*p, *nextp;
1532 
1533 	/*
1534 	 * See if there are any other references to this mac_t (e.g., VLAN's).
1535 	 * If not, set mi_disabled to prevent any new VLAN's from being
1536 	 * created while we're destroying this mac. Once mac_disable() returns
1537 	 * 0, the rest of mac_unregister() stuff should continue without
1538 	 * returning an error.
1539 	 */
1540 	if (!mip->mi_disabled) {
1541 		if ((err = mac_disable(mh)) != 0)
1542 			return (err);
1543 	}
1544 
1545 	/*
1546 	 * Clean up notification thread (wait for it to exit).
1547 	 */
1548 	mutex_enter(&mip->mi_notify_bits_lock);
1549 	mip->mi_notify_bits = (1 << MAC_NNOTE);
1550 	cv_broadcast(&mip->mi_notify_cv);
1551 	while (mip->mi_notify_bits != 0)
1552 		cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock);
1553 	mutex_exit(&mip->mi_notify_bits_lock);
1554 
1555 	/*
1556 	 * Remove both style 1 and style 2 minor nodes
1557 	 */
1558 	ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
1559 	ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
1560 
1561 	ASSERT(!mip->mi_activelink);
1562 
1563 	mac_stat_destroy(mip);
1564 
1565 	(void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name,
1566 	    &val);
1567 	ASSERT(mip == (mac_impl_t *)val);
1568 
1569 	ASSERT(i_mac_impl_count > 0);
1570 	atomic_dec_32(&i_mac_impl_count);
1571 
1572 	if (mip->mi_pdata != NULL)
1573 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1574 	mip->mi_pdata = NULL;
1575 	mip->mi_pdata_size = 0;
1576 
1577 	/*
1578 	 * Free the list of multicast addresses.
1579 	 */
1580 	for (p = mip->mi_mmap; p != NULL; p = nextp) {
1581 		nextp = p->mma_nextp;
1582 		kmem_free(p, sizeof (mac_multicst_addr_t));
1583 	}
1584 	mip->mi_mmap = NULL;
1585 
1586 	mip->mi_linkstate = LINK_STATE_UNKNOWN;
1587 	kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
1588 	mip->mi_info.mi_unicst_addr = NULL;
1589 
1590 	atomic_dec_32(&mip->mi_type->mt_ref);
1591 	mip->mi_type = NULL;
1592 
1593 	cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name);
1594 
1595 	kmem_cache_free(i_mac_impl_cachep, mip);
1596 
1597 	return (0);
1598 }
1599 
1600 /*
1601  * To avoid potential deadlocks, mac_rx() releases mi_rx_lock
1602  * before invoking its list of upcalls. This introduces races with
1603  * mac_rx_remove() and mac_rx_add(), who can potentially modify the
1604  * upcall list while mi_rx_lock is not being held. The race with
1605  * mac_rx_remove() is handled by incrementing mi_rx_ref upon entering
1606  * mac_rx(); a non-zero mi_rx_ref would tell mac_rx_remove()
1607  * to not modify the list but instead mark an upcall for deletion.
1608  * before mac_rx() exits, mi_rx_ref is decremented and if it
1609  * is 0, the marked upcalls will be removed from the list and freed.
1610  * The race with mac_rx_add() is harmless because mac_rx_add() only
1611  * prepends to the list and since mac_rx() saves the list head
1612  * before releasing mi_rx_lock, any prepended upcall won't be seen
1613  * until the next packet chain arrives.
1614  *
1615  * To minimize lock contention between multiple parallel invocations
1616  * of mac_rx(), mi_rx_lock is acquired as a READER lock. The
1617  * use of atomic operations ensures the sanity of mi_rx_ref. mi_rx_lock
1618  * will be upgraded to WRITER mode when there are marked upcalls to be
1619  * cleaned.
1620  */
1621 static void
1622 mac_do_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain,
1623     boolean_t active_only)
1624 {
1625 	mac_impl_t	*mip = (mac_impl_t *)mh;
1626 	mblk_t		*bp = mp_chain;
1627 	mac_rx_fn_t	*mrfp;
1628 
1629 	/*
1630 	 * Call all registered receive functions.
1631 	 */
1632 	rw_enter(&mip->mi_rx_lock, RW_READER);
1633 	if ((mrfp = mip->mi_mrfp) == NULL) {
1634 		/* There are no registered receive functions. */
1635 		freemsgchain(bp);
1636 		rw_exit(&mip->mi_rx_lock);
1637 		return;
1638 	}
1639 	atomic_inc_32(&mip->mi_rx_ref);
1640 	rw_exit(&mip->mi_rx_lock);
1641 
1642 	/*
1643 	 * Call registered receive functions.
1644 	 */
1645 	do {
1646 		mblk_t *recv_bp;
1647 
1648 		if (active_only && !mrfp->mrf_active) {
1649 			mrfp = mrfp->mrf_nextp;
1650 			if (mrfp == NULL) {
1651 				/*
1652 				 * We hit the last receiver, but it's not
1653 				 * active.
1654 				 */
1655 				freemsgchain(bp);
1656 			}
1657 			continue;
1658 		}
1659 
1660 		recv_bp = (mrfp->mrf_nextp != NULL) ? copymsgchain(bp) : bp;
1661 		if (recv_bp != NULL) {
1662 			if (mrfp->mrf_inuse) {
1663 				/*
1664 				 * Send bp itself and keep the copy.
1665 				 * If there's only one active receiver,
1666 				 * it should get the original message,
1667 				 * tagged with the hardware checksum flags.
1668 				 */
1669 				mrfp->mrf_fn(mrfp->mrf_arg, mrh, bp);
1670 				bp = recv_bp;
1671 			} else {
1672 				freemsgchain(recv_bp);
1673 			}
1674 		}
1675 
1676 		mrfp = mrfp->mrf_nextp;
1677 	} while (mrfp != NULL);
1678 
1679 	rw_enter(&mip->mi_rx_lock, RW_READER);
1680 	if (atomic_dec_32_nv(&mip->mi_rx_ref) == 0 && mip->mi_rx_removed > 0) {
1681 		mac_rx_fn_t	**pp, *p;
1682 		uint32_t	cnt = 0;
1683 
1684 		DTRACE_PROBE1(delete_callbacks, mac_impl_t *, mip);
1685 
1686 		/*
1687 		 * Need to become exclusive before doing cleanup
1688 		 */
1689 		if (rw_tryupgrade(&mip->mi_rx_lock) == 0) {
1690 			rw_exit(&mip->mi_rx_lock);
1691 			rw_enter(&mip->mi_rx_lock, RW_WRITER);
1692 		}
1693 
1694 		/*
1695 		 * We return if another thread has already entered and cleaned
1696 		 * up the list.
1697 		 */
1698 		if (mip->mi_rx_ref > 0 || mip->mi_rx_removed == 0) {
1699 			rw_exit(&mip->mi_rx_lock);
1700 			return;
1701 		}
1702 
1703 		/*
1704 		 * Free removed callbacks.
1705 		 */
1706 		pp = &mip->mi_mrfp;
1707 		while (*pp != NULL) {
1708 			if (!(*pp)->mrf_inuse) {
1709 				p = *pp;
1710 				*pp = (*pp)->mrf_nextp;
1711 				kmem_free(p, sizeof (*p));
1712 				cnt++;
1713 				continue;
1714 			}
1715 			pp = &(*pp)->mrf_nextp;
1716 		}
1717 
1718 		/*
1719 		 * Wake up mac_rx_remove_wait()
1720 		 */
1721 		mutex_enter(&mip->mi_lock);
1722 		ASSERT(mip->mi_rx_removed == cnt);
1723 		mip->mi_rx_removed = 0;
1724 		cv_broadcast(&mip->mi_rx_cv);
1725 		mutex_exit(&mip->mi_lock);
1726 	}
1727 	rw_exit(&mip->mi_rx_lock);
1728 }
1729 
1730 void
1731 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain)
1732 {
1733 	mac_do_rx(mh, mrh, mp_chain, B_FALSE);
1734 }
1735 
1736 /*
1737  * Send a packet chain up to the receive callbacks which declared
1738  * themselves as being active.
1739  */
1740 void
1741 mac_active_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp_chain)
1742 {
1743 	mac_do_rx(arg, mrh, mp_chain, B_TRUE);
1744 }
1745 
1746 /*
1747  * Function passed to the active client sharing a VNIC. This function
1748  * is returned by mac_tx_get() when a VNIC is present. It invokes
1749  * the VNIC transmit entry point which was specified by the VNIC when
1750  * it called mac_vnic_set(). The VNIC transmit entry point will
1751  * pass the packets to the local VNICs and/or to the underlying VNICs
1752  * if needed.
1753  */
1754 static mblk_t *
1755 mac_vnic_tx(void *arg, mblk_t *mp)
1756 {
1757 	mac_impl_t	*mip = arg;
1758 	mac_txinfo_t	*mtfp;
1759 	mac_vnic_tx_t	*mvt;
1760 
1761 	/*
1762 	 * There is a race between the notification of the VNIC
1763 	 * addition and removal, and the processing of the VNIC notification
1764 	 * by the MAC client. During this window, it is possible for
1765 	 * an active MAC client to contine invoking mac_vnic_tx() while
1766 	 * the VNIC has already been removed. So we cannot assume
1767 	 * that mi_vnic_present will always be true when mac_vnic_tx()
1768 	 * is invoked.
1769 	 */
1770 	rw_enter(&mip->mi_tx_lock, RW_READER);
1771 	if (!mip->mi_vnic_present) {
1772 		rw_exit(&mip->mi_tx_lock);
1773 		freemsgchain(mp);
1774 		return (NULL);
1775 	}
1776 
1777 	ASSERT(mip->mi_vnic_tx != NULL);
1778 	mvt = mip->mi_vnic_tx;
1779 	MAC_VNIC_TXINFO_REFHOLD(mvt);
1780 	rw_exit(&mip->mi_tx_lock);
1781 
1782 	mtfp = &mvt->mv_txinfo;
1783 	mtfp->mt_fn(mtfp->mt_arg, mp);
1784 
1785 	MAC_VNIC_TXINFO_REFRELE(mvt);
1786 	return (NULL);
1787 }
1788 
1789 /*
1790  * Transmit function -- ONLY used when there are registered loopback listeners.
1791  */
1792 mblk_t *
1793 mac_do_txloop(void *arg, mblk_t *bp, boolean_t call_vnic)
1794 {
1795 	mac_impl_t	*mip = arg;
1796 	mac_txloop_fn_t	*mtfp;
1797 	mblk_t		*loop_bp, *resid_bp, *next_bp;
1798 
1799 	if (call_vnic) {
1800 		/*
1801 		 * In promiscous mode, a copy of the sent packet will
1802 		 * be sent to the client's promiscous receive entry
1803 		 * points via mac_vnic_tx()->
1804 		 * mac_active_rx_promisc()->mac_rx_default().
1805 		 */
1806 		return (mac_vnic_tx(arg, bp));
1807 	}
1808 
1809 	while (bp != NULL) {
1810 		next_bp = bp->b_next;
1811 		bp->b_next = NULL;
1812 
1813 		if ((loop_bp = copymsg(bp)) == NULL)
1814 			goto noresources;
1815 
1816 		if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) {
1817 			ASSERT(resid_bp == bp);
1818 			freemsg(loop_bp);
1819 			goto noresources;
1820 		}
1821 
1822 		rw_enter(&mip->mi_tx_lock, RW_READER);
1823 		mtfp = mip->mi_mtfp;
1824 		while (mtfp != NULL && loop_bp != NULL) {
1825 			bp = loop_bp;
1826 
1827 			/* XXX counter bump if copymsg() fails? */
1828 			if (mtfp->mtf_nextp != NULL)
1829 				loop_bp = copymsg(bp);
1830 			else
1831 				loop_bp = NULL;
1832 
1833 			mtfp->mtf_fn(mtfp->mtf_arg, bp);
1834 			mtfp = mtfp->mtf_nextp;
1835 		}
1836 		rw_exit(&mip->mi_tx_lock);
1837 
1838 		/*
1839 		 * It's possible we've raced with the disabling of promiscuous
1840 		 * mode, in which case we can discard our copy.
1841 		 */
1842 		if (loop_bp != NULL)
1843 			freemsg(loop_bp);
1844 
1845 		bp = next_bp;
1846 	}
1847 
1848 	return (NULL);
1849 
1850 noresources:
1851 	bp->b_next = next_bp;
1852 	return (bp);
1853 }
1854 
1855 mblk_t *
1856 mac_txloop(void *arg, mblk_t *bp)
1857 {
1858 	return (mac_do_txloop(arg, bp, B_FALSE));
1859 }
1860 
1861 static mblk_t *
1862 mac_vnic_txloop(void *arg, mblk_t *bp)
1863 {
1864 	return (mac_do_txloop(arg, bp, B_TRUE));
1865 }
1866 
1867 void
1868 mac_link_update(mac_handle_t mh, link_state_t link)
1869 {
1870 	mac_impl_t	*mip = (mac_impl_t *)mh;
1871 
1872 	/*
1873 	 * Save the link state.
1874 	 */
1875 	mip->mi_linkstate = link;
1876 
1877 	/*
1878 	 * Send a MAC_NOTE_LINK notification.
1879 	 */
1880 	i_mac_notify(mip, MAC_NOTE_LINK);
1881 }
1882 
1883 void
1884 mac_unicst_update(mac_handle_t mh, const uint8_t *addr)
1885 {
1886 	mac_impl_t	*mip = (mac_impl_t *)mh;
1887 
1888 	if (mip->mi_type->mt_addr_length == 0)
1889 		return;
1890 
1891 	/*
1892 	 * Save the address.
1893 	 */
1894 	bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
1895 
1896 	/*
1897 	 * Send a MAC_NOTE_UNICST notification.
1898 	 */
1899 	i_mac_notify(mip, MAC_NOTE_UNICST);
1900 }
1901 
1902 void
1903 mac_tx_update(mac_handle_t mh)
1904 {
1905 	/*
1906 	 * Send a MAC_NOTE_TX notification.
1907 	 */
1908 	i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX);
1909 }
1910 
1911 void
1912 mac_resource_update(mac_handle_t mh)
1913 {
1914 	/*
1915 	 * Send a MAC_NOTE_RESOURCE notification.
1916 	 */
1917 	i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE);
1918 }
1919 
1920 mac_resource_handle_t
1921 mac_resource_add(mac_handle_t mh, mac_resource_t *mrp)
1922 {
1923 	mac_impl_t		*mip = (mac_impl_t *)mh;
1924 	mac_resource_handle_t	mrh;
1925 	mac_resource_add_t	add;
1926 	void			*arg;
1927 
1928 	rw_enter(&mip->mi_resource_lock, RW_READER);
1929 	add = mip->mi_resource_add;
1930 	arg = mip->mi_resource_add_arg;
1931 
1932 	if (add != NULL)
1933 		mrh = add(arg, mrp);
1934 	else
1935 		mrh = NULL;
1936 	rw_exit(&mip->mi_resource_lock);
1937 
1938 	return (mrh);
1939 }
1940 
1941 int
1942 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize)
1943 {
1944 	mac_impl_t	*mip = (mac_impl_t *)mh;
1945 
1946 	/*
1947 	 * Verify that the plugin supports MAC plugin data and that the
1948 	 * supplied data is valid.
1949 	 */
1950 	if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY))
1951 		return (EINVAL);
1952 	if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize))
1953 		return (EINVAL);
1954 
1955 	if (mip->mi_pdata != NULL)
1956 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1957 
1958 	mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP);
1959 	bcopy(mac_pdata, mip->mi_pdata, dsize);
1960 	mip->mi_pdata_size = dsize;
1961 
1962 	/*
1963 	 * Since the MAC plugin data is used to construct MAC headers that
1964 	 * were cached in fast-path headers, we need to flush fast-path
1965 	 * information for links associated with this mac.
1966 	 */
1967 	i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH);
1968 	return (0);
1969 }
1970 
1971 void
1972 mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg,
1973     boolean_t add)
1974 {
1975 	mac_impl_t		*mip = (mac_impl_t *)mh;
1976 	mac_multicst_addr_t	*p;
1977 
1978 	/*
1979 	 * If no specific refresh function was given then default to the
1980 	 * driver's m_multicst entry point.
1981 	 */
1982 	if (refresh == NULL) {
1983 		refresh = mip->mi_multicst;
1984 		arg = mip->mi_driver;
1985 	}
1986 	ASSERT(refresh != NULL);
1987 
1988 	/*
1989 	 * Walk the multicast address list and call the refresh function for
1990 	 * each address.
1991 	 */
1992 	rw_enter(&(mip->mi_data_lock), RW_READER);
1993 	for (p = mip->mi_mmap; p != NULL; p = p->mma_nextp)
1994 		refresh(arg, add, p->mma_addr);
1995 	rw_exit(&(mip->mi_data_lock));
1996 }
1997 
1998 void
1999 mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg)
2000 {
2001 	mac_impl_t	*mip = (mac_impl_t *)mh;
2002 	/*
2003 	 * If no specific refresh function was given then default to the
2004 	 * driver's mi_unicst entry point.
2005 	 */
2006 	if (refresh == NULL) {
2007 		refresh = mip->mi_unicst;
2008 		arg = mip->mi_driver;
2009 	}
2010 	ASSERT(refresh != NULL);
2011 
2012 	/*
2013 	 * Call the refresh function with the current unicast address.
2014 	 */
2015 	refresh(arg, mip->mi_addr);
2016 }
2017 
2018 void
2019 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg)
2020 {
2021 	mac_impl_t	*mip = (mac_impl_t *)mh;
2022 
2023 	/*
2024 	 * If no specific refresh function was given then default to the
2025 	 * driver's m_promisc entry point.
2026 	 */
2027 	if (refresh == NULL) {
2028 		refresh = mip->mi_setpromisc;
2029 		arg = mip->mi_driver;
2030 	}
2031 	ASSERT(refresh != NULL);
2032 
2033 	/*
2034 	 * Call the refresh function with the current promiscuity.
2035 	 */
2036 	refresh(arg, (mip->mi_devpromisc != 0));
2037 }
2038 
2039 boolean_t
2040 mac_do_active_set(mac_handle_t mh, boolean_t shareable)
2041 {
2042 	mac_impl_t *mip = (mac_impl_t *)mh;
2043 
2044 	mutex_enter(&mip->mi_activelink_lock);
2045 	if (mip->mi_activelink) {
2046 		mutex_exit(&mip->mi_activelink_lock);
2047 		return (B_FALSE);
2048 	}
2049 	mip->mi_activelink = B_TRUE;
2050 	mip->mi_shareable = shareable;
2051 	mutex_exit(&mip->mi_activelink_lock);
2052 	return (B_TRUE);
2053 }
2054 
2055 /*
2056  * Called by MAC clients. By default, active MAC clients cannot
2057  * share the NIC with VNICs.
2058  */
2059 boolean_t
2060 mac_active_set(mac_handle_t mh)
2061 {
2062 	return (mac_do_active_set(mh, B_FALSE));
2063 }
2064 
2065 /*
2066  * Called by MAC clients which can share the NIC with VNICS, e.g. DLS.
2067  */
2068 boolean_t
2069 mac_active_shareable_set(mac_handle_t mh)
2070 {
2071 	return (mac_do_active_set(mh, B_TRUE));
2072 }
2073 
2074 void
2075 mac_active_clear(mac_handle_t mh)
2076 {
2077 	mac_impl_t *mip = (mac_impl_t *)mh;
2078 
2079 	mutex_enter(&mip->mi_activelink_lock);
2080 	ASSERT(mip->mi_activelink);
2081 	mip->mi_activelink = B_FALSE;
2082 	mutex_exit(&mip->mi_activelink_lock);
2083 }
2084 
2085 boolean_t
2086 mac_vnic_set(mac_handle_t mh, mac_txinfo_t *tx_info, mac_getcapab_t getcapab_fn,
2087     void *getcapab_arg)
2088 {
2089 	mac_impl_t	*mip = (mac_impl_t *)mh;
2090 	mac_vnic_tx_t	*vnic_tx;
2091 
2092 	mutex_enter(&mip->mi_activelink_lock);
2093 	rw_enter(&mip->mi_tx_lock, RW_WRITER);
2094 	ASSERT(!mip->mi_vnic_present);
2095 
2096 	if (mip->mi_activelink && !mip->mi_shareable) {
2097 		/*
2098 		 * The NIC is already used by an active client which cannot
2099 		 * share it with VNICs.
2100 		 */
2101 		rw_exit(&mip->mi_tx_lock);
2102 		mutex_exit(&mip->mi_activelink_lock);
2103 		return (B_FALSE);
2104 	}
2105 
2106 	vnic_tx = kmem_cache_alloc(mac_vnic_tx_cache, KM_SLEEP);
2107 	vnic_tx->mv_refs = 0;
2108 	vnic_tx->mv_txinfo = *tx_info;
2109 	vnic_tx->mv_clearing = B_FALSE;
2110 
2111 	mip->mi_vnic_present = B_TRUE;
2112 	mip->mi_vnic_tx = vnic_tx;
2113 	mip->mi_vnic_getcapab_fn = getcapab_fn;
2114 	mip->mi_vnic_getcapab_arg = getcapab_arg;
2115 	rw_exit(&mip->mi_tx_lock);
2116 	mutex_exit(&mip->mi_activelink_lock);
2117 
2118 	i_mac_notify(mip, MAC_NOTE_VNIC);
2119 	return (B_TRUE);
2120 }
2121 
2122 void
2123 mac_vnic_clear(mac_handle_t mh)
2124 {
2125 	mac_impl_t *mip = (mac_impl_t *)mh;
2126 	mac_vnic_tx_t	*vnic_tx;
2127 
2128 	rw_enter(&mip->mi_tx_lock, RW_WRITER);
2129 	ASSERT(mip->mi_vnic_present);
2130 	mip->mi_vnic_present = B_FALSE;
2131 	/*
2132 	 * Setting mi_vnic_tx to NULL here under the lock guarantees
2133 	 * that no new references to the current VNIC transmit structure
2134 	 * will be taken by mac_vnic_tx(). This is a necessary condition
2135 	 * for safely waiting for the reference count to drop to
2136 	 * zero below.
2137 	 */
2138 	vnic_tx = mip->mi_vnic_tx;
2139 	mip->mi_vnic_tx = NULL;
2140 	mip->mi_vnic_getcapab_fn = NULL;
2141 	mip->mi_vnic_getcapab_arg = NULL;
2142 	rw_exit(&mip->mi_tx_lock);
2143 
2144 	i_mac_notify(mip, MAC_NOTE_VNIC);
2145 
2146 	/*
2147 	 * Wait for all TX calls referencing the VNIC transmit
2148 	 * entry point that was removed to complete.
2149 	 */
2150 	mutex_enter(&vnic_tx->mv_lock);
2151 	vnic_tx->mv_clearing = B_TRUE;
2152 	while (vnic_tx->mv_refs > 0)
2153 		cv_wait(&vnic_tx->mv_cv, &vnic_tx->mv_lock);
2154 	mutex_exit(&vnic_tx->mv_lock);
2155 	kmem_cache_free(mac_vnic_tx_cache, vnic_tx);
2156 }
2157 
2158 /*
2159  * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is
2160  * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find
2161  * the first mac_impl_t with a matching driver name; then we copy its mac_info_t
2162  * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t
2163  * cannot disappear while we are accessing it.
2164  */
2165 typedef struct i_mac_info_state_s {
2166 	const char	*mi_name;
2167 	mac_info_t	*mi_infop;
2168 } i_mac_info_state_t;
2169 
2170 /*ARGSUSED*/
2171 static uint_t
2172 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
2173 {
2174 	i_mac_info_state_t	*statep = arg;
2175 	mac_impl_t		*mip = (mac_impl_t *)val;
2176 
2177 	if (mip->mi_disabled)
2178 		return (MH_WALK_CONTINUE);
2179 
2180 	if (strcmp(statep->mi_name,
2181 	    ddi_driver_name(mip->mi_dip)) != 0)
2182 		return (MH_WALK_CONTINUE);
2183 
2184 	statep->mi_infop = &mip->mi_info;
2185 	return (MH_WALK_TERMINATE);
2186 }
2187 
2188 boolean_t
2189 mac_info_get(const char *name, mac_info_t *minfop)
2190 {
2191 	i_mac_info_state_t	state;
2192 
2193 	rw_enter(&i_mac_impl_lock, RW_READER);
2194 	state.mi_name = name;
2195 	state.mi_infop = NULL;
2196 	mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state);
2197 	if (state.mi_infop == NULL) {
2198 		rw_exit(&i_mac_impl_lock);
2199 		return (B_FALSE);
2200 	}
2201 	*minfop = *state.mi_infop;
2202 	rw_exit(&i_mac_impl_lock);
2203 	return (B_TRUE);
2204 }
2205 
2206 boolean_t
2207 mac_do_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data,
2208     boolean_t is_vnic)
2209 {
2210 	mac_impl_t *mip = (mac_impl_t *)mh;
2211 
2212 	if (!is_vnic) {
2213 		rw_enter(&mip->mi_tx_lock, RW_READER);
2214 		if (mip->mi_vnic_present) {
2215 			boolean_t rv;
2216 
2217 			rv = mip->mi_vnic_getcapab_fn(mip->mi_vnic_getcapab_arg,
2218 			    cap, cap_data);
2219 			rw_exit(&mip->mi_tx_lock);
2220 			return (rv);
2221 		}
2222 		rw_exit(&mip->mi_tx_lock);
2223 	}
2224 
2225 	if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB)
2226 		return (mip->mi_getcapab(mip->mi_driver, cap, cap_data));
2227 	else
2228 		return (B_FALSE);
2229 }
2230 
2231 boolean_t
2232 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
2233 {
2234 	return (mac_do_capab_get(mh, cap, cap_data, B_FALSE));
2235 }
2236 
2237 boolean_t
2238 mac_vnic_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
2239 {
2240 	return (mac_do_capab_get(mh, cap, cap_data, B_TRUE));
2241 }
2242 
2243 boolean_t
2244 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap)
2245 {
2246 	mac_impl_t	*mip = (mac_impl_t *)mh;
2247 	return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap,
2248 	    mip->mi_pdata));
2249 }
2250 
2251 mblk_t *
2252 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload,
2253     size_t extra_len)
2254 {
2255 	mac_impl_t	*mip = (mac_impl_t *)mh;
2256 	return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap,
2257 	    mip->mi_pdata, payload, extra_len));
2258 }
2259 
2260 int
2261 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip)
2262 {
2263 	mac_impl_t	*mip = (mac_impl_t *)mh;
2264 	return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata,
2265 	    mhip));
2266 }
2267 
2268 mblk_t *
2269 mac_header_cook(mac_handle_t mh, mblk_t *mp)
2270 {
2271 	mac_impl_t	*mip = (mac_impl_t *)mh;
2272 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) {
2273 		if (DB_REF(mp) > 1) {
2274 			mblk_t *newmp = copymsg(mp);
2275 			if (newmp == NULL)
2276 				return (NULL);
2277 			freemsg(mp);
2278 			mp = newmp;
2279 		}
2280 		return (mip->mi_type->mt_ops.mtops_header_cook(mp,
2281 		    mip->mi_pdata));
2282 	}
2283 	return (mp);
2284 }
2285 
2286 mblk_t *
2287 mac_header_uncook(mac_handle_t mh, mblk_t *mp)
2288 {
2289 	mac_impl_t	*mip = (mac_impl_t *)mh;
2290 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) {
2291 		if (DB_REF(mp) > 1) {
2292 			mblk_t *newmp = copymsg(mp);
2293 			if (newmp == NULL)
2294 				return (NULL);
2295 			freemsg(mp);
2296 			mp = newmp;
2297 		}
2298 		return (mip->mi_type->mt_ops.mtops_header_uncook(mp,
2299 		    mip->mi_pdata));
2300 	}
2301 	return (mp);
2302 }
2303 
2304 void
2305 mac_init_ops(struct dev_ops *ops, const char *name)
2306 {
2307 	dld_init_ops(ops, name);
2308 }
2309 
2310 void
2311 mac_fini_ops(struct dev_ops *ops)
2312 {
2313 	dld_fini_ops(ops);
2314 }
2315 
2316 /*
2317  * MAC Type Plugin functions.
2318  */
2319 
2320 mactype_register_t *
2321 mactype_alloc(uint_t mactype_version)
2322 {
2323 	mactype_register_t *mtrp;
2324 
2325 	/*
2326 	 * Make sure there isn't a version mismatch between the plugin and
2327 	 * the framework.  In the future, if multiple versions are
2328 	 * supported, this check could become more sophisticated.
2329 	 */
2330 	if (mactype_version != MACTYPE_VERSION)
2331 		return (NULL);
2332 
2333 	mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP);
2334 	mtrp->mtr_version = mactype_version;
2335 	return (mtrp);
2336 }
2337 
2338 void
2339 mactype_free(mactype_register_t *mtrp)
2340 {
2341 	kmem_free(mtrp, sizeof (mactype_register_t));
2342 }
2343 
2344 int
2345 mactype_register(mactype_register_t *mtrp)
2346 {
2347 	mactype_t	*mtp;
2348 	mactype_ops_t	*ops = mtrp->mtr_ops;
2349 
2350 	/* Do some sanity checking before we register this MAC type. */
2351 	if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0)
2352 		return (EINVAL);
2353 
2354 	/*
2355 	 * Verify that all mandatory callbacks are set in the ops
2356 	 * vector.
2357 	 */
2358 	if (ops->mtops_unicst_verify == NULL ||
2359 	    ops->mtops_multicst_verify == NULL ||
2360 	    ops->mtops_sap_verify == NULL ||
2361 	    ops->mtops_header == NULL ||
2362 	    ops->mtops_header_info == NULL) {
2363 		return (EINVAL);
2364 	}
2365 
2366 	mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP);
2367 	mtp->mt_ident = mtrp->mtr_ident;
2368 	mtp->mt_ops = *ops;
2369 	mtp->mt_type = mtrp->mtr_mactype;
2370 	mtp->mt_nativetype = mtrp->mtr_nativetype;
2371 	mtp->mt_addr_length = mtrp->mtr_addrlen;
2372 	if (mtrp->mtr_brdcst_addr != NULL) {
2373 		mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP);
2374 		bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr,
2375 		    mtrp->mtr_addrlen);
2376 	}
2377 
2378 	mtp->mt_stats = mtrp->mtr_stats;
2379 	mtp->mt_statcount = mtrp->mtr_statcount;
2380 
2381 	if (mod_hash_insert(i_mactype_hash,
2382 	    (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) {
2383 		kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
2384 		kmem_free(mtp, sizeof (*mtp));
2385 		return (EEXIST);
2386 	}
2387 	return (0);
2388 }
2389 
2390 int
2391 mactype_unregister(const char *ident)
2392 {
2393 	mactype_t	*mtp;
2394 	mod_hash_val_t	val;
2395 	int 		err;
2396 
2397 	/*
2398 	 * Let's not allow MAC drivers to use this plugin while we're
2399 	 * trying to unregister it.  Holding i_mactype_lock also prevents a
2400 	 * plugin from unregistering while a MAC driver is attempting to
2401 	 * hold a reference to it in i_mactype_getplugin().
2402 	 */
2403 	mutex_enter(&i_mactype_lock);
2404 
2405 	if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident,
2406 	    (mod_hash_val_t *)&mtp)) != 0) {
2407 		/* A plugin is trying to unregister, but it never registered. */
2408 		err = ENXIO;
2409 		goto done;
2410 	}
2411 
2412 	if (mtp->mt_ref != 0) {
2413 		err = EBUSY;
2414 		goto done;
2415 	}
2416 
2417 	err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val);
2418 	ASSERT(err == 0);
2419 	if (err != 0) {
2420 		/* This should never happen, thus the ASSERT() above. */
2421 		err = EINVAL;
2422 		goto done;
2423 	}
2424 	ASSERT(mtp == (mactype_t *)val);
2425 
2426 	kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
2427 	kmem_free(mtp, sizeof (mactype_t));
2428 done:
2429 	mutex_exit(&i_mactype_lock);
2430 	return (err);
2431 }
2432 
2433 int
2434 mac_vlan_create(mac_handle_t mh, const char *name, minor_t minor)
2435 {
2436 	mac_impl_t		*mip = (mac_impl_t *)mh;
2437 
2438 	/* Create a style-1 DLPI device */
2439 	if (ddi_create_minor_node(mip->mi_dip, (char *)name, S_IFCHR, minor,
2440 	    DDI_NT_NET, 0) != DDI_SUCCESS) {
2441 		return (-1);
2442 	}
2443 	return (0);
2444 }
2445 
2446 void
2447 mac_vlan_remove(mac_handle_t mh, const char *name)
2448 {
2449 	mac_impl_t		*mip = (mac_impl_t *)mh;
2450 	dev_info_t		*dipp;
2451 
2452 	ddi_remove_minor_node(mip->mi_dip, (char *)name);
2453 	dipp = ddi_get_parent(mip->mi_dip);
2454 	(void) devfs_clean(dipp, NULL, 0);
2455 }
2456