xref: /titanic_52/usr/src/uts/common/io/mac/mac.c (revision 69112edd987c28fa551d4f8d9362a84a45365f17)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * MAC Services Module
29  *
30  * The GLDv3 framework locking -  The MAC layer
31  * --------------------------------------------
32  *
33  * The MAC layer is central to the GLD framework and can provide the locking
34  * framework needed for itself and for the use of MAC clients. MAC end points
35  * are fairly disjoint and don't share a lot of state. So a coarse grained
36  * multi-threading scheme is to single thread all create/modify/delete or set
37  * type of control operations on a per mac end point while allowing data threads
38  * concurrently.
39  *
40  * Control operations (set) that modify a mac end point are always serialized on
41  * a per mac end point basis, We have at most 1 such thread per mac end point
42  * at a time.
43  *
44  * All other operations that are not serialized are essentially multi-threaded.
45  * For example a control operation (get) like getting statistics which may not
46  * care about reading values atomically or data threads sending or receiving
47  * data. Mostly these type of operations don't modify the control state. Any
48  * state these operations care about are protected using traditional locks.
49  *
50  * The perimeter only serializes serial operations. It does not imply there
51  * aren't any other concurrent operations. However a serialized operation may
52  * sometimes need to make sure it is the only thread. In this case it needs
53  * to use reference counting mechanisms to cv_wait until any current data
54  * threads are done.
55  *
56  * The mac layer itself does not hold any locks across a call to another layer.
57  * The perimeter is however held across a down call to the driver to make the
58  * whole control operation atomic with respect to other control operations.
59  * Also the data path and get type control operations may proceed concurrently.
60  * These operations synchronize with the single serial operation on a given mac
61  * end point using regular locks. The perimeter ensures that conflicting
62  * operations like say a mac_multicast_add and a mac_multicast_remove on the
63  * same mac end point don't interfere with each other and also ensures that the
64  * changes in the mac layer and the call to the underlying driver to say add a
65  * multicast address are done atomically without interference from a thread
66  * trying to delete the same address.
67  *
68  * For example, consider
69  * mac_multicst_add()
70  * {
71  *	mac_perimeter_enter();	serialize all control operations
72  *
73  *	grab list lock		protect against access by data threads
74  *	add to list
75  *	drop list lock
76  *
77  *	call driver's mi_multicst
78  *
79  *	mac_perimeter_exit();
80  * }
81  *
82  * To lessen the number of serialization locks and simplify the lock hierarchy,
83  * we serialize all the control operations on a per mac end point by using a
84  * single serialization lock called the perimeter. We allow recursive entry into
85  * the perimeter to facilitate use of this mechanism by both the mac client and
86  * the MAC layer itself.
87  *
88  * MAC client means an entity that does an operation on a mac handle
89  * obtained from a mac_open/mac_client_open. Similarly MAC driver means
90  * an entity that does an operation on a mac handle obtained from a
91  * mac_register. An entity could be both client and driver but on different
92  * handles eg. aggr. and should only make the corresponding mac interface calls
93  * i.e. mac driver interface or mac client interface as appropriate for that
94  * mac handle.
95  *
96  * General rules.
97  * -------------
98  *
99  * R1. The lock order of upcall threads is natually opposite to downcall
100  * threads. Hence upcalls must not hold any locks across layers for fear of
101  * recursive lock enter and lock order violation. This applies to all layers.
102  *
103  * R2. The perimeter is just another lock. Since it is held in the down
104  * direction, acquiring the perimeter in an upcall is prohibited as it would
105  * cause a deadlock. This applies to all layers.
106  *
107  * Note that upcalls that need to grab the mac perimeter (for example
108  * mac_notify upcalls) can still achieve that by posting the request to a
109  * thread, which can then grab all the required perimeters and locks in the
110  * right global order. Note that in the above example the mac layer iself
111  * won't grab the mac perimeter in the mac_notify upcall, instead the upcall
112  * to the client must do that. Please see the aggr code for an example.
113  *
114  * MAC client rules
115  * ----------------
116  *
117  * R3. A MAC client may use the MAC provided perimeter facility to serialize
118  * control operations on a per mac end point. It does this by by acquring
119  * and holding the perimeter across a sequence of calls to the mac layer.
120  * This ensures atomicity across the entire block of mac calls. In this
121  * model the MAC client must not hold any client locks across the calls to
122  * the mac layer. This model is the preferred solution.
123  *
124  * R4. However if a MAC client has a lot of global state across all mac end
125  * points the per mac end point serialization may not be sufficient. In this
126  * case the client may choose to use global locks or use its own serialization.
127  * To avoid deadlocks, these client layer locks held across the mac calls
128  * in the control path must never be acquired by the data path for the reason
129  * mentioned below.
130  *
131  * (Assume that a control operation that holds a client lock blocks in the
132  * mac layer waiting for upcall reference counts to drop to zero. If an upcall
133  * data thread that holds this reference count, tries to acquire the same
134  * client lock subsequently it will deadlock).
135  *
136  * A MAC client may follow either the R3 model or the R4 model, but can't
137  * mix both. In the former, the hierarchy is Perim -> client locks, but in
138  * the latter it is client locks -> Perim.
139  *
140  * R5. MAC clients must make MAC calls (excluding data calls) in a cv_wait'able
141  * context since they may block while trying to acquire the perimeter.
142  * In addition some calls may block waiting for upcall refcnts to come down to
143  * zero.
144  *
145  * R6. MAC clients must make sure that they are single threaded and all threads
146  * from the top (in particular data threads) have finished before calling
147  * mac_client_close. The MAC framework does not track the number of client
148  * threads using the mac client handle. Also mac clients must make sure
149  * they have undone all the control operations before calling mac_client_close.
150  * For example mac_unicast_remove/mac_multicast_remove to undo the corresponding
151  * mac_unicast_add/mac_multicast_add.
152  *
153  * MAC framework rules
154  * -------------------
155  *
156  * R7. The mac layer itself must not hold any mac layer locks (except the mac
157  * perimeter) across a call to any other layer from the mac layer. The call to
158  * any other layer could be via mi_* entry points, classifier entry points into
159  * the driver or via upcall pointers into layers above. The mac perimeter may
160  * be acquired or held only in the down direction, for e.g. when calling into
161  * a mi_* driver enty point to provide atomicity of the operation.
162  *
163  * R8. Since it is not guaranteed (see R14) that drivers won't hold locks across
164  * mac driver interfaces, the MAC layer must provide a cut out for control
165  * interfaces like upcall notifications and start them in a separate thread.
166  *
167  * R9. Note that locking order also implies a plumbing order. For example
168  * VNICs are allowed to be created over aggrs, but not vice-versa. An attempt
169  * to plumb in any other order must be failed at mac_open time, otherwise it
170  * could lead to deadlocks due to inverse locking order.
171  *
172  * R10. MAC driver interfaces must not block since the driver could call them
173  * in interrupt context.
174  *
175  * R11. Walkers must preferably not hold any locks while calling walker
176  * callbacks. Instead these can operate on reference counts. In simple
177  * callbacks it may be ok to hold a lock and call the callbacks, but this is
178  * harder to maintain in the general case of arbitrary callbacks.
179  *
180  * R12. The MAC layer must protect upcall notification callbacks using reference
181  * counts rather than holding locks across the callbacks.
182  *
183  * R13. Given the variety of drivers, it is preferable if the MAC layer can make
184  * sure that any pointers (such as mac ring pointers) it passes to the driver
185  * remain valid until mac unregister time. Currently the mac layer achieves
186  * this by using generation numbers for rings and freeing the mac rings only
187  * at unregister time.  The MAC layer must provide a layer of indirection and
188  * must not expose underlying driver rings or driver data structures/pointers
189  * directly to MAC clients.
190  *
191  * MAC driver rules
192  * ----------------
193  *
194  * R14. It would be preferable if MAC drivers don't hold any locks across any
195  * mac call. However at a minimum they must not hold any locks across data
196  * upcalls. They must also make sure that all references to mac data structures
197  * are cleaned up and that it is single threaded at mac_unregister time.
198  *
199  * R15. MAC driver interfaces don't block and so the action may be done
200  * asynchronously in a separate thread as for example handling notifications.
201  * The driver must not assume that the action is complete when the call
202  * returns.
203  *
204  * R16. Drivers must maintain a generation number per Rx ring, and pass it
205  * back to mac_rx_ring(); They are expected to increment the generation
206  * number whenever the ring's stop routine is invoked.
207  * See comments in mac_rx_ring();
208  *
209  * R17 Similarly mi_stop is another synchronization point and the driver must
210  * ensure that all upcalls are done and there won't be any future upcall
211  * before returning from mi_stop.
212  *
213  * R18. The driver may assume that all set/modify control operations via
214  * the mi_* entry points are single threaded on a per mac end point.
215  *
216  * Lock and Perimeter hierarchy scenarios
217  * ---------------------------------------
218  *
219  * i_mac_impl_lock -> mi_rw_lock -> srs_lock -> s_ring_lock[i_mac_tx_srs_notify]
220  *
221  * ft_lock -> fe_lock [mac_flow_lookup]
222  *
223  * mi_rw_lock -> fe_lock [mac_bcast_send]
224  *
225  * srs_lock -> mac_bw_lock [mac_rx_srs_drain_bw]
226  *
227  * cpu_lock -> mac_srs_g_lock -> srs_lock -> s_ring_lock [mac_walk_srs_and_bind]
228  *
229  * i_dls_devnet_lock -> mac layer locks [dls_devnet_rename]
230  *
231  * Perimeters are ordered P1 -> P2 -> P3 from top to bottom in order of mac
232  * client to driver. In the case of clients that explictly use the mac provided
233  * perimeter mechanism for its serialization, the hierarchy is
234  * Perimeter -> mac layer locks, since the client never holds any locks across
235  * the mac calls. In the case of clients that use its own locks the hierarchy
236  * is Client locks -> Mac Perim -> Mac layer locks. The client never explicitly
237  * calls mac_perim_enter/exit in this case.
238  *
239  * Subflow creation rules
240  * ---------------------------
241  * o In case of a user specified cpulist present on underlying link and flows,
242  * the flows cpulist must be a subset of the underlying link.
243  * o In case of a user specified fanout mode present on link and flow, the
244  * subflow fanout count has to be less than or equal to that of the
245  * underlying link. The cpu-bindings for the subflows will be a subset of
246  * the underlying link.
247  * o In case if no cpulist specified on both underlying link and flow, the
248  * underlying link relies on a  MAC tunable to provide out of box fanout.
249  * The subflow will have no cpulist (the subflow will be unbound)
250  * o In case if no cpulist is specified on the underlying link, a subflow can
251  * carry  either a user-specified cpulist or fanout count. The cpu-bindings
252  * for the subflow will not adhere to restriction that they need to be subset
253  * of the underlying link.
254  * o In case where the underlying link is carrying either a user specified
255  * cpulist or fanout mode and for a unspecified subflow, the subflow will be
256  * created unbound.
257  * o While creating unbound subflows, bandwidth mode changes attempt to
258  * figure a right fanout count. In such cases the fanout count will override
259  * the unbound cpu-binding behavior.
260  * o In addition to this, while cycling between flow and link properties, we
261  * impose a restriction that if a link property has a subflow with
262  * user-specified attributes, we will not allow changing the link property.
263  * The administrator needs to reset all the user specified properties for the
264  * subflows before attempting a link property change.
265  * Some of the above rules can be overridden by specifying additional command
266  * line options while creating or modifying link or subflow properties.
267  */
268 
269 #include <sys/types.h>
270 #include <sys/conf.h>
271 #include <sys/id_space.h>
272 #include <sys/esunddi.h>
273 #include <sys/stat.h>
274 #include <sys/mkdev.h>
275 #include <sys/stream.h>
276 #include <sys/strsun.h>
277 #include <sys/strsubr.h>
278 #include <sys/dlpi.h>
279 #include <sys/modhash.h>
280 #include <sys/mac_provider.h>
281 #include <sys/mac_client_impl.h>
282 #include <sys/mac_soft_ring.h>
283 #include <sys/mac_impl.h>
284 #include <sys/mac.h>
285 #include <sys/dls.h>
286 #include <sys/dld.h>
287 #include <sys/modctl.h>
288 #include <sys/fs/dv_node.h>
289 #include <sys/thread.h>
290 #include <sys/proc.h>
291 #include <sys/callb.h>
292 #include <sys/cpuvar.h>
293 #include <sys/atomic.h>
294 #include <sys/bitmap.h>
295 #include <sys/sdt.h>
296 #include <sys/mac_flow.h>
297 #include <sys/ddi_intr_impl.h>
298 #include <sys/disp.h>
299 #include <sys/sdt.h>
300 #include <sys/vnic.h>
301 #include <sys/vnic_impl.h>
302 #include <sys/vlan.h>
303 #include <inet/ip.h>
304 #include <inet/ip6.h>
305 #include <sys/exacct.h>
306 #include <sys/exacct_impl.h>
307 #include <inet/nd.h>
308 #include <sys/ethernet.h>
309 
310 #define	IMPL_HASHSZ	67	/* prime */
311 
312 kmem_cache_t	*i_mac_impl_cachep;
313 mod_hash_t		*i_mac_impl_hash;
314 krwlock_t		i_mac_impl_lock;
315 uint_t			i_mac_impl_count;
316 static kmem_cache_t	*mac_ring_cache;
317 static id_space_t	*minor_ids;
318 static uint32_t		minor_count;
319 
320 /*
321  * Logging stuff. Perhaps mac_logging_interval could be broken into
322  * mac_flow_log_interval and mac_link_log_interval if we want to be
323  * able to schedule them differently.
324  */
325 uint_t			mac_logging_interval;
326 boolean_t		mac_flow_log_enable;
327 boolean_t		mac_link_log_enable;
328 timeout_id_t		mac_logging_timer;
329 
330 /* for debugging, see MAC_DBG_PRT() in mac_impl.h */
331 int mac_dbg = 0;
332 
333 #define	MACTYPE_KMODDIR	"mac"
334 #define	MACTYPE_HASHSZ	67
335 static mod_hash_t	*i_mactype_hash;
336 /*
337  * i_mactype_lock synchronizes threads that obtain references to mactype_t
338  * structures through i_mactype_getplugin().
339  */
340 static kmutex_t		i_mactype_lock;
341 
342 /*
343  * mac_tx_percpu_cnt
344  *
345  * Number of per cpu locks per mac_client_impl_t. Used by the transmit side
346  * in mac_tx to reduce lock contention. This is sized at boot time in mac_init.
347  * mac_tx_percpu_cnt_max is settable in /etc/system and must be a power of 2.
348  * Per cpu locks may be disabled by setting mac_tx_percpu_cnt_max to 1.
349  */
350 int mac_tx_percpu_cnt;
351 int mac_tx_percpu_cnt_max = 128;
352 
353 /*
354  * Call back functions for the bridge module.  These are guaranteed to be valid
355  * when holding a reference on a link or when holding mip->mi_bridge_lock and
356  * mi_bridge_link is non-NULL.
357  */
358 mac_bridge_tx_t mac_bridge_tx_cb;
359 mac_bridge_rx_t mac_bridge_rx_cb;
360 mac_bridge_ref_t mac_bridge_ref_cb;
361 mac_bridge_ls_t mac_bridge_ls_cb;
362 
363 static int i_mac_constructor(void *, void *, int);
364 static void i_mac_destructor(void *, void *);
365 static int i_mac_ring_ctor(void *, void *, int);
366 static void i_mac_ring_dtor(void *, void *);
367 static mblk_t *mac_rx_classify(mac_impl_t *, mac_resource_handle_t, mblk_t *);
368 void mac_tx_client_flush(mac_client_impl_t *);
369 void mac_tx_client_block(mac_client_impl_t *);
370 static void mac_rx_ring_quiesce(mac_ring_t *, uint_t);
371 static int mac_start_group_and_rings(mac_group_t *);
372 static void mac_stop_group_and_rings(mac_group_t *);
373 
374 /*
375  * Module initialization functions.
376  */
377 
378 void
379 mac_init(void)
380 {
381 	mac_tx_percpu_cnt = ((boot_max_ncpus == -1) ? max_ncpus :
382 	    boot_max_ncpus);
383 
384 	/* Upper bound is mac_tx_percpu_cnt_max */
385 	if (mac_tx_percpu_cnt > mac_tx_percpu_cnt_max)
386 		mac_tx_percpu_cnt = mac_tx_percpu_cnt_max;
387 
388 	if (mac_tx_percpu_cnt < 1) {
389 		/* Someone set max_tx_percpu_cnt_max to 0 or less */
390 		mac_tx_percpu_cnt = 1;
391 	}
392 
393 	ASSERT(mac_tx_percpu_cnt >= 1);
394 	mac_tx_percpu_cnt = (1 << highbit(mac_tx_percpu_cnt - 1));
395 	/*
396 	 * Make it of the form 2**N - 1 in the range
397 	 * [0 .. mac_tx_percpu_cnt_max - 1]
398 	 */
399 	mac_tx_percpu_cnt--;
400 
401 	i_mac_impl_cachep = kmem_cache_create("mac_impl_cache",
402 	    sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor,
403 	    NULL, NULL, NULL, 0);
404 	ASSERT(i_mac_impl_cachep != NULL);
405 
406 	mac_ring_cache = kmem_cache_create("mac_ring_cache",
407 	    sizeof (mac_ring_t), 0, i_mac_ring_ctor, i_mac_ring_dtor, NULL,
408 	    NULL, NULL, 0);
409 	ASSERT(mac_ring_cache != NULL);
410 
411 	i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash",
412 	    IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
413 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
414 	rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL);
415 
416 	mac_flow_init();
417 	mac_soft_ring_init();
418 	mac_bcast_init();
419 	mac_client_init();
420 
421 	i_mac_impl_count = 0;
422 
423 	i_mactype_hash = mod_hash_create_extended("mactype_hash",
424 	    MACTYPE_HASHSZ,
425 	    mod_hash_null_keydtor, mod_hash_null_valdtor,
426 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
427 
428 	/*
429 	 * Allocate an id space to manage minor numbers. The range of the
430 	 * space will be from MAC_MAX_MINOR+1 to MAC_PRIVATE_MINOR-1.  This
431 	 * leaves half of the 32-bit minors available for driver private use.
432 	 */
433 	minor_ids = id_space_create("mac_minor_ids", MAC_MAX_MINOR+1,
434 	    MAC_PRIVATE_MINOR-1);
435 	ASSERT(minor_ids != NULL);
436 	minor_count = 0;
437 
438 	/* Let's default to 20 seconds */
439 	mac_logging_interval = 20;
440 	mac_flow_log_enable = B_FALSE;
441 	mac_link_log_enable = B_FALSE;
442 	mac_logging_timer = 0;
443 }
444 
445 int
446 mac_fini(void)
447 {
448 	if (i_mac_impl_count > 0 || minor_count > 0)
449 		return (EBUSY);
450 
451 	id_space_destroy(minor_ids);
452 	mac_flow_fini();
453 
454 	mod_hash_destroy_hash(i_mac_impl_hash);
455 	rw_destroy(&i_mac_impl_lock);
456 
457 	mac_client_fini();
458 	kmem_cache_destroy(mac_ring_cache);
459 
460 	mod_hash_destroy_hash(i_mactype_hash);
461 	mac_soft_ring_finish();
462 	return (0);
463 }
464 
465 /*
466  * Initialize a GLDv3 driver's device ops.  A driver that manages its own ops
467  * (e.g. softmac) may pass in a NULL ops argument.
468  */
469 void
470 mac_init_ops(struct dev_ops *ops, const char *name)
471 {
472 	major_t major = ddi_name_to_major((char *)name);
473 
474 	/*
475 	 * By returning on error below, we are not letting the driver continue
476 	 * in an undefined context.  The mac_register() function will faill if
477 	 * DN_GLDV3_DRIVER isn't set.
478 	 */
479 	if (major == DDI_MAJOR_T_NONE)
480 		return;
481 	LOCK_DEV_OPS(&devnamesp[major].dn_lock);
482 	devnamesp[major].dn_flags |= (DN_GLDV3_DRIVER | DN_NETWORK_DRIVER);
483 	UNLOCK_DEV_OPS(&devnamesp[major].dn_lock);
484 	if (ops != NULL)
485 		dld_init_ops(ops, name);
486 }
487 
488 void
489 mac_fini_ops(struct dev_ops *ops)
490 {
491 	dld_fini_ops(ops);
492 }
493 
494 /*ARGSUSED*/
495 static int
496 i_mac_constructor(void *buf, void *arg, int kmflag)
497 {
498 	mac_impl_t	*mip = buf;
499 
500 	bzero(buf, sizeof (mac_impl_t));
501 
502 	mip->mi_linkstate = LINK_STATE_UNKNOWN;
503 
504 	mutex_init(&mip->mi_lock, NULL, MUTEX_DRIVER, NULL);
505 	rw_init(&mip->mi_rw_lock, NULL, RW_DRIVER, NULL);
506 	mutex_init(&mip->mi_notify_lock, NULL, MUTEX_DRIVER, NULL);
507 	mutex_init(&mip->mi_promisc_lock, NULL, MUTEX_DRIVER, NULL);
508 	mutex_init(&mip->mi_ring_lock, NULL, MUTEX_DEFAULT, NULL);
509 
510 	mip->mi_notify_cb_info.mcbi_lockp = &mip->mi_notify_lock;
511 	cv_init(&mip->mi_notify_cb_info.mcbi_cv, NULL, CV_DRIVER, NULL);
512 	mip->mi_promisc_cb_info.mcbi_lockp = &mip->mi_promisc_lock;
513 	cv_init(&mip->mi_promisc_cb_info.mcbi_cv, NULL, CV_DRIVER, NULL);
514 
515 	mutex_init(&mip->mi_bridge_lock, NULL, MUTEX_DEFAULT, NULL);
516 
517 	return (0);
518 }
519 
520 /*ARGSUSED*/
521 static void
522 i_mac_destructor(void *buf, void *arg)
523 {
524 	mac_impl_t	*mip = buf;
525 	mac_cb_info_t	*mcbi;
526 
527 	ASSERT(mip->mi_ref == 0);
528 	ASSERT(mip->mi_active == 0);
529 	ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN);
530 	ASSERT(mip->mi_devpromisc == 0);
531 	ASSERT(mip->mi_ksp == NULL);
532 	ASSERT(mip->mi_kstat_count == 0);
533 	ASSERT(mip->mi_nclients == 0);
534 	ASSERT(mip->mi_nactiveclients == 0);
535 	ASSERT(mip->mi_single_active_client == NULL);
536 	ASSERT(mip->mi_state_flags == 0);
537 	ASSERT(mip->mi_factory_addr == NULL);
538 	ASSERT(mip->mi_factory_addr_num == 0);
539 	ASSERT(mip->mi_default_tx_ring == NULL);
540 
541 	mcbi = &mip->mi_notify_cb_info;
542 	ASSERT(mcbi->mcbi_del_cnt == 0 && mcbi->mcbi_walker_cnt == 0);
543 	ASSERT(mip->mi_notify_bits == 0);
544 	ASSERT(mip->mi_notify_thread == NULL);
545 	ASSERT(mcbi->mcbi_lockp == &mip->mi_notify_lock);
546 	mcbi->mcbi_lockp = NULL;
547 
548 	mcbi = &mip->mi_promisc_cb_info;
549 	ASSERT(mcbi->mcbi_del_cnt == 0 && mip->mi_promisc_list == NULL);
550 	ASSERT(mip->mi_promisc_list == NULL);
551 	ASSERT(mcbi->mcbi_lockp == &mip->mi_promisc_lock);
552 	mcbi->mcbi_lockp = NULL;
553 
554 	ASSERT(mip->mi_bcast_ngrps == 0 && mip->mi_bcast_grp == NULL);
555 	ASSERT(mip->mi_perim_owner == NULL && mip->mi_perim_ocnt == 0);
556 
557 	mutex_destroy(&mip->mi_lock);
558 	rw_destroy(&mip->mi_rw_lock);
559 
560 	mutex_destroy(&mip->mi_promisc_lock);
561 	cv_destroy(&mip->mi_promisc_cb_info.mcbi_cv);
562 	mutex_destroy(&mip->mi_notify_lock);
563 	cv_destroy(&mip->mi_notify_cb_info.mcbi_cv);
564 	mutex_destroy(&mip->mi_ring_lock);
565 
566 	ASSERT(mip->mi_bridge_link == NULL);
567 }
568 
569 /* ARGSUSED */
570 static int
571 i_mac_ring_ctor(void *buf, void *arg, int kmflag)
572 {
573 	mac_ring_t *ring = (mac_ring_t *)buf;
574 
575 	bzero(ring, sizeof (mac_ring_t));
576 	cv_init(&ring->mr_cv, NULL, CV_DEFAULT, NULL);
577 	mutex_init(&ring->mr_lock, NULL, MUTEX_DEFAULT, NULL);
578 	ring->mr_state = MR_FREE;
579 	return (0);
580 }
581 
582 /* ARGSUSED */
583 static void
584 i_mac_ring_dtor(void *buf, void *arg)
585 {
586 	mac_ring_t *ring = (mac_ring_t *)buf;
587 
588 	cv_destroy(&ring->mr_cv);
589 	mutex_destroy(&ring->mr_lock);
590 }
591 
592 /*
593  * Common functions to do mac callback addition and deletion. Currently this is
594  * used by promisc callbacks and notify callbacks. List addition and deletion
595  * need to take care of list walkers. List walkers in general, can't hold list
596  * locks and make upcall callbacks due to potential lock order and recursive
597  * reentry issues. Instead list walkers increment the list walker count to mark
598  * the presence of a walker thread. Addition can be carefully done to ensure
599  * that the list walker always sees either the old list or the new list.
600  * However the deletion can't be done while the walker is active, instead the
601  * deleting thread simply marks the entry as logically deleted. The last walker
602  * physically deletes and frees up the logically deleted entries when the walk
603  * is complete.
604  */
605 void
606 mac_callback_add(mac_cb_info_t *mcbi, mac_cb_t **mcb_head,
607     mac_cb_t *mcb_elem)
608 {
609 	mac_cb_t	*p;
610 	mac_cb_t	**pp;
611 
612 	/* Verify it is not already in the list */
613 	for (pp = mcb_head; (p = *pp) != NULL; pp = &p->mcb_nextp) {
614 		if (p == mcb_elem)
615 			break;
616 	}
617 	VERIFY(p == NULL);
618 
619 	/*
620 	 * Add it to the head of the callback list. The membar ensures that
621 	 * the following list pointer manipulations reach global visibility
622 	 * in exactly the program order below.
623 	 */
624 	ASSERT(MUTEX_HELD(mcbi->mcbi_lockp));
625 
626 	mcb_elem->mcb_nextp = *mcb_head;
627 	membar_producer();
628 	*mcb_head = mcb_elem;
629 }
630 
631 /*
632  * Mark the entry as logically deleted. If there aren't any walkers unlink
633  * from the list. In either case return the corresponding status.
634  */
635 boolean_t
636 mac_callback_remove(mac_cb_info_t *mcbi, mac_cb_t **mcb_head,
637     mac_cb_t *mcb_elem)
638 {
639 	mac_cb_t	*p;
640 	mac_cb_t	**pp;
641 
642 	ASSERT(MUTEX_HELD(mcbi->mcbi_lockp));
643 	/*
644 	 * Search the callback list for the entry to be removed
645 	 */
646 	for (pp = mcb_head; (p = *pp) != NULL; pp = &p->mcb_nextp) {
647 		if (p == mcb_elem)
648 			break;
649 	}
650 	VERIFY(p != NULL);
651 
652 	/*
653 	 * If there are walkers just mark it as deleted and the last walker
654 	 * will remove from the list and free it.
655 	 */
656 	if (mcbi->mcbi_walker_cnt != 0) {
657 		p->mcb_flags |= MCB_CONDEMNED;
658 		mcbi->mcbi_del_cnt++;
659 		return (B_FALSE);
660 	}
661 
662 	ASSERT(mcbi->mcbi_del_cnt == 0);
663 	*pp = p->mcb_nextp;
664 	p->mcb_nextp = NULL;
665 	return (B_TRUE);
666 }
667 
668 /*
669  * Wait for all pending callback removals to be completed
670  */
671 void
672 mac_callback_remove_wait(mac_cb_info_t *mcbi)
673 {
674 	ASSERT(MUTEX_HELD(mcbi->mcbi_lockp));
675 	while (mcbi->mcbi_del_cnt != 0) {
676 		DTRACE_PROBE1(need_wait, mac_cb_info_t *, mcbi);
677 		cv_wait(&mcbi->mcbi_cv, mcbi->mcbi_lockp);
678 	}
679 }
680 
681 /*
682  * The last mac callback walker does the cleanup. Walk the list and unlik
683  * all the logically deleted entries and construct a temporary list of
684  * removed entries. Return the list of removed entries to the caller.
685  */
686 mac_cb_t *
687 mac_callback_walker_cleanup(mac_cb_info_t *mcbi, mac_cb_t **mcb_head)
688 {
689 	mac_cb_t	*p;
690 	mac_cb_t	**pp;
691 	mac_cb_t	*rmlist = NULL;		/* List of removed elements */
692 	int	cnt = 0;
693 
694 	ASSERT(MUTEX_HELD(mcbi->mcbi_lockp));
695 	ASSERT(mcbi->mcbi_del_cnt != 0 && mcbi->mcbi_walker_cnt == 0);
696 
697 	pp = mcb_head;
698 	while (*pp != NULL) {
699 		if ((*pp)->mcb_flags & MCB_CONDEMNED) {
700 			p = *pp;
701 			*pp = p->mcb_nextp;
702 			p->mcb_nextp = rmlist;
703 			rmlist = p;
704 			cnt++;
705 			continue;
706 		}
707 		pp = &(*pp)->mcb_nextp;
708 	}
709 
710 	ASSERT(mcbi->mcbi_del_cnt == cnt);
711 	mcbi->mcbi_del_cnt = 0;
712 	return (rmlist);
713 }
714 
715 boolean_t
716 mac_callback_lookup(mac_cb_t **mcb_headp, mac_cb_t *mcb_elem)
717 {
718 	mac_cb_t	*mcb;
719 
720 	/* Verify it is not already in the list */
721 	for (mcb = *mcb_headp; mcb != NULL; mcb = mcb->mcb_nextp) {
722 		if (mcb == mcb_elem)
723 			return (B_TRUE);
724 	}
725 
726 	return (B_FALSE);
727 }
728 
729 boolean_t
730 mac_callback_find(mac_cb_info_t *mcbi, mac_cb_t **mcb_headp, mac_cb_t *mcb_elem)
731 {
732 	boolean_t	found;
733 
734 	mutex_enter(mcbi->mcbi_lockp);
735 	found = mac_callback_lookup(mcb_headp, mcb_elem);
736 	mutex_exit(mcbi->mcbi_lockp);
737 
738 	return (found);
739 }
740 
741 /* Free the list of removed callbacks */
742 void
743 mac_callback_free(mac_cb_t *rmlist)
744 {
745 	mac_cb_t	*mcb;
746 	mac_cb_t	*mcb_next;
747 
748 	for (mcb = rmlist; mcb != NULL; mcb = mcb_next) {
749 		mcb_next = mcb->mcb_nextp;
750 		kmem_free(mcb->mcb_objp, mcb->mcb_objsize);
751 	}
752 }
753 
754 /*
755  * The promisc callbacks are in 2 lists, one off the 'mip' and another off the
756  * 'mcip' threaded by mpi_mi_link and mpi_mci_link respectively. However there
757  * is only a single shared total walker count, and an entry can't be physically
758  * unlinked if a walker is active on either list. The last walker does this
759  * cleanup of logically deleted entries.
760  */
761 void
762 i_mac_promisc_walker_cleanup(mac_impl_t *mip)
763 {
764 	mac_cb_t	*rmlist;
765 	mac_cb_t	*mcb;
766 	mac_cb_t	*mcb_next;
767 	mac_promisc_impl_t	*mpip;
768 
769 	/*
770 	 * Construct a temporary list of deleted callbacks by walking the
771 	 * the mi_promisc_list. Then for each entry in the temporary list,
772 	 * remove it from the mci_promisc_list and free the entry.
773 	 */
774 	rmlist = mac_callback_walker_cleanup(&mip->mi_promisc_cb_info,
775 	    &mip->mi_promisc_list);
776 
777 	for (mcb = rmlist; mcb != NULL; mcb = mcb_next) {
778 		mcb_next = mcb->mcb_nextp;
779 		mpip = (mac_promisc_impl_t *)mcb->mcb_objp;
780 		VERIFY(mac_callback_remove(&mip->mi_promisc_cb_info,
781 		    &mpip->mpi_mcip->mci_promisc_list, &mpip->mpi_mci_link));
782 		mcb->mcb_flags = 0;
783 		mcb->mcb_nextp = NULL;
784 		kmem_cache_free(mac_promisc_impl_cache, mpip);
785 	}
786 }
787 
788 void
789 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type)
790 {
791 	mac_cb_info_t	*mcbi;
792 
793 	/*
794 	 * Signal the notify thread even after mi_ref has become zero and
795 	 * mi_disabled is set. The synchronization with the notify thread
796 	 * happens in mac_unregister and that implies the driver must make
797 	 * sure it is single-threaded (with respect to mac calls) and that
798 	 * all pending mac calls have returned before it calls mac_unregister
799 	 */
800 	rw_enter(&i_mac_impl_lock, RW_READER);
801 	if (mip->mi_state_flags & MIS_DISABLED)
802 		goto exit;
803 
804 	/*
805 	 * Guard against incorrect notifications.  (Running a newer
806 	 * mac client against an older implementation?)
807 	 */
808 	if (type >= MAC_NNOTE)
809 		goto exit;
810 
811 	mcbi = &mip->mi_notify_cb_info;
812 	mutex_enter(mcbi->mcbi_lockp);
813 	mip->mi_notify_bits |= (1 << type);
814 	cv_broadcast(&mcbi->mcbi_cv);
815 	mutex_exit(mcbi->mcbi_lockp);
816 
817 exit:
818 	rw_exit(&i_mac_impl_lock);
819 }
820 
821 /*
822  * Mac serialization primitives. Please see the block comment at the
823  * top of the file.
824  */
825 void
826 i_mac_perim_enter(mac_impl_t *mip)
827 {
828 	mac_client_impl_t	*mcip;
829 
830 	if (mip->mi_state_flags & MIS_IS_VNIC) {
831 		/*
832 		 * This is a VNIC. Return the lower mac since that is what
833 		 * we want to serialize on.
834 		 */
835 		mcip = mac_vnic_lower(mip);
836 		mip = mcip->mci_mip;
837 	}
838 
839 	mutex_enter(&mip->mi_perim_lock);
840 	if (mip->mi_perim_owner == curthread) {
841 		mip->mi_perim_ocnt++;
842 		mutex_exit(&mip->mi_perim_lock);
843 		return;
844 	}
845 
846 	while (mip->mi_perim_owner != NULL)
847 		cv_wait(&mip->mi_perim_cv, &mip->mi_perim_lock);
848 
849 	mip->mi_perim_owner = curthread;
850 	ASSERT(mip->mi_perim_ocnt == 0);
851 	mip->mi_perim_ocnt++;
852 #ifdef DEBUG
853 	mip->mi_perim_stack_depth = getpcstack(mip->mi_perim_stack,
854 	    MAC_PERIM_STACK_DEPTH);
855 #endif
856 	mutex_exit(&mip->mi_perim_lock);
857 }
858 
859 int
860 i_mac_perim_enter_nowait(mac_impl_t *mip)
861 {
862 	/*
863 	 * The vnic is a special case, since the serialization is done based
864 	 * on the lower mac. If the lower mac is busy, it does not imply the
865 	 * vnic can't be unregistered. But in the case of other drivers,
866 	 * a busy perimeter or open mac handles implies that the mac is busy
867 	 * and can't be unregistered.
868 	 */
869 	if (mip->mi_state_flags & MIS_IS_VNIC) {
870 		i_mac_perim_enter(mip);
871 		return (0);
872 	}
873 
874 	mutex_enter(&mip->mi_perim_lock);
875 	if (mip->mi_perim_owner != NULL) {
876 		mutex_exit(&mip->mi_perim_lock);
877 		return (EBUSY);
878 	}
879 	ASSERT(mip->mi_perim_ocnt == 0);
880 	mip->mi_perim_owner = curthread;
881 	mip->mi_perim_ocnt++;
882 	mutex_exit(&mip->mi_perim_lock);
883 
884 	return (0);
885 }
886 
887 void
888 i_mac_perim_exit(mac_impl_t *mip)
889 {
890 	mac_client_impl_t *mcip;
891 
892 	if (mip->mi_state_flags & MIS_IS_VNIC) {
893 		/*
894 		 * This is a VNIC. Return the lower mac since that is what
895 		 * we want to serialize on.
896 		 */
897 		mcip = mac_vnic_lower(mip);
898 		mip = mcip->mci_mip;
899 	}
900 
901 	ASSERT(mip->mi_perim_owner == curthread && mip->mi_perim_ocnt != 0);
902 
903 	mutex_enter(&mip->mi_perim_lock);
904 	if (--mip->mi_perim_ocnt == 0) {
905 		mip->mi_perim_owner = NULL;
906 		cv_signal(&mip->mi_perim_cv);
907 	}
908 	mutex_exit(&mip->mi_perim_lock);
909 }
910 
911 /*
912  * Returns whether the current thread holds the mac perimeter. Used in making
913  * assertions.
914  */
915 boolean_t
916 mac_perim_held(mac_handle_t mh)
917 {
918 	mac_impl_t	*mip = (mac_impl_t *)mh;
919 	mac_client_impl_t *mcip;
920 
921 	if (mip->mi_state_flags & MIS_IS_VNIC) {
922 		/*
923 		 * This is a VNIC. Return the lower mac since that is what
924 		 * we want to serialize on.
925 		 */
926 		mcip = mac_vnic_lower(mip);
927 		mip = mcip->mci_mip;
928 	}
929 	return (mip->mi_perim_owner == curthread);
930 }
931 
932 /*
933  * mac client interfaces to enter the mac perimeter of a mac end point, given
934  * its mac handle, or macname or linkid.
935  */
936 void
937 mac_perim_enter_by_mh(mac_handle_t mh, mac_perim_handle_t *mphp)
938 {
939 	mac_impl_t	*mip = (mac_impl_t *)mh;
940 
941 	i_mac_perim_enter(mip);
942 	/*
943 	 * The mac_perim_handle_t returned encodes the 'mip' and whether a
944 	 * mac_open has been done internally while entering the perimeter.
945 	 * This information is used in mac_perim_exit
946 	 */
947 	MAC_ENCODE_MPH(*mphp, mip, 0);
948 }
949 
950 int
951 mac_perim_enter_by_macname(const char *name, mac_perim_handle_t *mphp)
952 {
953 	int	err;
954 	mac_handle_t	mh;
955 
956 	if ((err = mac_open(name, &mh)) != 0)
957 		return (err);
958 
959 	mac_perim_enter_by_mh(mh, mphp);
960 	MAC_ENCODE_MPH(*mphp, mh, 1);
961 	return (0);
962 }
963 
964 int
965 mac_perim_enter_by_linkid(datalink_id_t linkid, mac_perim_handle_t *mphp)
966 {
967 	int	err;
968 	mac_handle_t	mh;
969 
970 	if ((err = mac_open_by_linkid(linkid, &mh)) != 0)
971 		return (err);
972 
973 	mac_perim_enter_by_mh(mh, mphp);
974 	MAC_ENCODE_MPH(*mphp, mh, 1);
975 	return (0);
976 }
977 
978 void
979 mac_perim_exit(mac_perim_handle_t mph)
980 {
981 	mac_impl_t	*mip;
982 	boolean_t	need_close;
983 
984 	MAC_DECODE_MPH(mph, mip, need_close);
985 	i_mac_perim_exit(mip);
986 	if (need_close)
987 		mac_close((mac_handle_t)mip);
988 }
989 
990 int
991 mac_hold(const char *macname, mac_impl_t **pmip)
992 {
993 	mac_impl_t	*mip;
994 	int		err;
995 
996 	/*
997 	 * Check the device name length to make sure it won't overflow our
998 	 * buffer.
999 	 */
1000 	if (strlen(macname) >= MAXNAMELEN)
1001 		return (EINVAL);
1002 
1003 	/*
1004 	 * Look up its entry in the global hash table.
1005 	 */
1006 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1007 	err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname,
1008 	    (mod_hash_val_t *)&mip);
1009 
1010 	if (err != 0) {
1011 		rw_exit(&i_mac_impl_lock);
1012 		return (ENOENT);
1013 	}
1014 
1015 	if (mip->mi_state_flags & MIS_DISABLED) {
1016 		rw_exit(&i_mac_impl_lock);
1017 		return (ENOENT);
1018 	}
1019 
1020 	if (mip->mi_state_flags & MIS_EXCLUSIVE_HELD) {
1021 		rw_exit(&i_mac_impl_lock);
1022 		return (EBUSY);
1023 	}
1024 
1025 	mip->mi_ref++;
1026 	rw_exit(&i_mac_impl_lock);
1027 
1028 	*pmip = mip;
1029 	return (0);
1030 }
1031 
1032 void
1033 mac_rele(mac_impl_t *mip)
1034 {
1035 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1036 	ASSERT(mip->mi_ref != 0);
1037 	if (--mip->mi_ref == 0) {
1038 		ASSERT(mip->mi_nactiveclients == 0 &&
1039 		    !(mip->mi_state_flags & MIS_EXCLUSIVE));
1040 	}
1041 	rw_exit(&i_mac_impl_lock);
1042 }
1043 
1044 /*
1045  * Private GLDv3 function to start a MAC instance.
1046  */
1047 int
1048 mac_start(mac_handle_t mh)
1049 {
1050 	mac_impl_t	*mip = (mac_impl_t *)mh;
1051 	int		err = 0;
1052 
1053 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1054 	ASSERT(mip->mi_start != NULL);
1055 
1056 	/*
1057 	 * Check whether the device is already started.
1058 	 */
1059 	if (mip->mi_active++ == 0) {
1060 		mac_ring_t *ring = NULL;
1061 
1062 		/*
1063 		 * Start the device.
1064 		 */
1065 		err = mip->mi_start(mip->mi_driver);
1066 		if (err != 0) {
1067 			mip->mi_active--;
1068 			return (err);
1069 		}
1070 
1071 		/*
1072 		 * Start the default tx ring.
1073 		 */
1074 		if (mip->mi_default_tx_ring != NULL) {
1075 
1076 			ring = (mac_ring_t *)mip->mi_default_tx_ring;
1077 			err = mac_start_ring(ring);
1078 			if (err != 0) {
1079 				mip->mi_active--;
1080 				return (err);
1081 			}
1082 			ring->mr_state = MR_INUSE;
1083 		}
1084 
1085 		if (mip->mi_rx_groups != NULL) {
1086 			/*
1087 			 * Start the default ring, since it will be needed
1088 			 * to receive broadcast and multicast traffic for
1089 			 * both primary and non-primary MAC clients.
1090 			 */
1091 			mac_group_t *grp = &mip->mi_rx_groups[0];
1092 
1093 			ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
1094 			err = mac_start_group_and_rings(grp);
1095 			if (err != 0) {
1096 				mip->mi_active--;
1097 				if (ring != NULL) {
1098 					mac_stop_ring(ring);
1099 					ring->mr_state = MR_FREE;
1100 				}
1101 				return (err);
1102 			}
1103 			mac_set_rx_group_state(grp, MAC_GROUP_STATE_SHARED);
1104 		}
1105 	}
1106 
1107 	return (err);
1108 }
1109 
1110 /*
1111  * Private GLDv3 function to stop a MAC instance.
1112  */
1113 void
1114 mac_stop(mac_handle_t mh)
1115 {
1116 	mac_impl_t	*mip = (mac_impl_t *)mh;
1117 
1118 	ASSERT(mip->mi_stop != NULL);
1119 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1120 
1121 	/*
1122 	 * Check whether the device is still needed.
1123 	 */
1124 	ASSERT(mip->mi_active != 0);
1125 	if (--mip->mi_active == 0) {
1126 		if (mip->mi_rx_groups != NULL) {
1127 			/*
1128 			 * There should be no more active clients since the
1129 			 * MAC is being stopped. Stop the default RX group
1130 			 * and transition it back to registered state.
1131 			 */
1132 			mac_group_t *grp = &mip->mi_rx_groups[0];
1133 
1134 			/*
1135 			 * When clients are torn down, the groups
1136 			 * are release via mac_release_rx_group which
1137 			 * knows the the default group is always in
1138 			 * started mode since broadcast uses it. So
1139 			 * we can assert that their are no clients
1140 			 * (since mac_bcast_add doesn't register itself
1141 			 * as a client) and group is in SHARED state.
1142 			 */
1143 			ASSERT(grp->mrg_state == MAC_GROUP_STATE_SHARED);
1144 			ASSERT(MAC_RX_GROUP_NO_CLIENT(grp) &&
1145 			    mip->mi_nactiveclients == 0);
1146 			mac_stop_group_and_rings(grp);
1147 			mac_set_rx_group_state(grp, MAC_GROUP_STATE_REGISTERED);
1148 		}
1149 
1150 		if (mip->mi_default_tx_ring != NULL) {
1151 			mac_ring_t *ring;
1152 
1153 			ring = (mac_ring_t *)mip->mi_default_tx_ring;
1154 			mac_stop_ring(ring);
1155 			ring->mr_state = MR_FREE;
1156 		}
1157 
1158 		/*
1159 		 * Stop the device.
1160 		 */
1161 		mip->mi_stop(mip->mi_driver);
1162 	}
1163 }
1164 
1165 int
1166 i_mac_promisc_set(mac_impl_t *mip, boolean_t on)
1167 {
1168 	int		err = 0;
1169 
1170 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1171 	ASSERT(mip->mi_setpromisc != NULL);
1172 
1173 	if (on) {
1174 		/*
1175 		 * Enable promiscuous mode on the device if not yet enabled.
1176 		 */
1177 		if (mip->mi_devpromisc++ == 0) {
1178 			err = mip->mi_setpromisc(mip->mi_driver, B_TRUE);
1179 			if (err != 0) {
1180 				mip->mi_devpromisc--;
1181 				return (err);
1182 			}
1183 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
1184 		}
1185 	} else {
1186 		if (mip->mi_devpromisc == 0)
1187 			return (EPROTO);
1188 
1189 		/*
1190 		 * Disable promiscuous mode on the device if this is the last
1191 		 * enabling.
1192 		 */
1193 		if (--mip->mi_devpromisc == 0) {
1194 			err = mip->mi_setpromisc(mip->mi_driver, B_FALSE);
1195 			if (err != 0) {
1196 				mip->mi_devpromisc++;
1197 				return (err);
1198 			}
1199 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
1200 		}
1201 	}
1202 
1203 	return (0);
1204 }
1205 
1206 /*
1207  * The promiscuity state can change any time. If the caller needs to take
1208  * actions that are atomic with the promiscuity state, then the caller needs
1209  * to bracket the entire sequence with mac_perim_enter/exit
1210  */
1211 boolean_t
1212 mac_promisc_get(mac_handle_t mh)
1213 {
1214 	mac_impl_t		*mip = (mac_impl_t *)mh;
1215 
1216 	/*
1217 	 * Return the current promiscuity.
1218 	 */
1219 	return (mip->mi_devpromisc != 0);
1220 }
1221 
1222 /*
1223  * Invoked at MAC instance attach time to initialize the list
1224  * of factory MAC addresses supported by a MAC instance. This function
1225  * builds a local cache in the mac_impl_t for the MAC addresses
1226  * supported by the underlying hardware. The MAC clients themselves
1227  * use the mac_addr_factory*() functions to query and reserve
1228  * factory MAC addresses.
1229  */
1230 void
1231 mac_addr_factory_init(mac_impl_t *mip)
1232 {
1233 	mac_capab_multifactaddr_t capab;
1234 	uint8_t *addr;
1235 	int i;
1236 
1237 	/*
1238 	 * First round to see how many factory MAC addresses are available.
1239 	 */
1240 	bzero(&capab, sizeof (capab));
1241 	if (!i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_MULTIFACTADDR,
1242 	    &capab) || (capab.mcm_naddr == 0)) {
1243 		/*
1244 		 * The MAC instance doesn't support multiple factory
1245 		 * MAC addresses, we're done here.
1246 		 */
1247 		return;
1248 	}
1249 
1250 	/*
1251 	 * Allocate the space and get all the factory addresses.
1252 	 */
1253 	addr = kmem_alloc(capab.mcm_naddr * MAXMACADDRLEN, KM_SLEEP);
1254 	capab.mcm_getaddr(mip->mi_driver, capab.mcm_naddr, addr);
1255 
1256 	mip->mi_factory_addr_num = capab.mcm_naddr;
1257 	mip->mi_factory_addr = kmem_zalloc(mip->mi_factory_addr_num *
1258 	    sizeof (mac_factory_addr_t), KM_SLEEP);
1259 
1260 	for (i = 0; i < capab.mcm_naddr; i++) {
1261 		bcopy(addr + i * MAXMACADDRLEN,
1262 		    mip->mi_factory_addr[i].mfa_addr,
1263 		    mip->mi_type->mt_addr_length);
1264 		mip->mi_factory_addr[i].mfa_in_use = B_FALSE;
1265 	}
1266 
1267 	kmem_free(addr, capab.mcm_naddr * MAXMACADDRLEN);
1268 }
1269 
1270 void
1271 mac_addr_factory_fini(mac_impl_t *mip)
1272 {
1273 	if (mip->mi_factory_addr == NULL) {
1274 		ASSERT(mip->mi_factory_addr_num == 0);
1275 		return;
1276 	}
1277 
1278 	kmem_free(mip->mi_factory_addr, mip->mi_factory_addr_num *
1279 	    sizeof (mac_factory_addr_t));
1280 
1281 	mip->mi_factory_addr = NULL;
1282 	mip->mi_factory_addr_num = 0;
1283 }
1284 
1285 /*
1286  * Reserve a factory MAC address. If *slot is set to -1, the function
1287  * attempts to reserve any of the available factory MAC addresses and
1288  * returns the reserved slot id. If no slots are available, the function
1289  * returns ENOSPC. If *slot is not set to -1, the function reserves
1290  * the specified slot if it is available, or returns EBUSY is the slot
1291  * is already used. Returns ENOTSUP if the underlying MAC does not
1292  * support multiple factory addresses. If the slot number is not -1 but
1293  * is invalid, returns EINVAL.
1294  */
1295 int
1296 mac_addr_factory_reserve(mac_client_handle_t mch, int *slot)
1297 {
1298 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1299 	mac_impl_t *mip = mcip->mci_mip;
1300 	int i, ret = 0;
1301 
1302 	i_mac_perim_enter(mip);
1303 	/*
1304 	 * Protect against concurrent readers that may need a self-consistent
1305 	 * view of the factory addresses
1306 	 */
1307 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
1308 
1309 	if (mip->mi_factory_addr_num == 0) {
1310 		ret = ENOTSUP;
1311 		goto bail;
1312 	}
1313 
1314 	if (*slot != -1) {
1315 		/* check the specified slot */
1316 		if (*slot < 1 || *slot > mip->mi_factory_addr_num) {
1317 			ret = EINVAL;
1318 			goto bail;
1319 		}
1320 		if (mip->mi_factory_addr[*slot-1].mfa_in_use) {
1321 			ret = EBUSY;
1322 			goto bail;
1323 		}
1324 	} else {
1325 		/* pick the next available slot */
1326 		for (i = 0; i < mip->mi_factory_addr_num; i++) {
1327 			if (!mip->mi_factory_addr[i].mfa_in_use)
1328 				break;
1329 		}
1330 
1331 		if (i == mip->mi_factory_addr_num) {
1332 			ret = ENOSPC;
1333 			goto bail;
1334 		}
1335 		*slot = i+1;
1336 	}
1337 
1338 	mip->mi_factory_addr[*slot-1].mfa_in_use = B_TRUE;
1339 	mip->mi_factory_addr[*slot-1].mfa_client = mcip;
1340 
1341 bail:
1342 	rw_exit(&mip->mi_rw_lock);
1343 	i_mac_perim_exit(mip);
1344 	return (ret);
1345 }
1346 
1347 /*
1348  * Release the specified factory MAC address slot.
1349  */
1350 void
1351 mac_addr_factory_release(mac_client_handle_t mch, uint_t slot)
1352 {
1353 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1354 	mac_impl_t *mip = mcip->mci_mip;
1355 
1356 	i_mac_perim_enter(mip);
1357 	/*
1358 	 * Protect against concurrent readers that may need a self-consistent
1359 	 * view of the factory addresses
1360 	 */
1361 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
1362 
1363 	ASSERT(slot > 0 && slot <= mip->mi_factory_addr_num);
1364 	ASSERT(mip->mi_factory_addr[slot-1].mfa_in_use);
1365 
1366 	mip->mi_factory_addr[slot-1].mfa_in_use = B_FALSE;
1367 
1368 	rw_exit(&mip->mi_rw_lock);
1369 	i_mac_perim_exit(mip);
1370 }
1371 
1372 /*
1373  * Stores in mac_addr the value of the specified MAC address. Returns
1374  * 0 on success, or EINVAL if the slot number is not valid for the MAC.
1375  * The caller must provide a string of at least MAXNAMELEN bytes.
1376  */
1377 void
1378 mac_addr_factory_value(mac_handle_t mh, int slot, uchar_t *mac_addr,
1379     uint_t *addr_len, char *client_name, boolean_t *in_use_arg)
1380 {
1381 	mac_impl_t *mip = (mac_impl_t *)mh;
1382 	boolean_t in_use;
1383 
1384 	ASSERT(slot > 0 && slot <= mip->mi_factory_addr_num);
1385 
1386 	/*
1387 	 * Readers need to hold mi_rw_lock. Writers need to hold mac perimeter
1388 	 * and mi_rw_lock
1389 	 */
1390 	rw_enter(&mip->mi_rw_lock, RW_READER);
1391 	bcopy(mip->mi_factory_addr[slot-1].mfa_addr, mac_addr, MAXMACADDRLEN);
1392 	*addr_len = mip->mi_type->mt_addr_length;
1393 	in_use = mip->mi_factory_addr[slot-1].mfa_in_use;
1394 	if (in_use && client_name != NULL) {
1395 		bcopy(mip->mi_factory_addr[slot-1].mfa_client->mci_name,
1396 		    client_name, MAXNAMELEN);
1397 	}
1398 	if (in_use_arg != NULL)
1399 		*in_use_arg = in_use;
1400 	rw_exit(&mip->mi_rw_lock);
1401 }
1402 
1403 /*
1404  * Returns the number of factory MAC addresses (in addition to the
1405  * primary MAC address), 0 if the underlying MAC doesn't support
1406  * that feature.
1407  */
1408 uint_t
1409 mac_addr_factory_num(mac_handle_t mh)
1410 {
1411 	mac_impl_t *mip = (mac_impl_t *)mh;
1412 
1413 	return (mip->mi_factory_addr_num);
1414 }
1415 
1416 
1417 void
1418 mac_rx_group_unmark(mac_group_t *grp, uint_t flag)
1419 {
1420 	mac_ring_t	*ring;
1421 
1422 	for (ring = grp->mrg_rings; ring != NULL; ring = ring->mr_next)
1423 		ring->mr_flag &= ~flag;
1424 }
1425 
1426 /*
1427  * The following mac_hwrings_xxx() functions are private mac client functions
1428  * used by the aggr driver to access and control the underlying HW Rx group
1429  * and rings. In this case, the aggr driver has exclusive control of the
1430  * underlying HW Rx group/rings, it calls the following functions to
1431  * start/stop the HW Rx rings, disable/enable polling, add/remove mac'
1432  * addresses, or set up the Rx callback.
1433  */
1434 /* ARGSUSED */
1435 static void
1436 mac_hwrings_rx_process(void *arg, mac_resource_handle_t srs,
1437     mblk_t *mp_chain, boolean_t loopback)
1438 {
1439 	mac_soft_ring_set_t	*mac_srs = (mac_soft_ring_set_t *)srs;
1440 	mac_srs_rx_t		*srs_rx = &mac_srs->srs_rx;
1441 	mac_direct_rx_t		proc;
1442 	void			*arg1;
1443 	mac_resource_handle_t	arg2;
1444 
1445 	proc = srs_rx->sr_func;
1446 	arg1 = srs_rx->sr_arg1;
1447 	arg2 = mac_srs->srs_mrh;
1448 
1449 	proc(arg1, arg2, mp_chain, NULL);
1450 }
1451 
1452 /*
1453  * This function is called to get the list of HW rings that are reserved by
1454  * an exclusive mac client.
1455  *
1456  * Return value: the number of HW rings.
1457  */
1458 int
1459 mac_hwrings_get(mac_client_handle_t mch, mac_group_handle_t *hwgh,
1460     mac_ring_handle_t *hwrh, mac_ring_type_t rtype)
1461 {
1462 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
1463 	int			cnt = 0;
1464 
1465 	switch (rtype) {
1466 	case MAC_RING_TYPE_RX: {
1467 		flow_entry_t	*flent = mcip->mci_flent;
1468 		mac_group_t	*grp;
1469 		mac_ring_t	*ring;
1470 
1471 		grp = flent->fe_rx_ring_group;
1472 		/*
1473 		 * The mac client did not reserve any RX group, return directly.
1474 		 * This is probably because the underlying MAC does not support
1475 		 * any groups.
1476 		 */
1477 		*hwgh = NULL;
1478 		if (grp == NULL)
1479 			return (0);
1480 		/*
1481 		 * This group must be reserved by this mac client.
1482 		 */
1483 		ASSERT((grp->mrg_state == MAC_GROUP_STATE_RESERVED) &&
1484 		    (mch == (mac_client_handle_t)
1485 		    (MAC_RX_GROUP_ONLY_CLIENT(grp))));
1486 		for (ring = grp->mrg_rings;
1487 		    ring != NULL; ring = ring->mr_next, cnt++) {
1488 			ASSERT(cnt < MAX_RINGS_PER_GROUP);
1489 			hwrh[cnt] = (mac_ring_handle_t)ring;
1490 		}
1491 		*hwgh = (mac_group_handle_t)grp;
1492 		return (cnt);
1493 	}
1494 	case MAC_RING_TYPE_TX: {
1495 		mac_soft_ring_set_t	*tx_srs;
1496 		mac_srs_tx_t		*tx;
1497 
1498 		tx_srs = MCIP_TX_SRS(mcip);
1499 		tx = &tx_srs->srs_tx;
1500 		for (; cnt < tx->st_ring_count; cnt++)
1501 			hwrh[cnt] = tx->st_rings[cnt];
1502 		return (cnt);
1503 	}
1504 	default:
1505 		ASSERT(B_FALSE);
1506 		return (-1);
1507 	}
1508 }
1509 
1510 /*
1511  * Setup the RX callback of the mac client which exclusively controls HW ring.
1512  */
1513 void
1514 mac_hwring_setup(mac_ring_handle_t hwrh, mac_resource_handle_t prh)
1515 {
1516 	mac_ring_t		*hw_ring = (mac_ring_t *)hwrh;
1517 	mac_soft_ring_set_t	*mac_srs = hw_ring->mr_srs;
1518 
1519 	mac_srs->srs_mrh = prh;
1520 	mac_srs->srs_rx.sr_lower_proc = mac_hwrings_rx_process;
1521 }
1522 
1523 void
1524 mac_hwring_teardown(mac_ring_handle_t hwrh)
1525 {
1526 	mac_ring_t		*hw_ring = (mac_ring_t *)hwrh;
1527 	mac_soft_ring_set_t	*mac_srs = hw_ring->mr_srs;
1528 
1529 	mac_srs->srs_rx.sr_lower_proc = mac_rx_srs_process;
1530 	mac_srs->srs_mrh = NULL;
1531 }
1532 
1533 int
1534 mac_hwring_disable_intr(mac_ring_handle_t rh)
1535 {
1536 	mac_ring_t *rr_ring = (mac_ring_t *)rh;
1537 	mac_intr_t *intr = &rr_ring->mr_info.mri_intr;
1538 
1539 	return (intr->mi_disable(intr->mi_handle));
1540 }
1541 
1542 int
1543 mac_hwring_enable_intr(mac_ring_handle_t rh)
1544 {
1545 	mac_ring_t *rr_ring = (mac_ring_t *)rh;
1546 	mac_intr_t *intr = &rr_ring->mr_info.mri_intr;
1547 
1548 	return (intr->mi_enable(intr->mi_handle));
1549 }
1550 
1551 int
1552 mac_hwring_start(mac_ring_handle_t rh)
1553 {
1554 	mac_ring_t *rr_ring = (mac_ring_t *)rh;
1555 
1556 	MAC_RING_UNMARK(rr_ring, MR_QUIESCE);
1557 	return (0);
1558 }
1559 
1560 void
1561 mac_hwring_stop(mac_ring_handle_t rh)
1562 {
1563 	mac_ring_t *rr_ring = (mac_ring_t *)rh;
1564 
1565 	mac_rx_ring_quiesce(rr_ring, MR_QUIESCE);
1566 }
1567 
1568 mblk_t *
1569 mac_hwring_poll(mac_ring_handle_t rh, int bytes_to_pickup)
1570 {
1571 	mac_ring_t *rr_ring = (mac_ring_t *)rh;
1572 	mac_ring_info_t *info = &rr_ring->mr_info;
1573 
1574 	return (info->mri_poll(info->mri_driver, bytes_to_pickup));
1575 }
1576 
1577 /*
1578  * Send packets through the selected tx ring.
1579  */
1580 mblk_t *
1581 mac_hwring_tx(mac_ring_handle_t rh, mblk_t *mp)
1582 {
1583 	mac_ring_t *ring = (mac_ring_t *)rh;
1584 	mac_ring_info_t *info = &ring->mr_info;
1585 
1586 	ASSERT(ring->mr_type == MAC_RING_TYPE_TX &&
1587 	    ring->mr_state >= MR_INUSE);
1588 	return (info->mri_tx(info->mri_driver, mp));
1589 }
1590 
1591 int
1592 mac_hwgroup_addmac(mac_group_handle_t gh, const uint8_t *addr)
1593 {
1594 	mac_group_t *group = (mac_group_t *)gh;
1595 
1596 	return (mac_group_addmac(group, addr));
1597 }
1598 
1599 int
1600 mac_hwgroup_remmac(mac_group_handle_t gh, const uint8_t *addr)
1601 {
1602 	mac_group_t *group = (mac_group_t *)gh;
1603 
1604 	return (mac_group_remmac(group, addr));
1605 }
1606 
1607 /*
1608  * Set the RX group to be shared/reserved. Note that the group must be
1609  * started/stopped outside of this function.
1610  */
1611 void
1612 mac_set_rx_group_state(mac_group_t *grp, mac_group_state_t state)
1613 {
1614 	/*
1615 	 * If there is no change in the group state, just return.
1616 	 */
1617 	if (grp->mrg_state == state)
1618 		return;
1619 
1620 	switch (state) {
1621 	case MAC_GROUP_STATE_RESERVED:
1622 		/*
1623 		 * Successfully reserved the group.
1624 		 *
1625 		 * Given that there is an exclusive client controlling this
1626 		 * group, we enable the group level polling when available,
1627 		 * so that SRSs get to turn on/off individual rings they's
1628 		 * assigned to.
1629 		 */
1630 		ASSERT(MAC_PERIM_HELD(grp->mrg_mh));
1631 
1632 		if (GROUP_INTR_DISABLE_FUNC(grp) != NULL)
1633 			GROUP_INTR_DISABLE_FUNC(grp)(GROUP_INTR_HANDLE(grp));
1634 
1635 		break;
1636 
1637 	case MAC_GROUP_STATE_SHARED:
1638 		/*
1639 		 * Set all rings of this group to software classified.
1640 		 * If the group has an overriding interrupt, then re-enable it.
1641 		 */
1642 		ASSERT(MAC_PERIM_HELD(grp->mrg_mh));
1643 
1644 		if (GROUP_INTR_ENABLE_FUNC(grp) != NULL)
1645 			GROUP_INTR_ENABLE_FUNC(grp)(GROUP_INTR_HANDLE(grp));
1646 
1647 		/* The ring is not available for reservations any more */
1648 		break;
1649 
1650 	case MAC_GROUP_STATE_REGISTERED:
1651 		/* Also callable from mac_register, perim is not held */
1652 		break;
1653 
1654 	default:
1655 		ASSERT(B_FALSE);
1656 		break;
1657 	}
1658 
1659 	grp->mrg_state = state;
1660 }
1661 
1662 /*
1663  * Quiesce future hardware classified packets for the specified Rx ring
1664  */
1665 static void
1666 mac_rx_ring_quiesce(mac_ring_t *rx_ring, uint_t ring_flag)
1667 {
1668 	ASSERT(rx_ring->mr_classify_type == MAC_HW_CLASSIFIER);
1669 	ASSERT(ring_flag == MR_CONDEMNED || ring_flag  == MR_QUIESCE);
1670 
1671 	mutex_enter(&rx_ring->mr_lock);
1672 	rx_ring->mr_flag |= ring_flag;
1673 	while (rx_ring->mr_refcnt != 0)
1674 		cv_wait(&rx_ring->mr_cv, &rx_ring->mr_lock);
1675 	mutex_exit(&rx_ring->mr_lock);
1676 }
1677 
1678 /*
1679  * Please see mac_tx for details about the per cpu locking scheme
1680  */
1681 static void
1682 mac_tx_lock_all(mac_client_impl_t *mcip)
1683 {
1684 	int	i;
1685 
1686 	for (i = 0; i <= mac_tx_percpu_cnt; i++)
1687 		mutex_enter(&mcip->mci_tx_pcpu[i].pcpu_tx_lock);
1688 }
1689 
1690 static void
1691 mac_tx_unlock_all(mac_client_impl_t *mcip)
1692 {
1693 	int	i;
1694 
1695 	for (i = mac_tx_percpu_cnt; i >= 0; i--)
1696 		mutex_exit(&mcip->mci_tx_pcpu[i].pcpu_tx_lock);
1697 }
1698 
1699 static void
1700 mac_tx_unlock_allbutzero(mac_client_impl_t *mcip)
1701 {
1702 	int	i;
1703 
1704 	for (i = mac_tx_percpu_cnt; i > 0; i--)
1705 		mutex_exit(&mcip->mci_tx_pcpu[i].pcpu_tx_lock);
1706 }
1707 
1708 static int
1709 mac_tx_sum_refcnt(mac_client_impl_t *mcip)
1710 {
1711 	int	i;
1712 	int	refcnt = 0;
1713 
1714 	for (i = 0; i <= mac_tx_percpu_cnt; i++)
1715 		refcnt += mcip->mci_tx_pcpu[i].pcpu_tx_refcnt;
1716 
1717 	return (refcnt);
1718 }
1719 
1720 /*
1721  * Stop future Tx packets coming down from the client in preparation for
1722  * quiescing the Tx side. This is needed for dynamic reclaim and reassignment
1723  * of rings between clients
1724  */
1725 void
1726 mac_tx_client_block(mac_client_impl_t *mcip)
1727 {
1728 	mac_tx_lock_all(mcip);
1729 	mcip->mci_tx_flag |= MCI_TX_QUIESCE;
1730 	while (mac_tx_sum_refcnt(mcip) != 0) {
1731 		mac_tx_unlock_allbutzero(mcip);
1732 		cv_wait(&mcip->mci_tx_cv, &mcip->mci_tx_pcpu[0].pcpu_tx_lock);
1733 		mutex_exit(&mcip->mci_tx_pcpu[0].pcpu_tx_lock);
1734 		mac_tx_lock_all(mcip);
1735 	}
1736 	mac_tx_unlock_all(mcip);
1737 }
1738 
1739 void
1740 mac_tx_client_unblock(mac_client_impl_t *mcip)
1741 {
1742 	mac_tx_lock_all(mcip);
1743 	mcip->mci_tx_flag &= ~MCI_TX_QUIESCE;
1744 	mac_tx_unlock_all(mcip);
1745 	/*
1746 	 * We may fail to disable flow control for the last MAC_NOTE_TX
1747 	 * notification because the MAC client is quiesced. Send the
1748 	 * notification again.
1749 	 */
1750 	i_mac_notify(mcip->mci_mip, MAC_NOTE_TX);
1751 }
1752 
1753 /*
1754  * Wait for an SRS to quiesce. The SRS worker will signal us when the
1755  * quiesce is done.
1756  */
1757 static void
1758 mac_srs_quiesce_wait(mac_soft_ring_set_t *srs, uint_t srs_flag)
1759 {
1760 	mutex_enter(&srs->srs_lock);
1761 	while (!(srs->srs_state & srs_flag))
1762 		cv_wait(&srs->srs_quiesce_done_cv, &srs->srs_lock);
1763 	mutex_exit(&srs->srs_lock);
1764 }
1765 
1766 /*
1767  * Quiescing an Rx SRS is achieved by the following sequence. The protocol
1768  * works bottom up by cutting off packet flow from the bottommost point in the
1769  * mac, then the SRS, and then the soft rings. There are 2 use cases of this
1770  * mechanism. One is a temporary quiesce of the SRS, such as say while changing
1771  * the Rx callbacks. Another use case is Rx SRS teardown. In the former case
1772  * the QUIESCE prefix/suffix is used and in the latter the CONDEMNED is used
1773  * for the SRS and MR flags. In the former case the threads pause waiting for
1774  * a restart, while in the latter case the threads exit. The Tx SRS teardown
1775  * is also mostly similar to the above.
1776  *
1777  * 1. Stop future hardware classified packets at the lowest level in the mac.
1778  *    Remove any hardware classification rule (CONDEMNED case) and mark the
1779  *    rings as CONDEMNED or QUIESCE as appropriate. This prevents the mr_refcnt
1780  *    from increasing. Upcalls from the driver that come through hardware
1781  *    classification will be dropped in mac_rx from now on. Then we wait for
1782  *    the mr_refcnt to drop to zero. When the mr_refcnt reaches zero we are
1783  *    sure there aren't any upcall threads from the driver through hardware
1784  *    classification. In the case of SRS teardown we also remove the
1785  *    classification rule in the driver.
1786  *
1787  * 2. Stop future software classified packets by marking the flow entry with
1788  *    FE_QUIESCE or FE_CONDEMNED as appropriate which prevents the refcnt from
1789  *    increasing. We also remove the flow entry from the table in the latter
1790  *    case. Then wait for the fe_refcnt to reach an appropriate quiescent value
1791  *    that indicates there aren't any active threads using that flow entry.
1792  *
1793  * 3. Quiesce the SRS and softrings by signaling the SRS. The SRS poll thread,
1794  *    SRS worker thread, and the soft ring threads are quiesced in sequence
1795  *    with the SRS worker thread serving as a master controller. This
1796  *    mechansim is explained in mac_srs_worker_quiesce().
1797  *
1798  * The restart mechanism to reactivate the SRS and softrings is explained
1799  * in mac_srs_worker_restart(). Here we just signal the SRS worker to start the
1800  * restart sequence.
1801  */
1802 void
1803 mac_rx_srs_quiesce(mac_soft_ring_set_t *srs, uint_t srs_quiesce_flag)
1804 {
1805 	flow_entry_t	*flent = srs->srs_flent;
1806 	uint_t	mr_flag, srs_done_flag;
1807 
1808 	ASSERT(MAC_PERIM_HELD((mac_handle_t)FLENT_TO_MIP(flent)));
1809 	ASSERT(!(srs->srs_type & SRST_TX));
1810 
1811 	if (srs_quiesce_flag == SRS_CONDEMNED) {
1812 		mr_flag = MR_CONDEMNED;
1813 		srs_done_flag = SRS_CONDEMNED_DONE;
1814 		if (srs->srs_type & SRST_CLIENT_POLL_ENABLED)
1815 			mac_srs_client_poll_disable(srs->srs_mcip, srs);
1816 	} else {
1817 		ASSERT(srs_quiesce_flag == SRS_QUIESCE);
1818 		mr_flag = MR_QUIESCE;
1819 		srs_done_flag = SRS_QUIESCE_DONE;
1820 		if (srs->srs_type & SRST_CLIENT_POLL_ENABLED)
1821 			mac_srs_client_poll_quiesce(srs->srs_mcip, srs);
1822 	}
1823 
1824 	if (srs->srs_ring != NULL) {
1825 		mac_rx_ring_quiesce(srs->srs_ring, mr_flag);
1826 	} else {
1827 		/*
1828 		 * SRS is driven by software classification. In case
1829 		 * of CONDEMNED, the top level teardown functions will
1830 		 * deal with flow removal.
1831 		 */
1832 		if (srs_quiesce_flag != SRS_CONDEMNED) {
1833 			FLOW_MARK(flent, FE_QUIESCE);
1834 			mac_flow_wait(flent, FLOW_DRIVER_UPCALL);
1835 		}
1836 	}
1837 
1838 	/*
1839 	 * Signal the SRS to quiesce itself, and then cv_wait for the
1840 	 * SRS quiesce to complete. The SRS worker thread will wake us
1841 	 * up when the quiesce is complete
1842 	 */
1843 	mac_srs_signal(srs, srs_quiesce_flag);
1844 	mac_srs_quiesce_wait(srs, srs_done_flag);
1845 }
1846 
1847 /*
1848  * Remove an SRS.
1849  */
1850 void
1851 mac_rx_srs_remove(mac_soft_ring_set_t *srs)
1852 {
1853 	flow_entry_t *flent = srs->srs_flent;
1854 	int i;
1855 
1856 	mac_rx_srs_quiesce(srs, SRS_CONDEMNED);
1857 	/*
1858 	 * Locate and remove our entry in the fe_rx_srs[] array, and
1859 	 * adjust the fe_rx_srs array entries and array count by
1860 	 * moving the last entry into the vacated spot.
1861 	 */
1862 	mutex_enter(&flent->fe_lock);
1863 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
1864 		if (flent->fe_rx_srs[i] == srs)
1865 			break;
1866 	}
1867 
1868 	ASSERT(i != 0 && i < flent->fe_rx_srs_cnt);
1869 	if (i != flent->fe_rx_srs_cnt - 1) {
1870 		flent->fe_rx_srs[i] =
1871 		    flent->fe_rx_srs[flent->fe_rx_srs_cnt - 1];
1872 		i = flent->fe_rx_srs_cnt - 1;
1873 	}
1874 
1875 	flent->fe_rx_srs[i] = NULL;
1876 	flent->fe_rx_srs_cnt--;
1877 	mutex_exit(&flent->fe_lock);
1878 
1879 	mac_srs_free(srs);
1880 }
1881 
1882 static void
1883 mac_srs_clear_flag(mac_soft_ring_set_t *srs, uint_t flag)
1884 {
1885 	mutex_enter(&srs->srs_lock);
1886 	srs->srs_state &= ~flag;
1887 	mutex_exit(&srs->srs_lock);
1888 }
1889 
1890 void
1891 mac_rx_srs_restart(mac_soft_ring_set_t *srs)
1892 {
1893 	flow_entry_t	*flent = srs->srs_flent;
1894 	mac_ring_t	*mr;
1895 
1896 	ASSERT(MAC_PERIM_HELD((mac_handle_t)FLENT_TO_MIP(flent)));
1897 	ASSERT((srs->srs_type & SRST_TX) == 0);
1898 
1899 	/*
1900 	 * This handles a change in the number of SRSs between the quiesce and
1901 	 * and restart operation of a flow.
1902 	 */
1903 	if (!SRS_QUIESCED(srs))
1904 		return;
1905 
1906 	/*
1907 	 * Signal the SRS to restart itself. Wait for the restart to complete
1908 	 * Note that we only restart the SRS if it is not marked as
1909 	 * permanently quiesced.
1910 	 */
1911 	if (!SRS_QUIESCED_PERMANENT(srs)) {
1912 		mac_srs_signal(srs, SRS_RESTART);
1913 		mac_srs_quiesce_wait(srs, SRS_RESTART_DONE);
1914 		mac_srs_clear_flag(srs, SRS_RESTART_DONE);
1915 
1916 		mac_srs_client_poll_restart(srs->srs_mcip, srs);
1917 	}
1918 
1919 	/* Finally clear the flags to let the packets in */
1920 	mr = srs->srs_ring;
1921 	if (mr != NULL) {
1922 		MAC_RING_UNMARK(mr, MR_QUIESCE);
1923 		/* In case the ring was stopped, safely restart it */
1924 		(void) mac_start_ring(mr);
1925 	} else {
1926 		FLOW_UNMARK(flent, FE_QUIESCE);
1927 	}
1928 }
1929 
1930 /*
1931  * Temporary quiesce of a flow and associated Rx SRS.
1932  * Please see block comment above mac_rx_classify_flow_rem.
1933  */
1934 /* ARGSUSED */
1935 int
1936 mac_rx_classify_flow_quiesce(flow_entry_t *flent, void *arg)
1937 {
1938 	int		i;
1939 
1940 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
1941 		mac_rx_srs_quiesce((mac_soft_ring_set_t *)flent->fe_rx_srs[i],
1942 		    SRS_QUIESCE);
1943 	}
1944 	return (0);
1945 }
1946 
1947 /*
1948  * Restart a flow and associated Rx SRS that has been quiesced temporarily
1949  * Please see block comment above mac_rx_classify_flow_rem
1950  */
1951 /* ARGSUSED */
1952 int
1953 mac_rx_classify_flow_restart(flow_entry_t *flent, void *arg)
1954 {
1955 	int		i;
1956 
1957 	for (i = 0; i < flent->fe_rx_srs_cnt; i++)
1958 		mac_rx_srs_restart((mac_soft_ring_set_t *)flent->fe_rx_srs[i]);
1959 
1960 	return (0);
1961 }
1962 
1963 void
1964 mac_srs_perm_quiesce(mac_client_handle_t mch, boolean_t on)
1965 {
1966 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
1967 	flow_entry_t		*flent = mcip->mci_flent;
1968 	mac_impl_t		*mip = mcip->mci_mip;
1969 	mac_soft_ring_set_t	*mac_srs;
1970 	int			i;
1971 
1972 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1973 
1974 	if (flent == NULL)
1975 		return;
1976 
1977 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
1978 		mac_srs = flent->fe_rx_srs[i];
1979 		mutex_enter(&mac_srs->srs_lock);
1980 		if (on)
1981 			mac_srs->srs_state |= SRS_QUIESCE_PERM;
1982 		else
1983 			mac_srs->srs_state &= ~SRS_QUIESCE_PERM;
1984 		mutex_exit(&mac_srs->srs_lock);
1985 	}
1986 }
1987 
1988 void
1989 mac_rx_client_quiesce(mac_client_handle_t mch)
1990 {
1991 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
1992 	mac_impl_t		*mip = mcip->mci_mip;
1993 
1994 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1995 
1996 	if (MCIP_DATAPATH_SETUP(mcip)) {
1997 		(void) mac_rx_classify_flow_quiesce(mcip->mci_flent,
1998 		    NULL);
1999 		(void) mac_flow_walk_nolock(mcip->mci_subflow_tab,
2000 		    mac_rx_classify_flow_quiesce, NULL);
2001 	}
2002 }
2003 
2004 void
2005 mac_rx_client_restart(mac_client_handle_t mch)
2006 {
2007 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
2008 	mac_impl_t		*mip = mcip->mci_mip;
2009 
2010 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
2011 
2012 	if (MCIP_DATAPATH_SETUP(mcip)) {
2013 		(void) mac_rx_classify_flow_restart(mcip->mci_flent, NULL);
2014 		(void) mac_flow_walk_nolock(mcip->mci_subflow_tab,
2015 		    mac_rx_classify_flow_restart, NULL);
2016 	}
2017 }
2018 
2019 /*
2020  * This function only quiesces the Tx SRS and softring worker threads. Callers
2021  * need to make sure that there aren't any mac client threads doing current or
2022  * future transmits in the mac before calling this function.
2023  */
2024 void
2025 mac_tx_srs_quiesce(mac_soft_ring_set_t *srs, uint_t srs_quiesce_flag)
2026 {
2027 	mac_client_impl_t	*mcip = srs->srs_mcip;
2028 
2029 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
2030 
2031 	ASSERT(srs->srs_type & SRST_TX);
2032 	ASSERT(srs_quiesce_flag == SRS_CONDEMNED ||
2033 	    srs_quiesce_flag == SRS_QUIESCE);
2034 
2035 	/*
2036 	 * Signal the SRS to quiesce itself, and then cv_wait for the
2037 	 * SRS quiesce to complete. The SRS worker thread will wake us
2038 	 * up when the quiesce is complete
2039 	 */
2040 	mac_srs_signal(srs, srs_quiesce_flag);
2041 	mac_srs_quiesce_wait(srs, srs_quiesce_flag == SRS_QUIESCE ?
2042 	    SRS_QUIESCE_DONE : SRS_CONDEMNED_DONE);
2043 }
2044 
2045 void
2046 mac_tx_srs_restart(mac_soft_ring_set_t *srs)
2047 {
2048 	/*
2049 	 * Resizing the fanout could result in creation of new SRSs.
2050 	 * They may not necessarily be in the quiesced state in which
2051 	 * case it need be restarted
2052 	 */
2053 	if (!SRS_QUIESCED(srs))
2054 		return;
2055 
2056 	mac_srs_signal(srs, SRS_RESTART);
2057 	mac_srs_quiesce_wait(srs, SRS_RESTART_DONE);
2058 	mac_srs_clear_flag(srs, SRS_RESTART_DONE);
2059 }
2060 
2061 /*
2062  * Temporary quiesce of a flow and associated Rx SRS.
2063  * Please see block comment above mac_rx_srs_quiesce
2064  */
2065 /* ARGSUSED */
2066 int
2067 mac_tx_flow_quiesce(flow_entry_t *flent, void *arg)
2068 {
2069 	/*
2070 	 * The fe_tx_srs is null for a subflow on an interface that is
2071 	 * not plumbed
2072 	 */
2073 	if (flent->fe_tx_srs != NULL)
2074 		mac_tx_srs_quiesce(flent->fe_tx_srs, SRS_QUIESCE);
2075 	return (0);
2076 }
2077 
2078 /* ARGSUSED */
2079 int
2080 mac_tx_flow_restart(flow_entry_t *flent, void *arg)
2081 {
2082 	/*
2083 	 * The fe_tx_srs is null for a subflow on an interface that is
2084 	 * not plumbed
2085 	 */
2086 	if (flent->fe_tx_srs != NULL)
2087 		mac_tx_srs_restart(flent->fe_tx_srs);
2088 	return (0);
2089 }
2090 
2091 void
2092 mac_tx_client_quiesce(mac_client_impl_t *mcip, uint_t srs_quiesce_flag)
2093 {
2094 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
2095 
2096 	mac_tx_client_block(mcip);
2097 	if (MCIP_TX_SRS(mcip) != NULL) {
2098 		mac_tx_srs_quiesce(MCIP_TX_SRS(mcip), srs_quiesce_flag);
2099 		(void) mac_flow_walk_nolock(mcip->mci_subflow_tab,
2100 		    mac_tx_flow_quiesce, NULL);
2101 	}
2102 }
2103 
2104 void
2105 mac_tx_client_restart(mac_client_impl_t *mcip)
2106 {
2107 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
2108 
2109 	mac_tx_client_unblock(mcip);
2110 	if (MCIP_TX_SRS(mcip) != NULL) {
2111 		mac_tx_srs_restart(MCIP_TX_SRS(mcip));
2112 		(void) mac_flow_walk_nolock(mcip->mci_subflow_tab,
2113 		    mac_tx_flow_restart, NULL);
2114 	}
2115 }
2116 
2117 void
2118 mac_tx_client_flush(mac_client_impl_t *mcip)
2119 {
2120 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
2121 
2122 	mac_tx_client_quiesce(mcip, SRS_QUIESCE);
2123 	mac_tx_client_restart(mcip);
2124 }
2125 
2126 void
2127 mac_client_quiesce(mac_client_impl_t *mcip)
2128 {
2129 	mac_rx_client_quiesce((mac_client_handle_t)mcip);
2130 	mac_tx_client_quiesce(mcip, SRS_QUIESCE);
2131 }
2132 
2133 void
2134 mac_client_restart(mac_client_impl_t *mcip)
2135 {
2136 	mac_rx_client_restart((mac_client_handle_t)mcip);
2137 	mac_tx_client_restart(mcip);
2138 }
2139 
2140 /*
2141  * Allocate a minor number.
2142  */
2143 minor_t
2144 mac_minor_hold(boolean_t sleep)
2145 {
2146 	minor_t	minor;
2147 
2148 	/*
2149 	 * Grab a value from the arena.
2150 	 */
2151 	atomic_add_32(&minor_count, 1);
2152 
2153 	if (sleep)
2154 		minor = (uint_t)id_alloc(minor_ids);
2155 	else
2156 		minor = (uint_t)id_alloc_nosleep(minor_ids);
2157 
2158 	if (minor == 0) {
2159 		atomic_add_32(&minor_count, -1);
2160 		return (0);
2161 	}
2162 
2163 	return (minor);
2164 }
2165 
2166 /*
2167  * Release a previously allocated minor number.
2168  */
2169 void
2170 mac_minor_rele(minor_t minor)
2171 {
2172 	/*
2173 	 * Return the value to the arena.
2174 	 */
2175 	id_free(minor_ids, minor);
2176 	atomic_add_32(&minor_count, -1);
2177 }
2178 
2179 uint32_t
2180 mac_no_notification(mac_handle_t mh)
2181 {
2182 	mac_impl_t *mip = (mac_impl_t *)mh;
2183 
2184 	return (((mip->mi_state_flags & MIS_LEGACY) != 0) ?
2185 	    mip->mi_capab_legacy.ml_unsup_note : 0);
2186 }
2187 
2188 /*
2189  * Prevent any new opens of this mac in preparation for unregister
2190  */
2191 int
2192 i_mac_disable(mac_impl_t *mip)
2193 {
2194 	mac_client_impl_t	*mcip;
2195 
2196 	rw_enter(&i_mac_impl_lock, RW_WRITER);
2197 	if (mip->mi_state_flags & MIS_DISABLED) {
2198 		/* Already disabled, return success */
2199 		rw_exit(&i_mac_impl_lock);
2200 		return (0);
2201 	}
2202 	/*
2203 	 * See if there are any other references to this mac_t (e.g., VLAN's).
2204 	 * If so return failure. If all the other checks below pass, then
2205 	 * set mi_disabled atomically under the i_mac_impl_lock to prevent
2206 	 * any new VLAN's from being created or new mac client opens of this
2207 	 * mac end point.
2208 	 */
2209 	if (mip->mi_ref > 0) {
2210 		rw_exit(&i_mac_impl_lock);
2211 		return (EBUSY);
2212 	}
2213 
2214 	/*
2215 	 * mac clients must delete all multicast groups they join before
2216 	 * closing. bcast groups are reference counted, the last client
2217 	 * to delete the group will wait till the group is physically
2218 	 * deleted. Since all clients have closed this mac end point
2219 	 * mi_bcast_ngrps must be zero at this point
2220 	 */
2221 	ASSERT(mip->mi_bcast_ngrps == 0);
2222 
2223 	/*
2224 	 * Don't let go of this if it has some flows.
2225 	 * All other code guarantees no flows are added to a disabled
2226 	 * mac, therefore it is sufficient to check for the flow table
2227 	 * only here.
2228 	 */
2229 	mcip = mac_primary_client_handle(mip);
2230 	if ((mcip != NULL) && mac_link_has_flows((mac_client_handle_t)mcip)) {
2231 		rw_exit(&i_mac_impl_lock);
2232 		return (ENOTEMPTY);
2233 	}
2234 
2235 	mip->mi_state_flags |= MIS_DISABLED;
2236 	rw_exit(&i_mac_impl_lock);
2237 	return (0);
2238 }
2239 
2240 int
2241 mac_disable_nowait(mac_handle_t mh)
2242 {
2243 	mac_impl_t	*mip = (mac_impl_t *)mh;
2244 	int err;
2245 
2246 	if ((err = i_mac_perim_enter_nowait(mip)) != 0)
2247 		return (err);
2248 	err = i_mac_disable(mip);
2249 	i_mac_perim_exit(mip);
2250 	return (err);
2251 }
2252 
2253 int
2254 mac_disable(mac_handle_t mh)
2255 {
2256 	mac_impl_t	*mip = (mac_impl_t *)mh;
2257 	int err;
2258 
2259 	i_mac_perim_enter(mip);
2260 	err = i_mac_disable(mip);
2261 	i_mac_perim_exit(mip);
2262 
2263 	/*
2264 	 * Clean up notification thread and wait for it to exit.
2265 	 */
2266 	if (err == 0)
2267 		i_mac_notify_exit(mip);
2268 
2269 	return (err);
2270 }
2271 
2272 /*
2273  * Called when the MAC instance has a non empty flow table, to de-multiplex
2274  * incoming packets to the right flow.
2275  * The MAC's rw lock is assumed held as a READER.
2276  */
2277 /* ARGSUSED */
2278 static mblk_t *
2279 mac_rx_classify(mac_impl_t *mip, mac_resource_handle_t mrh, mblk_t *mp)
2280 {
2281 	flow_entry_t	*flent = NULL;
2282 	uint_t		flags = FLOW_INBOUND;
2283 	int		err;
2284 
2285 	/*
2286 	 * If the mac is a port of an aggregation, pass FLOW_IGNORE_VLAN
2287 	 * to mac_flow_lookup() so that the VLAN packets can be successfully
2288 	 * passed to the non-VLAN aggregation flows.
2289 	 *
2290 	 * Note that there is possibly a race between this and
2291 	 * mac_unicast_remove/add() and VLAN packets could be incorrectly
2292 	 * classified to non-VLAN flows of non-aggregation mac clients. These
2293 	 * VLAN packets will be then filtered out by the mac module.
2294 	 */
2295 	if ((mip->mi_state_flags & MIS_EXCLUSIVE) != 0)
2296 		flags |= FLOW_IGNORE_VLAN;
2297 
2298 	err = mac_flow_lookup(mip->mi_flow_tab, mp, flags, &flent);
2299 	if (err != 0) {
2300 		/* no registered receive function */
2301 		return (mp);
2302 	} else {
2303 		mac_client_impl_t	*mcip;
2304 
2305 		/*
2306 		 * This flent might just be an additional one on the MAC client,
2307 		 * i.e. for classification purposes (different fdesc), however
2308 		 * the resources, SRS et. al., are in the mci_flent, so if
2309 		 * this isn't the mci_flent, we need to get it.
2310 		 */
2311 		if ((mcip = flent->fe_mcip) != NULL &&
2312 		    mcip->mci_flent != flent) {
2313 			FLOW_REFRELE(flent);
2314 			flent = mcip->mci_flent;
2315 			FLOW_TRY_REFHOLD(flent, err);
2316 			if (err != 0)
2317 				return (mp);
2318 		}
2319 		(flent->fe_cb_fn)(flent->fe_cb_arg1, flent->fe_cb_arg2, mp,
2320 		    B_FALSE);
2321 		FLOW_REFRELE(flent);
2322 	}
2323 	return (NULL);
2324 }
2325 
2326 mblk_t *
2327 mac_rx_flow(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain)
2328 {
2329 	mac_impl_t	*mip = (mac_impl_t *)mh;
2330 	mblk_t		*bp, *bp1, **bpp, *list = NULL;
2331 
2332 	/*
2333 	 * We walk the chain and attempt to classify each packet.
2334 	 * The packets that couldn't be classified will be returned
2335 	 * back to the caller.
2336 	 */
2337 	bp = mp_chain;
2338 	bpp = &list;
2339 	while (bp != NULL) {
2340 		bp1 = bp;
2341 		bp = bp->b_next;
2342 		bp1->b_next = NULL;
2343 
2344 		if (mac_rx_classify(mip, mrh, bp1) != NULL) {
2345 			*bpp = bp1;
2346 			bpp = &bp1->b_next;
2347 		}
2348 	}
2349 	return (list);
2350 }
2351 
2352 static int
2353 mac_tx_flow_srs_wakeup(flow_entry_t *flent, void *arg)
2354 {
2355 	mac_ring_handle_t ring = arg;
2356 
2357 	if (flent->fe_tx_srs)
2358 		mac_tx_srs_wakeup(flent->fe_tx_srs, ring);
2359 	return (0);
2360 }
2361 
2362 void
2363 i_mac_tx_srs_notify(mac_impl_t *mip, mac_ring_handle_t ring)
2364 {
2365 	mac_client_impl_t	*cclient;
2366 	mac_soft_ring_set_t	*mac_srs;
2367 
2368 	/*
2369 	 * After grabbing the mi_rw_lock, the list of clients can't change.
2370 	 * If there are any clients mi_disabled must be B_FALSE and can't
2371 	 * get set since there are clients. If there aren't any clients we
2372 	 * don't do anything. In any case the mip has to be valid. The driver
2373 	 * must make sure that it goes single threaded (with respect to mac
2374 	 * calls) and wait for all pending mac calls to finish before calling
2375 	 * mac_unregister.
2376 	 */
2377 	rw_enter(&i_mac_impl_lock, RW_READER);
2378 	if (mip->mi_state_flags & MIS_DISABLED) {
2379 		rw_exit(&i_mac_impl_lock);
2380 		return;
2381 	}
2382 
2383 	/*
2384 	 * Get MAC tx srs from walking mac_client_handle list.
2385 	 */
2386 	rw_enter(&mip->mi_rw_lock, RW_READER);
2387 	for (cclient = mip->mi_clients_list; cclient != NULL;
2388 	    cclient = cclient->mci_client_next) {
2389 		if ((mac_srs = MCIP_TX_SRS(cclient)) != NULL)
2390 			mac_tx_srs_wakeup(mac_srs, ring);
2391 		(void) mac_flow_walk(cclient->mci_subflow_tab,
2392 		    mac_tx_flow_srs_wakeup, ring);
2393 	}
2394 	rw_exit(&mip->mi_rw_lock);
2395 	rw_exit(&i_mac_impl_lock);
2396 }
2397 
2398 /* ARGSUSED */
2399 void
2400 mac_multicast_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg,
2401     boolean_t add)
2402 {
2403 	mac_impl_t *mip = (mac_impl_t *)mh;
2404 
2405 	i_mac_perim_enter((mac_impl_t *)mh);
2406 	/*
2407 	 * If no specific refresh function was given then default to the
2408 	 * driver's m_multicst entry point.
2409 	 */
2410 	if (refresh == NULL) {
2411 		refresh = mip->mi_multicst;
2412 		arg = mip->mi_driver;
2413 	}
2414 
2415 	mac_bcast_refresh(mip, refresh, arg, add);
2416 	i_mac_perim_exit((mac_impl_t *)mh);
2417 }
2418 
2419 void
2420 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg)
2421 {
2422 	mac_impl_t	*mip = (mac_impl_t *)mh;
2423 
2424 	/*
2425 	 * If no specific refresh function was given then default to the
2426 	 * driver's m_promisc entry point.
2427 	 */
2428 	if (refresh == NULL) {
2429 		refresh = mip->mi_setpromisc;
2430 		arg = mip->mi_driver;
2431 	}
2432 	ASSERT(refresh != NULL);
2433 
2434 	/*
2435 	 * Call the refresh function with the current promiscuity.
2436 	 */
2437 	refresh(arg, (mip->mi_devpromisc != 0));
2438 }
2439 
2440 /*
2441  * The mac client requests that the mac not to change its margin size to
2442  * be less than the specified value.  If "current" is B_TRUE, then the client
2443  * requests the mac not to change its margin size to be smaller than the
2444  * current size. Further, return the current margin size value in this case.
2445  *
2446  * We keep every requested size in an ordered list from largest to smallest.
2447  */
2448 int
2449 mac_margin_add(mac_handle_t mh, uint32_t *marginp, boolean_t current)
2450 {
2451 	mac_impl_t		*mip = (mac_impl_t *)mh;
2452 	mac_margin_req_t	**pp, *p;
2453 	int			err = 0;
2454 
2455 	rw_enter(&(mip->mi_rw_lock), RW_WRITER);
2456 	if (current)
2457 		*marginp = mip->mi_margin;
2458 
2459 	/*
2460 	 * If the current margin value cannot satisfy the margin requested,
2461 	 * return ENOTSUP directly.
2462 	 */
2463 	if (*marginp > mip->mi_margin) {
2464 		err = ENOTSUP;
2465 		goto done;
2466 	}
2467 
2468 	/*
2469 	 * Check whether the given margin is already in the list. If so,
2470 	 * bump the reference count.
2471 	 */
2472 	for (pp = &mip->mi_mmrp; (p = *pp) != NULL; pp = &p->mmr_nextp) {
2473 		if (p->mmr_margin == *marginp) {
2474 			/*
2475 			 * The margin requested is already in the list,
2476 			 * so just bump the reference count.
2477 			 */
2478 			p->mmr_ref++;
2479 			goto done;
2480 		}
2481 		if (p->mmr_margin < *marginp)
2482 			break;
2483 	}
2484 
2485 
2486 	p = kmem_zalloc(sizeof (mac_margin_req_t), KM_SLEEP);
2487 	p->mmr_margin = *marginp;
2488 	p->mmr_ref++;
2489 	p->mmr_nextp = *pp;
2490 	*pp = p;
2491 
2492 done:
2493 	rw_exit(&(mip->mi_rw_lock));
2494 	return (err);
2495 }
2496 
2497 /*
2498  * The mac client requests to cancel its previous mac_margin_add() request.
2499  * We remove the requested margin size from the list.
2500  */
2501 int
2502 mac_margin_remove(mac_handle_t mh, uint32_t margin)
2503 {
2504 	mac_impl_t		*mip = (mac_impl_t *)mh;
2505 	mac_margin_req_t	**pp, *p;
2506 	int			err = 0;
2507 
2508 	rw_enter(&(mip->mi_rw_lock), RW_WRITER);
2509 	/*
2510 	 * Find the entry in the list for the given margin.
2511 	 */
2512 	for (pp = &(mip->mi_mmrp); (p = *pp) != NULL; pp = &(p->mmr_nextp)) {
2513 		if (p->mmr_margin == margin) {
2514 			if (--p->mmr_ref == 0)
2515 				break;
2516 
2517 			/*
2518 			 * There is still a reference to this address so
2519 			 * there's nothing more to do.
2520 			 */
2521 			goto done;
2522 		}
2523 	}
2524 
2525 	/*
2526 	 * We did not find an entry for the given margin.
2527 	 */
2528 	if (p == NULL) {
2529 		err = ENOENT;
2530 		goto done;
2531 	}
2532 
2533 	ASSERT(p->mmr_ref == 0);
2534 
2535 	/*
2536 	 * Remove it from the list.
2537 	 */
2538 	*pp = p->mmr_nextp;
2539 	kmem_free(p, sizeof (mac_margin_req_t));
2540 done:
2541 	rw_exit(&(mip->mi_rw_lock));
2542 	return (err);
2543 }
2544 
2545 boolean_t
2546 mac_margin_update(mac_handle_t mh, uint32_t margin)
2547 {
2548 	mac_impl_t	*mip = (mac_impl_t *)mh;
2549 	uint32_t	margin_needed = 0;
2550 
2551 	rw_enter(&(mip->mi_rw_lock), RW_WRITER);
2552 
2553 	if (mip->mi_mmrp != NULL)
2554 		margin_needed = mip->mi_mmrp->mmr_margin;
2555 
2556 	if (margin_needed <= margin)
2557 		mip->mi_margin = margin;
2558 
2559 	rw_exit(&(mip->mi_rw_lock));
2560 
2561 	if (margin_needed <= margin)
2562 		i_mac_notify(mip, MAC_NOTE_MARGIN);
2563 
2564 	return (margin_needed <= margin);
2565 }
2566 
2567 /*
2568  * MAC Type Plugin functions.
2569  */
2570 
2571 mactype_t *
2572 mactype_getplugin(const char *pname)
2573 {
2574 	mactype_t	*mtype = NULL;
2575 	boolean_t	tried_modload = B_FALSE;
2576 
2577 	mutex_enter(&i_mactype_lock);
2578 
2579 find_registered_mactype:
2580 	if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)pname,
2581 	    (mod_hash_val_t *)&mtype) != 0) {
2582 		if (!tried_modload) {
2583 			/*
2584 			 * If the plugin has not yet been loaded, then
2585 			 * attempt to load it now.  If modload() succeeds,
2586 			 * the plugin should have registered using
2587 			 * mactype_register(), in which case we can go back
2588 			 * and attempt to find it again.
2589 			 */
2590 			if (modload(MACTYPE_KMODDIR, (char *)pname) != -1) {
2591 				tried_modload = B_TRUE;
2592 				goto find_registered_mactype;
2593 			}
2594 		}
2595 	} else {
2596 		/*
2597 		 * Note that there's no danger that the plugin we've loaded
2598 		 * could be unloaded between the modload() step and the
2599 		 * reference count bump here, as we're holding
2600 		 * i_mactype_lock, which mactype_unregister() also holds.
2601 		 */
2602 		atomic_inc_32(&mtype->mt_ref);
2603 	}
2604 
2605 	mutex_exit(&i_mactype_lock);
2606 	return (mtype);
2607 }
2608 
2609 mactype_register_t *
2610 mactype_alloc(uint_t mactype_version)
2611 {
2612 	mactype_register_t *mtrp;
2613 
2614 	/*
2615 	 * Make sure there isn't a version mismatch between the plugin and
2616 	 * the framework.  In the future, if multiple versions are
2617 	 * supported, this check could become more sophisticated.
2618 	 */
2619 	if (mactype_version != MACTYPE_VERSION)
2620 		return (NULL);
2621 
2622 	mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP);
2623 	mtrp->mtr_version = mactype_version;
2624 	return (mtrp);
2625 }
2626 
2627 void
2628 mactype_free(mactype_register_t *mtrp)
2629 {
2630 	kmem_free(mtrp, sizeof (mactype_register_t));
2631 }
2632 
2633 int
2634 mactype_register(mactype_register_t *mtrp)
2635 {
2636 	mactype_t	*mtp;
2637 	mactype_ops_t	*ops = mtrp->mtr_ops;
2638 
2639 	/* Do some sanity checking before we register this MAC type. */
2640 	if (mtrp->mtr_ident == NULL || ops == NULL)
2641 		return (EINVAL);
2642 
2643 	/*
2644 	 * Verify that all mandatory callbacks are set in the ops
2645 	 * vector.
2646 	 */
2647 	if (ops->mtops_unicst_verify == NULL ||
2648 	    ops->mtops_multicst_verify == NULL ||
2649 	    ops->mtops_sap_verify == NULL ||
2650 	    ops->mtops_header == NULL ||
2651 	    ops->mtops_header_info == NULL) {
2652 		return (EINVAL);
2653 	}
2654 
2655 	mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP);
2656 	mtp->mt_ident = mtrp->mtr_ident;
2657 	mtp->mt_ops = *ops;
2658 	mtp->mt_type = mtrp->mtr_mactype;
2659 	mtp->mt_nativetype = mtrp->mtr_nativetype;
2660 	mtp->mt_addr_length = mtrp->mtr_addrlen;
2661 	if (mtrp->mtr_brdcst_addr != NULL) {
2662 		mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP);
2663 		bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr,
2664 		    mtrp->mtr_addrlen);
2665 	}
2666 
2667 	mtp->mt_stats = mtrp->mtr_stats;
2668 	mtp->mt_statcount = mtrp->mtr_statcount;
2669 
2670 	mtp->mt_mapping = mtrp->mtr_mapping;
2671 	mtp->mt_mappingcount = mtrp->mtr_mappingcount;
2672 
2673 	if (mod_hash_insert(i_mactype_hash,
2674 	    (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) {
2675 		kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
2676 		kmem_free(mtp, sizeof (*mtp));
2677 		return (EEXIST);
2678 	}
2679 	return (0);
2680 }
2681 
2682 int
2683 mactype_unregister(const char *ident)
2684 {
2685 	mactype_t	*mtp;
2686 	mod_hash_val_t	val;
2687 	int 		err;
2688 
2689 	/*
2690 	 * Let's not allow MAC drivers to use this plugin while we're
2691 	 * trying to unregister it.  Holding i_mactype_lock also prevents a
2692 	 * plugin from unregistering while a MAC driver is attempting to
2693 	 * hold a reference to it in i_mactype_getplugin().
2694 	 */
2695 	mutex_enter(&i_mactype_lock);
2696 
2697 	if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident,
2698 	    (mod_hash_val_t *)&mtp)) != 0) {
2699 		/* A plugin is trying to unregister, but it never registered. */
2700 		err = ENXIO;
2701 		goto done;
2702 	}
2703 
2704 	if (mtp->mt_ref != 0) {
2705 		err = EBUSY;
2706 		goto done;
2707 	}
2708 
2709 	err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val);
2710 	ASSERT(err == 0);
2711 	if (err != 0) {
2712 		/* This should never happen, thus the ASSERT() above. */
2713 		err = EINVAL;
2714 		goto done;
2715 	}
2716 	ASSERT(mtp == (mactype_t *)val);
2717 
2718 	if (mtp->mt_brdcst_addr != NULL)
2719 		kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
2720 	kmem_free(mtp, sizeof (mactype_t));
2721 done:
2722 	mutex_exit(&i_mactype_lock);
2723 	return (err);
2724 }
2725 
2726 /*
2727  * mac_set_prop() sets mac or hardware driver properties:
2728  * 	MAC resource properties include maxbw, priority, and cpu binding list.
2729  *	Driver properties are private properties to the hardware, such as mtu
2730  *	and speed.  There's one other MAC property -- the PVID.
2731  * If the property is a driver property, mac_set_prop() calls driver's callback
2732  * function to set it.
2733  * If the property is a mac resource property, mac_set_prop() invokes
2734  * mac_set_resources() which will cache the property value in mac_impl_t and
2735  * may call mac_client_set_resource() to update property value of the primary
2736  * mac client, if it exists.
2737  */
2738 int
2739 mac_set_prop(mac_handle_t mh, mac_prop_t *macprop, void *val, uint_t valsize)
2740 {
2741 	int err = ENOTSUP;
2742 	mac_impl_t *mip = (mac_impl_t *)mh;
2743 
2744 	ASSERT(MAC_PERIM_HELD(mh));
2745 
2746 	switch (macprop->mp_id) {
2747 	case MAC_PROP_MAXBW:
2748 	case MAC_PROP_PRIO:
2749 	case MAC_PROP_PROTECT:
2750 	case MAC_PROP_BIND_CPU: {
2751 		mac_resource_props_t mrp;
2752 
2753 		/* If it is mac property, call mac_set_resources() */
2754 		if (valsize < sizeof (mac_resource_props_t))
2755 			return (EINVAL);
2756 		bcopy(val, &mrp, sizeof (mrp));
2757 		err = mac_set_resources(mh, &mrp);
2758 		break;
2759 	}
2760 
2761 	case MAC_PROP_PVID:
2762 		if (valsize < sizeof (uint16_t) ||
2763 		    (mip->mi_state_flags & MIS_IS_VNIC))
2764 			return (EINVAL);
2765 		err = mac_set_pvid(mh, *(uint16_t *)val);
2766 		break;
2767 
2768 	case MAC_PROP_MTU: {
2769 		uint32_t mtu;
2770 
2771 		if (valsize < sizeof (mtu))
2772 			return (EINVAL);
2773 		bcopy(val, &mtu, sizeof (mtu));
2774 		err = mac_set_mtu(mh, mtu, NULL);
2775 		break;
2776 	}
2777 
2778 	case MAC_PROP_LLIMIT:
2779 	case MAC_PROP_LDECAY: {
2780 		uint32_t learnval;
2781 
2782 		if (valsize < sizeof (learnval) ||
2783 		    (mip->mi_state_flags & MIS_IS_VNIC))
2784 			return (EINVAL);
2785 		bcopy(val, &learnval, sizeof (learnval));
2786 		if (learnval == 0 && macprop->mp_id == MAC_PROP_LDECAY)
2787 			return (EINVAL);
2788 		if (macprop->mp_id == MAC_PROP_LLIMIT)
2789 			mip->mi_llimit = learnval;
2790 		else
2791 			mip->mi_ldecay = learnval;
2792 		err = 0;
2793 		break;
2794 	}
2795 
2796 	default:
2797 		/* For other driver properties, call driver's callback */
2798 		if (mip->mi_callbacks->mc_callbacks & MC_SETPROP) {
2799 			err = mip->mi_callbacks->mc_setprop(mip->mi_driver,
2800 			    macprop->mp_name, macprop->mp_id, valsize, val);
2801 		}
2802 	}
2803 	return (err);
2804 }
2805 
2806 /*
2807  * mac_get_prop() gets mac or hardware driver properties.
2808  *
2809  * If the property is a driver property, mac_get_prop() calls driver's callback
2810  * function to get it.
2811  * If the property is a mac property, mac_get_prop() invokes mac_get_resources()
2812  * which returns the cached value in mac_impl_t.
2813  */
2814 int
2815 mac_get_prop(mac_handle_t mh, mac_prop_t *macprop, void *val, uint_t valsize,
2816     uint_t *perm)
2817 {
2818 	int err = ENOTSUP;
2819 	mac_impl_t *mip = (mac_impl_t *)mh;
2820 	link_state_t link_state;
2821 	boolean_t is_getprop, is_setprop;
2822 
2823 	is_getprop = (mip->mi_callbacks->mc_callbacks & MC_GETPROP);
2824 	is_setprop = (mip->mi_callbacks->mc_callbacks & MC_SETPROP);
2825 
2826 	switch (macprop->mp_id) {
2827 	case MAC_PROP_MAXBW:
2828 	case MAC_PROP_PRIO:
2829 	case MAC_PROP_PROTECT:
2830 	case MAC_PROP_BIND_CPU: {
2831 		mac_resource_props_t mrp;
2832 
2833 		/* If mac property, read from cache */
2834 		if (valsize < sizeof (mac_resource_props_t))
2835 			return (EINVAL);
2836 		mac_get_resources(mh, &mrp);
2837 		bcopy(&mrp, val, sizeof (mac_resource_props_t));
2838 		return (0);
2839 	}
2840 
2841 	case MAC_PROP_PVID:
2842 		if (valsize < sizeof (uint16_t) ||
2843 		    (mip->mi_state_flags & MIS_IS_VNIC))
2844 			return (EINVAL);
2845 		*(uint16_t *)val = mac_get_pvid(mh);
2846 		return (0);
2847 
2848 	case MAC_PROP_LLIMIT:
2849 	case MAC_PROP_LDECAY:
2850 		if (valsize < sizeof (uint32_t) ||
2851 		    (mip->mi_state_flags & MIS_IS_VNIC))
2852 			return (EINVAL);
2853 		if (macprop->mp_id == MAC_PROP_LLIMIT)
2854 			bcopy(&mip->mi_llimit, val, sizeof (mip->mi_llimit));
2855 		else
2856 			bcopy(&mip->mi_ldecay, val, sizeof (mip->mi_ldecay));
2857 		return (0);
2858 
2859 	case MAC_PROP_MTU: {
2860 		uint32_t sdu;
2861 		mac_propval_range_t range;
2862 
2863 		if ((macprop->mp_flags & MAC_PROP_POSSIBLE) != 0) {
2864 			if (valsize < sizeof (mac_propval_range_t))
2865 				return (EINVAL);
2866 			if (is_getprop) {
2867 				err = mip->mi_callbacks->mc_getprop(mip->
2868 				    mi_driver, macprop->mp_name, macprop->mp_id,
2869 				    macprop->mp_flags, valsize, val, perm);
2870 			}
2871 			/*
2872 			 * If the driver doesn't have *_m_getprop defined or
2873 			 * if the driver doesn't support setting MTU then
2874 			 * return the CURRENT value as POSSIBLE value.
2875 			 */
2876 			if (!is_getprop || err == ENOTSUP) {
2877 				mac_sdu_get(mh, NULL, &sdu);
2878 				range.mpr_count = 1;
2879 				range.mpr_type = MAC_PROPVAL_UINT32;
2880 				range.range_uint32[0].mpur_min =
2881 				    range.range_uint32[0].mpur_max = sdu;
2882 				bcopy(&range, val, sizeof (range));
2883 				err = 0;
2884 			}
2885 			return (err);
2886 		}
2887 		if (valsize < sizeof (sdu))
2888 			return (EINVAL);
2889 		if ((macprop->mp_flags & MAC_PROP_DEFAULT) == 0) {
2890 			mac_sdu_get(mh, NULL, &sdu);
2891 			bcopy(&sdu, val, sizeof (sdu));
2892 			if (is_setprop && (mip->mi_callbacks->mc_setprop(mip->
2893 			    mi_driver, macprop->mp_name, macprop->mp_id,
2894 			    valsize, val) == 0)) {
2895 				*perm = MAC_PROP_PERM_RW;
2896 			} else {
2897 				*perm = MAC_PROP_PERM_READ;
2898 			}
2899 			return (0);
2900 		} else {
2901 			if (mip->mi_info.mi_media == DL_ETHER) {
2902 				sdu = ETHERMTU;
2903 				bcopy(&sdu, val, sizeof (sdu));
2904 
2905 				return (0);
2906 			}
2907 			/*
2908 			 * ask driver for its default.
2909 			 */
2910 			break;
2911 		}
2912 	}
2913 	case MAC_PROP_STATUS:
2914 		if (valsize < sizeof (link_state))
2915 			return (EINVAL);
2916 		*perm = MAC_PROP_PERM_READ;
2917 		link_state = mac_link_get(mh);
2918 		bcopy(&link_state, val, sizeof (link_state));
2919 		return (0);
2920 	default:
2921 		break;
2922 
2923 	}
2924 	/* If driver property, request from driver */
2925 	if (is_getprop) {
2926 		err = mip->mi_callbacks->mc_getprop(mip->mi_driver,
2927 		    macprop->mp_name, macprop->mp_id, macprop->mp_flags,
2928 		    valsize, val, perm);
2929 	}
2930 	return (err);
2931 }
2932 
2933 int
2934 mac_fastpath_disable(mac_handle_t mh)
2935 {
2936 	mac_impl_t	*mip = (mac_impl_t *)mh;
2937 
2938 	if ((mip->mi_state_flags & MIS_LEGACY) == 0)
2939 		return (0);
2940 
2941 	return (mip->mi_capab_legacy.ml_fastpath_disable(mip->mi_driver));
2942 }
2943 
2944 void
2945 mac_fastpath_enable(mac_handle_t mh)
2946 {
2947 	mac_impl_t	*mip = (mac_impl_t *)mh;
2948 
2949 	if ((mip->mi_state_flags & MIS_LEGACY) == 0)
2950 		return;
2951 
2952 	mip->mi_capab_legacy.ml_fastpath_enable(mip->mi_driver);
2953 }
2954 
2955 void
2956 mac_register_priv_prop(mac_impl_t *mip, mac_priv_prop_t *mpp, uint_t nprop)
2957 {
2958 	mac_priv_prop_t *mpriv;
2959 
2960 	if (mpp == NULL)
2961 		return;
2962 
2963 	mpriv = kmem_zalloc(nprop * sizeof (*mpriv), KM_SLEEP);
2964 	(void) memcpy(mpriv, mpp, nprop * sizeof (*mpriv));
2965 	mip->mi_priv_prop = mpriv;
2966 	mip->mi_priv_prop_count = nprop;
2967 }
2968 
2969 void
2970 mac_unregister_priv_prop(mac_impl_t *mip)
2971 {
2972 	mac_priv_prop_t	*mpriv;
2973 
2974 	mpriv = mip->mi_priv_prop;
2975 	if (mpriv != NULL) {
2976 		kmem_free(mpriv, mip->mi_priv_prop_count * sizeof (*mpriv));
2977 		mip->mi_priv_prop = NULL;
2978 	}
2979 	mip->mi_priv_prop_count = 0;
2980 }
2981 
2982 /*
2983  * mac_ring_t 'mr' macros. Some rogue drivers may access ring structure
2984  * (by invoking mac_rx()) even after processing mac_stop_ring(). In such
2985  * cases if MAC free's the ring structure after mac_stop_ring(), any
2986  * illegal access to the ring structure coming from the driver will panic
2987  * the system. In order to protect the system from such inadverent access,
2988  * we maintain a cache of rings in the mac_impl_t after they get free'd up.
2989  * When packets are received on free'd up rings, MAC (through the generation
2990  * count mechanism) will drop such packets.
2991  */
2992 static mac_ring_t *
2993 mac_ring_alloc(mac_impl_t *mip, mac_capab_rings_t *cap_rings)
2994 {
2995 	mac_ring_t *ring;
2996 
2997 	if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
2998 		mutex_enter(&mip->mi_ring_lock);
2999 		if (mip->mi_ring_freelist != NULL) {
3000 			ring = mip->mi_ring_freelist;
3001 			mip->mi_ring_freelist = ring->mr_next;
3002 			bzero(ring, sizeof (mac_ring_t));
3003 		} else {
3004 			ring = kmem_cache_alloc(mac_ring_cache, KM_SLEEP);
3005 		}
3006 		mutex_exit(&mip->mi_ring_lock);
3007 	} else {
3008 		ring = kmem_zalloc(sizeof (mac_ring_t), KM_SLEEP);
3009 	}
3010 	ASSERT((ring != NULL) && (ring->mr_state == MR_FREE));
3011 	return (ring);
3012 }
3013 
3014 static void
3015 mac_ring_free(mac_impl_t *mip, mac_ring_t *ring)
3016 {
3017 	if (ring->mr_type == MAC_RING_TYPE_RX) {
3018 		mutex_enter(&mip->mi_ring_lock);
3019 		ring->mr_state = MR_FREE;
3020 		ring->mr_flag = 0;
3021 		ring->mr_next = mip->mi_ring_freelist;
3022 		mip->mi_ring_freelist = ring;
3023 		mutex_exit(&mip->mi_ring_lock);
3024 	} else {
3025 		kmem_free(ring, sizeof (mac_ring_t));
3026 	}
3027 }
3028 
3029 static void
3030 mac_ring_freeall(mac_impl_t *mip)
3031 {
3032 	mac_ring_t *ring_next;
3033 	mutex_enter(&mip->mi_ring_lock);
3034 	mac_ring_t *ring = mip->mi_ring_freelist;
3035 	while (ring != NULL) {
3036 		ring_next = ring->mr_next;
3037 		kmem_cache_free(mac_ring_cache, ring);
3038 		ring = ring_next;
3039 	}
3040 	mip->mi_ring_freelist = NULL;
3041 	mutex_exit(&mip->mi_ring_lock);
3042 }
3043 
3044 int
3045 mac_start_ring(mac_ring_t *ring)
3046 {
3047 	int rv = 0;
3048 
3049 	if (ring->mr_start != NULL)
3050 		rv = ring->mr_start(ring->mr_driver, ring->mr_gen_num);
3051 
3052 	return (rv);
3053 }
3054 
3055 void
3056 mac_stop_ring(mac_ring_t *ring)
3057 {
3058 	if (ring->mr_stop != NULL)
3059 		ring->mr_stop(ring->mr_driver);
3060 
3061 	/*
3062 	 * Increment the ring generation number for this ring.
3063 	 */
3064 	ring->mr_gen_num++;
3065 }
3066 
3067 int
3068 mac_start_group(mac_group_t *group)
3069 {
3070 	int rv = 0;
3071 
3072 	if (group->mrg_start != NULL)
3073 		rv = group->mrg_start(group->mrg_driver);
3074 
3075 	return (rv);
3076 }
3077 
3078 void
3079 mac_stop_group(mac_group_t *group)
3080 {
3081 	if (group->mrg_stop != NULL)
3082 		group->mrg_stop(group->mrg_driver);
3083 }
3084 
3085 /*
3086  * Called from mac_start() on the default Rx group. Broadcast and multicast
3087  * packets are received only on the default group. Hence the default group
3088  * needs to be up even if the primary client is not up, for the other groups
3089  * to be functional. We do this by calling this function at mac_start time
3090  * itself. However the broadcast packets that are received can't make their
3091  * way beyond mac_rx until a mac client creates a broadcast flow.
3092  */
3093 static int
3094 mac_start_group_and_rings(mac_group_t *group)
3095 {
3096 	mac_ring_t	*ring;
3097 	int		rv = 0;
3098 
3099 	ASSERT(group->mrg_state == MAC_GROUP_STATE_REGISTERED);
3100 	if ((rv = mac_start_group(group)) != 0)
3101 		return (rv);
3102 
3103 	for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
3104 		ASSERT(ring->mr_state == MR_FREE);
3105 		if ((rv = mac_start_ring(ring)) != 0)
3106 			goto error;
3107 		ring->mr_state = MR_INUSE;
3108 		ring->mr_classify_type = MAC_SW_CLASSIFIER;
3109 	}
3110 	return (0);
3111 
3112 error:
3113 	mac_stop_group_and_rings(group);
3114 	return (rv);
3115 }
3116 
3117 /* Called from mac_stop on the default Rx group */
3118 static void
3119 mac_stop_group_and_rings(mac_group_t *group)
3120 {
3121 	mac_ring_t	*ring;
3122 
3123 	for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
3124 		if (ring->mr_state != MR_FREE) {
3125 			mac_stop_ring(ring);
3126 			ring->mr_state = MR_FREE;
3127 			ring->mr_flag = 0;
3128 			ring->mr_classify_type = MAC_NO_CLASSIFIER;
3129 		}
3130 	}
3131 	mac_stop_group(group);
3132 }
3133 
3134 
3135 static mac_ring_t *
3136 mac_init_ring(mac_impl_t *mip, mac_group_t *group, int index,
3137     mac_capab_rings_t *cap_rings)
3138 {
3139 	mac_ring_t *ring;
3140 	mac_ring_info_t ring_info;
3141 
3142 	ring = mac_ring_alloc(mip, cap_rings);
3143 
3144 	/* Prepare basic information of ring */
3145 	ring->mr_index = index;
3146 	ring->mr_type = group->mrg_type;
3147 	ring->mr_gh = (mac_group_handle_t)group;
3148 
3149 	/* Insert the new ring to the list. */
3150 	ring->mr_next = group->mrg_rings;
3151 	group->mrg_rings = ring;
3152 
3153 	/* Zero to reuse the info data structure */
3154 	bzero(&ring_info, sizeof (ring_info));
3155 
3156 	/* Query ring information from driver */
3157 	cap_rings->mr_rget(mip->mi_driver, group->mrg_type, group->mrg_index,
3158 	    index, &ring_info, (mac_ring_handle_t)ring);
3159 
3160 	ring->mr_info = ring_info;
3161 
3162 	/* Update ring's status */
3163 	ring->mr_state = MR_FREE;
3164 	ring->mr_flag = 0;
3165 
3166 	/* Update the ring count of the group */
3167 	group->mrg_cur_count++;
3168 	return (ring);
3169 }
3170 
3171 /*
3172  * Rings are chained together for easy regrouping.
3173  */
3174 static void
3175 mac_init_group(mac_impl_t *mip, mac_group_t *group, int size,
3176     mac_capab_rings_t *cap_rings)
3177 {
3178 	int index;
3179 
3180 	/*
3181 	 * Initialize all ring members of this group. Size of zero will not
3182 	 * enter the loop, so it's safe for initializing an empty group.
3183 	 */
3184 	for (index = size - 1; index >= 0; index--)
3185 		(void) mac_init_ring(mip, group, index, cap_rings);
3186 }
3187 
3188 int
3189 mac_init_rings(mac_impl_t *mip, mac_ring_type_t rtype)
3190 {
3191 	mac_capab_rings_t *cap_rings;
3192 	mac_group_t *group, *groups;
3193 	mac_group_info_t group_info;
3194 	uint_t group_free = 0;
3195 	uint_t ring_left;
3196 	mac_ring_t *ring;
3197 	int g, err = 0;
3198 
3199 	switch (rtype) {
3200 	case MAC_RING_TYPE_RX:
3201 		ASSERT(mip->mi_rx_groups == NULL);
3202 
3203 		cap_rings = &mip->mi_rx_rings_cap;
3204 		cap_rings->mr_type = MAC_RING_TYPE_RX;
3205 		break;
3206 	case MAC_RING_TYPE_TX:
3207 		ASSERT(mip->mi_tx_groups == NULL);
3208 
3209 		cap_rings = &mip->mi_tx_rings_cap;
3210 		cap_rings->mr_type = MAC_RING_TYPE_TX;
3211 		break;
3212 	default:
3213 		ASSERT(B_FALSE);
3214 	}
3215 
3216 	if (!i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_RINGS,
3217 	    cap_rings))
3218 		return (0);
3219 
3220 	/*
3221 	 * Allocate a contiguous buffer for all groups.
3222 	 */
3223 	groups = kmem_zalloc(sizeof (mac_group_t) * (cap_rings->mr_gnum + 1),
3224 	    KM_SLEEP);
3225 
3226 	ring_left = cap_rings->mr_rnum;
3227 
3228 	/*
3229 	 * Get all ring groups if any, and get their ring members
3230 	 * if any.
3231 	 */
3232 	for (g = 0; g < cap_rings->mr_gnum; g++) {
3233 		group = groups + g;
3234 
3235 		/* Prepare basic information of the group */
3236 		group->mrg_index = g;
3237 		group->mrg_type = rtype;
3238 		group->mrg_state = MAC_GROUP_STATE_UNINIT;
3239 		group->mrg_mh = (mac_handle_t)mip;
3240 		group->mrg_next = group + 1;
3241 
3242 		/* Zero to reuse the info data structure */
3243 		bzero(&group_info, sizeof (group_info));
3244 
3245 		/* Query group information from driver */
3246 		cap_rings->mr_gget(mip->mi_driver, rtype, g, &group_info,
3247 		    (mac_group_handle_t)group);
3248 
3249 		switch (cap_rings->mr_group_type) {
3250 		case MAC_GROUP_TYPE_DYNAMIC:
3251 			if (cap_rings->mr_gaddring == NULL ||
3252 			    cap_rings->mr_gremring == NULL) {
3253 				DTRACE_PROBE3(
3254 				    mac__init__rings_no_addremring,
3255 				    char *, mip->mi_name,
3256 				    mac_group_add_ring_t,
3257 				    cap_rings->mr_gaddring,
3258 				    mac_group_add_ring_t,
3259 				    cap_rings->mr_gremring);
3260 				err = EINVAL;
3261 				goto bail;
3262 			}
3263 
3264 			switch (rtype) {
3265 			case MAC_RING_TYPE_RX:
3266 				/*
3267 				 * The first RX group must have non-zero
3268 				 * rings, and the following groups must
3269 				 * have zero rings.
3270 				 */
3271 				if (g == 0 && group_info.mgi_count == 0) {
3272 					DTRACE_PROBE1(
3273 					    mac__init__rings__rx__def__zero,
3274 					    char *, mip->mi_name);
3275 					err = EINVAL;
3276 					goto bail;
3277 				}
3278 				if (g > 0 && group_info.mgi_count != 0) {
3279 					DTRACE_PROBE3(
3280 					    mac__init__rings__rx__nonzero,
3281 					    char *, mip->mi_name,
3282 					    int, g, int, group_info.mgi_count);
3283 					err = EINVAL;
3284 					goto bail;
3285 				}
3286 				break;
3287 			case MAC_RING_TYPE_TX:
3288 				/*
3289 				 * All TX ring groups must have zero rings.
3290 				 */
3291 				if (group_info.mgi_count != 0) {
3292 					DTRACE_PROBE3(
3293 					    mac__init__rings__tx__nonzero,
3294 					    char *, mip->mi_name,
3295 					    int, g, int, group_info.mgi_count);
3296 					err = EINVAL;
3297 					goto bail;
3298 				}
3299 				break;
3300 			}
3301 			break;
3302 		case MAC_GROUP_TYPE_STATIC:
3303 			/*
3304 			 * Note that an empty group is allowed, e.g., an aggr
3305 			 * would start with an empty group.
3306 			 */
3307 			break;
3308 		default:
3309 			/* unknown group type */
3310 			DTRACE_PROBE2(mac__init__rings__unknown__type,
3311 			    char *, mip->mi_name,
3312 			    int, cap_rings->mr_group_type);
3313 			err = EINVAL;
3314 			goto bail;
3315 		}
3316 
3317 
3318 		/*
3319 		 * Driver must register group->mgi_addmac/remmac() for rx groups
3320 		 * to support multiple MAC addresses.
3321 		 */
3322 		if (rtype == MAC_RING_TYPE_RX) {
3323 			if ((group_info.mgi_addmac == NULL) ||
3324 			    (group_info.mgi_addmac == NULL))
3325 				goto bail;
3326 		}
3327 
3328 		/* Cache driver-supplied information */
3329 		group->mrg_info = group_info;
3330 
3331 		/* Update the group's status and group count. */
3332 		mac_set_rx_group_state(group, MAC_GROUP_STATE_REGISTERED);
3333 		group_free++;
3334 
3335 		group->mrg_rings = NULL;
3336 		group->mrg_cur_count = 0;
3337 		mac_init_group(mip, group, group_info.mgi_count, cap_rings);
3338 		ring_left -= group_info.mgi_count;
3339 
3340 		/* The current group size should be equal to default value */
3341 		ASSERT(group->mrg_cur_count == group_info.mgi_count);
3342 	}
3343 
3344 	/* Build up a dummy group for free resources as a pool */
3345 	group = groups + cap_rings->mr_gnum;
3346 
3347 	/* Prepare basic information of the group */
3348 	group->mrg_index = -1;
3349 	group->mrg_type = rtype;
3350 	group->mrg_state = MAC_GROUP_STATE_UNINIT;
3351 	group->mrg_mh = (mac_handle_t)mip;
3352 	group->mrg_next = NULL;
3353 
3354 	/*
3355 	 * If there are ungrouped rings, allocate a continuous buffer for
3356 	 * remaining resources.
3357 	 */
3358 	if (ring_left != 0) {
3359 		group->mrg_rings = NULL;
3360 		group->mrg_cur_count = 0;
3361 		mac_init_group(mip, group, ring_left, cap_rings);
3362 
3363 		/* The current group size should be equal to ring_left */
3364 		ASSERT(group->mrg_cur_count == ring_left);
3365 
3366 		ring_left = 0;
3367 
3368 		/* Update this group's status */
3369 		mac_set_rx_group_state(group, MAC_GROUP_STATE_REGISTERED);
3370 	} else
3371 		group->mrg_rings = NULL;
3372 
3373 	ASSERT(ring_left == 0);
3374 
3375 bail:
3376 	/* Cache other important information to finalize the initialization */
3377 	switch (rtype) {
3378 	case MAC_RING_TYPE_RX:
3379 		mip->mi_rx_group_type = cap_rings->mr_group_type;
3380 		mip->mi_rx_group_count = cap_rings->mr_gnum;
3381 		mip->mi_rx_groups = groups;
3382 		break;
3383 	case MAC_RING_TYPE_TX:
3384 		mip->mi_tx_group_type = cap_rings->mr_group_type;
3385 		mip->mi_tx_group_count = cap_rings->mr_gnum;
3386 		mip->mi_tx_group_free = group_free;
3387 		mip->mi_tx_groups = groups;
3388 
3389 		/*
3390 		 * Ring 0 is used as the default one and it could be assigned
3391 		 * to a client as well.
3392 		 */
3393 		group = groups + cap_rings->mr_gnum;
3394 		ring = group->mrg_rings;
3395 		while ((ring->mr_index != 0) && (ring->mr_next != NULL))
3396 			ring = ring->mr_next;
3397 		ASSERT(ring->mr_index == 0);
3398 		mip->mi_default_tx_ring = (mac_ring_handle_t)ring;
3399 		break;
3400 	default:
3401 		ASSERT(B_FALSE);
3402 	}
3403 
3404 	if (err != 0)
3405 		mac_free_rings(mip, rtype);
3406 
3407 	return (err);
3408 }
3409 
3410 /*
3411  * Called to free all ring groups with particular type. It's supposed all groups
3412  * have been released by clinet.
3413  */
3414 void
3415 mac_free_rings(mac_impl_t *mip, mac_ring_type_t rtype)
3416 {
3417 	mac_group_t *group, *groups;
3418 	uint_t group_count;
3419 
3420 	switch (rtype) {
3421 	case MAC_RING_TYPE_RX:
3422 		if (mip->mi_rx_groups == NULL)
3423 			return;
3424 
3425 		groups = mip->mi_rx_groups;
3426 		group_count = mip->mi_rx_group_count;
3427 
3428 		mip->mi_rx_groups = NULL;
3429 		mip->mi_rx_group_count = 0;
3430 		break;
3431 	case MAC_RING_TYPE_TX:
3432 		ASSERT(mip->mi_tx_group_count == mip->mi_tx_group_free);
3433 
3434 		if (mip->mi_tx_groups == NULL)
3435 			return;
3436 
3437 		groups = mip->mi_tx_groups;
3438 		group_count = mip->mi_tx_group_count;
3439 
3440 		mip->mi_tx_groups = NULL;
3441 		mip->mi_tx_group_count = 0;
3442 		mip->mi_tx_group_free = 0;
3443 		mip->mi_default_tx_ring = NULL;
3444 		break;
3445 	default:
3446 		ASSERT(B_FALSE);
3447 	}
3448 
3449 	for (group = groups; group != NULL; group = group->mrg_next) {
3450 		mac_ring_t *ring;
3451 
3452 		if (group->mrg_cur_count == 0)
3453 			continue;
3454 
3455 		ASSERT(group->mrg_rings != NULL);
3456 
3457 		while ((ring = group->mrg_rings) != NULL) {
3458 			group->mrg_rings = ring->mr_next;
3459 			mac_ring_free(mip, ring);
3460 		}
3461 	}
3462 
3463 	/* Free all the cached rings */
3464 	mac_ring_freeall(mip);
3465 	/* Free the block of group data strutures */
3466 	kmem_free(groups, sizeof (mac_group_t) * (group_count + 1));
3467 }
3468 
3469 /*
3470  * Associate a MAC address with a receive group.
3471  *
3472  * The return value of this function should always be checked properly, because
3473  * any type of failure could cause unexpected results. A group can be added
3474  * or removed with a MAC address only after it has been reserved. Ideally,
3475  * a successful reservation always leads to calling mac_group_addmac() to
3476  * steer desired traffic. Failure of adding an unicast MAC address doesn't
3477  * always imply that the group is functioning abnormally.
3478  *
3479  * Currently this function is called everywhere, and it reflects assumptions
3480  * about MAC addresses in the implementation. CR 6735196.
3481  */
3482 int
3483 mac_group_addmac(mac_group_t *group, const uint8_t *addr)
3484 {
3485 	ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
3486 	ASSERT(group->mrg_info.mgi_addmac != NULL);
3487 
3488 	return (group->mrg_info.mgi_addmac(group->mrg_info.mgi_driver, addr));
3489 }
3490 
3491 /*
3492  * Remove the association between MAC address and receive group.
3493  */
3494 int
3495 mac_group_remmac(mac_group_t *group, const uint8_t *addr)
3496 {
3497 	ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
3498 	ASSERT(group->mrg_info.mgi_remmac != NULL);
3499 
3500 	return (group->mrg_info.mgi_remmac(group->mrg_info.mgi_driver, addr));
3501 }
3502 
3503 /*
3504  * Release a ring in use by marking it MR_FREE.
3505  * Any other client may reserve it for its use.
3506  */
3507 void
3508 mac_release_tx_ring(mac_ring_handle_t rh)
3509 {
3510 	mac_ring_t *ring = (mac_ring_t *)rh;
3511 	mac_group_t *group = (mac_group_t *)ring->mr_gh;
3512 	mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
3513 
3514 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3515 	ASSERT(ring->mr_state != MR_FREE);
3516 
3517 	/*
3518 	 * Default tx ring will be released by mac_stop().
3519 	 */
3520 	if (rh == mip->mi_default_tx_ring)
3521 		return;
3522 
3523 	mac_stop_ring(ring);
3524 
3525 	ring->mr_state = MR_FREE;
3526 	ring->mr_flag = 0;
3527 }
3528 
3529 /*
3530  * This is the entry point for packets transmitted through the bridging code.
3531  * If no bridge is in place, MAC_RING_TX transmits using tx ring. The 'rh'
3532  * pointer may be NULL to select the default ring.
3533  */
3534 mblk_t *
3535 mac_bridge_tx(mac_impl_t *mip, mac_ring_handle_t rh, mblk_t *mp)
3536 {
3537 	mac_handle_t mh;
3538 
3539 	/*
3540 	 * Once we take a reference on the bridge link, the bridge
3541 	 * module itself can't unload, so the callback pointers are
3542 	 * stable.
3543 	 */
3544 	mutex_enter(&mip->mi_bridge_lock);
3545 	if ((mh = mip->mi_bridge_link) != NULL)
3546 		mac_bridge_ref_cb(mh, B_TRUE);
3547 	mutex_exit(&mip->mi_bridge_lock);
3548 	if (mh == NULL) {
3549 		MAC_RING_TX(mip, rh, mp, mp);
3550 	} else {
3551 		mp = mac_bridge_tx_cb(mh, rh, mp);
3552 		mac_bridge_ref_cb(mh, B_FALSE);
3553 	}
3554 
3555 	return (mp);
3556 }
3557 
3558 /*
3559  * Find a ring from its index.
3560  */
3561 mac_ring_t *
3562 mac_find_ring(mac_group_t *group, int index)
3563 {
3564 	mac_ring_t *ring = group->mrg_rings;
3565 
3566 	for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next)
3567 		if (ring->mr_index == index)
3568 			break;
3569 
3570 	return (ring);
3571 }
3572 /*
3573  * Add a ring to an existing group.
3574  *
3575  * The ring must be either passed directly (for example if the ring
3576  * movement is initiated by the framework), or specified through a driver
3577  * index (for example when the ring is added by the driver.
3578  *
3579  * The caller needs to call mac_perim_enter() before calling this function.
3580  */
3581 int
3582 i_mac_group_add_ring(mac_group_t *group, mac_ring_t *ring, int index)
3583 {
3584 	mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
3585 	mac_capab_rings_t *cap_rings;
3586 	boolean_t driver_call = (ring == NULL);
3587 	mac_group_type_t group_type;
3588 	int ret = 0;
3589 
3590 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3591 
3592 	switch (group->mrg_type) {
3593 	case MAC_RING_TYPE_RX:
3594 		cap_rings = &mip->mi_rx_rings_cap;
3595 		group_type = mip->mi_rx_group_type;
3596 		break;
3597 	case MAC_RING_TYPE_TX:
3598 		cap_rings = &mip->mi_tx_rings_cap;
3599 		group_type = mip->mi_tx_group_type;
3600 		break;
3601 	default:
3602 		ASSERT(B_FALSE);
3603 	}
3604 
3605 	/*
3606 	 * There should be no ring with the same ring index in the target
3607 	 * group.
3608 	 */
3609 	ASSERT(mac_find_ring(group, driver_call ? index : ring->mr_index) ==
3610 	    NULL);
3611 
3612 	if (driver_call) {
3613 		/*
3614 		 * The function is called as a result of a request from
3615 		 * a driver to add a ring to an existing group, for example
3616 		 * from the aggregation driver. Allocate a new mac_ring_t
3617 		 * for that ring.
3618 		 */
3619 		ring = mac_init_ring(mip, group, index, cap_rings);
3620 		ASSERT(group->mrg_state > MAC_GROUP_STATE_UNINIT);
3621 	} else {
3622 		/*
3623 		 * The function is called as a result of a MAC layer request
3624 		 * to add a ring to an existing group. In this case the
3625 		 * ring is being moved between groups, which requires
3626 		 * the underlying driver to support dynamic grouping,
3627 		 * and the mac_ring_t already exists.
3628 		 */
3629 		ASSERT(group_type == MAC_GROUP_TYPE_DYNAMIC);
3630 		ASSERT(cap_rings->mr_gaddring != NULL);
3631 		ASSERT(ring->mr_gh == NULL);
3632 	}
3633 
3634 	/*
3635 	 * At this point the ring should not be in use, and it should be
3636 	 * of the right for the target group.
3637 	 */
3638 	ASSERT(ring->mr_state < MR_INUSE);
3639 	ASSERT(ring->mr_srs == NULL);
3640 	ASSERT(ring->mr_type == group->mrg_type);
3641 
3642 	if (!driver_call) {
3643 		/*
3644 		 * Add the driver level hardware ring if the process was not
3645 		 * initiated by the driver, and the target group is not the
3646 		 * group.
3647 		 */
3648 		if (group->mrg_driver != NULL) {
3649 			cap_rings->mr_gaddring(group->mrg_driver,
3650 			    ring->mr_driver, ring->mr_type);
3651 		}
3652 
3653 		/*
3654 		 * Insert the ring ahead existing rings.
3655 		 */
3656 		ring->mr_next = group->mrg_rings;
3657 		group->mrg_rings = ring;
3658 		ring->mr_gh = (mac_group_handle_t)group;
3659 		group->mrg_cur_count++;
3660 	}
3661 
3662 	/*
3663 	 * If the group has not been actively used, we're done.
3664 	 */
3665 	if (group->mrg_index != -1 &&
3666 	    group->mrg_state < MAC_GROUP_STATE_RESERVED)
3667 		return (0);
3668 
3669 	/*
3670 	 * Set up SRS/SR according to the ring type.
3671 	 */
3672 	switch (ring->mr_type) {
3673 	case MAC_RING_TYPE_RX:
3674 		/*
3675 		 * Setup SRS on top of the new ring if the group is
3676 		 * reserved for someones exclusive use.
3677 		 */
3678 		if (group->mrg_state == MAC_GROUP_STATE_RESERVED) {
3679 			flow_entry_t *flent;
3680 			mac_client_impl_t *mcip;
3681 
3682 			mcip = MAC_RX_GROUP_ONLY_CLIENT(group);
3683 			ASSERT(mcip != NULL);
3684 			flent = mcip->mci_flent;
3685 			ASSERT(flent->fe_rx_srs_cnt > 0);
3686 			mac_srs_group_setup(mcip, flent, group, SRST_LINK);
3687 		}
3688 		break;
3689 	case MAC_RING_TYPE_TX:
3690 		/*
3691 		 * For TX this function is only invoked during the
3692 		 * initial creation of a group when a share is
3693 		 * associated with a MAC client. So the datapath is not
3694 		 * yet setup, and will be setup later after the
3695 		 * group has been reserved and populated.
3696 		 */
3697 		break;
3698 	default:
3699 		ASSERT(B_FALSE);
3700 	}
3701 
3702 	/*
3703 	 * Start the ring if needed. Failure causes to undo the grouping action.
3704 	 */
3705 	if ((ret = mac_start_ring(ring)) != 0) {
3706 		if (ring->mr_type == MAC_RING_TYPE_RX) {
3707 			if (ring->mr_srs != NULL) {
3708 				mac_rx_srs_remove(ring->mr_srs);
3709 				ring->mr_srs = NULL;
3710 			}
3711 		}
3712 		if (!driver_call) {
3713 			cap_rings->mr_gremring(group->mrg_driver,
3714 			    ring->mr_driver, ring->mr_type);
3715 		}
3716 		group->mrg_cur_count--;
3717 		group->mrg_rings = ring->mr_next;
3718 
3719 		ring->mr_gh = NULL;
3720 
3721 		if (driver_call)
3722 			mac_ring_free(mip, ring);
3723 
3724 		return (ret);
3725 	}
3726 
3727 	/*
3728 	 * Update the ring's state.
3729 	 */
3730 	ring->mr_state = MR_INUSE;
3731 	MAC_RING_UNMARK(ring, MR_INCIPIENT);
3732 	return (0);
3733 }
3734 
3735 /*
3736  * Remove a ring from it's current group. MAC internal function for dynamic
3737  * grouping.
3738  *
3739  * The caller needs to call mac_perim_enter() before calling this function.
3740  */
3741 void
3742 i_mac_group_rem_ring(mac_group_t *group, mac_ring_t *ring,
3743     boolean_t driver_call)
3744 {
3745 	mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
3746 	mac_capab_rings_t *cap_rings = NULL;
3747 	mac_group_type_t group_type;
3748 
3749 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3750 
3751 	ASSERT(mac_find_ring(group, ring->mr_index) == ring);
3752 	ASSERT((mac_group_t *)ring->mr_gh == group);
3753 	ASSERT(ring->mr_type == group->mrg_type);
3754 
3755 	switch (ring->mr_type) {
3756 	case MAC_RING_TYPE_RX:
3757 		group_type = mip->mi_rx_group_type;
3758 		cap_rings = &mip->mi_rx_rings_cap;
3759 
3760 		if (group->mrg_state >= MAC_GROUP_STATE_RESERVED)
3761 			mac_stop_ring(ring);
3762 
3763 		/*
3764 		 * Only hardware classified packets hold a reference to the
3765 		 * ring all the way up the Rx path. mac_rx_srs_remove()
3766 		 * will take care of quiescing the Rx path and removing the
3767 		 * SRS. The software classified path neither holds a reference
3768 		 * nor any association with the ring in mac_rx.
3769 		 */
3770 		if (ring->mr_srs != NULL) {
3771 			mac_rx_srs_remove(ring->mr_srs);
3772 			ring->mr_srs = NULL;
3773 		}
3774 		ring->mr_state = MR_FREE;
3775 		ring->mr_flag = 0;
3776 
3777 		break;
3778 	case MAC_RING_TYPE_TX:
3779 		/*
3780 		 * For TX this function is only invoked in two
3781 		 * cases:
3782 		 *
3783 		 * 1) In the case of a failure during the
3784 		 * initial creation of a group when a share is
3785 		 * associated with a MAC client. So the SRS is not
3786 		 * yet setup, and will be setup later after the
3787 		 * group has been reserved and populated.
3788 		 *
3789 		 * 2) From mac_release_tx_group() when freeing
3790 		 * a TX SRS.
3791 		 *
3792 		 * In both cases the SRS and its soft rings are
3793 		 * already quiesced.
3794 		 */
3795 		ASSERT(!driver_call);
3796 		group_type = mip->mi_tx_group_type;
3797 		cap_rings = &mip->mi_tx_rings_cap;
3798 		break;
3799 	default:
3800 		ASSERT(B_FALSE);
3801 	}
3802 
3803 	/*
3804 	 * Remove the ring from the group.
3805 	 */
3806 	if (ring == group->mrg_rings)
3807 		group->mrg_rings = ring->mr_next;
3808 	else {
3809 		mac_ring_t *pre;
3810 
3811 		pre = group->mrg_rings;
3812 		while (pre->mr_next != ring)
3813 			pre = pre->mr_next;
3814 		pre->mr_next = ring->mr_next;
3815 	}
3816 	group->mrg_cur_count--;
3817 
3818 	if (!driver_call) {
3819 		ASSERT(group_type == MAC_GROUP_TYPE_DYNAMIC);
3820 		ASSERT(cap_rings->mr_gremring != NULL);
3821 
3822 		/*
3823 		 * Remove the driver level hardware ring.
3824 		 */
3825 		if (group->mrg_driver != NULL) {
3826 			cap_rings->mr_gremring(group->mrg_driver,
3827 			    ring->mr_driver, ring->mr_type);
3828 		}
3829 	}
3830 
3831 	ring->mr_gh = NULL;
3832 	if (driver_call) {
3833 		mac_ring_free(mip, ring);
3834 	} else {
3835 		ring->mr_state = MR_FREE;
3836 		ring->mr_flag = 0;
3837 	}
3838 }
3839 
3840 /*
3841  * Move a ring to the target group. If needed, remove the ring from the group
3842  * that it currently belongs to.
3843  *
3844  * The caller need to enter MAC's perimeter by calling mac_perim_enter().
3845  */
3846 static int
3847 mac_group_mov_ring(mac_impl_t *mip, mac_group_t *d_group, mac_ring_t *ring)
3848 {
3849 	mac_group_t *s_group = (mac_group_t *)ring->mr_gh;
3850 	int rv;
3851 
3852 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3853 	ASSERT(d_group != NULL);
3854 	ASSERT(s_group->mrg_mh == d_group->mrg_mh);
3855 
3856 	if (s_group == d_group)
3857 		return (0);
3858 
3859 	/*
3860 	 * Remove it from current group first.
3861 	 */
3862 	if (s_group != NULL)
3863 		i_mac_group_rem_ring(s_group, ring, B_FALSE);
3864 
3865 	/*
3866 	 * Add it to the new group.
3867 	 */
3868 	rv = i_mac_group_add_ring(d_group, ring, 0);
3869 	if (rv != 0) {
3870 		/*
3871 		 * Failed to add ring back to source group. If
3872 		 * that fails, the ring is stuck in limbo, log message.
3873 		 */
3874 		if (i_mac_group_add_ring(s_group, ring, 0)) {
3875 			cmn_err(CE_WARN, "%s: failed to move ring %p\n",
3876 			    mip->mi_name, (void *)ring);
3877 		}
3878 	}
3879 
3880 	return (rv);
3881 }
3882 
3883 /*
3884  * Find a MAC address according to its value.
3885  */
3886 mac_address_t *
3887 mac_find_macaddr(mac_impl_t *mip, uint8_t *mac_addr)
3888 {
3889 	mac_address_t *map;
3890 
3891 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3892 
3893 	for (map = mip->mi_addresses; map != NULL; map = map->ma_next) {
3894 		if (bcmp(mac_addr, map->ma_addr, map->ma_len) == 0)
3895 			break;
3896 	}
3897 
3898 	return (map);
3899 }
3900 
3901 /*
3902  * Check whether the MAC address is shared by multiple clients.
3903  */
3904 boolean_t
3905 mac_check_macaddr_shared(mac_address_t *map)
3906 {
3907 	ASSERT(MAC_PERIM_HELD((mac_handle_t)map->ma_mip));
3908 
3909 	return (map->ma_nusers > 1);
3910 }
3911 
3912 /*
3913  * Remove the specified MAC address from the MAC address list and free it.
3914  */
3915 static void
3916 mac_free_macaddr(mac_address_t *map)
3917 {
3918 	mac_impl_t *mip = map->ma_mip;
3919 
3920 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3921 	ASSERT(mip->mi_addresses != NULL);
3922 
3923 	map = mac_find_macaddr(mip, map->ma_addr);
3924 
3925 	ASSERT(map != NULL);
3926 	ASSERT(map->ma_nusers == 0);
3927 
3928 	if (map == mip->mi_addresses) {
3929 		mip->mi_addresses = map->ma_next;
3930 	} else {
3931 		mac_address_t *pre;
3932 
3933 		pre = mip->mi_addresses;
3934 		while (pre->ma_next != map)
3935 			pre = pre->ma_next;
3936 		pre->ma_next = map->ma_next;
3937 	}
3938 
3939 	kmem_free(map, sizeof (mac_address_t));
3940 }
3941 
3942 /*
3943  * Add a MAC address reference for a client. If the desired MAC address
3944  * exists, add a reference to it. Otherwise, add the new address by adding
3945  * it to a reserved group or setting promiscuous mode. Won't try different
3946  * group is the group is non-NULL, so the caller must explictly share
3947  * default group when needed.
3948  *
3949  * Note, the primary MAC address is initialized at registration time, so
3950  * to add it to default group only need to activate it if its reference
3951  * count is still zero. Also, some drivers may not have advertised RINGS
3952  * capability.
3953  */
3954 int
3955 mac_add_macaddr(mac_impl_t *mip, mac_group_t *group, uint8_t *mac_addr,
3956     boolean_t use_hw)
3957 {
3958 	mac_address_t *map;
3959 	int err = 0;
3960 	boolean_t allocated_map = B_FALSE;
3961 
3962 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
3963 
3964 	map = mac_find_macaddr(mip, mac_addr);
3965 
3966 	/*
3967 	 * If the new MAC address has not been added. Allocate a new one
3968 	 * and set it up.
3969 	 */
3970 	if (map == NULL) {
3971 		map = kmem_zalloc(sizeof (mac_address_t), KM_SLEEP);
3972 		map->ma_len = mip->mi_type->mt_addr_length;
3973 		bcopy(mac_addr, map->ma_addr, map->ma_len);
3974 		map->ma_nusers = 0;
3975 		map->ma_group = group;
3976 		map->ma_mip = mip;
3977 
3978 		/* add the new MAC address to the head of the address list */
3979 		map->ma_next = mip->mi_addresses;
3980 		mip->mi_addresses = map;
3981 
3982 		allocated_map = B_TRUE;
3983 	}
3984 
3985 	ASSERT(map->ma_group == group);
3986 
3987 	/*
3988 	 * If the MAC address is already in use, simply account for the
3989 	 * new client.
3990 	 */
3991 	if (map->ma_nusers++ > 0)
3992 		return (0);
3993 
3994 	/*
3995 	 * Activate this MAC address by adding it to the reserved group.
3996 	 */
3997 	if (group != NULL) {
3998 		err = mac_group_addmac(group, (const uint8_t *)mac_addr);
3999 		if (err == 0) {
4000 			map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
4001 			return (0);
4002 		}
4003 	}
4004 
4005 	/*
4006 	 * The MAC address addition failed. If the client requires a
4007 	 * hardware classified MAC address, fail the operation.
4008 	 */
4009 	if (use_hw) {
4010 		err = ENOSPC;
4011 		goto bail;
4012 	}
4013 
4014 	/*
4015 	 * Try promiscuous mode.
4016 	 *
4017 	 * For drivers that don't advertise RINGS capability, do
4018 	 * nothing for the primary address.
4019 	 */
4020 	if ((group == NULL) &&
4021 	    (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0)) {
4022 		map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
4023 		return (0);
4024 	}
4025 
4026 	/*
4027 	 * Enable promiscuous mode in order to receive traffic
4028 	 * to the new MAC address.
4029 	 */
4030 	if ((err = i_mac_promisc_set(mip, B_TRUE)) == 0) {
4031 		map->ma_type = MAC_ADDRESS_TYPE_UNICAST_PROMISC;
4032 		return (0);
4033 	}
4034 
4035 	/*
4036 	 * Free the MAC address that could not be added. Don't free
4037 	 * a pre-existing address, it could have been the entry
4038 	 * for the primary MAC address which was pre-allocated by
4039 	 * mac_init_macaddr(), and which must remain on the list.
4040 	 */
4041 bail:
4042 	map->ma_nusers--;
4043 	if (allocated_map)
4044 		mac_free_macaddr(map);
4045 	return (err);
4046 }
4047 
4048 /*
4049  * Remove a reference to a MAC address. This may cause to remove the MAC
4050  * address from an associated group or to turn off promiscuous mode.
4051  * The caller needs to handle the failure properly.
4052  */
4053 int
4054 mac_remove_macaddr(mac_address_t *map)
4055 {
4056 	mac_impl_t *mip = map->ma_mip;
4057 	int err = 0;
4058 
4059 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4060 
4061 	ASSERT(map == mac_find_macaddr(mip, map->ma_addr));
4062 
4063 	/*
4064 	 * If it's not the last client using this MAC address, only update
4065 	 * the MAC clients count.
4066 	 */
4067 	if (--map->ma_nusers > 0)
4068 		return (0);
4069 
4070 	/*
4071 	 * The MAC address is no longer used by any MAC client, so remove
4072 	 * it from its associated group, or turn off promiscuous mode
4073 	 * if it was enabled for the MAC address.
4074 	 */
4075 	switch (map->ma_type) {
4076 	case MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED:
4077 		/*
4078 		 * Don't free the preset primary address for drivers that
4079 		 * don't advertise RINGS capability.
4080 		 */
4081 		if (map->ma_group == NULL)
4082 			return (0);
4083 
4084 		err = mac_group_remmac(map->ma_group, map->ma_addr);
4085 		break;
4086 	case MAC_ADDRESS_TYPE_UNICAST_PROMISC:
4087 		err = i_mac_promisc_set(mip, B_FALSE);
4088 		break;
4089 	default:
4090 		ASSERT(B_FALSE);
4091 	}
4092 
4093 	if (err != 0)
4094 		return (err);
4095 
4096 	/*
4097 	 * We created MAC address for the primary one at registration, so we
4098 	 * won't free it here. mac_fini_macaddr() will take care of it.
4099 	 */
4100 	if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) != 0)
4101 		mac_free_macaddr(map);
4102 
4103 	return (0);
4104 }
4105 
4106 /*
4107  * Update an existing MAC address. The caller need to make sure that the new
4108  * value has not been used.
4109  */
4110 int
4111 mac_update_macaddr(mac_address_t *map, uint8_t *mac_addr)
4112 {
4113 	mac_impl_t *mip = map->ma_mip;
4114 	int err = 0;
4115 
4116 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4117 	ASSERT(mac_find_macaddr(mip, mac_addr) == NULL);
4118 
4119 	switch (map->ma_type) {
4120 	case MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED:
4121 		/*
4122 		 * Update the primary address for drivers that are not
4123 		 * RINGS capable.
4124 		 */
4125 		if (map->ma_group == NULL) {
4126 			err = mip->mi_unicst(mip->mi_driver, (const uint8_t *)
4127 			    mac_addr);
4128 			if (err != 0)
4129 				return (err);
4130 			break;
4131 		}
4132 
4133 		/*
4134 		 * If this MAC address is not currently in use,
4135 		 * simply break out and update the value.
4136 		 */
4137 		if (map->ma_nusers == 0)
4138 			break;
4139 
4140 		/*
4141 		 * Need to replace the MAC address associated with a group.
4142 		 */
4143 		err = mac_group_remmac(map->ma_group, map->ma_addr);
4144 		if (err != 0)
4145 			return (err);
4146 
4147 		err = mac_group_addmac(map->ma_group, mac_addr);
4148 
4149 		/*
4150 		 * Failure hints hardware error. The MAC layer needs to
4151 		 * have error notification facility to handle this.
4152 		 * Now, simply try to restore the value.
4153 		 */
4154 		if (err != 0)
4155 			(void) mac_group_addmac(map->ma_group, map->ma_addr);
4156 
4157 		break;
4158 	case MAC_ADDRESS_TYPE_UNICAST_PROMISC:
4159 		/*
4160 		 * Need to do nothing more if in promiscuous mode.
4161 		 */
4162 		break;
4163 	default:
4164 		ASSERT(B_FALSE);
4165 	}
4166 
4167 	/*
4168 	 * Successfully replaced the MAC address.
4169 	 */
4170 	if (err == 0)
4171 		bcopy(mac_addr, map->ma_addr, map->ma_len);
4172 
4173 	return (err);
4174 }
4175 
4176 /*
4177  * Freshen the MAC address with new value. Its caller must have updated the
4178  * hardware MAC address before calling this function.
4179  * This funcitons is supposed to be used to handle the MAC address change
4180  * notification from underlying drivers.
4181  */
4182 void
4183 mac_freshen_macaddr(mac_address_t *map, uint8_t *mac_addr)
4184 {
4185 	mac_impl_t *mip = map->ma_mip;
4186 
4187 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4188 	ASSERT(mac_find_macaddr(mip, mac_addr) == NULL);
4189 
4190 	/*
4191 	 * Freshen the MAC address with new value.
4192 	 */
4193 	bcopy(mac_addr, map->ma_addr, map->ma_len);
4194 	bcopy(mac_addr, mip->mi_addr, map->ma_len);
4195 
4196 	/*
4197 	 * Update all MAC clients that share this MAC address.
4198 	 */
4199 	mac_unicast_update_clients(mip, map);
4200 }
4201 
4202 /*
4203  * Set up the primary MAC address.
4204  */
4205 void
4206 mac_init_macaddr(mac_impl_t *mip)
4207 {
4208 	mac_address_t *map;
4209 
4210 	/*
4211 	 * The reference count is initialized to zero, until it's really
4212 	 * activated.
4213 	 */
4214 	map = kmem_zalloc(sizeof (mac_address_t), KM_SLEEP);
4215 	map->ma_len = mip->mi_type->mt_addr_length;
4216 	bcopy(mip->mi_addr, map->ma_addr, map->ma_len);
4217 
4218 	/*
4219 	 * If driver advertises RINGS capability, it shouldn't have initialized
4220 	 * its primary MAC address. For other drivers, including VNIC, the
4221 	 * primary address must work after registration.
4222 	 */
4223 	if (mip->mi_rx_groups == NULL)
4224 		map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
4225 
4226 	/*
4227 	 * The primary MAC address is reserved for default group according
4228 	 * to current design.
4229 	 */
4230 	map->ma_group = mip->mi_rx_groups;
4231 	map->ma_mip = mip;
4232 
4233 	mip->mi_addresses = map;
4234 }
4235 
4236 /*
4237  * Clean up the primary MAC address. Note, only one primary MAC address
4238  * is allowed. All other MAC addresses must have been freed appropriately.
4239  */
4240 void
4241 mac_fini_macaddr(mac_impl_t *mip)
4242 {
4243 	mac_address_t *map = mip->mi_addresses;
4244 
4245 	if (map == NULL)
4246 		return;
4247 
4248 	/*
4249 	 * If mi_addresses is initialized, there should be exactly one
4250 	 * entry left on the list with no users.
4251 	 */
4252 	ASSERT(map->ma_nusers == 0);
4253 	ASSERT(map->ma_next == NULL);
4254 
4255 	kmem_free(map, sizeof (mac_address_t));
4256 	mip->mi_addresses = NULL;
4257 }
4258 
4259 /*
4260  * Logging related functions.
4261  */
4262 
4263 /* Write the Flow description to the log file */
4264 int
4265 mac_write_flow_desc(flow_entry_t *flent, mac_client_impl_t *mcip)
4266 {
4267 	flow_desc_t		*fdesc;
4268 	mac_resource_props_t	*mrp;
4269 	net_desc_t		ndesc;
4270 
4271 	bzero(&ndesc, sizeof (net_desc_t));
4272 
4273 	/*
4274 	 * Grab the fe_lock to see a self-consistent fe_flow_desc.
4275 	 * Updates to the fe_flow_desc are done under the fe_lock
4276 	 */
4277 	mutex_enter(&flent->fe_lock);
4278 	fdesc = &flent->fe_flow_desc;
4279 	mrp = &flent->fe_resource_props;
4280 
4281 	ndesc.nd_name = flent->fe_flow_name;
4282 	ndesc.nd_devname = mcip->mci_name;
4283 	bcopy(fdesc->fd_src_mac, ndesc.nd_ehost, ETHERADDRL);
4284 	bcopy(fdesc->fd_dst_mac, ndesc.nd_edest, ETHERADDRL);
4285 	ndesc.nd_sap = htonl(fdesc->fd_sap);
4286 	ndesc.nd_isv4 = (uint8_t)fdesc->fd_ipversion == IPV4_VERSION;
4287 	ndesc.nd_bw_limit = mrp->mrp_maxbw;
4288 	if (ndesc.nd_isv4) {
4289 		ndesc.nd_saddr[3] = htonl(fdesc->fd_local_addr.s6_addr32[3]);
4290 		ndesc.nd_daddr[3] = htonl(fdesc->fd_remote_addr.s6_addr32[3]);
4291 	} else {
4292 		bcopy(&fdesc->fd_local_addr, ndesc.nd_saddr, IPV6_ADDR_LEN);
4293 		bcopy(&fdesc->fd_remote_addr, ndesc.nd_daddr, IPV6_ADDR_LEN);
4294 	}
4295 	ndesc.nd_sport = htons(fdesc->fd_local_port);
4296 	ndesc.nd_dport = htons(fdesc->fd_remote_port);
4297 	ndesc.nd_protocol = (uint8_t)fdesc->fd_protocol;
4298 	mutex_exit(&flent->fe_lock);
4299 
4300 	return (exacct_commit_netinfo((void *)&ndesc, EX_NET_FLDESC_REC));
4301 }
4302 
4303 /* Write the Flow statistics to the log file */
4304 int
4305 mac_write_flow_stats(flow_entry_t *flent)
4306 {
4307 	flow_stats_t	*fl_stats;
4308 	net_stat_t	nstat;
4309 
4310 	fl_stats = &flent->fe_flowstats;
4311 	nstat.ns_name = flent->fe_flow_name;
4312 	nstat.ns_ibytes = fl_stats->fs_rbytes;
4313 	nstat.ns_obytes = fl_stats->fs_obytes;
4314 	nstat.ns_ipackets = fl_stats->fs_ipackets;
4315 	nstat.ns_opackets = fl_stats->fs_opackets;
4316 	nstat.ns_ierrors = fl_stats->fs_ierrors;
4317 	nstat.ns_oerrors = fl_stats->fs_oerrors;
4318 
4319 	return (exacct_commit_netinfo((void *)&nstat, EX_NET_FLSTAT_REC));
4320 }
4321 
4322 /* Write the Link Description to the log file */
4323 int
4324 mac_write_link_desc(mac_client_impl_t *mcip)
4325 {
4326 	net_desc_t		ndesc;
4327 	flow_entry_t		*flent = mcip->mci_flent;
4328 
4329 	bzero(&ndesc, sizeof (net_desc_t));
4330 
4331 	ndesc.nd_name = mcip->mci_name;
4332 	ndesc.nd_devname = mcip->mci_name;
4333 	ndesc.nd_isv4 = B_TRUE;
4334 	/*
4335 	 * Grab the fe_lock to see a self-consistent fe_flow_desc.
4336 	 * Updates to the fe_flow_desc are done under the fe_lock
4337 	 * after removing the flent from the flow table.
4338 	 */
4339 	mutex_enter(&flent->fe_lock);
4340 	bcopy(flent->fe_flow_desc.fd_src_mac, ndesc.nd_ehost, ETHERADDRL);
4341 	mutex_exit(&flent->fe_lock);
4342 
4343 	return (exacct_commit_netinfo((void *)&ndesc, EX_NET_LNDESC_REC));
4344 }
4345 
4346 /* Write the Link statistics to the log file */
4347 int
4348 mac_write_link_stats(mac_client_impl_t *mcip)
4349 {
4350 	net_stat_t	nstat;
4351 
4352 	nstat.ns_name = mcip->mci_name;
4353 	nstat.ns_ibytes = mcip->mci_stat_ibytes;
4354 	nstat.ns_obytes = mcip->mci_stat_obytes;
4355 	nstat.ns_ipackets = mcip->mci_stat_ipackets;
4356 	nstat.ns_opackets = mcip->mci_stat_opackets;
4357 	nstat.ns_ierrors = mcip->mci_stat_ierrors;
4358 	nstat.ns_oerrors = mcip->mci_stat_oerrors;
4359 
4360 	return (exacct_commit_netinfo((void *)&nstat, EX_NET_LNSTAT_REC));
4361 }
4362 
4363 /*
4364  * For a given flow, if the descrition has not been logged before, do it now.
4365  * If it is a VNIC, then we have collected information about it from the MAC
4366  * table, so skip it.
4367  */
4368 /*ARGSUSED*/
4369 static int
4370 mac_log_flowinfo(flow_entry_t *flent, void *args)
4371 {
4372 	mac_client_impl_t	*mcip = flent->fe_mcip;
4373 
4374 	if (mcip == NULL)
4375 		return (0);
4376 
4377 	/*
4378 	 * If the name starts with "vnic", and fe_user_generated is true (to
4379 	 * exclude the mcast and active flow entries created implicitly for
4380 	 * a vnic, it is a VNIC flow.  i.e. vnic1 is a vnic flow,
4381 	 * vnic/bge1/mcast1 is not and neither is vnic/bge1/active.
4382 	 */
4383 	if (strncasecmp(flent->fe_flow_name, "vnic", 4) == 0 &&
4384 	    (flent->fe_type & FLOW_USER) != 0) {
4385 		return (0);
4386 	}
4387 
4388 	if (!flent->fe_desc_logged) {
4389 		/*
4390 		 * We don't return error because we want to continu the
4391 		 * walk in case this is the last walk which means we
4392 		 * need to reset fe_desc_logged in all the flows.
4393 		 */
4394 		if (mac_write_flow_desc(flent, mcip) != 0)
4395 			return (0);
4396 		flent->fe_desc_logged = B_TRUE;
4397 	}
4398 
4399 	/*
4400 	 * Regardless of the error, we want to proceed in case we have to
4401 	 * reset fe_desc_logged.
4402 	 */
4403 	(void) mac_write_flow_stats(flent);
4404 
4405 	if (mcip != NULL && !(mcip->mci_state_flags & MCIS_DESC_LOGGED))
4406 		flent->fe_desc_logged = B_FALSE;
4407 
4408 	return (0);
4409 }
4410 
4411 typedef struct i_mac_log_state_s {
4412 	boolean_t	mi_last;
4413 	int		mi_fenable;
4414 	int		mi_lenable;
4415 } i_mac_log_state_t;
4416 
4417 /*
4418  * Walk the mac_impl_ts and log the description for each mac client of this mac,
4419  * if it hasn't already been done. Additionally, log statistics for the link as
4420  * well. Walk the flow table and log information for each flow as well.
4421  * If it is the last walk (mci_last), then we turn off mci_desc_logged (and
4422  * also fe_desc_logged, if flow logging is on) since we want to log the
4423  * description if and when logging is restarted.
4424  */
4425 /*ARGSUSED*/
4426 static uint_t
4427 i_mac_log_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
4428 {
4429 	mac_impl_t		*mip = (mac_impl_t *)val;
4430 	i_mac_log_state_t	*lstate = (i_mac_log_state_t *)arg;
4431 	int			ret;
4432 	mac_client_impl_t	*mcip;
4433 
4434 	/*
4435 	 * Only walk the client list for NIC and etherstub
4436 	 */
4437 	if ((mip->mi_state_flags & MIS_DISABLED) ||
4438 	    ((mip->mi_state_flags & MIS_IS_VNIC) &&
4439 	    (mac_get_lower_mac_handle((mac_handle_t)mip) != NULL)))
4440 		return (MH_WALK_CONTINUE);
4441 
4442 	for (mcip = mip->mi_clients_list; mcip != NULL;
4443 	    mcip = mcip->mci_client_next) {
4444 		if (!MCIP_DATAPATH_SETUP(mcip))
4445 			continue;
4446 		if (lstate->mi_lenable) {
4447 			if (!(mcip->mci_state_flags & MCIS_DESC_LOGGED)) {
4448 				ret = mac_write_link_desc(mcip);
4449 				if (ret != 0) {
4450 				/*
4451 				 * We can't terminate it if this is the last
4452 				 * walk, else there might be some links with
4453 				 * mi_desc_logged set to true, which means
4454 				 * their description won't be logged the next
4455 				 * time logging is started (similarly for the
4456 				 * flows within such links). We can continue
4457 				 * without walking the flow table (i.e. to
4458 				 * set fe_desc_logged to false) because we
4459 				 * won't have written any flow stuff for this
4460 				 * link as we haven't logged the link itself.
4461 				 */
4462 					if (lstate->mi_last)
4463 						return (MH_WALK_CONTINUE);
4464 					else
4465 						return (MH_WALK_TERMINATE);
4466 				}
4467 				mcip->mci_state_flags |= MCIS_DESC_LOGGED;
4468 			}
4469 		}
4470 
4471 		if (mac_write_link_stats(mcip) != 0 && !lstate->mi_last)
4472 			return (MH_WALK_TERMINATE);
4473 
4474 		if (lstate->mi_last)
4475 			mcip->mci_state_flags &= ~MCIS_DESC_LOGGED;
4476 
4477 		if (lstate->mi_fenable) {
4478 			if (mcip->mci_subflow_tab != NULL) {
4479 				(void) mac_flow_walk(mcip->mci_subflow_tab,
4480 				    mac_log_flowinfo, mip);
4481 			}
4482 		}
4483 	}
4484 	return (MH_WALK_CONTINUE);
4485 }
4486 
4487 /*
4488  * The timer thread that runs every mac_logging_interval seconds and logs
4489  * link and/or flow information.
4490  */
4491 /* ARGSUSED */
4492 void
4493 mac_log_linkinfo(void *arg)
4494 {
4495 	i_mac_log_state_t	lstate;
4496 
4497 	rw_enter(&i_mac_impl_lock, RW_READER);
4498 	if (!mac_flow_log_enable && !mac_link_log_enable) {
4499 		rw_exit(&i_mac_impl_lock);
4500 		return;
4501 	}
4502 	lstate.mi_fenable = mac_flow_log_enable;
4503 	lstate.mi_lenable = mac_link_log_enable;
4504 	lstate.mi_last = B_FALSE;
4505 	rw_exit(&i_mac_impl_lock);
4506 
4507 	mod_hash_walk(i_mac_impl_hash, i_mac_log_walker, &lstate);
4508 
4509 	rw_enter(&i_mac_impl_lock, RW_WRITER);
4510 	if (mac_flow_log_enable || mac_link_log_enable) {
4511 		mac_logging_timer = timeout(mac_log_linkinfo, NULL,
4512 		    SEC_TO_TICK(mac_logging_interval));
4513 	}
4514 	rw_exit(&i_mac_impl_lock);
4515 }
4516 
4517 typedef struct i_mac_fastpath_state_s {
4518 	boolean_t	mf_disable;
4519 	int		mf_err;
4520 } i_mac_fastpath_state_t;
4521 
4522 /*ARGSUSED*/
4523 static uint_t
4524 i_mac_fastpath_disable_walker(mod_hash_key_t key, mod_hash_val_t *val,
4525     void *arg)
4526 {
4527 	i_mac_fastpath_state_t	*state = arg;
4528 	mac_handle_t		mh = (mac_handle_t)val;
4529 
4530 	if (state->mf_disable)
4531 		state->mf_err = mac_fastpath_disable(mh);
4532 	else
4533 		mac_fastpath_enable(mh);
4534 
4535 	return (state->mf_err == 0 ? MH_WALK_CONTINUE : MH_WALK_TERMINATE);
4536 }
4537 
4538 /*
4539  * Start the logging timer.
4540  */
4541 int
4542 mac_start_logusage(mac_logtype_t type, uint_t interval)
4543 {
4544 	i_mac_fastpath_state_t state = {B_TRUE, 0};
4545 	int err;
4546 
4547 	rw_enter(&i_mac_impl_lock, RW_WRITER);
4548 	switch (type) {
4549 	case MAC_LOGTYPE_FLOW:
4550 		if (mac_flow_log_enable) {
4551 			rw_exit(&i_mac_impl_lock);
4552 			return (0);
4553 		}
4554 		/* FALLTHRU */
4555 	case MAC_LOGTYPE_LINK:
4556 		if (mac_link_log_enable) {
4557 			rw_exit(&i_mac_impl_lock);
4558 			return (0);
4559 		}
4560 		break;
4561 	default:
4562 		ASSERT(0);
4563 	}
4564 
4565 	/* Disable fastpath */
4566 	mod_hash_walk(i_mac_impl_hash, i_mac_fastpath_disable_walker, &state);
4567 	if ((err = state.mf_err) != 0) {
4568 		/* Reenable fastpath  */
4569 		state.mf_disable = B_FALSE;
4570 		state.mf_err = 0;
4571 		mod_hash_walk(i_mac_impl_hash,
4572 		    i_mac_fastpath_disable_walker, &state);
4573 		rw_exit(&i_mac_impl_lock);
4574 		return (err);
4575 	}
4576 
4577 	switch (type) {
4578 	case MAC_LOGTYPE_FLOW:
4579 		mac_flow_log_enable = B_TRUE;
4580 		/* FALLTHRU */
4581 	case MAC_LOGTYPE_LINK:
4582 		mac_link_log_enable = B_TRUE;
4583 		break;
4584 	}
4585 
4586 	mac_logging_interval = interval;
4587 	rw_exit(&i_mac_impl_lock);
4588 	mac_log_linkinfo(NULL);
4589 	return (0);
4590 }
4591 
4592 /*
4593  * Stop the logging timer if both Link and Flow logging are turned off.
4594  */
4595 void
4596 mac_stop_logusage(mac_logtype_t type)
4597 {
4598 	i_mac_log_state_t	lstate;
4599 	i_mac_fastpath_state_t	state = {B_FALSE, 0};
4600 
4601 	rw_enter(&i_mac_impl_lock, RW_WRITER);
4602 	lstate.mi_fenable = mac_flow_log_enable;
4603 	lstate.mi_lenable = mac_link_log_enable;
4604 
4605 	/* Last walk */
4606 	lstate.mi_last = B_TRUE;
4607 
4608 	switch (type) {
4609 	case MAC_LOGTYPE_FLOW:
4610 		if (lstate.mi_fenable) {
4611 			ASSERT(mac_link_log_enable);
4612 			mac_flow_log_enable = B_FALSE;
4613 			mac_link_log_enable = B_FALSE;
4614 			break;
4615 		}
4616 		/* FALLTHRU */
4617 	case MAC_LOGTYPE_LINK:
4618 		if (!lstate.mi_lenable || mac_flow_log_enable) {
4619 			rw_exit(&i_mac_impl_lock);
4620 			return;
4621 		}
4622 		mac_link_log_enable = B_FALSE;
4623 		break;
4624 	default:
4625 		ASSERT(0);
4626 	}
4627 
4628 	/* Reenable fastpath */
4629 	mod_hash_walk(i_mac_impl_hash, i_mac_fastpath_disable_walker, &state);
4630 
4631 	rw_exit(&i_mac_impl_lock);
4632 	(void) untimeout(mac_logging_timer);
4633 	mac_logging_timer = 0;
4634 
4635 	/* Last walk */
4636 	mod_hash_walk(i_mac_impl_hash, i_mac_log_walker, &lstate);
4637 }
4638 
4639 /*
4640  * Walk the rx and tx SRS/SRs for a flow and update the priority value.
4641  */
4642 void
4643 mac_flow_update_priority(mac_client_impl_t *mcip, flow_entry_t *flent)
4644 {
4645 	pri_t			pri;
4646 	int			count;
4647 	mac_soft_ring_set_t	*mac_srs;
4648 
4649 	if (flent->fe_rx_srs_cnt <= 0)
4650 		return;
4651 
4652 	if (((mac_soft_ring_set_t *)flent->fe_rx_srs[0])->srs_type ==
4653 	    SRST_FLOW) {
4654 		pri = FLOW_PRIORITY(mcip->mci_min_pri,
4655 		    mcip->mci_max_pri,
4656 		    flent->fe_resource_props.mrp_priority);
4657 	} else {
4658 		pri = mcip->mci_max_pri;
4659 	}
4660 
4661 	for (count = 0; count < flent->fe_rx_srs_cnt; count++) {
4662 		mac_srs = flent->fe_rx_srs[count];
4663 		mac_update_srs_priority(mac_srs, pri);
4664 	}
4665 	/*
4666 	 * If we have a Tx SRS, we need to modify all the threads associated
4667 	 * with it.
4668 	 */
4669 	if (flent->fe_tx_srs != NULL)
4670 		mac_update_srs_priority(flent->fe_tx_srs, pri);
4671 }
4672 
4673 /*
4674  * RX and TX rings are reserved according to different semantics depending
4675  * on the requests from the MAC clients and type of rings:
4676  *
4677  * On the Tx side, by default we reserve individual rings, independently from
4678  * the groups.
4679  *
4680  * On the Rx side, the reservation is at the granularity of the group
4681  * of rings, and used for v12n level 1 only. It has a special case for the
4682  * primary client.
4683  *
4684  * If a share is allocated to a MAC client, we allocate a TX group and an
4685  * RX group to the client, and assign TX rings and RX rings to these
4686  * groups according to information gathered from the driver through
4687  * the share capability.
4688  *
4689  * The foreseable evolution of Rx rings will handle v12n level 2 and higher
4690  * to allocate individual rings out of a group and program the hw classifier
4691  * based on IP address or higher level criteria.
4692  */
4693 
4694 /*
4695  * mac_reserve_tx_ring()
4696  * Reserve a unused ring by marking it with MR_INUSE state.
4697  * As reserved, the ring is ready to function.
4698  *
4699  * Notes for Hybrid I/O:
4700  *
4701  * If a specific ring is needed, it is specified through the desired_ring
4702  * argument. Otherwise that argument is set to NULL.
4703  * If the desired ring was previous allocated to another client, this
4704  * function swaps it with a new ring from the group of unassigned rings.
4705  */
4706 mac_ring_t *
4707 mac_reserve_tx_ring(mac_impl_t *mip, mac_ring_t *desired_ring)
4708 {
4709 	mac_group_t *group;
4710 	mac_ring_t *ring;
4711 
4712 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4713 
4714 	if (mip->mi_tx_groups == NULL)
4715 		return (NULL);
4716 
4717 	/*
4718 	 * Find an available ring and start it before changing its status.
4719 	 * The unassigned rings are at the end of the mi_tx_groups
4720 	 * array.
4721 	 */
4722 	group = mip->mi_tx_groups + mip->mi_tx_group_count;
4723 
4724 	for (ring = group->mrg_rings; ring != NULL;
4725 	    ring = ring->mr_next) {
4726 		if (desired_ring == NULL) {
4727 			if (ring->mr_state == MR_FREE)
4728 				/* wanted any free ring and found one */
4729 				break;
4730 		} else {
4731 			mac_ring_t *sring;
4732 			mac_client_impl_t *client;
4733 			mac_soft_ring_set_t *srs;
4734 
4735 			if (ring != desired_ring)
4736 				/* wants a desired ring but this one ain't it */
4737 				continue;
4738 
4739 			if (ring->mr_state == MR_FREE)
4740 				break;
4741 
4742 			/*
4743 			 * Found the desired ring but it's already in use.
4744 			 * Swap it with a new ring.
4745 			 */
4746 
4747 			/* find the client which owns that ring */
4748 			for (client = mip->mi_clients_list; client != NULL;
4749 			    client = client->mci_client_next) {
4750 				srs = MCIP_TX_SRS(client);
4751 				if (srs != NULL && mac_tx_srs_ring_present(srs,
4752 				    desired_ring)) {
4753 					/* found our ring */
4754 					break;
4755 				}
4756 			}
4757 			if (client == NULL) {
4758 				/*
4759 				 * The TX ring is in use, but it's not
4760 				 * associated with any clients, so it
4761 				 * has to be the default ring. In that
4762 				 * case we can simply assign a new ring
4763 				 * as the default ring, and we're done.
4764 				 */
4765 				ASSERT(mip->mi_default_tx_ring ==
4766 				    (mac_ring_handle_t)desired_ring);
4767 
4768 				/*
4769 				 * Quiesce all clients on top of
4770 				 * the NIC to make sure there are no
4771 				 * pending threads still relying on
4772 				 * that default ring, for example
4773 				 * the multicast path.
4774 				 */
4775 				for (client = mip->mi_clients_list;
4776 				    client != NULL;
4777 				    client = client->mci_client_next) {
4778 					mac_tx_client_quiesce(client,
4779 					    SRS_QUIESCE);
4780 				}
4781 
4782 				mip->mi_default_tx_ring = (mac_ring_handle_t)
4783 				    mac_reserve_tx_ring(mip, NULL);
4784 
4785 				/* resume the clients */
4786 				for (client = mip->mi_clients_list;
4787 				    client != NULL;
4788 				    client = client->mci_client_next)
4789 					mac_tx_client_restart(client);
4790 
4791 				break;
4792 			}
4793 
4794 			/*
4795 			 * Note that we cannot simply invoke the group
4796 			 * add/rem routines since the client doesn't have a
4797 			 * TX group. So we need to instead add/remove
4798 			 * the rings from the SRS.
4799 			 */
4800 			ASSERT(client->mci_share == NULL);
4801 
4802 			/* first quiece the client */
4803 			mac_tx_client_quiesce(client, SRS_QUIESCE);
4804 
4805 			/* give a new ring to the client... */
4806 			sring = mac_reserve_tx_ring(mip, NULL);
4807 			if (sring != NULL) {
4808 				/*
4809 				 * There are no other available ring
4810 				 * on that MAC instance. The client
4811 				 * will fallback to the shared TX
4812 				 * ring.
4813 				 */
4814 				mac_tx_srs_add_ring(srs, sring);
4815 			}
4816 
4817 			/* ... in exchange for our desired ring */
4818 			mac_tx_srs_del_ring(srs, desired_ring);
4819 
4820 			/* restart the client */
4821 			mac_tx_client_restart(client);
4822 
4823 			if (mip->mi_default_tx_ring ==
4824 			    (mac_ring_handle_t)desired_ring) {
4825 				/*
4826 				 * The desired ring is the default ring,
4827 				 * and there are one or more clients
4828 				 * using that default ring directly.
4829 				 */
4830 				mip->mi_default_tx_ring =
4831 				    (mac_ring_handle_t)sring;
4832 				/*
4833 				 * Find clients using default ring and
4834 				 * swap it with the new default ring.
4835 				 */
4836 				for (client = mip->mi_clients_list;
4837 				    client != NULL;
4838 				    client = client->mci_client_next) {
4839 					srs = MCIP_TX_SRS(client);
4840 					if (srs != NULL &&
4841 					    mac_tx_srs_ring_present(srs,
4842 					    desired_ring)) {
4843 						/* first quiece the client */
4844 						mac_tx_client_quiesce(client,
4845 						    SRS_QUIESCE);
4846 
4847 						/*
4848 						 * Give it the new default
4849 						 * ring, and remove the old
4850 						 * one.
4851 						 */
4852 						if (sring != NULL) {
4853 							mac_tx_srs_add_ring(srs,
4854 							    sring);
4855 						}
4856 						mac_tx_srs_del_ring(srs,
4857 						    desired_ring);
4858 
4859 						/* restart the client */
4860 						mac_tx_client_restart(client);
4861 					}
4862 				}
4863 			}
4864 			break;
4865 		}
4866 	}
4867 
4868 	if (ring != NULL) {
4869 		if (mac_start_ring(ring) != 0)
4870 			return (NULL);
4871 		ring->mr_state = MR_INUSE;
4872 	}
4873 
4874 	return (ring);
4875 }
4876 
4877 /*
4878  * Minimum number of rings to leave in the default TX group when allocating
4879  * rings to new clients.
4880  */
4881 static uint_t mac_min_rx_default_rings = 1;
4882 
4883 /*
4884  * Populate a zero-ring group with rings. If the share is non-NULL,
4885  * the rings are chosen according to that share.
4886  * Invoked after allocating a new RX or TX group through
4887  * mac_reserve_rx_group() or mac_reserve_tx_group(), respectively.
4888  * Returns zero on success, an errno otherwise.
4889  */
4890 int
4891 i_mac_group_allocate_rings(mac_impl_t *mip, mac_ring_type_t ring_type,
4892     mac_group_t *src_group, mac_group_t *new_group, mac_share_handle_t share)
4893 {
4894 	mac_ring_t **rings, *tmp_ring[1], *ring;
4895 	uint_t nrings;
4896 	int rv, i, j;
4897 
4898 	ASSERT(mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC &&
4899 	    mip->mi_tx_group_type == MAC_GROUP_TYPE_DYNAMIC);
4900 	ASSERT(new_group->mrg_cur_count == 0);
4901 
4902 	/*
4903 	 * First find the rings to allocate to the group.
4904 	 */
4905 	if (share != NULL) {
4906 		/* get rings through ms_squery() */
4907 		mip->mi_share_capab.ms_squery(share, ring_type, NULL, &nrings);
4908 		ASSERT(nrings != 0);
4909 		rings = kmem_alloc(nrings * sizeof (mac_ring_handle_t),
4910 		    KM_SLEEP);
4911 		mip->mi_share_capab.ms_squery(share, ring_type,
4912 		    (mac_ring_handle_t *)rings, &nrings);
4913 	} else {
4914 		/* this function is called for TX only with a share */
4915 		ASSERT(ring_type == MAC_RING_TYPE_RX);
4916 		/*
4917 		 * Pick one ring from default group.
4918 		 *
4919 		 * for now pick the second ring which requires the first ring
4920 		 * at index 0 to stay in the default group, since it is the
4921 		 * ring which carries the multicast traffic.
4922 		 * We need a better way for a driver to indicate this,
4923 		 * for example a per-ring flag.
4924 		 */
4925 		for (ring = src_group->mrg_rings; ring != NULL;
4926 		    ring = ring->mr_next) {
4927 			if (ring->mr_index != 0)
4928 				break;
4929 		}
4930 		ASSERT(ring != NULL);
4931 		nrings = 1;
4932 		tmp_ring[0] = ring;
4933 		rings = tmp_ring;
4934 	}
4935 
4936 	switch (ring_type) {
4937 	case MAC_RING_TYPE_RX:
4938 		if (src_group->mrg_cur_count - nrings <
4939 		    mac_min_rx_default_rings) {
4940 			/* we ran out of rings */
4941 			return (ENOSPC);
4942 		}
4943 
4944 		/* move receive rings to new group */
4945 		for (i = 0; i < nrings; i++) {
4946 			rv = mac_group_mov_ring(mip, new_group, rings[i]);
4947 			if (rv != 0) {
4948 				/* move rings back on failure */
4949 				for (j = 0; j < i; j++) {
4950 					(void) mac_group_mov_ring(mip,
4951 					    src_group, rings[j]);
4952 				}
4953 				return (rv);
4954 			}
4955 		}
4956 		break;
4957 
4958 	case MAC_RING_TYPE_TX: {
4959 		mac_ring_t *tmp_ring;
4960 
4961 		/* move the TX rings to the new group */
4962 		ASSERT(src_group == NULL);
4963 		for (i = 0; i < nrings; i++) {
4964 			/* get the desired ring */
4965 			tmp_ring = mac_reserve_tx_ring(mip, rings[i]);
4966 			ASSERT(tmp_ring == rings[i]);
4967 			rv = mac_group_mov_ring(mip, new_group, rings[i]);
4968 			if (rv != 0) {
4969 				/* cleanup on failure */
4970 				for (j = 0; j < i; j++) {
4971 					(void) mac_group_mov_ring(mip,
4972 					    mip->mi_tx_groups +
4973 					    mip->mi_tx_group_count, rings[j]);
4974 				}
4975 			}
4976 		}
4977 		break;
4978 	}
4979 	}
4980 
4981 	if (share != NULL) {
4982 		/* add group to share */
4983 		mip->mi_share_capab.ms_sadd(share, new_group->mrg_driver);
4984 		/* free temporary array of rings */
4985 		kmem_free(rings, nrings * sizeof (mac_ring_handle_t));
4986 	}
4987 
4988 	return (0);
4989 }
4990 
4991 void
4992 mac_rx_group_add_client(mac_group_t *grp, mac_client_impl_t *mcip)
4993 {
4994 	mac_grp_client_t *mgcp;
4995 
4996 	for (mgcp = grp->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
4997 		if (mgcp->mgc_client == mcip)
4998 			break;
4999 	}
5000 
5001 	VERIFY(mgcp == NULL);
5002 
5003 	mgcp = kmem_zalloc(sizeof (mac_grp_client_t), KM_SLEEP);
5004 	mgcp->mgc_client = mcip;
5005 	mgcp->mgc_next = grp->mrg_clients;
5006 	grp->mrg_clients = mgcp;
5007 
5008 }
5009 
5010 void
5011 mac_rx_group_remove_client(mac_group_t *grp, mac_client_impl_t *mcip)
5012 {
5013 	mac_grp_client_t *mgcp, **pprev;
5014 
5015 	for (pprev = &grp->mrg_clients, mgcp = *pprev; mgcp != NULL;
5016 	    pprev = &mgcp->mgc_next, mgcp = *pprev) {
5017 		if (mgcp->mgc_client == mcip)
5018 			break;
5019 	}
5020 
5021 	ASSERT(mgcp != NULL);
5022 
5023 	*pprev = mgcp->mgc_next;
5024 	kmem_free(mgcp, sizeof (mac_grp_client_t));
5025 }
5026 
5027 /*
5028  * mac_reserve_rx_group()
5029  *
5030  * Finds an available group and exclusively reserves it for a client.
5031  * The group is chosen to suit the flow's resource controls (bandwidth and
5032  * fanout requirements) and the address type.
5033  * If the requestor is the pimary MAC then return the group with the
5034  * largest number of rings, otherwise the default ring when available.
5035  */
5036 mac_group_t *
5037 mac_reserve_rx_group(mac_client_impl_t *mcip, uint8_t *mac_addr,
5038     mac_rx_group_reserve_type_t rtype)
5039 {
5040 	mac_share_handle_t	share = mcip->mci_share;
5041 	mac_impl_t		*mip = mcip->mci_mip;
5042 	mac_group_t		*grp = NULL;
5043 	int			i, start, loopcount;
5044 	int			err;
5045 	mac_address_t		*map;
5046 
5047 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
5048 
5049 	/* Check if a group already has this mac address (case of VLANs) */
5050 	if ((map = mac_find_macaddr(mip, mac_addr)) != NULL)
5051 		return (map->ma_group);
5052 
5053 	if (mip->mi_rx_groups == NULL || mip->mi_rx_group_count == 0 ||
5054 	    rtype == MAC_RX_NO_RESERVE)
5055 		return (NULL);
5056 
5057 	/*
5058 	 * Try to exclusively reserve a RX group.
5059 	 *
5060 	 * For flows requires SW_RING it always goes to the default group
5061 	 * (Until we can explicitely call out default groups (CR 6695600),
5062 	 * we assume that the default group is always at position zero);
5063 	 *
5064 	 * For flows requires HW_DEFAULT_RING (unicast flow of the primary
5065 	 * client), try to reserve the default RX group only.
5066 	 *
5067 	 * For flows requires HW_RING (unicast flow of other clients), try
5068 	 * to reserve non-default RX group then the default group.
5069 	 */
5070 	switch (rtype) {
5071 	case MAC_RX_RESERVE_DEFAULT:
5072 		start = 0;
5073 		loopcount = 1;
5074 		break;
5075 	case MAC_RX_RESERVE_NONDEFAULT:
5076 		start = 1;
5077 		loopcount = mip->mi_rx_group_count;
5078 	}
5079 
5080 	for (i = start; i < start + loopcount; i++) {
5081 		grp = &mip->mi_rx_groups[i % mip->mi_rx_group_count];
5082 
5083 		DTRACE_PROBE3(rx__group__trying, char *, mip->mi_name,
5084 		    int, grp->mrg_index, mac_group_state_t, grp->mrg_state);
5085 
5086 		/*
5087 		 * Check to see whether this mac client is the only client
5088 		 * on this RX group. If not, we cannot exclusively reserve
5089 		 * this RX group.
5090 		 */
5091 		if (!MAC_RX_GROUP_NO_CLIENT(grp) &&
5092 		    (MAC_RX_GROUP_ONLY_CLIENT(grp) != mcip)) {
5093 			continue;
5094 		}
5095 
5096 		/*
5097 		 * This group could already be SHARED by other multicast
5098 		 * flows on this client. In that case, the group would
5099 		 * be shared and has already been started.
5100 		 */
5101 		ASSERT(grp->mrg_state != MAC_GROUP_STATE_UNINIT);
5102 
5103 		if ((grp->mrg_state == MAC_GROUP_STATE_REGISTERED) &&
5104 		    (mac_start_group(grp) != 0)) {
5105 			continue;
5106 		}
5107 
5108 		if ((i % mip->mi_rx_group_count) == 0 ||
5109 		    mip->mi_rx_group_type != MAC_GROUP_TYPE_DYNAMIC) {
5110 			break;
5111 		}
5112 
5113 		ASSERT(grp->mrg_cur_count == 0);
5114 
5115 		/*
5116 		 * Populate the group. Rings should be taken
5117 		 * from the default group at position 0 for now.
5118 		 */
5119 
5120 		err = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_RX,
5121 		    &mip->mi_rx_groups[0], grp, share);
5122 		if (err == 0)
5123 			break;
5124 
5125 		DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
5126 		    mip->mi_name, int, grp->mrg_index, int, err);
5127 
5128 		/*
5129 		 * It's a dynamic group but the grouping operation failed.
5130 		 */
5131 		mac_stop_group(grp);
5132 	}
5133 
5134 	if (i == start + loopcount)
5135 		return (NULL);
5136 
5137 	ASSERT(grp != NULL);
5138 
5139 	DTRACE_PROBE2(rx__group__reserved,
5140 	    char *, mip->mi_name, int, grp->mrg_index);
5141 	return (grp);
5142 }
5143 
5144 /*
5145  * mac_rx_release_group()
5146  *
5147  * This is called when there are no clients left for the group.
5148  * The group is stopped and marked MAC_GROUP_STATE_REGISTERED,
5149  * and if it is a non default group, the shares are removed and
5150  * all rings are assigned back to default group.
5151  */
5152 void
5153 mac_release_rx_group(mac_client_impl_t *mcip, mac_group_t *group)
5154 {
5155 	mac_impl_t	*mip = mcip->mci_mip;
5156 	mac_ring_t	*ring;
5157 
5158 	ASSERT(group != &mip->mi_rx_groups[0]);
5159 
5160 	/*
5161 	 * This is the case where there are no clients left. Any
5162 	 * SRS etc on this group have also be quiesced.
5163 	 */
5164 	for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
5165 		if (ring->mr_classify_type == MAC_HW_CLASSIFIER) {
5166 			ASSERT(group->mrg_state == MAC_GROUP_STATE_RESERVED);
5167 			/*
5168 			 * Remove the SRS associated with the HW ring.
5169 			 * As a result, polling will be disabled.
5170 			 */
5171 			ring->mr_srs = NULL;
5172 		}
5173 		ASSERT(ring->mr_state == MR_INUSE);
5174 		mac_stop_ring(ring);
5175 		ring->mr_state = MR_FREE;
5176 		ring->mr_flag = 0;
5177 	}
5178 
5179 	/* remove group from share */
5180 	if (mcip->mci_share != NULL) {
5181 		mip->mi_share_capab.ms_sremove(mcip->mci_share,
5182 		    group->mrg_driver);
5183 	}
5184 
5185 	if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
5186 		mac_ring_t *ring;
5187 
5188 		/*
5189 		 * Rings were dynamically allocated to group.
5190 		 * Move rings back to default group.
5191 		 */
5192 		while ((ring = group->mrg_rings) != NULL) {
5193 			(void) mac_group_mov_ring(mip,
5194 			    &mip->mi_rx_groups[0], ring);
5195 		}
5196 	}
5197 	mac_stop_group(group);
5198 	/*
5199 	 * Possible improvement: See if we can assign the group just released
5200 	 * to a another client of the mip
5201 	 */
5202 }
5203 
5204 /*
5205  * Reserves a TX group for the specified share. Invoked by mac_tx_srs_setup()
5206  * when a share was allocated to the client.
5207  */
5208 mac_group_t *
5209 mac_reserve_tx_group(mac_impl_t *mip, mac_share_handle_t share)
5210 {
5211 	mac_group_t *grp;
5212 	int rv, i;
5213 
5214 	/*
5215 	 * TX groups are currently allocated only to MAC clients
5216 	 * which are associated with a share. Since we have a fixed
5217 	 * number of share and groups, and we already successfully
5218 	 * allocated a share, find an available TX group.
5219 	 */
5220 	ASSERT(share != NULL);
5221 	ASSERT(mip->mi_tx_group_free > 0);
5222 
5223 	for (i = 0; i <  mip->mi_tx_group_count; i++) {
5224 		grp = &mip->mi_tx_groups[i];
5225 
5226 		if ((grp->mrg_state == MAC_GROUP_STATE_RESERVED) ||
5227 		    (grp->mrg_state == MAC_GROUP_STATE_UNINIT))
5228 			continue;
5229 
5230 		rv = mac_start_group(grp);
5231 		ASSERT(rv == 0);
5232 
5233 		grp->mrg_state = MAC_GROUP_STATE_RESERVED;
5234 		break;
5235 	}
5236 
5237 	ASSERT(grp != NULL);
5238 
5239 	/*
5240 	 * Populate the group. Rings should be taken from the group
5241 	 * of unassigned rings, which is past the array of TX
5242 	 * groups adversized by the driver.
5243 	 */
5244 	rv = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_TX, NULL,
5245 	    grp, share);
5246 	if (rv != 0) {
5247 		DTRACE_PROBE3(tx__group__reserve__alloc__rings,
5248 		    char *, mip->mi_name, int, grp->mrg_index, int, rv);
5249 
5250 		mac_stop_group(grp);
5251 		grp->mrg_state = MAC_GROUP_STATE_UNINIT;
5252 
5253 		return (NULL);
5254 	}
5255 
5256 	mip->mi_tx_group_free--;
5257 
5258 	return (grp);
5259 }
5260 
5261 void
5262 mac_release_tx_group(mac_impl_t *mip, mac_group_t *grp)
5263 {
5264 	mac_client_impl_t *mcip = grp->mrg_tx_client;
5265 	mac_share_handle_t share = mcip->mci_share;
5266 	mac_ring_t *ring;
5267 
5268 	ASSERT(mip->mi_tx_group_type == MAC_GROUP_TYPE_DYNAMIC);
5269 	ASSERT(share != NULL);
5270 	ASSERT(grp->mrg_state == MAC_GROUP_STATE_RESERVED);
5271 
5272 	mip->mi_share_capab.ms_sremove(share, grp->mrg_driver);
5273 	while ((ring = grp->mrg_rings) != NULL) {
5274 		/* move the ring back to the pool */
5275 		(void) mac_group_mov_ring(mip, mip->mi_tx_groups +
5276 		    mip->mi_tx_group_count, ring);
5277 	}
5278 	mac_stop_group(grp);
5279 	mac_set_rx_group_state(grp, MAC_GROUP_STATE_REGISTERED);
5280 	grp->mrg_tx_client = NULL;
5281 	mip->mi_tx_group_free++;
5282 }
5283 
5284 /*
5285  * This is a 1-time control path activity initiated by the client (IP).
5286  * The mac perimeter protects against other simultaneous control activities,
5287  * for example an ioctl that attempts to change the degree of fanout and
5288  * increase or decrease the number of softrings associated with this Tx SRS.
5289  */
5290 static mac_tx_notify_cb_t *
5291 mac_client_tx_notify_add(mac_client_impl_t *mcip,
5292     mac_tx_notify_t notify, void *arg)
5293 {
5294 	mac_cb_info_t *mcbi;
5295 	mac_tx_notify_cb_t *mtnfp;
5296 
5297 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5298 
5299 	mtnfp = kmem_zalloc(sizeof (mac_tx_notify_cb_t), KM_SLEEP);
5300 	mtnfp->mtnf_fn = notify;
5301 	mtnfp->mtnf_arg = arg;
5302 	mtnfp->mtnf_link.mcb_objp = mtnfp;
5303 	mtnfp->mtnf_link.mcb_objsize = sizeof (mac_tx_notify_cb_t);
5304 	mtnfp->mtnf_link.mcb_flags = MCB_TX_NOTIFY_CB_T;
5305 
5306 	mcbi = &mcip->mci_tx_notify_cb_info;
5307 	mutex_enter(mcbi->mcbi_lockp);
5308 	mac_callback_add(mcbi, &mcip->mci_tx_notify_cb_list, &mtnfp->mtnf_link);
5309 	mutex_exit(mcbi->mcbi_lockp);
5310 	return (mtnfp);
5311 }
5312 
5313 static void
5314 mac_client_tx_notify_remove(mac_client_impl_t *mcip, mac_tx_notify_cb_t *mtnfp)
5315 {
5316 	mac_cb_info_t	*mcbi;
5317 	mac_cb_t	**cblist;
5318 
5319 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5320 
5321 	if (!mac_callback_find(&mcip->mci_tx_notify_cb_info,
5322 	    &mcip->mci_tx_notify_cb_list, &mtnfp->mtnf_link)) {
5323 		cmn_err(CE_WARN,
5324 		    "mac_client_tx_notify_remove: callback not "
5325 		    "found, mcip 0x%p mtnfp 0x%p", (void *)mcip, (void *)mtnfp);
5326 		return;
5327 	}
5328 
5329 	mcbi = &mcip->mci_tx_notify_cb_info;
5330 	cblist = &mcip->mci_tx_notify_cb_list;
5331 	mutex_enter(mcbi->mcbi_lockp);
5332 	if (mac_callback_remove(mcbi, cblist, &mtnfp->mtnf_link))
5333 		kmem_free(mtnfp, sizeof (mac_tx_notify_cb_t));
5334 	else
5335 		mac_callback_remove_wait(&mcip->mci_tx_notify_cb_info);
5336 	mutex_exit(mcbi->mcbi_lockp);
5337 }
5338 
5339 /*
5340  * mac_client_tx_notify():
5341  * call to add and remove flow control callback routine.
5342  */
5343 mac_tx_notify_handle_t
5344 mac_client_tx_notify(mac_client_handle_t mch, mac_tx_notify_t callb_func,
5345     void *ptr)
5346 {
5347 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
5348 	mac_tx_notify_cb_t	*mtnfp = NULL;
5349 
5350 	i_mac_perim_enter(mcip->mci_mip);
5351 
5352 	if (callb_func != NULL) {
5353 		/* Add a notify callback */
5354 		mtnfp = mac_client_tx_notify_add(mcip, callb_func, ptr);
5355 	} else {
5356 		mac_client_tx_notify_remove(mcip, (mac_tx_notify_cb_t *)ptr);
5357 	}
5358 	i_mac_perim_exit(mcip->mci_mip);
5359 
5360 	return ((mac_tx_notify_handle_t)mtnfp);
5361 }
5362 
5363 void
5364 mac_bridge_vectors(mac_bridge_tx_t txf, mac_bridge_rx_t rxf,
5365     mac_bridge_ref_t reff, mac_bridge_ls_t lsf)
5366 {
5367 	mac_bridge_tx_cb = txf;
5368 	mac_bridge_rx_cb = rxf;
5369 	mac_bridge_ref_cb = reff;
5370 	mac_bridge_ls_cb = lsf;
5371 }
5372 
5373 int
5374 mac_bridge_set(mac_handle_t mh, mac_handle_t link)
5375 {
5376 	mac_impl_t *mip = (mac_impl_t *)mh;
5377 	int retv;
5378 
5379 	mutex_enter(&mip->mi_bridge_lock);
5380 	if (mip->mi_bridge_link == NULL) {
5381 		mip->mi_bridge_link = link;
5382 		retv = 0;
5383 	} else {
5384 		retv = EBUSY;
5385 	}
5386 	mutex_exit(&mip->mi_bridge_lock);
5387 	if (retv == 0) {
5388 		mac_poll_state_change(mh, B_FALSE);
5389 		mac_capab_update(mh);
5390 	}
5391 	return (retv);
5392 }
5393 
5394 /*
5395  * Disable bridging on the indicated link.
5396  */
5397 void
5398 mac_bridge_clear(mac_handle_t mh, mac_handle_t link)
5399 {
5400 	mac_impl_t *mip = (mac_impl_t *)mh;
5401 
5402 	mutex_enter(&mip->mi_bridge_lock);
5403 	ASSERT(mip->mi_bridge_link == link);
5404 	mip->mi_bridge_link = NULL;
5405 	mutex_exit(&mip->mi_bridge_lock);
5406 	mac_poll_state_change(mh, B_TRUE);
5407 	mac_capab_update(mh);
5408 }
5409 
5410 void
5411 mac_no_active(mac_handle_t mh)
5412 {
5413 	mac_impl_t *mip = (mac_impl_t *)mh;
5414 
5415 	i_mac_perim_enter(mip);
5416 	mip->mi_state_flags |= MIS_NO_ACTIVE;
5417 	i_mac_perim_exit(mip);
5418 }
5419