2 * Copyright (c) 2007-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
36 static __checkReturn efx_rc_t
37 siena_mac_multicast_list_set(
40 #endif /* 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 */
54 #endif /* EFSYS_OPT_SIENA */
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 */
69 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
71 __checkReturn efx_rc_t
76 efx_port_t *epp = &(enp->en_port);
77 const efx_mac_ops_t *emop = epp->ep_emop;
81 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
82 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
83 EFSYS_ASSERT(emop != NULL);
85 if (pdu < EFX_MAC_PDU_MIN) {
90 if (pdu > EFX_MAC_PDU_MAX) {
95 old_pdu = epp->ep_mac_pdu;
96 epp->ep_mac_pdu = (uint32_t)pdu;
97 if ((rc = emop->emo_pdu_set(enp)) != 0)
105 epp->ep_mac_pdu = old_pdu;
110 EFSYS_PROBE1(fail1, efx_rc_t, rc);
115 __checkReturn efx_rc_t
120 efx_port_t *epp = &(enp->en_port);
121 const efx_mac_ops_t *emop = epp->ep_emop;
124 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
130 EFSYS_PROBE1(fail1, efx_rc_t, rc);
135 __checkReturn efx_rc_t
140 efx_port_t *epp = &(enp->en_port);
141 const efx_mac_ops_t *emop = epp->ep_emop;
146 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
149 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
154 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
155 if (oui == 0x000000) {
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)
170 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
175 EFSYS_PROBE1(fail1, efx_rc_t, rc);
180 __checkReturn efx_rc_t
183 __in boolean_t all_unicst,
184 __in boolean_t mulcst,
185 __in boolean_t all_mulcst,
186 __in boolean_t brdcst)
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;
196 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
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;
204 epp->ep_all_unicst = all_unicst;
205 epp->ep_mulcst = mulcst;
206 epp->ep_all_mulcst = all_mulcst;
207 epp->ep_brdcst = brdcst;
209 if ((rc = emop->emo_reconfigure(enp)) != 0)
215 EFSYS_PROBE1(fail1, efx_rc_t, rc);
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;
225 __checkReturn efx_rc_t
228 __in boolean_t enabled)
230 efx_port_t *epp = &(enp->en_port);
231 const efx_mac_ops_t *emop = epp->ep_emop;
234 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
235 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
236 EFSYS_ASSERT(emop != NULL);
238 if (epp->ep_mac_drain == enabled)
241 epp->ep_mac_drain = enabled;
243 if ((rc = emop->emo_reconfigure(enp)) != 0)
249 EFSYS_PROBE1(fail1, efx_rc_t, rc);
254 __checkReturn efx_rc_t
257 __out boolean_t *mac_upp)
259 efx_port_t *epp = &(enp->en_port);
260 const efx_mac_ops_t *emop = epp->ep_emop;
263 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
264 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
266 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
272 EFSYS_PROBE1(fail1, efx_rc_t, rc);
277 __checkReturn efx_rc_t
280 __in unsigned int fcntl,
281 __in boolean_t autoneg)
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;
291 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
292 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
294 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
300 * Ignore a request to set flow control auto-negotiation
301 * if the PHY doesn't support it.
303 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
306 old_fcntl = epp->ep_fcntl;
307 old_autoneg = epp->ep_fcntl_autoneg;
308 old_adv_cap = epp->ep_adv_cap_mask;
310 epp->ep_fcntl = fcntl;
311 epp->ep_fcntl_autoneg = autoneg;
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.
318 if (fcntl & EFX_FCNTL_RESPOND)
319 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
320 1 << EFX_PHY_CAP_ASYM);
322 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
323 1 << EFX_PHY_CAP_ASYM);
325 if (fcntl & EFX_FCNTL_GENERATE)
326 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
328 if ((rc = epop->epo_reconfigure(enp)) != 0)
331 if ((rc = emop->emo_reconfigure(enp)) != 0)
342 epp->ep_fcntl = old_fcntl;
343 epp->ep_fcntl_autoneg = old_autoneg;
344 epp->ep_adv_cap_mask = old_adv_cap;
347 EFSYS_PROBE1(fail1, efx_rc_t, rc);
355 __out unsigned int *fcntl_wantedp,
356 __out unsigned int *fcntl_linkp)
358 efx_port_t *epp = &(enp->en_port);
359 unsigned int wanted = 0;
361 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
362 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
365 * Decode the requested flow control settings from the PHY
366 * advertised capabilities.
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;
373 *fcntl_linkp = epp->ep_fcntl;
374 *fcntl_wantedp = wanted;
377 __checkReturn efx_rc_t
378 efx_mac_multicast_list_set(
380 __in_ecount(6*count) uint8_t const *addrs,
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;
389 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
390 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
392 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
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) {
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);
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;
418 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
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);
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);
438 EFSYS_KMEM_FREE(enp->en_esip,
439 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
440 old_mulcst_addr_list);
447 EFSYS_PROBE1(fail1, efx_rc_t, rc);
453 __checkReturn efx_rc_t
454 efx_mac_filter_default_rxq_set(
457 __in boolean_t using_rss)
459 efx_port_t *epp = &(enp->en_port);
460 const efx_mac_ops_t *emop = epp->ep_emop;
463 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
464 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
466 if (emop->emo_filter_default_rxq_set != NULL) {
467 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
475 EFSYS_PROBE1(fail1, efx_rc_t, rc);
481 efx_mac_filter_default_rxq_clear(
484 efx_port_t *epp = &(enp->en_port);
485 const efx_mac_ops_t *emop = epp->ep_emop;
487 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
488 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
490 if (emop->emo_filter_default_rxq_clear != NULL)
491 emop->emo_filter_default_rxq_clear(enp);
495 __checkReturn efx_rc_t
499 efx_port_t *epp = &(enp->en_port);
500 efx_mac_type_t type = EFX_MAC_INVALID;
501 const efx_mac_ops_t *emop;
504 switch (enp->en_family) {
506 case EFX_FAMILY_SIENA:
507 emop = &__efx_siena_mac_ops;
508 type = EFX_MAC_SIENA;
510 #endif /* EFSYS_OPT_SIENA */
512 #if EFSYS_OPT_HUNTINGTON
513 case EFX_FAMILY_HUNTINGTON:
514 emop = &__efx_ef10_mac_ops;
515 type = EFX_MAC_HUNTINGTON;
517 #endif /* EFSYS_OPT_HUNTINGTON */
524 EFSYS_ASSERT(type != EFX_MAC_INVALID);
525 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
526 EFSYS_ASSERT(emop != NULL);
529 epp->ep_mac_type = type;
534 EFSYS_PROBE1(fail1, efx_rc_t, rc);
542 #define EFX_MAC_HASH_BITS (1 << 8)
544 /* Compute the multicast hash as used on Falcon and Siena. */
546 siena_mac_multicast_hash_compute(
547 __in_ecount(6*count) uint8_t const *addrs,
549 __out efx_oword_t *hash_low,
550 __out efx_oword_t *hash_high)
555 EFSYS_ASSERT(hash_low != NULL);
556 EFSYS_ASSERT(hash_high != NULL);
558 EFX_ZERO_OWORD(*hash_low);
559 EFX_ZERO_OWORD(*hash_high);
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;
566 EFX_SET_OWORD_BIT(*hash_low, index);
568 EFX_SET_OWORD_BIT(*hash_high, index - 128);
571 addrs += EFX_MAC_ADDR_LEN;
575 static __checkReturn efx_rc_t
576 siena_mac_multicast_list_set(
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];
584 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
585 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
587 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
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]);
595 if ((rc = emop->emo_reconfigure(enp)) != 0)
601 EFSYS_PROBE1(fail1, efx_rc_t, rc);
603 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
608 #endif /* EFSYS_OPT_SIENA */