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