diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc')
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc.h | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_defines.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_ethtool.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 22 |
4 files changed, 49 insertions, 3 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index fdec66caef4d..266bfcf2a28f 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -631,6 +631,7 @@ enum igc_filter_match_flags { IGC_FILTER_FLAG_DST_MAC_ADDR = BIT(3), IGC_FILTER_FLAG_USER_DATA = BIT(4), IGC_FILTER_FLAG_VLAN_ETYPE = BIT(5), + IGC_FILTER_FLAG_DEFAULT_QUEUE = BIT(6), }; struct igc_nfc_filter { @@ -658,10 +659,14 @@ struct igc_nfc_rule { bool flex; }; -/* IGC supports a total of 32 NFC rules: 16 MAC address based, 8 VLAN priority - * based, 8 ethertype based and 32 Flex filter based rules. +/* IGC supports a total of 65 NFC rules, listed below in order of priority: + * - 16 MAC address based filtering rules (highest priority) + * - 8 ethertype based filtering rules + * - 32 Flex filter based filtering rules + * - 8 VLAN priority based filtering rules + * - 1 default queue rule (lowest priority) */ -#define IGC_MAX_RXNFC_RULES 64 +#define IGC_MAX_RXNFC_RULES 65 struct igc_flex_filter { u8 index; diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index d80254f2a278..498ba1522ca4 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -391,6 +391,7 @@ #define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 +#define IGC_MRQC_DEFAULT_QUEUE_MASK GENMASK(5, 3) /* Header split receive */ #define IGC_RFCTL_IPV6_EX_DIS 0x00010000 diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index a7f397b58cd6..ecb35b693ce5 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1283,6 +1283,24 @@ static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule, rule->flex = true; else rule->flex = false; + + /* The wildcard rule is only applied if: + * a) None of the other filtering rules match (match_flags is zero) + * b) The flow type is ETHER_FLOW only (no additional fields set) + * c) Mask for Source MAC address is not specified (all zeros) + * d) Mask for Destination MAC address is not specified (all zeros) + * e) Mask for L2 EtherType is not specified (zero) + * + * If all these conditions are met, the rule is treated as a wildcard + * rule. Default queue feature will be used, so that all packets that do + * not match any other rule will be routed to the default queue. + */ + if (!rule->filter.match_flags && + fsp->flow_type == ETHER_FLOW && + is_zero_ether_addr(fsp->m_u.ether_spec.h_source) && + is_zero_ether_addr(fsp->m_u.ether_spec.h_dest) && + !fsp->m_u.ether_spec.h_proto) + rule->filter.match_flags = IGC_FILTER_FLAG_DEFAULT_QUEUE; } /** diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 32ea4fdd3e2b..458e5eaa92e5 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3874,6 +3874,22 @@ static void igc_del_flex_filter(struct igc_adapter *adapter, wr32(IGC_WUFC, wufc); } +static void igc_set_default_queue_filter(struct igc_adapter *adapter, u32 queue) +{ + struct igc_hw *hw = &adapter->hw; + u32 mrqc = rd32(IGC_MRQC); + + mrqc &= ~IGC_MRQC_DEFAULT_QUEUE_MASK; + mrqc |= FIELD_PREP(IGC_MRQC_DEFAULT_QUEUE_MASK, queue); + wr32(IGC_MRQC, mrqc); +} + +static void igc_reset_default_queue_filter(struct igc_adapter *adapter) +{ + /* Reset the default queue to its default value which is Queue 0 */ + igc_set_default_queue_filter(adapter, 0); +} + static int igc_enable_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule) { @@ -3912,6 +3928,9 @@ static int igc_enable_nfc_rule(struct igc_adapter *adapter, return err; } + if (rule->filter.match_flags & IGC_FILTER_FLAG_DEFAULT_QUEUE) + igc_set_default_queue_filter(adapter, rule->action); + return 0; } @@ -3939,6 +3958,9 @@ static void igc_disable_nfc_rule(struct igc_adapter *adapter, if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, rule->filter.dst_addr); + + if (rule->filter.match_flags & IGC_FILTER_FLAG_DEFAULT_QUEUE) + igc_reset_default_queue_filter(adapter); } /** |