Print this page
11490 SRS ring polling disabled for VLANs
11491 Want DLS bypass for VLAN traffic
11492 add VLVF bypass to ixgbe core
2869 duplicate packets with vnics over aggrs
11489 DLS stat delete and aggr kstat can deadlock
Portions contributed by: Theo Schlossnagle <jesus@omniti.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/mac/mac_provider.c
+++ new/usr/src/uts/common/io/mac/mac_provider.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2018 Joyent, Inc.
24 25 * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
25 26 */
26 27
27 28 #include <sys/types.h>
28 29 #include <sys/conf.h>
29 30 #include <sys/id_space.h>
30 31 #include <sys/esunddi.h>
31 32 #include <sys/stat.h>
32 33 #include <sys/mkdev.h>
33 34 #include <sys/stream.h>
34 35 #include <sys/strsubr.h>
35 36 #include <sys/dlpi.h>
36 37 #include <sys/modhash.h>
37 38 #include <sys/mac.h>
38 39 #include <sys/mac_provider.h>
39 40 #include <sys/mac_impl.h>
40 41 #include <sys/mac_client_impl.h>
41 42 #include <sys/mac_client_priv.h>
42 43 #include <sys/mac_soft_ring.h>
43 44 #include <sys/mac_stat.h>
44 45 #include <sys/dld.h>
45 46 #include <sys/modctl.h>
46 47 #include <sys/fs/dv_node.h>
47 48 #include <sys/thread.h>
48 49 #include <sys/proc.h>
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
49 50 #include <sys/callb.h>
50 51 #include <sys/cpuvar.h>
51 52 #include <sys/atomic.h>
52 53 #include <sys/sdt.h>
53 54 #include <sys/mac_flow.h>
54 55 #include <sys/ddi_intr_impl.h>
55 56 #include <sys/disp.h>
56 57 #include <sys/sdt.h>
57 58 #include <sys/pattr.h>
58 59 #include <sys/strsun.h>
60 +#include <sys/vlan.h>
59 61
60 62 /*
61 63 * MAC Provider Interface.
62 64 *
63 65 * Interface for GLDv3 compatible NIC drivers.
64 66 */
65 67
66 68 static void i_mac_notify_thread(void *);
67 69
68 70 typedef void (*mac_notify_default_cb_fn_t)(mac_impl_t *);
69 71
70 72 static const mac_notify_default_cb_fn_t mac_notify_cb_list[MAC_NNOTE] = {
71 73 mac_fanout_recompute, /* MAC_NOTE_LINK */
72 74 NULL, /* MAC_NOTE_UNICST */
73 75 NULL, /* MAC_NOTE_TX */
74 76 NULL, /* MAC_NOTE_DEVPROMISC */
75 77 NULL, /* MAC_NOTE_FASTPATH_FLUSH */
76 78 NULL, /* MAC_NOTE_SDU_SIZE */
77 79 NULL, /* MAC_NOTE_MARGIN */
78 80 NULL, /* MAC_NOTE_CAPAB_CHG */
79 81 NULL /* MAC_NOTE_LOWLINK */
80 82 };
81 83
82 84 /*
83 85 * Driver support functions.
84 86 */
85 87
86 88 /* REGISTRATION */
87 89
88 90 mac_register_t *
89 91 mac_alloc(uint_t mac_version)
90 92 {
91 93 mac_register_t *mregp;
92 94
93 95 /*
94 96 * Make sure there isn't a version mismatch between the driver and
95 97 * the framework. In the future, if multiple versions are
96 98 * supported, this check could become more sophisticated.
97 99 */
98 100 if (mac_version != MAC_VERSION)
99 101 return (NULL);
100 102
101 103 mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP);
102 104 mregp->m_version = mac_version;
103 105 return (mregp);
104 106 }
105 107
106 108 void
107 109 mac_free(mac_register_t *mregp)
108 110 {
109 111 kmem_free(mregp, sizeof (mac_register_t));
110 112 }
111 113
112 114 /*
113 115 * mac_register() is how drivers register new MACs with the GLDv3
114 116 * framework. The mregp argument is allocated by drivers using the
115 117 * mac_alloc() function, and can be freed using mac_free() immediately upon
116 118 * return from mac_register(). Upon success (0 return value), the mhp
117 119 * opaque pointer becomes the driver's handle to its MAC interface, and is
118 120 * the argument to all other mac module entry points.
119 121 */
120 122 /* ARGSUSED */
121 123 int
122 124 mac_register(mac_register_t *mregp, mac_handle_t *mhp)
123 125 {
124 126 mac_impl_t *mip;
125 127 mactype_t *mtype;
126 128 int err = EINVAL;
127 129 struct devnames *dnp = NULL;
128 130 uint_t instance;
129 131 boolean_t style1_created = B_FALSE;
130 132 boolean_t style2_created = B_FALSE;
131 133 char *driver;
132 134 minor_t minor = 0;
133 135
134 136 /* A successful call to mac_init_ops() sets the DN_GLDV3_DRIVER flag. */
135 137 if (!GLDV3_DRV(ddi_driver_major(mregp->m_dip)))
136 138 return (EINVAL);
137 139
138 140 /* Find the required MAC-Type plugin. */
139 141 if ((mtype = mactype_getplugin(mregp->m_type_ident)) == NULL)
140 142 return (EINVAL);
141 143
142 144 /* Create a mac_impl_t to represent this MAC. */
143 145 mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP);
144 146
145 147 /*
146 148 * The mac is not ready for open yet.
147 149 */
148 150 mip->mi_state_flags |= MIS_DISABLED;
149 151
150 152 /*
151 153 * When a mac is registered, the m_instance field can be set to:
152 154 *
153 155 * 0: Get the mac's instance number from m_dip.
154 156 * This is usually used for physical device dips.
155 157 *
156 158 * [1 .. MAC_MAX_MINOR-1]: Use the value as the mac's instance number.
157 159 * For example, when an aggregation is created with the key option,
158 160 * "key" will be used as the instance number.
159 161 *
160 162 * -1: Assign an instance number from [MAC_MAX_MINOR .. MAXMIN-1].
161 163 * This is often used when a MAC of a virtual link is registered
162 164 * (e.g., aggregation when "key" is not specified, or vnic).
163 165 *
164 166 * Note that the instance number is used to derive the mi_minor field
165 167 * of mac_impl_t, which will then be used to derive the name of kstats
166 168 * and the devfs nodes. The first 2 cases are needed to preserve
167 169 * backward compatibility.
168 170 */
169 171 switch (mregp->m_instance) {
170 172 case 0:
171 173 instance = ddi_get_instance(mregp->m_dip);
172 174 break;
173 175 case ((uint_t)-1):
174 176 minor = mac_minor_hold(B_TRUE);
175 177 if (minor == 0) {
176 178 err = ENOSPC;
177 179 goto fail;
178 180 }
179 181 instance = minor - 1;
180 182 break;
181 183 default:
182 184 instance = mregp->m_instance;
183 185 if (instance >= MAC_MAX_MINOR) {
184 186 err = EINVAL;
185 187 goto fail;
186 188 }
187 189 break;
188 190 }
189 191
190 192 mip->mi_minor = (minor_t)(instance + 1);
191 193 mip->mi_dip = mregp->m_dip;
192 194 mip->mi_clients_list = NULL;
193 195 mip->mi_nclients = 0;
194 196
195 197 /* Set the default IEEE Port VLAN Identifier */
196 198 mip->mi_pvid = 1;
197 199
198 200 /* Default bridge link learning protection values */
199 201 mip->mi_llimit = 1000;
200 202 mip->mi_ldecay = 200;
201 203
202 204 driver = (char *)ddi_driver_name(mip->mi_dip);
203 205
204 206 /* Construct the MAC name as <drvname><instance> */
205 207 (void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d",
206 208 driver, instance);
207 209
208 210 mip->mi_driver = mregp->m_driver;
209 211
210 212 mip->mi_type = mtype;
211 213 mip->mi_margin = mregp->m_margin;
212 214 mip->mi_info.mi_media = mtype->mt_type;
213 215 mip->mi_info.mi_nativemedia = mtype->mt_nativetype;
214 216 if (mregp->m_max_sdu <= mregp->m_min_sdu)
215 217 goto fail;
216 218 if (mregp->m_multicast_sdu == 0)
217 219 mregp->m_multicast_sdu = mregp->m_max_sdu;
218 220 if (mregp->m_multicast_sdu < mregp->m_min_sdu ||
219 221 mregp->m_multicast_sdu > mregp->m_max_sdu)
220 222 goto fail;
221 223 mip->mi_sdu_min = mregp->m_min_sdu;
222 224 mip->mi_sdu_max = mregp->m_max_sdu;
223 225 mip->mi_sdu_multicast = mregp->m_multicast_sdu;
224 226 mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length;
225 227 /*
226 228 * If the media supports a broadcast address, cache a pointer to it
227 229 * in the mac_info_t so that upper layers can use it.
228 230 */
229 231 mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr;
230 232
231 233 mip->mi_v12n_level = mregp->m_v12n;
232 234
233 235 /*
234 236 * Copy the unicast source address into the mac_info_t, but only if
235 237 * the MAC-Type defines a non-zero address length. We need to
236 238 * handle MAC-Types that have an address length of 0
237 239 * (point-to-point protocol MACs for example).
238 240 */
239 241 if (mip->mi_type->mt_addr_length > 0) {
240 242 if (mregp->m_src_addr == NULL)
241 243 goto fail;
242 244 mip->mi_info.mi_unicst_addr =
243 245 kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP);
244 246 bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr,
245 247 mip->mi_type->mt_addr_length);
246 248
247 249 /*
248 250 * Copy the fixed 'factory' MAC address from the immutable
249 251 * info. This is taken to be the MAC address currently in
250 252 * use.
251 253 */
252 254 bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr,
253 255 mip->mi_type->mt_addr_length);
254 256
255 257 /*
256 258 * At this point, we should set up the classification
257 259 * rules etc but we delay it till mac_open() so that
258 260 * the resource discovery has taken place and we
259 261 * know someone wants to use the device. Otherwise
260 262 * memory gets allocated for Rx ring structures even
261 263 * during probe.
262 264 */
263 265
264 266 /* Copy the destination address if one is provided. */
265 267 if (mregp->m_dst_addr != NULL) {
266 268 bcopy(mregp->m_dst_addr, mip->mi_dstaddr,
267 269 mip->mi_type->mt_addr_length);
268 270 mip->mi_dstaddr_set = B_TRUE;
269 271 }
270 272 } else if (mregp->m_src_addr != NULL) {
271 273 goto fail;
272 274 }
273 275
274 276 /*
275 277 * The format of the m_pdata is specific to the plugin. It is
276 278 * passed in as an argument to all of the plugin callbacks. The
277 279 * driver can update this information by calling
278 280 * mac_pdata_update().
279 281 */
280 282 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY) {
281 283 /*
282 284 * Verify if the supplied plugin data is valid. Note that
283 285 * even if the caller passed in a NULL pointer as plugin data,
284 286 * we still need to verify if that's valid as the plugin may
285 287 * require plugin data to function.
286 288 */
287 289 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata,
288 290 mregp->m_pdata_size)) {
289 291 goto fail;
290 292 }
291 293 if (mregp->m_pdata != NULL) {
292 294 mip->mi_pdata =
293 295 kmem_alloc(mregp->m_pdata_size, KM_SLEEP);
294 296 bcopy(mregp->m_pdata, mip->mi_pdata,
295 297 mregp->m_pdata_size);
296 298 mip->mi_pdata_size = mregp->m_pdata_size;
297 299 }
298 300 } else if (mregp->m_pdata != NULL) {
299 301 /*
300 302 * The caller supplied non-NULL plugin data, but the plugin
301 303 * does not recognize plugin data.
302 304 */
303 305 err = EINVAL;
304 306 goto fail;
305 307 }
306 308
307 309 /*
308 310 * Register the private properties.
309 311 */
310 312 mac_register_priv_prop(mip, mregp->m_priv_props);
311 313
312 314 /*
313 315 * Stash the driver callbacks into the mac_impl_t, but first sanity
314 316 * check to make sure all mandatory callbacks are set.
315 317 */
316 318 if (mregp->m_callbacks->mc_getstat == NULL ||
317 319 mregp->m_callbacks->mc_start == NULL ||
318 320 mregp->m_callbacks->mc_stop == NULL ||
319 321 mregp->m_callbacks->mc_setpromisc == NULL ||
320 322 mregp->m_callbacks->mc_multicst == NULL) {
321 323 goto fail;
322 324 }
323 325 mip->mi_callbacks = mregp->m_callbacks;
324 326
325 327 if (mac_capab_get((mac_handle_t)mip, MAC_CAPAB_LEGACY,
326 328 &mip->mi_capab_legacy)) {
327 329 mip->mi_state_flags |= MIS_LEGACY;
328 330 mip->mi_phy_dev = mip->mi_capab_legacy.ml_dev;
329 331 } else {
330 332 mip->mi_phy_dev = makedevice(ddi_driver_major(mip->mi_dip),
331 333 mip->mi_minor);
332 334 }
333 335
334 336 /*
335 337 * Allocate a notification thread. thread_create blocks for memory
336 338 * if needed, it never fails.
337 339 */
338 340 mip->mi_notify_thread = thread_create(NULL, 0, i_mac_notify_thread,
339 341 mip, 0, &p0, TS_RUN, minclsyspri);
340 342
341 343 /*
342 344 * Initialize the capabilities
343 345 */
344 346
345 347 bzero(&mip->mi_rx_rings_cap, sizeof (mac_capab_rings_t));
346 348 bzero(&mip->mi_tx_rings_cap, sizeof (mac_capab_rings_t));
347 349
348 350 if (i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_VNIC, NULL))
349 351 mip->mi_state_flags |= MIS_IS_VNIC;
350 352
351 353 if (i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_AGGR, NULL))
352 354 mip->mi_state_flags |= MIS_IS_AGGR;
353 355
354 356 mac_addr_factory_init(mip);
355 357
356 358 mac_transceiver_init(mip);
357 359
358 360 mac_led_init(mip);
359 361
360 362 /*
361 363 * Enforce the virtrualization level registered.
362 364 */
363 365 if (mip->mi_v12n_level & MAC_VIRT_LEVEL1) {
364 366 if (mac_init_rings(mip, MAC_RING_TYPE_RX) != 0 ||
365 367 mac_init_rings(mip, MAC_RING_TYPE_TX) != 0)
366 368 goto fail;
367 369
368 370 /*
369 371 * The driver needs to register at least rx rings for this
370 372 * virtualization level.
371 373 */
372 374 if (mip->mi_rx_groups == NULL)
373 375 goto fail;
374 376 }
375 377
376 378 /*
377 379 * The driver must set mc_unicst entry point to NULL when it advertises
378 380 * CAP_RINGS for rx groups.
379 381 */
380 382 if (mip->mi_rx_groups != NULL) {
381 383 if (mregp->m_callbacks->mc_unicst != NULL)
382 384 goto fail;
383 385 } else {
384 386 if (mregp->m_callbacks->mc_unicst == NULL)
385 387 goto fail;
386 388 }
387 389
388 390 /*
389 391 * Initialize MAC addresses. Must be called after mac_init_rings().
390 392 */
391 393 mac_init_macaddr(mip);
392 394
393 395 mip->mi_share_capab.ms_snum = 0;
394 396 if (mip->mi_v12n_level & MAC_VIRT_HIO) {
395 397 (void) mac_capab_get((mac_handle_t)mip, MAC_CAPAB_SHARES,
396 398 &mip->mi_share_capab);
397 399 }
398 400
399 401 /*
400 402 * Initialize the kstats for this device.
401 403 */
402 404 mac_driver_stat_create(mip);
403 405
404 406 /* Zero out any properties. */
405 407 bzero(&mip->mi_resource_props, sizeof (mac_resource_props_t));
406 408
407 409 if (mip->mi_minor <= MAC_MAX_MINOR) {
408 410 /* Create a style-2 DLPI device */
409 411 if (ddi_create_minor_node(mip->mi_dip, driver, S_IFCHR, 0,
410 412 DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
411 413 goto fail;
412 414 style2_created = B_TRUE;
413 415
414 416 /* Create a style-1 DLPI device */
415 417 if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR,
416 418 mip->mi_minor, DDI_NT_NET, 0) != DDI_SUCCESS)
417 419 goto fail;
418 420 style1_created = B_TRUE;
419 421 }
420 422
421 423 mac_flow_l2tab_create(mip, &mip->mi_flow_tab);
422 424
423 425 rw_enter(&i_mac_impl_lock, RW_WRITER);
424 426 if (mod_hash_insert(i_mac_impl_hash,
425 427 (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) {
426 428 rw_exit(&i_mac_impl_lock);
427 429 err = EEXIST;
428 430 goto fail;
429 431 }
430 432
431 433 DTRACE_PROBE2(mac__register, struct devnames *, dnp,
432 434 (mac_impl_t *), mip);
433 435
434 436 /*
435 437 * Mark the MAC to be ready for open.
436 438 */
437 439 mip->mi_state_flags &= ~MIS_DISABLED;
438 440 rw_exit(&i_mac_impl_lock);
439 441
440 442 atomic_inc_32(&i_mac_impl_count);
441 443
442 444 cmn_err(CE_NOTE, "!%s registered", mip->mi_name);
443 445 *mhp = (mac_handle_t)mip;
444 446 return (0);
445 447
446 448 fail:
447 449 if (style1_created)
448 450 ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
449 451
450 452 if (style2_created)
451 453 ddi_remove_minor_node(mip->mi_dip, driver);
452 454
453 455 mac_addr_factory_fini(mip);
454 456
455 457 /* Clean up registered MAC addresses */
456 458 mac_fini_macaddr(mip);
457 459
458 460 /* Clean up registered rings */
459 461 mac_free_rings(mip, MAC_RING_TYPE_RX);
460 462 mac_free_rings(mip, MAC_RING_TYPE_TX);
461 463
462 464 /* Clean up notification thread */
463 465 if (mip->mi_notify_thread != NULL)
464 466 i_mac_notify_exit(mip);
465 467
466 468 if (mip->mi_info.mi_unicst_addr != NULL) {
467 469 kmem_free(mip->mi_info.mi_unicst_addr,
468 470 mip->mi_type->mt_addr_length);
469 471 mip->mi_info.mi_unicst_addr = NULL;
470 472 }
471 473
472 474 mac_driver_stat_delete(mip);
473 475
474 476 if (mip->mi_type != NULL) {
475 477 atomic_dec_32(&mip->mi_type->mt_ref);
476 478 mip->mi_type = NULL;
477 479 }
478 480
479 481 if (mip->mi_pdata != NULL) {
480 482 kmem_free(mip->mi_pdata, mip->mi_pdata_size);
481 483 mip->mi_pdata = NULL;
482 484 mip->mi_pdata_size = 0;
483 485 }
484 486
485 487 if (minor != 0) {
486 488 ASSERT(minor > MAC_MAX_MINOR);
487 489 mac_minor_rele(minor);
488 490 }
489 491
490 492 mip->mi_state_flags = 0;
491 493 mac_unregister_priv_prop(mip);
492 494
493 495 /*
494 496 * Clear the state before destroying the mac_impl_t
495 497 */
496 498 mip->mi_state_flags = 0;
497 499
498 500 kmem_cache_free(i_mac_impl_cachep, mip);
499 501 return (err);
500 502 }
501 503
502 504 /*
503 505 * Unregister from the GLDv3 framework
504 506 */
505 507 int
506 508 mac_unregister(mac_handle_t mh)
507 509 {
508 510 int err;
509 511 mac_impl_t *mip = (mac_impl_t *)mh;
510 512 mod_hash_val_t val;
511 513 mac_margin_req_t *mmr, *nextmmr;
512 514
513 515 /* Fail the unregister if there are any open references to this mac. */
514 516 if ((err = mac_disable_nowait(mh)) != 0)
515 517 return (err);
516 518
517 519 /*
518 520 * Clean up notification thread and wait for it to exit.
519 521 */
520 522 i_mac_notify_exit(mip);
521 523
522 524 /*
523 525 * Prior to acquiring the MAC perimeter, remove the MAC instance from
524 526 * the internal hash table. Such removal means table-walkers that
525 527 * acquire the perimeter will not do so on behalf of what we are
526 528 * unregistering, which prevents a deadlock.
527 529 */
528 530 rw_enter(&i_mac_impl_lock, RW_WRITER);
529 531 (void) mod_hash_remove(i_mac_impl_hash,
530 532 (mod_hash_key_t)mip->mi_name, &val);
531 533 rw_exit(&i_mac_impl_lock);
532 534 ASSERT(mip == (mac_impl_t *)val);
533 535
534 536 i_mac_perim_enter(mip);
535 537
536 538 /*
537 539 * There is still resource properties configured over this mac.
538 540 */
539 541 if (mip->mi_resource_props.mrp_mask != 0)
540 542 mac_fastpath_enable((mac_handle_t)mip);
541 543
542 544 if (mip->mi_minor < MAC_MAX_MINOR + 1) {
543 545 ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
544 546 ddi_remove_minor_node(mip->mi_dip,
545 547 (char *)ddi_driver_name(mip->mi_dip));
546 548 }
547 549
548 550 ASSERT(mip->mi_nactiveclients == 0 && !(mip->mi_state_flags &
549 551 MIS_EXCLUSIVE));
550 552
551 553 mac_driver_stat_delete(mip);
552 554
553 555 ASSERT(i_mac_impl_count > 0);
554 556 atomic_dec_32(&i_mac_impl_count);
555 557
556 558 if (mip->mi_pdata != NULL)
557 559 kmem_free(mip->mi_pdata, mip->mi_pdata_size);
558 560 mip->mi_pdata = NULL;
559 561 mip->mi_pdata_size = 0;
560 562
561 563 /*
562 564 * Free the list of margin request.
563 565 */
564 566 for (mmr = mip->mi_mmrp; mmr != NULL; mmr = nextmmr) {
565 567 nextmmr = mmr->mmr_nextp;
566 568 kmem_free(mmr, sizeof (mac_margin_req_t));
567 569 }
568 570 mip->mi_mmrp = NULL;
569 571
570 572 mip->mi_linkstate = mip->mi_lowlinkstate = LINK_STATE_UNKNOWN;
571 573 kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
572 574 mip->mi_info.mi_unicst_addr = NULL;
573 575
574 576 atomic_dec_32(&mip->mi_type->mt_ref);
575 577 mip->mi_type = NULL;
576 578
577 579 /*
578 580 * Free the primary MAC address.
579 581 */
580 582 mac_fini_macaddr(mip);
581 583
582 584 /*
583 585 * free all rings
584 586 */
585 587 mac_free_rings(mip, MAC_RING_TYPE_RX);
586 588 mac_free_rings(mip, MAC_RING_TYPE_TX);
587 589
588 590 mac_addr_factory_fini(mip);
589 591
590 592 bzero(mip->mi_addr, MAXMACADDRLEN);
591 593 bzero(mip->mi_dstaddr, MAXMACADDRLEN);
592 594 mip->mi_dstaddr_set = B_FALSE;
593 595
594 596 /* and the flows */
595 597 mac_flow_tab_destroy(mip->mi_flow_tab);
596 598 mip->mi_flow_tab = NULL;
597 599
598 600 if (mip->mi_minor > MAC_MAX_MINOR)
599 601 mac_minor_rele(mip->mi_minor);
600 602
601 603 cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name);
602 604
603 605 /*
604 606 * Reset the perim related fields to default values before
605 607 * kmem_cache_free
606 608 */
607 609 i_mac_perim_exit(mip);
608 610 mip->mi_state_flags = 0;
609 611
610 612 mac_unregister_priv_prop(mip);
611 613
612 614 ASSERT(mip->mi_bridge_link == NULL);
613 615 kmem_cache_free(i_mac_impl_cachep, mip);
614 616
615 617 return (0);
616 618 }
617 619
618 620 /* DATA RECEPTION */
619 621
620 622 /*
621 623 * This function is invoked for packets received by the MAC driver in
622 624 * interrupt context. The ring generation number provided by the driver
623 625 * is matched with the ring generation number held in MAC. If they do not
624 626 * match, received packets are considered stale packets coming from an older
625 627 * assignment of the ring. Drop them.
626 628 */
627 629 void
628 630 mac_rx_ring(mac_handle_t mh, mac_ring_handle_t mrh, mblk_t *mp_chain,
629 631 uint64_t mr_gen_num)
630 632 {
631 633 mac_ring_t *mr = (mac_ring_t *)mrh;
632 634
633 635 if ((mr != NULL) && (mr->mr_gen_num != mr_gen_num)) {
634 636 DTRACE_PROBE2(mac__rx__rings__stale__packet, uint64_t,
635 637 mr->mr_gen_num, uint64_t, mr_gen_num);
636 638 freemsgchain(mp_chain);
637 639 return;
638 640 }
639 641 mac_rx(mh, (mac_resource_handle_t)mrh, mp_chain);
640 642 }
641 643
642 644 /*
643 645 * This function is invoked for each packet received by the underlying driver.
644 646 */
645 647 void
646 648 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain)
647 649 {
648 650 mac_impl_t *mip = (mac_impl_t *)mh;
649 651
650 652 /*
651 653 * Check if the link is part of a bridge. If not, then we don't need
652 654 * to take the lock to remain consistent. Make this common case
653 655 * lock-free and tail-call optimized.
654 656 */
655 657 if (mip->mi_bridge_link == NULL) {
656 658 mac_rx_common(mh, mrh, mp_chain);
657 659 } else {
658 660 /*
659 661 * Once we take a reference on the bridge link, the bridge
660 662 * module itself can't unload, so the callback pointers are
661 663 * stable.
662 664 */
663 665 mutex_enter(&mip->mi_bridge_lock);
664 666 if ((mh = mip->mi_bridge_link) != NULL)
665 667 mac_bridge_ref_cb(mh, B_TRUE);
666 668 mutex_exit(&mip->mi_bridge_lock);
667 669 if (mh == NULL) {
668 670 mac_rx_common((mac_handle_t)mip, mrh, mp_chain);
669 671 } else {
670 672 mac_bridge_rx_cb(mh, mrh, mp_chain);
671 673 mac_bridge_ref_cb(mh, B_FALSE);
672 674 }
673 675 }
674 676 }
675 677
676 678 /*
677 679 * Special case function: this allows snooping of packets transmitted and
678 680 * received by TRILL. By design, they go directly into the TRILL module.
679 681 */
680 682 void
681 683 mac_trill_snoop(mac_handle_t mh, mblk_t *mp)
682 684 {
683 685 mac_impl_t *mip = (mac_impl_t *)mh;
684 686
685 687 if (mip->mi_promisc_list != NULL)
686 688 mac_promisc_dispatch(mip, mp, NULL);
687 689 }
↓ open down ↓ |
619 lines elided |
↑ open up ↑ |
688 690
689 691 /*
690 692 * This is the upward reentry point for packets arriving from the bridging
691 693 * module and from mac_rx for links not part of a bridge.
692 694 */
693 695 void
694 696 mac_rx_common(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain)
695 697 {
696 698 mac_impl_t *mip = (mac_impl_t *)mh;
697 699 mac_ring_t *mr = (mac_ring_t *)mrh;
698 - mac_soft_ring_set_t *mac_srs;
700 + mac_soft_ring_set_t *mac_srs;
699 701 mblk_t *bp = mp_chain;
700 702 boolean_t hw_classified = B_FALSE;
701 703
702 704 /*
703 705 * If there are any promiscuous mode callbacks defined for
704 706 * this MAC, pass them a copy if appropriate.
705 707 */
706 708 if (mip->mi_promisc_list != NULL)
707 709 mac_promisc_dispatch(mip, mp_chain, NULL);
708 710
709 711 if (mr != NULL) {
710 712 /*
711 713 * If the SRS teardown has started, just return. The 'mr'
712 714 * continues to be valid until the driver unregisters the mac.
713 715 * Hardware classified packets will not make their way up
714 716 * beyond this point once the teardown has started. The driver
715 717 * is never passed a pointer to a flow entry or SRS or any
716 718 * structure that can be freed much before mac_unregister.
717 719 */
718 720 mutex_enter(&mr->mr_lock);
719 721 if ((mr->mr_state != MR_INUSE) || (mr->mr_flag &
720 722 (MR_INCIPIENT | MR_CONDEMNED | MR_QUIESCE))) {
721 723 mutex_exit(&mr->mr_lock);
722 724 freemsgchain(mp_chain);
723 725 return;
724 726 }
725 727 if (mr->mr_classify_type == MAC_HW_CLASSIFIER) {
726 728 hw_classified = B_TRUE;
727 729 MR_REFHOLD_LOCKED(mr);
728 730 }
729 731 mutex_exit(&mr->mr_lock);
730 732
731 733 /*
732 734 * We check if an SRS is controlling this ring.
733 735 * If so, we can directly call the srs_lower_proc
734 736 * routine otherwise we need to go through mac_rx_classify
735 737 * to reach the right place.
736 738 */
737 739 if (hw_classified) {
738 740 mac_srs = mr->mr_srs;
739 741 /*
740 742 * This is supposed to be the fast path.
741 743 * All packets received though here were steered by
742 744 * the hardware classifier, and share the same
743 745 * MAC header info.
744 746 */
745 747 mac_srs->srs_rx.sr_lower_proc(mh,
746 748 (mac_resource_handle_t)mac_srs, mp_chain, B_FALSE);
747 749 MR_REFRELE(mr);
748 750 return;
749 751 }
750 752 /* We'll fall through to software classification */
751 753 } else {
752 754 flow_entry_t *flent;
753 755 int err;
754 756
755 757 rw_enter(&mip->mi_rw_lock, RW_READER);
756 758 if (mip->mi_single_active_client != NULL) {
757 759 flent = mip->mi_single_active_client->mci_flent_list;
758 760 FLOW_TRY_REFHOLD(flent, err);
759 761 rw_exit(&mip->mi_rw_lock);
760 762 if (err == 0) {
761 763 (flent->fe_cb_fn)(flent->fe_cb_arg1,
762 764 flent->fe_cb_arg2, mp_chain, B_FALSE);
763 765 FLOW_REFRELE(flent);
764 766 return;
765 767 }
766 768 } else {
767 769 rw_exit(&mip->mi_rw_lock);
768 770 }
769 771 }
770 772
771 773 if (!FLOW_TAB_EMPTY(mip->mi_flow_tab)) {
772 774 if ((bp = mac_rx_flow(mh, mrh, bp)) == NULL)
773 775 return;
774 776 }
775 777
776 778 freemsgchain(bp);
777 779 }
778 780
779 781 /* DATA TRANSMISSION */
780 782
781 783 /*
782 784 * A driver's notification to resume transmission, in case of a provider
783 785 * without TX rings.
784 786 */
785 787 void
786 788 mac_tx_update(mac_handle_t mh)
787 789 {
788 790 mac_tx_ring_update(mh, NULL);
789 791 }
790 792
791 793 /*
792 794 * A driver's notification to resume transmission on the specified TX ring.
793 795 */
794 796 void
795 797 mac_tx_ring_update(mac_handle_t mh, mac_ring_handle_t rh)
796 798 {
797 799 i_mac_tx_srs_notify((mac_impl_t *)mh, rh);
798 800 }
799 801
800 802 /* LINK STATE */
801 803 /*
802 804 * Notify the MAC layer about a link state change
803 805 */
804 806 void
805 807 mac_link_update(mac_handle_t mh, link_state_t link)
806 808 {
807 809 mac_impl_t *mip = (mac_impl_t *)mh;
808 810
809 811 /*
810 812 * Save the link state.
811 813 */
812 814 mip->mi_lowlinkstate = link;
813 815
814 816 /*
815 817 * Send a MAC_NOTE_LOWLINK notification. This tells the notification
816 818 * thread to deliver both lower and upper notifications.
817 819 */
818 820 i_mac_notify(mip, MAC_NOTE_LOWLINK);
819 821 }
820 822
821 823 /*
822 824 * Notify the MAC layer about a link state change due to bridging.
823 825 */
824 826 void
825 827 mac_link_redo(mac_handle_t mh, link_state_t link)
826 828 {
827 829 mac_impl_t *mip = (mac_impl_t *)mh;
828 830
829 831 /*
830 832 * Save the link state.
831 833 */
832 834 mip->mi_linkstate = link;
833 835
834 836 /*
835 837 * Send a MAC_NOTE_LINK notification. Only upper notifications are
836 838 * made.
837 839 */
838 840 i_mac_notify(mip, MAC_NOTE_LINK);
839 841 }
840 842
841 843 /* MINOR NODE HANDLING */
842 844
843 845 /*
844 846 * Given a dev_t, return the instance number (PPA) associated with it.
845 847 * Drivers can use this in their getinfo(9e) implementation to lookup
846 848 * the instance number (i.e. PPA) of the device, to use as an index to
847 849 * their own array of soft state structures.
848 850 *
849 851 * Returns -1 on error.
850 852 */
851 853 int
852 854 mac_devt_to_instance(dev_t devt)
853 855 {
854 856 return (dld_devt_to_instance(devt));
855 857 }
856 858
857 859 /*
858 860 * This function returns the first minor number that is available for
859 861 * driver private use. All minor numbers smaller than this are
860 862 * reserved for GLDv3 use.
861 863 */
862 864 minor_t
863 865 mac_private_minor(void)
864 866 {
865 867 return (MAC_PRIVATE_MINOR);
866 868 }
867 869
868 870 /* OTHER CONTROL INFORMATION */
869 871
870 872 /*
871 873 * A driver notified us that its primary MAC address has changed.
872 874 */
873 875 void
874 876 mac_unicst_update(mac_handle_t mh, const uint8_t *addr)
875 877 {
876 878 mac_impl_t *mip = (mac_impl_t *)mh;
877 879
878 880 if (mip->mi_type->mt_addr_length == 0)
879 881 return;
880 882
881 883 i_mac_perim_enter(mip);
882 884
883 885 /*
884 886 * If address changes, freshen the MAC address value and update
885 887 * all MAC clients that share this MAC address.
886 888 */
887 889 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) != 0) {
888 890 mac_freshen_macaddr(mac_find_macaddr(mip, mip->mi_addr),
889 891 (uint8_t *)addr);
890 892 }
891 893
892 894 i_mac_perim_exit(mip);
893 895
894 896 /*
895 897 * Send a MAC_NOTE_UNICST notification.
896 898 */
897 899 i_mac_notify(mip, MAC_NOTE_UNICST);
898 900 }
899 901
900 902 void
901 903 mac_dst_update(mac_handle_t mh, const uint8_t *addr)
902 904 {
903 905 mac_impl_t *mip = (mac_impl_t *)mh;
904 906
905 907 if (mip->mi_type->mt_addr_length == 0)
906 908 return;
907 909
908 910 i_mac_perim_enter(mip);
909 911 bcopy(addr, mip->mi_dstaddr, mip->mi_type->mt_addr_length);
910 912 i_mac_perim_exit(mip);
911 913 i_mac_notify(mip, MAC_NOTE_DEST);
912 914 }
913 915
914 916 /*
915 917 * MAC plugin information changed.
916 918 */
917 919 int
918 920 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize)
919 921 {
920 922 mac_impl_t *mip = (mac_impl_t *)mh;
921 923
922 924 /*
923 925 * Verify that the plugin supports MAC plugin data and that the
924 926 * supplied data is valid.
925 927 */
926 928 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY))
927 929 return (EINVAL);
928 930 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize))
929 931 return (EINVAL);
930 932
931 933 if (mip->mi_pdata != NULL)
932 934 kmem_free(mip->mi_pdata, mip->mi_pdata_size);
933 935
934 936 mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP);
935 937 bcopy(mac_pdata, mip->mi_pdata, dsize);
936 938 mip->mi_pdata_size = dsize;
937 939
938 940 /*
939 941 * Since the MAC plugin data is used to construct MAC headers that
940 942 * were cached in fast-path headers, we need to flush fast-path
941 943 * information for links associated with this mac.
942 944 */
943 945 i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH);
944 946 return (0);
945 947 }
946 948
947 949 /*
948 950 * Invoked by driver as well as the framework to notify its capability change.
949 951 */
950 952 void
951 953 mac_capab_update(mac_handle_t mh)
952 954 {
953 955 /* Send MAC_NOTE_CAPAB_CHG notification */
954 956 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_CAPAB_CHG);
955 957 }
956 958
957 959 /*
958 960 * Used by normal drivers to update the max sdu size.
959 961 * We need to handle the case of a smaller mi_sdu_multicast
960 962 * since this is called by mac_set_mtu() even for drivers that
961 963 * have differing unicast and multicast mtu and we don't want to
962 964 * increase the multicast mtu by accident in that case.
963 965 */
964 966 int
965 967 mac_maxsdu_update(mac_handle_t mh, uint_t sdu_max)
966 968 {
967 969 mac_impl_t *mip = (mac_impl_t *)mh;
968 970
969 971 if (sdu_max == 0 || sdu_max < mip->mi_sdu_min)
970 972 return (EINVAL);
971 973 mip->mi_sdu_max = sdu_max;
972 974 if (mip->mi_sdu_multicast > mip->mi_sdu_max)
973 975 mip->mi_sdu_multicast = mip->mi_sdu_max;
974 976
975 977 /* Send a MAC_NOTE_SDU_SIZE notification. */
976 978 i_mac_notify(mip, MAC_NOTE_SDU_SIZE);
977 979 return (0);
978 980 }
979 981
980 982 /*
981 983 * Version of the above function that is used by drivers that have a different
982 984 * max sdu size for multicast/broadcast vs. unicast.
983 985 */
984 986 int
985 987 mac_maxsdu_update2(mac_handle_t mh, uint_t sdu_max, uint_t sdu_multicast)
986 988 {
987 989 mac_impl_t *mip = (mac_impl_t *)mh;
988 990
989 991 if (sdu_max == 0 || sdu_max < mip->mi_sdu_min)
990 992 return (EINVAL);
991 993 if (sdu_multicast == 0)
992 994 sdu_multicast = sdu_max;
993 995 if (sdu_multicast > sdu_max || sdu_multicast < mip->mi_sdu_min)
994 996 return (EINVAL);
995 997 mip->mi_sdu_max = sdu_max;
996 998 mip->mi_sdu_multicast = sdu_multicast;
997 999
998 1000 /* Send a MAC_NOTE_SDU_SIZE notification. */
999 1001 i_mac_notify(mip, MAC_NOTE_SDU_SIZE);
1000 1002 return (0);
1001 1003 }
1002 1004
1003 1005 static void
1004 1006 mac_ring_intr_retarget(mac_group_t *group, mac_ring_t *ring)
1005 1007 {
1006 1008 mac_client_impl_t *mcip;
1007 1009 flow_entry_t *flent;
1008 1010 mac_soft_ring_set_t *mac_rx_srs;
1009 1011 mac_cpus_t *srs_cpu;
1010 1012 int i;
1011 1013
1012 1014 if (((mcip = MAC_GROUP_ONLY_CLIENT(group)) != NULL) &&
1013 1015 (!ring->mr_info.mri_intr.mi_ddi_shared)) {
1014 1016 /* interrupt can be re-targeted */
1015 1017 ASSERT(group->mrg_state == MAC_GROUP_STATE_RESERVED);
1016 1018 flent = mcip->mci_flent;
1017 1019 if (ring->mr_type == MAC_RING_TYPE_RX) {
1018 1020 for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
1019 1021 mac_rx_srs = flent->fe_rx_srs[i];
1020 1022 if (mac_rx_srs->srs_ring != ring)
1021 1023 continue;
1022 1024 srs_cpu = &mac_rx_srs->srs_cpu;
1023 1025 mutex_enter(&cpu_lock);
1024 1026 mac_rx_srs_retarget_intr(mac_rx_srs,
1025 1027 srs_cpu->mc_rx_intr_cpu);
1026 1028 mutex_exit(&cpu_lock);
1027 1029 break;
1028 1030 }
1029 1031 } else {
1030 1032 if (flent->fe_tx_srs != NULL) {
1031 1033 mutex_enter(&cpu_lock);
1032 1034 mac_tx_srs_retarget_intr(
1033 1035 flent->fe_tx_srs);
1034 1036 mutex_exit(&cpu_lock);
1035 1037 }
1036 1038 }
1037 1039 }
1038 1040 }
1039 1041
1040 1042 /*
1041 1043 * Clients like aggr create pseudo rings (mac_ring_t) and expose them to
1042 1044 * their clients. There is a 1-1 mapping pseudo ring and the hardware
1043 1045 * ring. ddi interrupt handles are exported from the hardware ring to
1044 1046 * the pseudo ring. Thus when the interrupt handle changes, clients of
1045 1047 * aggr that are using the handle need to use the new handle and
1046 1048 * re-target their interrupts.
1047 1049 */
1048 1050 static void
1049 1051 mac_pseudo_ring_intr_retarget(mac_impl_t *mip, mac_ring_t *ring,
1050 1052 ddi_intr_handle_t ddh)
1051 1053 {
1052 1054 mac_ring_t *pring;
1053 1055 mac_group_t *pgroup;
1054 1056 mac_impl_t *pmip;
1055 1057 char macname[MAXNAMELEN];
1056 1058 mac_perim_handle_t p_mph;
1057 1059 uint64_t saved_gen_num;
1058 1060
1059 1061 again:
1060 1062 pring = (mac_ring_t *)ring->mr_prh;
1061 1063 pgroup = (mac_group_t *)pring->mr_gh;
1062 1064 pmip = (mac_impl_t *)pgroup->mrg_mh;
1063 1065 saved_gen_num = ring->mr_gen_num;
1064 1066 (void) strlcpy(macname, pmip->mi_name, MAXNAMELEN);
1065 1067 /*
1066 1068 * We need to enter aggr's perimeter. The locking hierarchy
1067 1069 * dictates that aggr's perimeter should be entered first
1068 1070 * and then the port's perimeter. So drop the port's
1069 1071 * perimeter, enter aggr's and then re-enter port's
1070 1072 * perimeter.
1071 1073 */
1072 1074 i_mac_perim_exit(mip);
1073 1075 /*
1074 1076 * While we know pmip is the aggr's mip, there is a
1075 1077 * possibility that aggr could have unregistered by
1076 1078 * the time we exit port's perimeter (mip) and
1077 1079 * enter aggr's perimeter (pmip). To avoid that
1078 1080 * scenario, enter aggr's perimeter using its name.
1079 1081 */
1080 1082 if (mac_perim_enter_by_macname(macname, &p_mph) != 0)
1081 1083 return;
1082 1084 i_mac_perim_enter(mip);
1083 1085 /*
1084 1086 * Check if the ring got assigned to another aggregation before
1085 1087 * be could enter aggr's and the port's perimeter. When a ring
1086 1088 * gets deleted from an aggregation, it calls mac_stop_ring()
1087 1089 * which increments the generation number. So checking
1088 1090 * generation number will be enough.
1089 1091 */
1090 1092 if (ring->mr_gen_num != saved_gen_num && ring->mr_prh != NULL) {
1091 1093 i_mac_perim_exit(mip);
1092 1094 mac_perim_exit(p_mph);
1093 1095 i_mac_perim_enter(mip);
1094 1096 goto again;
1095 1097 }
1096 1098
1097 1099 /* Check if pseudo ring is still present */
1098 1100 if (ring->mr_prh != NULL) {
1099 1101 pring->mr_info.mri_intr.mi_ddi_handle = ddh;
1100 1102 pring->mr_info.mri_intr.mi_ddi_shared =
1101 1103 ring->mr_info.mri_intr.mi_ddi_shared;
1102 1104 if (ddh != NULL)
1103 1105 mac_ring_intr_retarget(pgroup, pring);
1104 1106 }
1105 1107 i_mac_perim_exit(mip);
1106 1108 mac_perim_exit(p_mph);
1107 1109 }
1108 1110 /*
1109 1111 * API called by driver to provide new interrupt handle for TX/RX rings.
1110 1112 * This usually happens when IRM (Interrupt Resource Manangement)
1111 1113 * framework either gives the driver more MSI-x interrupts or takes
1112 1114 * away MSI-x interrupts from the driver.
1113 1115 */
1114 1116 void
1115 1117 mac_ring_intr_set(mac_ring_handle_t mrh, ddi_intr_handle_t ddh)
1116 1118 {
1117 1119 mac_ring_t *ring = (mac_ring_t *)mrh;
1118 1120 mac_group_t *group = (mac_group_t *)ring->mr_gh;
1119 1121 mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
1120 1122
1121 1123 i_mac_perim_enter(mip);
1122 1124 ring->mr_info.mri_intr.mi_ddi_handle = ddh;
1123 1125 if (ddh == NULL) {
1124 1126 /* Interrupts being reset */
1125 1127 ring->mr_info.mri_intr.mi_ddi_shared = B_FALSE;
1126 1128 if (ring->mr_prh != NULL) {
1127 1129 mac_pseudo_ring_intr_retarget(mip, ring, ddh);
1128 1130 return;
1129 1131 }
1130 1132 } else {
1131 1133 /* New interrupt handle */
1132 1134 mac_compare_ddi_handle(mip->mi_rx_groups,
1133 1135 mip->mi_rx_group_count, ring);
1134 1136 if (!ring->mr_info.mri_intr.mi_ddi_shared) {
1135 1137 mac_compare_ddi_handle(mip->mi_tx_groups,
1136 1138 mip->mi_tx_group_count, ring);
1137 1139 }
1138 1140 if (ring->mr_prh != NULL) {
1139 1141 mac_pseudo_ring_intr_retarget(mip, ring, ddh);
1140 1142 return;
1141 1143 } else {
1142 1144 mac_ring_intr_retarget(group, ring);
1143 1145 }
1144 1146 }
1145 1147 i_mac_perim_exit(mip);
1146 1148 }
1147 1149
1148 1150 /* PRIVATE FUNCTIONS, FOR INTERNAL USE ONLY */
1149 1151
1150 1152 /*
1151 1153 * Updates the mac_impl structure with the current state of the link
1152 1154 */
1153 1155 static void
1154 1156 i_mac_log_link_state(mac_impl_t *mip)
1155 1157 {
1156 1158 /*
1157 1159 * If no change, then it is not interesting.
1158 1160 */
1159 1161 if (mip->mi_lastlowlinkstate == mip->mi_lowlinkstate)
1160 1162 return;
1161 1163
1162 1164 switch (mip->mi_lowlinkstate) {
1163 1165 case LINK_STATE_UP:
1164 1166 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_LINK_DETAILS) {
1165 1167 char det[200];
1166 1168
1167 1169 mip->mi_type->mt_ops.mtops_link_details(det,
1168 1170 sizeof (det), (mac_handle_t)mip, mip->mi_pdata);
1169 1171
1170 1172 cmn_err(CE_NOTE, "!%s link up, %s", mip->mi_name, det);
1171 1173 } else {
1172 1174 cmn_err(CE_NOTE, "!%s link up", mip->mi_name);
1173 1175 }
1174 1176 break;
1175 1177
1176 1178 case LINK_STATE_DOWN:
1177 1179 /*
1178 1180 * Only transitions from UP to DOWN are interesting
1179 1181 */
1180 1182 if (mip->mi_lastlowlinkstate != LINK_STATE_UNKNOWN)
1181 1183 cmn_err(CE_NOTE, "!%s link down", mip->mi_name);
1182 1184 break;
1183 1185
1184 1186 case LINK_STATE_UNKNOWN:
1185 1187 /*
1186 1188 * This case is normally not interesting.
1187 1189 */
1188 1190 break;
1189 1191 }
1190 1192 mip->mi_lastlowlinkstate = mip->mi_lowlinkstate;
1191 1193 }
1192 1194
1193 1195 /*
1194 1196 * Main routine for the callbacks notifications thread
1195 1197 */
1196 1198 static void
1197 1199 i_mac_notify_thread(void *arg)
1198 1200 {
1199 1201 mac_impl_t *mip = arg;
1200 1202 callb_cpr_t cprinfo;
1201 1203 mac_cb_t *mcb;
1202 1204 mac_cb_info_t *mcbi;
1203 1205 mac_notify_cb_t *mncb;
1204 1206
1205 1207 mcbi = &mip->mi_notify_cb_info;
1206 1208 CALLB_CPR_INIT(&cprinfo, mcbi->mcbi_lockp, callb_generic_cpr,
1207 1209 "i_mac_notify_thread");
1208 1210
1209 1211 mutex_enter(mcbi->mcbi_lockp);
1210 1212
1211 1213 for (;;) {
1212 1214 uint32_t bits;
1213 1215 uint32_t type;
1214 1216
1215 1217 bits = mip->mi_notify_bits;
1216 1218 if (bits == 0) {
1217 1219 CALLB_CPR_SAFE_BEGIN(&cprinfo);
1218 1220 cv_wait(&mcbi->mcbi_cv, mcbi->mcbi_lockp);
1219 1221 CALLB_CPR_SAFE_END(&cprinfo, mcbi->mcbi_lockp);
1220 1222 continue;
1221 1223 }
1222 1224 mip->mi_notify_bits = 0;
1223 1225 if ((bits & (1 << MAC_NNOTE)) != 0) {
1224 1226 /* request to quit */
1225 1227 ASSERT(mip->mi_state_flags & MIS_DISABLED);
1226 1228 break;
1227 1229 }
1228 1230
1229 1231 mutex_exit(mcbi->mcbi_lockp);
1230 1232
1231 1233 /*
1232 1234 * Log link changes on the actual link, but then do reports on
1233 1235 * synthetic state (if part of a bridge).
1234 1236 */
1235 1237 if ((bits & (1 << MAC_NOTE_LOWLINK)) != 0) {
1236 1238 link_state_t newstate;
1237 1239 mac_handle_t mh;
1238 1240
1239 1241 i_mac_log_link_state(mip);
1240 1242 newstate = mip->mi_lowlinkstate;
1241 1243 if (mip->mi_bridge_link != NULL) {
1242 1244 mutex_enter(&mip->mi_bridge_lock);
1243 1245 if ((mh = mip->mi_bridge_link) != NULL) {
1244 1246 newstate = mac_bridge_ls_cb(mh,
1245 1247 newstate);
1246 1248 }
1247 1249 mutex_exit(&mip->mi_bridge_lock);
1248 1250 }
1249 1251 if (newstate != mip->mi_linkstate) {
1250 1252 mip->mi_linkstate = newstate;
1251 1253 bits |= 1 << MAC_NOTE_LINK;
1252 1254 }
1253 1255 }
1254 1256
1255 1257 /*
1256 1258 * Do notification callbacks for each notification type.
1257 1259 */
1258 1260 for (type = 0; type < MAC_NNOTE; type++) {
1259 1261 if ((bits & (1 << type)) == 0) {
1260 1262 continue;
1261 1263 }
1262 1264
1263 1265 if (mac_notify_cb_list[type] != NULL)
1264 1266 (*mac_notify_cb_list[type])(mip);
1265 1267
1266 1268 /*
1267 1269 * Walk the list of notifications.
1268 1270 */
1269 1271 MAC_CALLBACK_WALKER_INC(&mip->mi_notify_cb_info);
1270 1272 for (mcb = mip->mi_notify_cb_list; mcb != NULL;
1271 1273 mcb = mcb->mcb_nextp) {
1272 1274 mncb = (mac_notify_cb_t *)mcb->mcb_objp;
1273 1275 mncb->mncb_fn(mncb->mncb_arg, type);
1274 1276 }
1275 1277 MAC_CALLBACK_WALKER_DCR(&mip->mi_notify_cb_info,
1276 1278 &mip->mi_notify_cb_list);
1277 1279 }
1278 1280
1279 1281 mutex_enter(mcbi->mcbi_lockp);
1280 1282 }
1281 1283
1282 1284 mip->mi_state_flags |= MIS_NOTIFY_DONE;
1283 1285 cv_broadcast(&mcbi->mcbi_cv);
1284 1286
1285 1287 /* CALLB_CPR_EXIT drops the lock */
1286 1288 CALLB_CPR_EXIT(&cprinfo);
1287 1289 thread_exit();
1288 1290 }
1289 1291
1290 1292 /*
1291 1293 * Signal the i_mac_notify_thread asking it to quit.
1292 1294 * Then wait till it is done.
1293 1295 */
1294 1296 void
1295 1297 i_mac_notify_exit(mac_impl_t *mip)
1296 1298 {
1297 1299 mac_cb_info_t *mcbi;
1298 1300
1299 1301 mcbi = &mip->mi_notify_cb_info;
1300 1302
1301 1303 mutex_enter(mcbi->mcbi_lockp);
1302 1304 mip->mi_notify_bits = (1 << MAC_NNOTE);
1303 1305 cv_broadcast(&mcbi->mcbi_cv);
1304 1306
1305 1307
1306 1308 while ((mip->mi_notify_thread != NULL) &&
1307 1309 !(mip->mi_state_flags & MIS_NOTIFY_DONE)) {
1308 1310 cv_wait(&mcbi->mcbi_cv, mcbi->mcbi_lockp);
1309 1311 }
1310 1312
1311 1313 /* Necessary clean up before doing kmem_cache_free */
1312 1314 mip->mi_state_flags &= ~MIS_NOTIFY_DONE;
1313 1315 mip->mi_notify_bits = 0;
1314 1316 mip->mi_notify_thread = NULL;
1315 1317 mutex_exit(mcbi->mcbi_lockp);
1316 1318 }
1317 1319
1318 1320 /*
1319 1321 * Entry point invoked by drivers to dynamically add a ring to an
1320 1322 * existing group.
1321 1323 */
1322 1324 int
1323 1325 mac_group_add_ring(mac_group_handle_t gh, int index)
1324 1326 {
1325 1327 mac_group_t *group = (mac_group_t *)gh;
1326 1328 mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
1327 1329 int ret;
1328 1330
1329 1331 i_mac_perim_enter(mip);
1330 1332 ret = i_mac_group_add_ring(group, NULL, index);
1331 1333 i_mac_perim_exit(mip);
1332 1334 return (ret);
1333 1335 }
1334 1336
1335 1337 /*
1336 1338 * Entry point invoked by drivers to dynamically remove a ring
1337 1339 * from an existing group. The specified ring handle must no longer
1338 1340 * be used by the driver after a call to this function.
1339 1341 */
1340 1342 void
1341 1343 mac_group_rem_ring(mac_group_handle_t gh, mac_ring_handle_t rh)
1342 1344 {
1343 1345 mac_group_t *group = (mac_group_t *)gh;
1344 1346 mac_impl_t *mip = (mac_impl_t *)group->mrg_mh;
1345 1347
1346 1348 i_mac_perim_enter(mip);
1347 1349 i_mac_group_rem_ring(group, (mac_ring_t *)rh, B_TRUE);
1348 1350 i_mac_perim_exit(mip);
1349 1351 }
1350 1352
1351 1353 /*
1352 1354 * mac_prop_info_*() callbacks called from the driver's prefix_propinfo()
1353 1355 * entry points.
1354 1356 */
1355 1357
1356 1358 void
1357 1359 mac_prop_info_set_default_uint8(mac_prop_info_handle_t ph, uint8_t val)
1358 1360 {
1359 1361 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1360 1362
1361 1363 /* nothing to do if the caller doesn't want the default value */
1362 1364 if (pr->pr_default == NULL)
1363 1365 return;
1364 1366
1365 1367 ASSERT(pr->pr_default_size >= sizeof (uint8_t));
1366 1368
1367 1369 *(uint8_t *)(pr->pr_default) = val;
1368 1370 pr->pr_flags |= MAC_PROP_INFO_DEFAULT;
1369 1371 }
1370 1372
1371 1373 void
1372 1374 mac_prop_info_set_default_uint64(mac_prop_info_handle_t ph, uint64_t val)
1373 1375 {
1374 1376 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1375 1377
1376 1378 /* nothing to do if the caller doesn't want the default value */
1377 1379 if (pr->pr_default == NULL)
1378 1380 return;
1379 1381
1380 1382 ASSERT(pr->pr_default_size >= sizeof (uint64_t));
1381 1383
1382 1384 bcopy(&val, pr->pr_default, sizeof (val));
1383 1385
1384 1386 pr->pr_flags |= MAC_PROP_INFO_DEFAULT;
1385 1387 }
1386 1388
1387 1389 void
1388 1390 mac_prop_info_set_default_uint32(mac_prop_info_handle_t ph, uint32_t val)
1389 1391 {
1390 1392 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1391 1393
1392 1394 /* nothing to do if the caller doesn't want the default value */
1393 1395 if (pr->pr_default == NULL)
1394 1396 return;
1395 1397
1396 1398 ASSERT(pr->pr_default_size >= sizeof (uint32_t));
1397 1399
1398 1400 bcopy(&val, pr->pr_default, sizeof (val));
1399 1401
1400 1402 pr->pr_flags |= MAC_PROP_INFO_DEFAULT;
1401 1403 }
1402 1404
1403 1405 void
1404 1406 mac_prop_info_set_default_str(mac_prop_info_handle_t ph, const char *str)
1405 1407 {
1406 1408 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1407 1409
1408 1410 /* nothing to do if the caller doesn't want the default value */
1409 1411 if (pr->pr_default == NULL)
1410 1412 return;
1411 1413
1412 1414 if (strlen(str) >= pr->pr_default_size)
1413 1415 pr->pr_errno = ENOBUFS;
1414 1416 else
1415 1417 (void) strlcpy(pr->pr_default, str, pr->pr_default_size);
1416 1418 pr->pr_flags |= MAC_PROP_INFO_DEFAULT;
1417 1419 }
1418 1420
1419 1421 void
1420 1422 mac_prop_info_set_default_link_flowctrl(mac_prop_info_handle_t ph,
1421 1423 link_flowctrl_t val)
1422 1424 {
1423 1425 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1424 1426
1425 1427 /* nothing to do if the caller doesn't want the default value */
1426 1428 if (pr->pr_default == NULL)
1427 1429 return;
1428 1430
1429 1431 ASSERT(pr->pr_default_size >= sizeof (link_flowctrl_t));
1430 1432
1431 1433 bcopy(&val, pr->pr_default, sizeof (val));
1432 1434
1433 1435 pr->pr_flags |= MAC_PROP_INFO_DEFAULT;
1434 1436 }
1435 1437
1436 1438 void
1437 1439 mac_prop_info_set_range_uint32(mac_prop_info_handle_t ph, uint32_t min,
1438 1440 uint32_t max)
1439 1441 {
1440 1442 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1441 1443 mac_propval_range_t *range = pr->pr_range;
1442 1444 mac_propval_uint32_range_t *range32;
1443 1445
1444 1446 /* nothing to do if the caller doesn't want the range info */
1445 1447 if (range == NULL)
1446 1448 return;
1447 1449
1448 1450 if (pr->pr_range_cur_count++ == 0) {
1449 1451 /* first range */
1450 1452 pr->pr_flags |= MAC_PROP_INFO_RANGE;
1451 1453 range->mpr_type = MAC_PROPVAL_UINT32;
1452 1454 } else {
1453 1455 /* all ranges of a property should be of the same type */
1454 1456 ASSERT(range->mpr_type == MAC_PROPVAL_UINT32);
1455 1457 if (pr->pr_range_cur_count > range->mpr_count) {
1456 1458 pr->pr_errno = ENOSPC;
1457 1459 return;
1458 1460 }
1459 1461 }
1460 1462
1461 1463 range32 = range->mpr_range_uint32;
1462 1464 range32[pr->pr_range_cur_count - 1].mpur_min = min;
1463 1465 range32[pr->pr_range_cur_count - 1].mpur_max = max;
1464 1466 }
1465 1467
1466 1468 void
1467 1469 mac_prop_info_set_perm(mac_prop_info_handle_t ph, uint8_t perm)
1468 1470 {
1469 1471 mac_prop_info_state_t *pr = (mac_prop_info_state_t *)ph;
1470 1472
1471 1473 pr->pr_perm = perm;
1472 1474 pr->pr_flags |= MAC_PROP_INFO_PERM;
1473 1475 }
1474 1476
1475 1477 void mac_hcksum_get(mblk_t *mp, uint32_t *start, uint32_t *stuff,
1476 1478 uint32_t *end, uint32_t *value, uint32_t *flags_ptr)
1477 1479 {
1478 1480 uint32_t flags;
1479 1481
1480 1482 ASSERT(DB_TYPE(mp) == M_DATA);
1481 1483
1482 1484 flags = DB_CKSUMFLAGS(mp) & HCK_FLAGS;
1483 1485 if ((flags & (HCK_PARTIALCKSUM | HCK_FULLCKSUM)) != 0) {
1484 1486 if (value != NULL)
1485 1487 *value = (uint32_t)DB_CKSUM16(mp);
1486 1488 if ((flags & HCK_PARTIALCKSUM) != 0) {
1487 1489 if (start != NULL)
1488 1490 *start = (uint32_t)DB_CKSUMSTART(mp);
1489 1491 if (stuff != NULL)
1490 1492 *stuff = (uint32_t)DB_CKSUMSTUFF(mp);
1491 1493 if (end != NULL)
1492 1494 *end = (uint32_t)DB_CKSUMEND(mp);
1493 1495 }
1494 1496 }
1495 1497
1496 1498 if (flags_ptr != NULL)
1497 1499 *flags_ptr = flags;
1498 1500 }
1499 1501
1500 1502 void mac_hcksum_set(mblk_t *mp, uint32_t start, uint32_t stuff,
1501 1503 uint32_t end, uint32_t value, uint32_t flags)
1502 1504 {
1503 1505 ASSERT(DB_TYPE(mp) == M_DATA);
1504 1506
1505 1507 DB_CKSUMSTART(mp) = (intptr_t)start;
1506 1508 DB_CKSUMSTUFF(mp) = (intptr_t)stuff;
1507 1509 DB_CKSUMEND(mp) = (intptr_t)end;
1508 1510 DB_CKSUMFLAGS(mp) = (uint16_t)flags;
1509 1511 DB_CKSUM16(mp) = (uint16_t)value;
1510 1512 }
1511 1513
1512 1514 void
1513 1515 mac_lso_get(mblk_t *mp, uint32_t *mss, uint32_t *flags)
1514 1516 {
1515 1517 ASSERT(DB_TYPE(mp) == M_DATA);
1516 1518
1517 1519 if (flags != NULL) {
1518 1520 *flags = DB_CKSUMFLAGS(mp) & HW_LSO;
1519 1521 if ((*flags != 0) && (mss != NULL))
1520 1522 *mss = (uint32_t)DB_LSOMSS(mp);
1521 1523 }
1522 1524 }
1523 1525
1524 1526 void
1525 1527 mac_transceiver_info_set_present(mac_transceiver_info_t *infop,
1526 1528 boolean_t present)
1527 1529 {
1528 1530 infop->mti_present = present;
1529 1531 }
1530 1532
1531 1533 void
1532 1534 mac_transceiver_info_set_usable(mac_transceiver_info_t *infop,
1533 1535 boolean_t usable)
1534 1536 {
1535 1537 infop->mti_usable = usable;
1536 1538 }
↓ open down ↓ |
828 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX