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