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