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 __checkReturn efx_rc_t
61 efx_port_t *epp = &(enp->en_port);
62 const efx_mac_ops_t *emop = epp->ep_emop;
66 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
67 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
68 EFSYS_ASSERT(emop != NULL);
70 if (pdu < EFX_MAC_PDU_MIN) {
75 if (pdu > EFX_MAC_PDU_MAX) {
80 old_pdu = epp->ep_mac_pdu;
81 epp->ep_mac_pdu = (uint32_t)pdu;
82 if ((rc = emop->emo_pdu_set(enp)) != 0)
90 epp->ep_mac_pdu = old_pdu;
95 EFSYS_PROBE1(fail1, efx_rc_t, rc);
100 __checkReturn efx_rc_t
105 efx_port_t *epp = &(enp->en_port);
106 const efx_mac_ops_t *emop = epp->ep_emop;
109 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
115 EFSYS_PROBE1(fail1, efx_rc_t, rc);
120 __checkReturn efx_rc_t
125 efx_port_t *epp = &(enp->en_port);
126 const efx_mac_ops_t *emop = epp->ep_emop;
131 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
132 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
134 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
139 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
140 if (oui == 0x000000) {
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)
155 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
160 EFSYS_PROBE1(fail1, efx_rc_t, rc);
165 __checkReturn efx_rc_t
168 __in boolean_t all_unicst,
169 __in boolean_t mulcst,
170 __in boolean_t all_mulcst,
171 __in boolean_t brdcst)
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;
181 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
182 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
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;
189 epp->ep_all_unicst = all_unicst;
190 epp->ep_mulcst = mulcst;
191 epp->ep_all_mulcst = all_mulcst;
192 epp->ep_brdcst = brdcst;
194 if ((rc = emop->emo_reconfigure(enp)) != 0)
200 EFSYS_PROBE1(fail1, efx_rc_t, rc);
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;
210 __checkReturn efx_rc_t
213 __in boolean_t enabled)
215 efx_port_t *epp = &(enp->en_port);
216 const efx_mac_ops_t *emop = epp->ep_emop;
219 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
220 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
221 EFSYS_ASSERT(emop != NULL);
223 if (epp->ep_mac_drain == enabled)
226 epp->ep_mac_drain = enabled;
228 if ((rc = emop->emo_reconfigure(enp)) != 0)
234 EFSYS_PROBE1(fail1, efx_rc_t, rc);
239 __checkReturn efx_rc_t
242 __out boolean_t *mac_upp)
244 efx_port_t *epp = &(enp->en_port);
245 const efx_mac_ops_t *emop = epp->ep_emop;
248 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
249 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
251 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
257 EFSYS_PROBE1(fail1, efx_rc_t, rc);
262 __checkReturn efx_rc_t
265 __in unsigned int fcntl,
266 __in boolean_t autoneg)
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;
276 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
277 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
279 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
285 * Ignore a request to set flow control auto-negotiation
286 * if the PHY doesn't support it.
288 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
291 old_fcntl = epp->ep_fcntl;
292 old_autoneg = epp->ep_fcntl_autoneg;
293 old_adv_cap = epp->ep_adv_cap_mask;
295 epp->ep_fcntl = fcntl;
296 epp->ep_fcntl_autoneg = autoneg;
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.
303 if (fcntl & EFX_FCNTL_RESPOND)
304 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
305 1 << EFX_PHY_CAP_ASYM);
307 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
308 1 << EFX_PHY_CAP_ASYM);
310 if (fcntl & EFX_FCNTL_GENERATE)
311 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
313 if ((rc = epop->epo_reconfigure(enp)) != 0)
316 if ((rc = emop->emo_reconfigure(enp)) != 0)
327 epp->ep_fcntl = old_fcntl;
328 epp->ep_fcntl_autoneg = old_autoneg;
329 epp->ep_adv_cap_mask = old_adv_cap;
332 EFSYS_PROBE1(fail1, efx_rc_t, rc);
340 __out unsigned int *fcntl_wantedp,
341 __out unsigned int *fcntl_linkp)
343 efx_port_t *epp = &(enp->en_port);
344 unsigned int wanted = 0;
346 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
347 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
350 * Decode the requested flow control settings from the PHY
351 * advertised capabilities.
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;
358 *fcntl_linkp = epp->ep_fcntl;
359 *fcntl_wantedp = wanted;
362 __checkReturn efx_rc_t
363 efx_mac_multicast_list_set(
365 __in_ecount(6*count) uint8_t const *addrs,
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;
374 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
375 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
377 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
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) {
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);
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;
403 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
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);
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);
423 EFSYS_KMEM_FREE(enp->en_esip,
424 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
425 old_mulcst_addr_list);
432 EFSYS_PROBE1(fail1, efx_rc_t, rc);
438 __checkReturn efx_rc_t
439 efx_mac_filter_default_rxq_set(
442 __in boolean_t using_rss)
444 efx_port_t *epp = &(enp->en_port);
445 const efx_mac_ops_t *emop = epp->ep_emop;
448 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
449 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
451 if (emop->emo_filter_default_rxq_set != NULL) {
452 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
460 EFSYS_PROBE1(fail1, efx_rc_t, rc);
466 efx_mac_filter_default_rxq_clear(
469 efx_port_t *epp = &(enp->en_port);
470 const efx_mac_ops_t *emop = epp->ep_emop;
472 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
473 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
475 if (emop->emo_filter_default_rxq_clear != NULL)
476 emop->emo_filter_default_rxq_clear(enp);
480 __checkReturn efx_rc_t
484 efx_port_t *epp = &(enp->en_port);
485 efx_mac_type_t type = EFX_MAC_INVALID;
486 const efx_mac_ops_t *emop;
489 switch (enp->en_family) {
491 case EFX_FAMILY_SIENA:
492 emop = &__efx_siena_mac_ops;
493 type = EFX_MAC_SIENA;
495 #endif /* EFSYS_OPT_SIENA */
502 EFSYS_ASSERT(type != EFX_MAC_INVALID);
503 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
504 EFSYS_ASSERT(emop != NULL);
507 epp->ep_mac_type = type;
512 EFSYS_PROBE1(fail1, efx_rc_t, rc);
520 #define EFX_MAC_HASH_BITS (1 << 8)
522 /* Compute the multicast hash as used on Falcon and Siena. */
524 siena_mac_multicast_hash_compute(
525 __in_ecount(6*count) uint8_t const *addrs,
527 __out efx_oword_t *hash_low,
528 __out efx_oword_t *hash_high)
533 EFSYS_ASSERT(hash_low != NULL);
534 EFSYS_ASSERT(hash_high != NULL);
536 EFX_ZERO_OWORD(*hash_low);
537 EFX_ZERO_OWORD(*hash_high);
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;
544 EFX_SET_OWORD_BIT(*hash_low, index);
546 EFX_SET_OWORD_BIT(*hash_high, index - 128);
549 addrs += EFX_MAC_ADDR_LEN;
553 static __checkReturn efx_rc_t
554 siena_mac_multicast_list_set(
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];
562 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
563 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
565 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
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]);
573 if ((rc = emop->emo_reconfigure(enp)) != 0)
579 EFSYS_PROBE1(fail1, efx_rc_t, rc);
581 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
586 #endif /* EFSYS_OPT_SIENA */