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