1 /*-
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efsys.h"
35 #include "efx.h"
36 #include "efx_types.h"
37 #include "efx_impl.h"
38
39 #if EFSYS_OPT_MAC_FALCON_GMAC
40 #include "falcon_gmac.h"
41 #endif
42
43 #if EFSYS_OPT_MAC_FALCON_XMAC
44 #include "falcon_xmac.h"
45 #endif
46
47 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
48
49 static __checkReturn efx_rc_t
50 falconsiena_mac_multicast_list_set(
51 __in efx_nic_t *enp);
52
53 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
54
55 #if EFSYS_OPT_MAC_FALCON_GMAC
56 static efx_mac_ops_t __efx_falcon_gmac_ops = {
57 falcon_gmac_reset, /* emo_reset */
58 falcon_mac_poll, /* emo_poll */
59 falcon_mac_up, /* emo_up */
60 falcon_gmac_reconfigure, /* emo_addr_set */
61 falcon_gmac_reconfigure, /* emo_reconfigure */
62 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
63 NULL, /* emo_filter_set_default_rxq */
64 NULL, /* emo_filter_default_rxq_clear */
65 #if EFSYS_OPT_LOOPBACK
66 falcon_mac_loopback_set, /* emo_loopback_set */
67 #endif /* EFSYS_OPT_LOOPBACK */
68 #if EFSYS_OPT_MAC_STATS
69 falcon_mac_stats_upload, /* emo_stats_upload */
70 NULL, /* emo_stats_periodic */
71 falcon_gmac_stats_update /* emo_stats_update */
72 #endif /* EFSYS_OPT_MAC_STATS */
73 };
74 #endif /* EFSYS_OPT_MAC_FALCON_GMAC */
75
76 #if EFSYS_OPT_MAC_FALCON_XMAC
77 static efx_mac_ops_t __efx_falcon_xmac_ops = {
78 falcon_xmac_reset, /* emo_reset */
79 falcon_mac_poll, /* emo_poll */
80 falcon_mac_up, /* emo_up */
81 falcon_xmac_reconfigure, /* emo_addr_set */
82 falcon_xmac_reconfigure, /* emo_reconfigure */
83 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
84 NULL, /* emo_filter_set_default_rxq */
85 NULL, /* emo_filter_default_rxq_clear */
86 #if EFSYS_OPT_LOOPBACK
87 falcon_mac_loopback_set, /* emo_loopback_set */
88 #endif /* EFSYS_OPT_LOOPBACK */
89 #if EFSYS_OPT_MAC_STATS
90 falcon_mac_stats_upload, /* emo_stats_upload */
91 NULL, /* emo_stats_periodic */
92 falcon_xmac_stats_update /* emo_stats_update */
93 #endif /* EFSYS_OPT_MAC_STATS */
94 };
95 #endif /* EFSYS_OPT_MAC_FALCON_XMAC */
96
97 #if EFSYS_OPT_SIENA
98 static efx_mac_ops_t __efx_siena_mac_ops = {
99 NULL, /* emo_reset */
100 siena_mac_poll, /* emo_poll */
101 siena_mac_up, /* emo_up */
102 siena_mac_reconfigure, /* emo_addr_set */
103 siena_mac_reconfigure, /* emo_reconfigure */
104 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
105 NULL, /* emo_filter_set_default_rxq */
106 NULL, /* emo_filter_default_rxq_clear */
107 #if EFSYS_OPT_LOOPBACK
108 siena_mac_loopback_set, /* emo_loopback_set */
109 #endif /* EFSYS_OPT_LOOPBACK */
110 #if EFSYS_OPT_MAC_STATS
111 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
112 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
113 siena_mac_stats_update /* emo_stats_update */
114 #endif /* EFSYS_OPT_MAC_STATS */
115 };
116 #endif /* EFSYS_OPT_SIENA */
117
118 #if EFSYS_OPT_HUNTINGTON
119 static efx_mac_ops_t __efx_hunt_mac_ops = {
120 NULL, /* emo_reset */
121 hunt_mac_poll, /* emo_poll */
122 hunt_mac_up, /* emo_up */
123 hunt_mac_addr_set, /* emo_addr_set */
124 hunt_mac_reconfigure, /* emo_reconfigure */
125 hunt_mac_multicast_list_set, /* emo_multicast_list_set */
126 hunt_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
127 hunt_mac_filter_default_rxq_clear,
128 /* emo_filter_default_rxq_clear */
129 #if EFSYS_OPT_LOOPBACK
130 hunt_mac_loopback_set, /* emo_loopback_set */
131 #endif /* EFSYS_OPT_LOOPBACK */
132 #if EFSYS_OPT_MAC_STATS
133 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
134 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
135 hunt_mac_stats_update /* emo_stats_update */
136 #endif /* EFSYS_OPT_MAC_STATS */
137 };
138 #endif /* EFSYS_OPT_HUNTINGTON */
139
140 static efx_mac_ops_t *__efx_mac_ops[] = {
141 /* [EFX_MAC_INVALID] */
142 NULL,
143 /* [EFX_MAC_FALCON_GMAC] */
144 #if EFSYS_OPT_MAC_FALCON_GMAC
145 &__efx_falcon_gmac_ops,
146 #else
147 NULL,
148 #endif
149 /* [EFX_MAC_FALCON_XMAC] */
150 #if EFSYS_OPT_MAC_FALCON_XMAC
151 &__efx_falcon_xmac_ops,
152 #else
153 NULL,
154 #endif
155 /* [EFX_MAC_SIENA] */
156 #if EFSYS_OPT_SIENA
157 &__efx_siena_mac_ops,
158 #else
159 NULL,
160 #endif
161 /* [EFX_MAC_HUNTINGTON] */
162 #if EFSYS_OPT_HUNTINGTON
163 &__efx_hunt_mac_ops,
164 #else
165 NULL,
166 #endif
167 };
168
169 __checkReturn efx_rc_t
efx_mac_pdu_set(__in efx_nic_t * enp,__in size_t pdu)170 efx_mac_pdu_set(
171 __in efx_nic_t *enp,
172 __in size_t pdu)
173 {
174 efx_port_t *epp = &(enp->en_port);
175 efx_mac_ops_t *emop = epp->ep_emop;
176 uint32_t old_pdu;
177 efx_rc_t rc;
178
179 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
180 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
181 EFSYS_ASSERT(emop != NULL);
182
183 if (pdu < EFX_MAC_PDU_MIN) {
184 rc = EINVAL;
185 goto fail1;
186 }
187
188 if (pdu > EFX_MAC_PDU_MAX) {
189 rc = EINVAL;
190 goto fail2;
191 }
192
193 old_pdu = epp->ep_mac_pdu;
194 epp->ep_mac_pdu = (uint32_t)pdu;
195 if ((rc = emop->emo_reconfigure(enp)) != 0)
196 goto fail3;
197
198 return (0);
199
200 fail3:
201 EFSYS_PROBE(fail3);
202
203 epp->ep_mac_pdu = old_pdu;
204
205 fail2:
206 EFSYS_PROBE(fail2);
207 fail1:
208 EFSYS_PROBE1(fail1, efx_rc_t, rc);
209
210 return (rc);
211 }
212
213 __checkReturn efx_rc_t
efx_mac_addr_set(__in efx_nic_t * enp,__in uint8_t * addr)214 efx_mac_addr_set(
215 __in efx_nic_t *enp,
216 __in uint8_t *addr)
217 {
218 efx_port_t *epp = &(enp->en_port);
219 efx_mac_ops_t *emop = epp->ep_emop;
220 uint8_t old_addr[6];
221 uint32_t oui;
222 efx_rc_t rc;
223
224 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
226
227 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
228 rc = EINVAL;
229 goto fail1;
230 }
231
232 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
233 if (oui == 0x000000) {
234 rc = EINVAL;
235 goto fail2;
236 }
237
238 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
239 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
240 if ((rc = emop->emo_addr_set(enp)) != 0)
241 goto fail3;
242
243 return (0);
244
245 fail3:
246 EFSYS_PROBE(fail3);
247
248 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
249
250 fail2:
251 EFSYS_PROBE(fail2);
252 fail1:
253 EFSYS_PROBE1(fail1, efx_rc_t, rc);
254
255 return (rc);
256 }
257
258 __checkReturn efx_rc_t
efx_mac_filter_set(__in efx_nic_t * enp,__in boolean_t all_unicst,__in boolean_t mulcst,__in boolean_t all_mulcst,__in boolean_t brdcst)259 efx_mac_filter_set(
260 __in efx_nic_t *enp,
261 __in boolean_t all_unicst,
262 __in boolean_t mulcst,
263 __in boolean_t all_mulcst,
264 __in boolean_t brdcst)
265 {
266 efx_port_t *epp = &(enp->en_port);
267 efx_mac_ops_t *emop = epp->ep_emop;
268 boolean_t old_all_unicst;
269 boolean_t old_mulcst;
270 boolean_t old_all_mulcst;
271 boolean_t old_brdcst;
272 efx_rc_t rc;
273
274 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
275 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
276
277 old_all_unicst = epp->ep_all_unicst;
278 old_mulcst = epp->ep_mulcst;
279 old_all_mulcst = epp->ep_all_mulcst;
280 old_brdcst = epp->ep_brdcst;
281
282 epp->ep_all_unicst = all_unicst;
283 epp->ep_mulcst = mulcst;
284 epp->ep_all_mulcst = all_mulcst;
285 epp->ep_brdcst = brdcst;
286
287 if ((rc = emop->emo_reconfigure(enp)) != 0)
288 goto fail1;
289
290 return (0);
291
292 fail1:
293 EFSYS_PROBE1(fail1, efx_rc_t, rc);
294
295 epp->ep_all_unicst = old_all_unicst;
296 epp->ep_mulcst = old_mulcst;
297 epp->ep_all_mulcst = old_all_mulcst;
298 epp->ep_brdcst = old_brdcst;
299
300 return (rc);
301 }
302
303 __checkReturn efx_rc_t
efx_mac_drain(__in efx_nic_t * enp,__in boolean_t enabled)304 efx_mac_drain(
305 __in efx_nic_t *enp,
306 __in boolean_t enabled)
307 {
308 efx_port_t *epp = &(enp->en_port);
309 efx_mac_ops_t *emop = epp->ep_emop;
310 efx_rc_t rc;
311
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
314 EFSYS_ASSERT(emop != NULL);
315
316 if (epp->ep_mac_drain == enabled)
317 return (0);
318
319 epp->ep_mac_drain = enabled;
320
321 if (enabled && emop->emo_reset != NULL) {
322 if ((rc = emop->emo_reset(enp)) != 0)
323 goto fail1;
324
325 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
326 enp->en_reset_flags &= ~EFX_RESET_PHY;
327 }
328
329 if ((rc = emop->emo_reconfigure(enp)) != 0)
330 goto fail2;
331
332 return (0);
333
334 fail2:
335 EFSYS_PROBE(fail2);
336 fail1:
337 EFSYS_PROBE1(fail1, efx_rc_t, rc);
338
339 return (rc);
340 }
341
342 __checkReturn efx_rc_t
efx_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)343 efx_mac_up(
344 __in efx_nic_t *enp,
345 __out boolean_t *mac_upp)
346 {
347 efx_port_t *epp = &(enp->en_port);
348 efx_mac_ops_t *emop = epp->ep_emop;
349 efx_rc_t rc;
350
351 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
352 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
353
354 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
355 goto fail1;
356
357 return (0);
358
359 fail1:
360 EFSYS_PROBE1(fail1, efx_rc_t, rc);
361
362 return (rc);
363 }
364
365 __checkReturn efx_rc_t
efx_mac_fcntl_set(__in efx_nic_t * enp,__in unsigned int fcntl,__in boolean_t autoneg)366 efx_mac_fcntl_set(
367 __in efx_nic_t *enp,
368 __in unsigned int fcntl,
369 __in boolean_t autoneg)
370 {
371 efx_port_t *epp = &(enp->en_port);
372 efx_mac_ops_t *emop = epp->ep_emop;
373 efx_phy_ops_t *epop = epp->ep_epop;
374 unsigned int old_fcntl;
375 boolean_t old_autoneg;
376 unsigned int old_adv_cap;
377 efx_rc_t rc;
378
379 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
380 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
381
382 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
383 rc = EINVAL;
384 goto fail1;
385 }
386
387 /*
388 * Ignore a request to set flow control auto-negotiation
389 * if the PHY doesn't support it.
390 */
391 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
392 autoneg = B_FALSE;
393
394 old_fcntl = epp->ep_fcntl;
395 old_autoneg = epp->ep_fcntl_autoneg;
396 old_adv_cap = epp->ep_adv_cap_mask;
397
398 epp->ep_fcntl = fcntl;
399 epp->ep_fcntl_autoneg = autoneg;
400
401 /*
402 * Always encode the flow control settings in the advertised
403 * capabilities even if we are not trying to auto-negotiate
404 * them and reconfigure both the PHY and the MAC.
405 */
406 if (fcntl & EFX_FCNTL_RESPOND)
407 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
408 1 << EFX_PHY_CAP_ASYM);
409 else
410 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
411 1 << EFX_PHY_CAP_ASYM);
412
413 if (fcntl & EFX_FCNTL_GENERATE)
414 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
415
416 if ((rc = epop->epo_reconfigure(enp)) != 0)
417 goto fail2;
418
419 if ((rc = emop->emo_reconfigure(enp)) != 0)
420 goto fail3;
421
422 return (0);
423
424 fail3:
425 EFSYS_PROBE(fail3);
426
427 fail2:
428 EFSYS_PROBE(fail2);
429
430 epp->ep_fcntl = old_fcntl;
431 epp->ep_fcntl_autoneg = old_autoneg;
432 epp->ep_adv_cap_mask = old_adv_cap;
433
434 fail1:
435 EFSYS_PROBE1(fail1, efx_rc_t, rc);
436
437 return (rc);
438 }
439
440 void
efx_mac_fcntl_get(__in efx_nic_t * enp,__out unsigned int * fcntl_wantedp,__out unsigned int * fcntl_linkp)441 efx_mac_fcntl_get(
442 __in efx_nic_t *enp,
443 __out unsigned int *fcntl_wantedp,
444 __out unsigned int *fcntl_linkp)
445 {
446 efx_port_t *epp = &(enp->en_port);
447 unsigned int wanted = 0;
448
449 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
450 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
451
452 /*
453 * Decode the requested flow control settings from the PHY
454 * advertised capabilities.
455 */
456 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
457 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
458 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
459 wanted ^= EFX_FCNTL_GENERATE;
460
461 *fcntl_linkp = epp->ep_fcntl;
462 *fcntl_wantedp = wanted;
463 }
464
465 /*
466 * FIXME: efx_mac_hash_set() should be deleted once all its callers have been
467 * updated to use efx_mac_multicast_list_set().
468 * Then efx_port_t.ep_multicst_hash could be made Falcon/Siena specific as
469 * well.
470 */
471 __checkReturn efx_rc_t
efx_mac_hash_set(__in efx_nic_t * enp,__in_ecount (EFX_MAC_HASH_BITS)unsigned int const * bucket)472 efx_mac_hash_set(
473 __in efx_nic_t *enp,
474 __in_ecount(EFX_MAC_HASH_BITS) unsigned int const *bucket)
475 {
476 efx_port_t *epp = &(enp->en_port);
477 efx_mac_ops_t *emop = epp->ep_emop;
478 efx_oword_t old_hash[2];
479 unsigned int index;
480 efx_rc_t rc;
481
482 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
483 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
484
485 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
486
487 /* Set the lower 128 bits of the hash */
488 EFX_ZERO_OWORD(epp->ep_multicst_hash[0]);
489 for (index = 0; index < 128; index++) {
490 if (bucket[index] != 0)
491 EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index);
492 }
493
494 /* Set the upper 128 bits of the hash */
495 EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
496 for (index = 0; index < 128; index++) {
497 if (bucket[index + 128] != 0)
498 EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index);
499 }
500
501 if ((rc = emop->emo_reconfigure(enp)) != 0)
502 goto fail1;
503
504 return (0);
505
506 fail1:
507 EFSYS_PROBE1(fail1, efx_rc_t, rc);
508
509 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
510
511 return (rc);
512 }
513
514 __checkReturn efx_rc_t
515 efx_mac_multicast_list_set(
516 __in efx_nic_t *enp,
517 __in_ecount(6*count) uint8_t const *addrs,
518 __in int count)
519 {
520 efx_port_t *epp = &(enp->en_port);
521 efx_mac_ops_t *emop = epp->ep_emop;
522 uint8_t *old_mulcst_addr_list = NULL;
523 uint32_t old_mulcst_addr_count;
524 efx_rc_t rc;
525
526 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
527 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
528
529 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
530 rc = EINVAL;
531 goto fail1;
532 }
533
534 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
535 if (old_mulcst_addr_count > 0) {
536 /* Allocate memory to store old list (instead of using stack) */
537 EFSYS_KMEM_ALLOC(enp->en_esip,
538 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
539 old_mulcst_addr_list);
540 if (old_mulcst_addr_list == NULL) {
541 rc = ENOMEM;
542 goto fail2;
543 }
544
545 /* Save the old list in case we need to rollback */
546 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
547 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
548 }
549
550 /* Store the new list */
551 memcpy(epp->ep_mulcst_addr_list, addrs,
552 count * EFX_MAC_ADDR_LEN);
553 epp->ep_mulcst_addr_count = count;
554
555 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
556 goto fail3;
557
558 if (old_mulcst_addr_count > 0) {
559 EFSYS_KMEM_FREE(enp->en_esip,
560 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
561 old_mulcst_addr_list);
562 }
563
564 return (0);
565
566 fail3:
567 EFSYS_PROBE(fail3);
568
569 /* Restore original list on failure */
570 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
571 if (old_mulcst_addr_count > 0) {
572 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
573 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
574
575 EFSYS_KMEM_FREE(enp->en_esip,
576 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
577 old_mulcst_addr_list);
578 }
579
580 fail2:
581 EFSYS_PROBE(fail2);
582
583 fail1:
584 EFSYS_PROBE1(fail1, efx_rc_t, rc);
585
586 return (rc);
587
588 }
589
590 __checkReturn efx_rc_t
efx_mac_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)591 efx_mac_filter_default_rxq_set(
592 __in efx_nic_t *enp,
593 __in efx_rxq_t *erp,
594 __in boolean_t using_rss)
595 {
596 efx_port_t *epp = &(enp->en_port);
597 efx_mac_ops_t *emop = epp->ep_emop;
598 efx_rc_t rc;
599
600 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
601 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
602
603 if (emop->emo_filter_default_rxq_set != NULL) {
604 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
605 if (rc != 0)
606 goto fail1;
607 }
608
609 return (0);
610
611 fail1:
612 EFSYS_PROBE1(fail1, efx_rc_t, rc);
613
614 return (rc);
615 }
616
617 void
efx_mac_filter_default_rxq_clear(__in efx_nic_t * enp)618 efx_mac_filter_default_rxq_clear(
619 __in efx_nic_t *enp)
620 {
621 efx_port_t *epp = &(enp->en_port);
622 efx_mac_ops_t *emop = epp->ep_emop;
623
624 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
625 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
626
627 if (emop->emo_filter_default_rxq_clear != NULL)
628 emop->emo_filter_default_rxq_clear(enp);
629 }
630
631
632 #if EFSYS_OPT_MAC_STATS
633
634 #if EFSYS_OPT_NAMES
635
636 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
637 static const char *__efx_mac_stat_name[] = {
638 "rx_octets",
639 "rx_pkts",
640 "rx_unicst_pkts",
641 "rx_multicst_pkts",
642 "rx_brdcst_pkts",
643 "rx_pause_pkts",
644 "rx_le_64_pkts",
645 "rx_65_to_127_pkts",
646 "rx_128_to_255_pkts",
647 "rx_256_to_511_pkts",
648 "rx_512_to_1023_pkts",
649 "rx_1024_to_15xx_pkts",
650 "rx_ge_15xx_pkts",
651 "rx_errors",
652 "rx_fcs_errors",
653 "rx_drop_events",
654 "rx_false_carrier_errors",
655 "rx_symbol_errors",
656 "rx_align_errors",
657 "rx_internal_errors",
658 "rx_jabber_pkts",
659 "rx_lane0_char_err",
660 "rx_lane1_char_err",
661 "rx_lane2_char_err",
662 "rx_lane3_char_err",
663 "rx_lane0_disp_err",
664 "rx_lane1_disp_err",
665 "rx_lane2_disp_err",
666 "rx_lane3_disp_err",
667 "rx_match_fault",
668 "rx_nodesc_drop_cnt",
669 "tx_octets",
670 "tx_pkts",
671 "tx_unicst_pkts",
672 "tx_multicst_pkts",
673 "tx_brdcst_pkts",
674 "tx_pause_pkts",
675 "tx_le_64_pkts",
676 "tx_65_to_127_pkts",
677 "tx_128_to_255_pkts",
678 "tx_256_to_511_pkts",
679 "tx_512_to_1023_pkts",
680 "tx_1024_to_15xx_pkts",
681 "tx_ge_15xx_pkts",
682 "tx_errors",
683 "tx_sgl_col_pkts",
684 "tx_mult_col_pkts",
685 "tx_ex_col_pkts",
686 "tx_late_col_pkts",
687 "tx_def_pkts",
688 "tx_ex_def_pkts",
689 "pm_trunc_bb_overflow",
690 "pm_discard_bb_overflow",
691 "pm_trunc_vfifo_full",
692 "pm_discard_vfifo_full",
693 "pm_trunc_qbb",
694 "pm_discard_qbb",
695 "pm_discard_mapping",
696 "rxdp_q_disabled_pkts",
697 "rxdp_di_dropped_pkts",
698 "rxdp_streaming_pkts",
699 "rxdp_hlb_fetch",
700 "rxdp_hlb_wait",
701 "vadapter_rx_unicast_packets",
702 "vadapter_rx_unicast_bytes",
703 "vadapter_rx_multicast_packets",
704 "vadapter_rx_multicast_bytes",
705 "vadapter_rx_broadcast_packets",
706 "vadapter_rx_broadcast_bytes",
707 "vadapter_rx_bad_packets",
708 "vadapter_rx_bad_bytes",
709 "vadapter_rx_overflow",
710 "vadapter_tx_unicast_packets",
711 "vadapter_tx_unicast_bytes",
712 "vadapter_tx_multicast_packets",
713 "vadapter_tx_multicast_bytes",
714 "vadapter_tx_broadcast_packets",
715 "vadapter_tx_broadcast_bytes",
716 "vadapter_tx_bad_packets",
717 "vadapter_tx_bad_bytes",
718 "vadapter_tx_overflow",
719 };
720 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
721
722 __checkReturn const char *
efx_mac_stat_name(__in efx_nic_t * enp,__in unsigned int id)723 efx_mac_stat_name(
724 __in efx_nic_t *enp,
725 __in unsigned int id)
726 {
727 _NOTE(ARGUNUSED(enp))
728 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
729
730 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
731 return (__efx_mac_stat_name[id]);
732 }
733
734 #endif /* EFSYS_OPT_NAMES */
735
736 __checkReturn efx_rc_t
efx_mac_stats_upload(__in efx_nic_t * enp,__in efsys_mem_t * esmp)737 efx_mac_stats_upload(
738 __in efx_nic_t *enp,
739 __in efsys_mem_t *esmp)
740 {
741 efx_port_t *epp = &(enp->en_port);
742 efx_mac_ops_t *emop = epp->ep_emop;
743 efx_rc_t rc;
744
745 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
746 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
747 EFSYS_ASSERT(emop != NULL);
748
749 /*
750 * Don't assert !ep_mac_stats_pending, because the client might
751 * have failed to finalise statistics when previously stopping
752 * the port.
753 */
754 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
755 goto fail1;
756
757 epp->ep_mac_stats_pending = B_TRUE;
758
759 return (0);
760
761 fail1:
762 EFSYS_PROBE1(fail1, efx_rc_t, rc);
763
764 return (rc);
765 }
766
767 __checkReturn efx_rc_t
efx_mac_stats_periodic(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint16_t period_ms,__in boolean_t events)768 efx_mac_stats_periodic(
769 __in efx_nic_t *enp,
770 __in efsys_mem_t *esmp,
771 __in uint16_t period_ms,
772 __in boolean_t events)
773 {
774 efx_port_t *epp = &(enp->en_port);
775 efx_mac_ops_t *emop = epp->ep_emop;
776 efx_rc_t rc;
777
778 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
779 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
780
781 EFSYS_ASSERT(emop != NULL);
782
783 if (emop->emo_stats_periodic == NULL) {
784 rc = EINVAL;
785 goto fail1;
786 }
787
788 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
789 goto fail2;
790
791 return (0);
792
793 fail2:
794 EFSYS_PROBE(fail2);
795 fail1:
796 EFSYS_PROBE1(fail1, efx_rc_t, rc);
797
798 return (rc);
799 }
800
801
802 __checkReturn efx_rc_t
efx_mac_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MAC_NSTATS)efsys_stat_t * essp,__inout_opt uint32_t * generationp)803 efx_mac_stats_update(
804 __in efx_nic_t *enp,
805 __in efsys_mem_t *esmp,
806 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
807 __inout_opt uint32_t *generationp)
808 {
809 efx_port_t *epp = &(enp->en_port);
810 efx_mac_ops_t *emop = epp->ep_emop;
811 efx_rc_t rc;
812
813 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
814 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
815 EFSYS_ASSERT(emop != NULL);
816
817 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
818 if (rc == 0)
819 epp->ep_mac_stats_pending = B_FALSE;
820
821 return (rc);
822 }
823
824 #endif /* EFSYS_OPT_MAC_STATS */
825
826 __checkReturn efx_rc_t
efx_mac_select(__in efx_nic_t * enp)827 efx_mac_select(
828 __in efx_nic_t *enp)
829 {
830 efx_port_t *epp = &(enp->en_port);
831 efx_mac_type_t type = EFX_MAC_INVALID;
832 efx_mac_ops_t *emop;
833 int rc = EINVAL;
834
835 #if EFSYS_OPT_HUNTINGTON
836 if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
837 type = EFX_MAC_HUNTINGTON;
838 goto chosen;
839 }
840 #endif
841
842 #if EFSYS_OPT_SIENA
843 if (enp->en_family == EFX_FAMILY_SIENA) {
844 type = EFX_MAC_SIENA;
845 goto chosen;
846 }
847 #endif
848
849 #if EFSYS_OPT_FALCON
850 switch (epp->ep_link_mode) {
851 #if EFSYS_OPT_MAC_FALCON_GMAC
852 case EFX_LINK_100HDX:
853 case EFX_LINK_100FDX:
854 case EFX_LINK_1000HDX:
855 case EFX_LINK_1000FDX:
856 type = EFX_MAC_FALCON_GMAC;
857 goto chosen;
858 #endif /* EFSYS_OPT_FALCON_GMAC */
859
860 #if EFSYS_OPT_MAC_FALCON_XMAC
861 case EFX_LINK_10000FDX:
862 type = EFX_MAC_FALCON_XMAC;
863 goto chosen;
864 #endif /* EFSYS_OPT_FALCON_XMAC */
865
866 default:
867 #if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
868 /* Only initialise a MAC supported by the PHY */
869 if (epp->ep_phy_cap_mask &
870 ((1 << EFX_PHY_CAP_1000FDX) |
871 (1 << EFX_PHY_CAP_1000HDX) |
872 (1 << EFX_PHY_CAP_100FDX) |
873 (1 << EFX_PHY_CAP_100HDX) |
874 (1 << EFX_PHY_CAP_10FDX) |
875 (1 << EFX_PHY_CAP_10FDX)))
876 type = EFX_MAC_FALCON_GMAC;
877 else
878 type = EFX_MAC_FALCON_XMAC;
879 #elif EFSYS_OPT_MAC_FALCON_GMAC
880 type = EFX_MAC_FALCON_GMAC;
881 #else
882 type = EFX_MAC_FALCON_XMAC;
883 #endif
884 goto chosen;
885 }
886 #endif /* EFSYS_OPT_FALCON */
887
888 chosen:
889 EFSYS_ASSERT(type != EFX_MAC_INVALID);
890 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
891 emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
892 EFSYS_ASSERT(emop != NULL);
893
894 epp->ep_mac_type = type;
895
896 if (emop->emo_reset != NULL) {
897 if ((rc = emop->emo_reset(enp)) != 0)
898 goto fail1;
899
900 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
901 enp->en_reset_flags &= ~EFX_RESET_MAC;
902 }
903
904 return (0);
905
906 fail1:
907 EFSYS_PROBE1(fail1, efx_rc_t, rc);
908
909 return (rc);
910 }
911
912
913 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
914
915 /* Compute the multicast hash as used on Falcon and Siena. */
916 static void
917 falconsiena_mac_multicast_hash_compute(
918 __in_ecount(6*count) uint8_t const *addrs,
919 __in int count,
920 __out efx_oword_t *hash_low,
921 __out efx_oword_t *hash_high)
922 {
923 uint32_t crc, index;
924 int i;
925
926 EFSYS_ASSERT(hash_low != NULL);
927 EFSYS_ASSERT(hash_high != NULL);
928
929 EFX_ZERO_OWORD(*hash_low);
930 EFX_ZERO_OWORD(*hash_high);
931
932 for (i = 0; i < count; i++) {
933 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
934 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
935 index = crc % EFX_MAC_HASH_BITS;
936 if (index < 128) {
937 EFX_SET_OWORD_BIT(*hash_low, index);
938 } else {
939 EFX_SET_OWORD_BIT(*hash_high, index - 128);
940 }
941
942 addrs += EFX_MAC_ADDR_LEN;
943 }
944 }
945
946 static __checkReturn efx_rc_t
falconsiena_mac_multicast_list_set(__in efx_nic_t * enp)947 falconsiena_mac_multicast_list_set(
948 __in efx_nic_t *enp)
949 {
950 efx_port_t *epp = &(enp->en_port);
951 efx_mac_ops_t *emop = epp->ep_emop;
952 efx_oword_t old_hash[2];
953 efx_rc_t rc;
954
955 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
956 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
957
958 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
959
960 falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list,
961 epp->ep_mulcst_addr_count,
962 &epp->ep_multicst_hash[0],
963 &epp->ep_multicst_hash[1]);
964
965 if ((rc = emop->emo_reconfigure(enp)) != 0)
966 goto fail1;
967
968 return (0);
969
970 fail1:
971 EFSYS_PROBE1(fail1, efx_rc_t, rc);
972
973 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
974
975 return (rc);
976 }
977
978 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
979