net/sfc/base: import SFN7xxx family support
[dpdk.git] / drivers / net / sfc / base / efx_mac.c
1 /*
2  * Copyright (c) 2007-2016 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 "efx.h"
32 #include "efx_impl.h"
33
34 #if EFSYS_OPT_SIENA
35
36 static  __checkReturn   efx_rc_t
37 siena_mac_multicast_list_set(
38         __in            efx_nic_t *enp);
39
40 #endif /* EFSYS_OPT_SIENA */
41
42 #if EFSYS_OPT_SIENA
43 static const efx_mac_ops_t      __efx_siena_mac_ops = {
44         siena_mac_poll,                         /* emo_poll */
45         siena_mac_up,                           /* emo_up */
46         siena_mac_reconfigure,                  /* emo_addr_set */
47         siena_mac_reconfigure,                  /* emo_pdu_set */
48         siena_mac_pdu_get,                      /* emo_pdu_get */
49         siena_mac_reconfigure,                  /* emo_reconfigure */
50         siena_mac_multicast_list_set,           /* emo_multicast_list_set */
51         NULL,                                   /* emo_filter_set_default_rxq */
52         NULL,                           /* emo_filter_default_rxq_clear */
53 };
54 #endif  /* EFSYS_OPT_SIENA */
55
56 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
57 static const efx_mac_ops_t      __efx_ef10_mac_ops = {
58         ef10_mac_poll,                          /* emo_poll */
59         ef10_mac_up,                            /* emo_up */
60         ef10_mac_addr_set,                      /* emo_addr_set */
61         ef10_mac_pdu_set,                       /* emo_pdu_set */
62         ef10_mac_pdu_get,                       /* emo_pdu_get */
63         ef10_mac_reconfigure,                   /* emo_reconfigure */
64         ef10_mac_multicast_list_set,            /* emo_multicast_list_set */
65         ef10_mac_filter_default_rxq_set,        /* emo_filter_default_rxq_set */
66         ef10_mac_filter_default_rxq_clear,
67                                         /* emo_filter_default_rxq_clear */
68 };
69 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
70
71         __checkReturn                   efx_rc_t
72 efx_mac_pdu_set(
73         __in                            efx_nic_t *enp,
74         __in                            size_t pdu)
75 {
76         efx_port_t *epp = &(enp->en_port);
77         const efx_mac_ops_t *emop = epp->ep_emop;
78         uint32_t old_pdu;
79         efx_rc_t rc;
80
81         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
82         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
83         EFSYS_ASSERT(emop != NULL);
84
85         if (pdu < EFX_MAC_PDU_MIN) {
86                 rc = EINVAL;
87                 goto fail1;
88         }
89
90         if (pdu > EFX_MAC_PDU_MAX) {
91                 rc = EINVAL;
92                 goto fail2;
93         }
94
95         old_pdu = epp->ep_mac_pdu;
96         epp->ep_mac_pdu = (uint32_t)pdu;
97         if ((rc = emop->emo_pdu_set(enp)) != 0)
98                 goto fail3;
99
100         return (0);
101
102 fail3:
103         EFSYS_PROBE(fail3);
104
105         epp->ep_mac_pdu = old_pdu;
106
107 fail2:
108         EFSYS_PROBE(fail2);
109 fail1:
110         EFSYS_PROBE1(fail1, efx_rc_t, rc);
111
112         return (rc);
113 }
114
115         __checkReturn   efx_rc_t
116 efx_mac_pdu_get(
117         __in            efx_nic_t *enp,
118         __out           size_t *pdu)
119 {
120         efx_port_t *epp = &(enp->en_port);
121         const efx_mac_ops_t *emop = epp->ep_emop;
122         efx_rc_t rc;
123
124         if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
125                 goto fail1;
126
127         return (0);
128
129 fail1:
130         EFSYS_PROBE1(fail1, efx_rc_t, rc);
131
132         return (rc);
133 }
134
135         __checkReturn                   efx_rc_t
136 efx_mac_addr_set(
137         __in                            efx_nic_t *enp,
138         __in                            uint8_t *addr)
139 {
140         efx_port_t *epp = &(enp->en_port);
141         const efx_mac_ops_t *emop = epp->ep_emop;
142         uint8_t old_addr[6];
143         uint32_t oui;
144         efx_rc_t rc;
145
146         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
148
149         if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
150                 rc = EINVAL;
151                 goto fail1;
152         }
153
154         oui = addr[0] << 16 | addr[1] << 8 | addr[2];
155         if (oui == 0x000000) {
156                 rc = EINVAL;
157                 goto fail2;
158         }
159
160         EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
161         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
162         if ((rc = emop->emo_addr_set(enp)) != 0)
163                 goto fail3;
164
165         return (0);
166
167 fail3:
168         EFSYS_PROBE(fail3);
169
170         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
171
172 fail2:
173         EFSYS_PROBE(fail2);
174 fail1:
175         EFSYS_PROBE1(fail1, efx_rc_t, rc);
176
177         return (rc);
178 }
179
180         __checkReturn                   efx_rc_t
181 efx_mac_filter_set(
182         __in                            efx_nic_t *enp,
183         __in                            boolean_t all_unicst,
184         __in                            boolean_t mulcst,
185         __in                            boolean_t all_mulcst,
186         __in                            boolean_t brdcst)
187 {
188         efx_port_t *epp = &(enp->en_port);
189         const efx_mac_ops_t *emop = epp->ep_emop;
190         boolean_t old_all_unicst;
191         boolean_t old_mulcst;
192         boolean_t old_all_mulcst;
193         boolean_t old_brdcst;
194         efx_rc_t rc;
195
196         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
198
199         old_all_unicst = epp->ep_all_unicst;
200         old_mulcst = epp->ep_mulcst;
201         old_all_mulcst = epp->ep_all_mulcst;
202         old_brdcst = epp->ep_brdcst;
203
204         epp->ep_all_unicst = all_unicst;
205         epp->ep_mulcst = mulcst;
206         epp->ep_all_mulcst = all_mulcst;
207         epp->ep_brdcst = brdcst;
208
209         if ((rc = emop->emo_reconfigure(enp)) != 0)
210                 goto fail1;
211
212         return (0);
213
214 fail1:
215         EFSYS_PROBE1(fail1, efx_rc_t, rc);
216
217         epp->ep_all_unicst = old_all_unicst;
218         epp->ep_mulcst = old_mulcst;
219         epp->ep_all_mulcst = old_all_mulcst;
220         epp->ep_brdcst = old_brdcst;
221
222         return (rc);
223 }
224
225         __checkReturn                   efx_rc_t
226 efx_mac_drain(
227         __in                            efx_nic_t *enp,
228         __in                            boolean_t enabled)
229 {
230         efx_port_t *epp = &(enp->en_port);
231         const efx_mac_ops_t *emop = epp->ep_emop;
232         efx_rc_t rc;
233
234         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
235         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
236         EFSYS_ASSERT(emop != NULL);
237
238         if (epp->ep_mac_drain == enabled)
239                 return (0);
240
241         epp->ep_mac_drain = enabled;
242
243         if ((rc = emop->emo_reconfigure(enp)) != 0)
244                 goto fail1;
245
246         return (0);
247
248 fail1:
249         EFSYS_PROBE1(fail1, efx_rc_t, rc);
250
251         return (rc);
252 }
253
254         __checkReturn   efx_rc_t
255 efx_mac_up(
256         __in            efx_nic_t *enp,
257         __out           boolean_t *mac_upp)
258 {
259         efx_port_t *epp = &(enp->en_port);
260         const efx_mac_ops_t *emop = epp->ep_emop;
261         efx_rc_t rc;
262
263         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
264         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
265
266         if ((rc = emop->emo_up(enp, mac_upp)) != 0)
267                 goto fail1;
268
269         return (0);
270
271 fail1:
272         EFSYS_PROBE1(fail1, efx_rc_t, rc);
273
274         return (rc);
275 }
276
277         __checkReturn                   efx_rc_t
278 efx_mac_fcntl_set(
279         __in                            efx_nic_t *enp,
280         __in                            unsigned int fcntl,
281         __in                            boolean_t autoneg)
282 {
283         efx_port_t *epp = &(enp->en_port);
284         const efx_mac_ops_t *emop = epp->ep_emop;
285         const efx_phy_ops_t *epop = epp->ep_epop;
286         unsigned int old_fcntl;
287         boolean_t old_autoneg;
288         unsigned int old_adv_cap;
289         efx_rc_t rc;
290
291         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
292         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
293
294         if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
295                 rc = EINVAL;
296                 goto fail1;
297         }
298
299         /*
300          * Ignore a request to set flow control auto-negotiation
301          * if the PHY doesn't support it.
302          */
303         if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
304                 autoneg = B_FALSE;
305
306         old_fcntl = epp->ep_fcntl;
307         old_autoneg = epp->ep_fcntl_autoneg;
308         old_adv_cap = epp->ep_adv_cap_mask;
309
310         epp->ep_fcntl = fcntl;
311         epp->ep_fcntl_autoneg = autoneg;
312
313         /*
314          * Always encode the flow control settings in the advertised
315          * capabilities even if we are not trying to auto-negotiate
316          * them and reconfigure both the PHY and the MAC.
317          */
318         if (fcntl & EFX_FCNTL_RESPOND)
319                 epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
320                                             1 << EFX_PHY_CAP_ASYM);
321         else
322                 epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
323                                             1 << EFX_PHY_CAP_ASYM);
324
325         if (fcntl & EFX_FCNTL_GENERATE)
326                 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
327
328         if ((rc = epop->epo_reconfigure(enp)) != 0)
329                 goto fail2;
330
331         if ((rc = emop->emo_reconfigure(enp)) != 0)
332                 goto fail3;
333
334         return (0);
335
336 fail3:
337         EFSYS_PROBE(fail3);
338
339 fail2:
340         EFSYS_PROBE(fail2);
341
342         epp->ep_fcntl = old_fcntl;
343         epp->ep_fcntl_autoneg = old_autoneg;
344         epp->ep_adv_cap_mask = old_adv_cap;
345
346 fail1:
347         EFSYS_PROBE1(fail1, efx_rc_t, rc);
348
349         return (rc);
350 }
351
352                         void
353 efx_mac_fcntl_get(
354         __in            efx_nic_t *enp,
355         __out           unsigned int *fcntl_wantedp,
356         __out           unsigned int *fcntl_linkp)
357 {
358         efx_port_t *epp = &(enp->en_port);
359         unsigned int wanted = 0;
360
361         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
362         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
363
364         /*
365          * Decode the requested flow control settings from the PHY
366          * advertised capabilities.
367          */
368         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
369                 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
370         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
371                 wanted ^= EFX_FCNTL_GENERATE;
372
373         *fcntl_linkp = epp->ep_fcntl;
374         *fcntl_wantedp = wanted;
375 }
376
377         __checkReturn   efx_rc_t
378 efx_mac_multicast_list_set(
379         __in                            efx_nic_t *enp,
380         __in_ecount(6*count)            uint8_t const *addrs,
381         __in                            int count)
382 {
383         efx_port_t *epp = &(enp->en_port);
384         const efx_mac_ops_t *emop = epp->ep_emop;
385         uint8_t *old_mulcst_addr_list = NULL;
386         uint32_t old_mulcst_addr_count;
387         efx_rc_t rc;
388
389         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
390         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
391
392         if (count > EFX_MAC_MULTICAST_LIST_MAX) {
393                 rc = EINVAL;
394                 goto fail1;
395         }
396
397         old_mulcst_addr_count = epp->ep_mulcst_addr_count;
398         if (old_mulcst_addr_count > 0) {
399                 /* Allocate memory to store old list (instead of using stack) */
400                 EFSYS_KMEM_ALLOC(enp->en_esip,
401                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
402                                 old_mulcst_addr_list);
403                 if (old_mulcst_addr_list == NULL) {
404                         rc = ENOMEM;
405                         goto fail2;
406                 }
407
408                 /* Save the old list in case we need to rollback */
409                 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
410                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
411         }
412
413         /* Store the new list */
414         memcpy(epp->ep_mulcst_addr_list, addrs,
415                 count * EFX_MAC_ADDR_LEN);
416         epp->ep_mulcst_addr_count = count;
417
418         if ((rc = emop->emo_multicast_list_set(enp)) != 0)
419                 goto fail3;
420
421         if (old_mulcst_addr_count > 0) {
422                 EFSYS_KMEM_FREE(enp->en_esip,
423                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
424                                 old_mulcst_addr_list);
425         }
426
427         return (0);
428
429 fail3:
430         EFSYS_PROBE(fail3);
431
432         /* Restore original list on failure */
433         epp->ep_mulcst_addr_count = old_mulcst_addr_count;
434         if (old_mulcst_addr_count > 0) {
435                 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
436                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
437
438                 EFSYS_KMEM_FREE(enp->en_esip,
439                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
440                                 old_mulcst_addr_list);
441         }
442
443 fail2:
444         EFSYS_PROBE(fail2);
445
446 fail1:
447         EFSYS_PROBE1(fail1, efx_rc_t, rc);
448
449         return (rc);
450
451 }
452
453         __checkReturn   efx_rc_t
454 efx_mac_filter_default_rxq_set(
455         __in            efx_nic_t *enp,
456         __in            efx_rxq_t *erp,
457         __in            boolean_t using_rss)
458 {
459         efx_port_t *epp = &(enp->en_port);
460         const efx_mac_ops_t *emop = epp->ep_emop;
461         efx_rc_t rc;
462
463         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
464         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
465
466         if (emop->emo_filter_default_rxq_set != NULL) {
467                 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
468                 if (rc != 0)
469                         goto fail1;
470         }
471
472         return (0);
473
474 fail1:
475         EFSYS_PROBE1(fail1, efx_rc_t, rc);
476
477         return (rc);
478 }
479
480                         void
481 efx_mac_filter_default_rxq_clear(
482         __in            efx_nic_t *enp)
483 {
484         efx_port_t *epp = &(enp->en_port);
485         const efx_mac_ops_t *emop = epp->ep_emop;
486
487         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
488         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
489
490         if (emop->emo_filter_default_rxq_clear != NULL)
491                 emop->emo_filter_default_rxq_clear(enp);
492 }
493
494
495         __checkReturn                   efx_rc_t
496 efx_mac_select(
497         __in                            efx_nic_t *enp)
498 {
499         efx_port_t *epp = &(enp->en_port);
500         efx_mac_type_t type = EFX_MAC_INVALID;
501         const efx_mac_ops_t *emop;
502         int rc = EINVAL;
503
504         switch (enp->en_family) {
505 #if EFSYS_OPT_SIENA
506         case EFX_FAMILY_SIENA:
507                 emop = &__efx_siena_mac_ops;
508                 type = EFX_MAC_SIENA;
509                 break;
510 #endif /* EFSYS_OPT_SIENA */
511
512 #if EFSYS_OPT_HUNTINGTON
513         case EFX_FAMILY_HUNTINGTON:
514                 emop = &__efx_ef10_mac_ops;
515                 type = EFX_MAC_HUNTINGTON;
516                 break;
517 #endif /* EFSYS_OPT_HUNTINGTON */
518
519         default:
520                 rc = EINVAL;
521                 goto fail1;
522         }
523
524         EFSYS_ASSERT(type != EFX_MAC_INVALID);
525         EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
526         EFSYS_ASSERT(emop != NULL);
527
528         epp->ep_emop = emop;
529         epp->ep_mac_type = type;
530
531         return (0);
532
533 fail1:
534         EFSYS_PROBE1(fail1, efx_rc_t, rc);
535
536         return (rc);
537 }
538
539
540 #if EFSYS_OPT_SIENA
541
542 #define EFX_MAC_HASH_BITS       (1 << 8)
543
544 /* Compute the multicast hash as used on Falcon and Siena. */
545 static  void
546 siena_mac_multicast_hash_compute(
547         __in_ecount(6*count)            uint8_t const *addrs,
548         __in                            int count,
549         __out                           efx_oword_t *hash_low,
550         __out                           efx_oword_t *hash_high)
551 {
552         uint32_t crc, index;
553         int i;
554
555         EFSYS_ASSERT(hash_low != NULL);
556         EFSYS_ASSERT(hash_high != NULL);
557
558         EFX_ZERO_OWORD(*hash_low);
559         EFX_ZERO_OWORD(*hash_high);
560
561         for (i = 0; i < count; i++) {
562                 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
563                 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
564                 index = crc % EFX_MAC_HASH_BITS;
565                 if (index < 128) {
566                         EFX_SET_OWORD_BIT(*hash_low, index);
567                 } else {
568                         EFX_SET_OWORD_BIT(*hash_high, index - 128);
569                 }
570
571                 addrs += EFX_MAC_ADDR_LEN;
572         }
573 }
574
575 static  __checkReturn   efx_rc_t
576 siena_mac_multicast_list_set(
577         __in            efx_nic_t *enp)
578 {
579         efx_port_t *epp = &(enp->en_port);
580         const efx_mac_ops_t *emop = epp->ep_emop;
581         efx_oword_t old_hash[2];
582         efx_rc_t rc;
583
584         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
585         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
586
587         memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
588
589         siena_mac_multicast_hash_compute(
590             epp->ep_mulcst_addr_list,
591             epp->ep_mulcst_addr_count,
592             &epp->ep_multicst_hash[0],
593             &epp->ep_multicst_hash[1]);
594
595         if ((rc = emop->emo_reconfigure(enp)) != 0)
596                 goto fail1;
597
598         return (0);
599
600 fail1:
601         EFSYS_PROBE1(fail1, efx_rc_t, rc);
602
603         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
604
605         return (rc);
606 }
607
608 #endif /* EFSYS_OPT_SIENA */