X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fsfc%2Fbase%2Fef10_filter.c;h=12c84a5640e7b629eb5a0bcf6bc842530d8da80a;hb=4868ae8322892ca916d71d5f8cf74cb2e5e0b5c4;hp=74d06ecf57f3112b67d0bbb6e198743c3ecbb1c1;hpb=d3794059d62c01ddbbcc9ad754a75df29e66109f;p=dpdk.git diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index 74d06ecf57..12c84a5640 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2007-2018 Solarflare Communications Inc. - * All rights reserved. + * Copyright(c) 2019-2020 Xilinx, Inc. + * Copyright(c) 2007-2019 Solarflare Communications Inc. */ #include "efx.h" @@ -1161,7 +1161,8 @@ ef10_filter_delete( i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); saved_spec = ef10_filter_entry_spec(table, i); if (saved_spec && ef10_filter_equal(spec, saved_spec) && - ef10_filter_same_dest(spec, saved_spec)) { + ef10_filter_same_dest(spec, saved_spec) && + saved_spec->efs_priority == EFX_FILTER_PRI_MANUAL) { break; } if (depth == EF10_FILTER_SEARCH_LIMIT) { @@ -1761,6 +1762,7 @@ ef10_filter_remove_all_existing_filters( __in efx_nic_t *enp) { ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; + efx_port_t *epp = &(enp->en_port); unsigned int i; for (i = 0; i < table->eft_unicst_filter_count; i++) { @@ -1780,50 +1782,18 @@ ef10_filter_remove_all_existing_filters( table->eft_encap_filter_indexes[i]); } table->eft_encap_filter_count = 0; + + epp->ep_all_unicst_inserted = B_FALSE; + epp->ep_all_mulcst_inserted = B_FALSE; } -/* - * Reconfigure all filters. - * If all_unicst and/or all mulcst filters cannot be applied then - * return ENOTSUP (Note the filters for the specified addresses are - * still applied in this case). - */ - __checkReturn efx_rc_t -ef10_filter_reconfigure( - __in efx_nic_t *enp, - __in_ecount(6) uint8_t const *mac_addr, - __in boolean_t all_unicst, - __in boolean_t mulcst, - __in boolean_t all_mulcst, - __in boolean_t brdcst, - __in_ecount(6*count) uint8_t const *addrs, - __in uint32_t count) +static void +ef10_filter_mark_old_filters( + __in efx_nic_t *enp) { - efx_nic_cfg_t *encp = &enp->en_nic_cfg; ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; - efx_filter_flags_t filter_flags; unsigned int i; - efx_rc_t all_unicst_rc = 0; - efx_rc_t all_mulcst_rc = 0; - efx_rc_t rc; - if (table->eft_default_rxq == NULL) { - /* - * Filters direct traffic to the default RXQ, and so cannot be - * inserted until it is available. Any currently configured - * filters must be removed (ignore errors in case the MC - * has rebooted, which removes hardware filters). - */ - ef10_filter_remove_all_existing_filters(enp); - return (0); - } - - if (table->eft_using_rss) - filter_flags = EFX_FILTER_FLAG_RX_RSS; - else - filter_flags = 0; - - /* Mark old filters which may need to be removed */ for (i = 0; i < table->eft_unicst_filter_count; i++) { ef10_filter_set_entry_auto_old(table, table->eft_unicst_filter_indexes[i]); @@ -1836,10 +1806,21 @@ ef10_filter_reconfigure( ef10_filter_set_entry_auto_old(table, table->eft_encap_filter_indexes[i]); } +} + +static __checkReturn efx_rc_t +ef10_filter_insert_renew_unicst_filters( + __in efx_nic_t *enp, + __in_ecount(6) uint8_t const *mac_addr, + __in boolean_t all_unicst, + __in efx_filter_flags_t filter_flags, + __out boolean_t *all_unicst_inserted) +{ + ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; + efx_port_t *epp = &(enp->en_port); + efx_rc_t rc; /* - * Insert or renew unicast filters. - * * Firmware does not perform chaining on unicast filters. As traffic is * therefore only delivered to the first matching filter, we should * always insert the specific filter for our MAC address, to try and @@ -1851,61 +1832,54 @@ ef10_filter_reconfigure( * therefore relies on the privilege model only allowing functions to * insert filters for their own MAC address unless explicitly given * additional privileges by the user. This also means that, even on a - * priviliged function, inserting a unicast mismatch filter may not + * privileged function, inserting a unicast mismatch filter may not * catch all traffic in multi PCI function scenarios.) */ table->eft_unicst_filter_count = 0; rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags); + *all_unicst_inserted = B_FALSE; if (all_unicst || (rc != 0)) { + efx_rc_t all_unicst_rc; + all_unicst_rc = ef10_filter_insert_all_unicast(enp, filter_flags); - if ((rc != 0) && (all_unicst_rc != 0)) + if (all_unicst_rc == 0) { + *all_unicst_inserted = B_TRUE; + epp->ep_all_unicst_inserted = B_TRUE; + } else if (rc != 0) goto fail1; } - /* - * WORKAROUND_BUG26807 controls firmware support for chained multicast - * filters, and can only be enabled or disabled when the hardware filter - * table is empty. - * - * Chained multicast filters require support from the datapath firmware, - * and may not be available (e.g. low-latency variants or old Huntington - * firmware). - * - * Firmware will reset (FLR) functions which have inserted filters in - * the hardware filter table when the workaround is enabled/disabled. - * Functions without any hardware filters are not reset. - * - * Re-check if the workaround is enabled after adding unicast hardware - * filters. This ensures that encp->enc_bug26807_workaround matches the - * firmware state, and that later changes to enable/disable the - * workaround will result in this function seeing a reset (FLR). - * - * In common-code drivers, we only support multiple PCI function - * scenarios with firmware that supports multicast chaining, so we can - * assume it is enabled for such cases and hence simplify the filter - * insertion logic. Firmware that does not support multicast chaining - * does not support multiple PCI function configurations either, so - * filter insertion is much simpler and the same strategies can still be - * used. - */ - if ((rc = ef10_filter_get_workarounds(enp)) != 0) - goto fail2; + return (0); - if ((table->eft_using_all_mulcst != all_mulcst) && - (encp->enc_bug26807_workaround == B_TRUE)) { - /* - * Multicast filter chaining is enabled, so traffic that matches - * more than one multicast filter will be replicated and - * delivered to multiple recipients. To avoid this duplicate - * delivery, remove old multicast filters before inserting new - * multicast filters. - */ - ef10_filter_remove_old(enp); - } +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +ef10_filter_insert_renew_mulcst_filters( + __in efx_nic_t *enp, + __in boolean_t mulcst, + __in boolean_t all_mulcst, + __in boolean_t brdcst, + __in_ecount(6*count) uint8_t const *addrs, + __in uint32_t count, + __in efx_filter_flags_t filter_flags, + __in boolean_t all_unicst_inserted, + __out boolean_t *all_mulcst_inserted) +{ + ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; + efx_nic_cfg_t *encp = &enp->en_nic_cfg; + efx_port_t *epp = &(enp->en_port); + efx_rc_t rc; + + *all_mulcst_inserted = B_FALSE; - /* Insert or renew multicast filters */ if (all_mulcst == B_TRUE) { + efx_rc_t all_mulcst_rc; + /* * Insert the all multicast filter. If that fails, try to insert * all of our multicast filters (but without rollback on @@ -1913,11 +1887,14 @@ ef10_filter_reconfigure( */ all_mulcst_rc = ef10_filter_insert_all_multicast(enp, filter_flags); - if (all_mulcst_rc != 0) { + if (all_mulcst_rc == 0) { + epp->ep_all_mulcst_inserted = B_TRUE; + *all_mulcst_inserted = B_TRUE; + } else { rc = ef10_filter_insert_multicast_list(enp, B_TRUE, brdcst, addrs, count, filter_flags, B_FALSE); if (rc != 0) - goto fail3; + goto fail1; } } else { /* @@ -1939,20 +1916,144 @@ ef10_filter_reconfigure( * by packets matching multiple filters. */ ef10_filter_remove_old(enp); + if (all_unicst_inserted == B_FALSE) + epp->ep_all_unicst_inserted = B_FALSE; + if (*all_mulcst_inserted == B_FALSE) + epp->ep_all_mulcst_inserted = B_FALSE; } rc = ef10_filter_insert_all_multicast(enp, filter_flags); - if (rc != 0) { + if (rc == 0) { + epp->ep_all_mulcst_inserted = B_TRUE; + *all_mulcst_inserted = B_TRUE; + } else { rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst, addrs, count, filter_flags, B_FALSE); if (rc != 0) - goto fail4; + goto fail2; } } } + return (0); + +fail2: + EFSYS_PROBE1(fail2, efx_rc_t, rc); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +/* + * Reconfigure all filters. + * If all_unicst and/or all mulcst filters cannot be applied then + * return ENOTSUP (Note the filters for the specified addresses are + * still applied in this case). + */ + __checkReturn efx_rc_t +ef10_filter_reconfigure( + __in efx_nic_t *enp, + __in_ecount(6) uint8_t const *mac_addr, + __in boolean_t all_unicst, + __in boolean_t mulcst, + __in boolean_t all_mulcst, + __in boolean_t brdcst, + __in_ecount(6*count) uint8_t const *addrs, + __in uint32_t count) +{ + efx_nic_cfg_t *encp = &enp->en_nic_cfg; + efx_port_t *epp = &(enp->en_port); + ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; + efx_filter_flags_t filter_flags; + unsigned int i; + boolean_t all_unicst_inserted = B_FALSE; + boolean_t all_mulcst_inserted = B_FALSE; + efx_rc_t rc; + + if (table->eft_default_rxq == NULL) { + /* + * Filters direct traffic to the default RXQ, and so cannot be + * inserted until it is available. Any currently configured + * filters must be removed (ignore errors in case the MC + * has rebooted, which removes hardware filters). + */ + ef10_filter_remove_all_existing_filters(enp); + return (0); + } + + if (table->eft_using_rss) + filter_flags = EFX_FILTER_FLAG_RX_RSS; + else + filter_flags = 0; + + /* Mark old filters which may need to be removed */ + ef10_filter_mark_old_filters(enp); + + /* Insert or renew unicast filters */ + rc = ef10_filter_insert_renew_unicst_filters(enp, mac_addr, all_unicst, + filter_flags, + &all_unicst_inserted); + if (rc != 0) + goto fail1; + + /* + * WORKAROUND_BUG26807 controls firmware support for chained multicast + * filters, and can only be enabled or disabled when the hardware filter + * table is empty. + * + * Chained multicast filters require support from the datapath firmware, + * and may not be available (e.g. low-latency variants or old Huntington + * firmware). + * + * Firmware will reset (FLR) functions which have inserted filters in + * the hardware filter table when the workaround is enabled/disabled. + * Functions without any hardware filters are not reset. + * + * Re-check if the workaround is enabled after adding unicast hardware + * filters. This ensures that encp->enc_bug26807_workaround matches the + * firmware state, and that later changes to enable/disable the + * workaround will result in this function seeing a reset (FLR). + * + * In common-code drivers, we only support multiple PCI function + * scenarios with firmware that supports multicast chaining, so we can + * assume it is enabled for such cases and hence simplify the filter + * insertion logic. Firmware that does not support multicast chaining + * does not support multiple PCI function configurations either, so + * filter insertion is much simpler and the same strategies can still be + * used. + */ + if ((rc = ef10_filter_get_workarounds(enp)) != 0) + goto fail2; + + if ((table->eft_using_all_mulcst != all_mulcst) && + (encp->enc_bug26807_workaround == B_TRUE)) { + /* + * Multicast filter chaining is enabled, so traffic that matches + * more than one multicast filter will be replicated and + * delivered to multiple recipients. To avoid this duplicate + * delivery, remove old multicast filters before inserting new + * multicast filters. + */ + ef10_filter_remove_old(enp); + if (all_unicst_inserted == B_FALSE) + epp->ep_all_unicst_inserted = B_FALSE; + + epp->ep_all_mulcst_inserted = B_FALSE; + } + + /* Insert or renew multicast filters */ + rc = ef10_filter_insert_renew_mulcst_filters(enp, mulcst, all_mulcst, + brdcst, addrs, count, + filter_flags, + all_unicst_inserted, + &all_mulcst_inserted); + if (rc != 0) + goto fail3; + if (encp->enc_tunnel_encapsulations_supported != 0) { /* Try to insert filters for encapsulated packets. */ (void) ef10_filter_insert_encap_filters(enp, @@ -1962,17 +2063,19 @@ ef10_filter_reconfigure( /* Remove old filters which were not renewed */ ef10_filter_remove_old(enp); + if (all_unicst_inserted == B_FALSE) + epp->ep_all_unicst_inserted = B_FALSE; + if (all_mulcst_inserted == B_FALSE) + epp->ep_all_mulcst_inserted = B_FALSE; /* report if any optional flags were rejected */ - if (((all_unicst != B_FALSE) && (all_unicst_rc != 0)) || - ((all_mulcst != B_FALSE) && (all_mulcst_rc != 0))) { + if (((all_unicst != B_FALSE) && (all_unicst_inserted == B_FALSE)) || + ((all_mulcst != B_FALSE) && (all_mulcst_inserted == B_FALSE))) { rc = ENOTSUP; } return (rc); -fail4: - EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: