@@ -507,6 +507,7 @@ struct igc_nfc_rule {
struct igc_nfc_filter filter;
u32 location;
u16 action;
+ bool flex;
};
/* IGC supports a total of 32 NFC rules: 16 MAC address based, 8 VLAN priority
@@ -1222,19 +1222,29 @@ static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
fsp->h_u.ether_spec.h_dest);
}
+ /* VLAN etype matching */
+ if ((fsp->flow_type & FLOW_EXT) && fsp->h_ext.vlan_etype) {
+ rule->filter.vlan_etype = fsp->h_ext.vlan_etype;
+ rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_ETYPE;
+ }
+
/* Check for user defined data */
if ((fsp->flow_type & FLOW_EXT) &&
(fsp->h_ext.data[0] || fsp->h_ext.data[1])) {
rule->filter.match_flags |= IGC_FILTER_FLAG_USER_DATA;
memcpy(rule->filter.user_data, fsp->h_ext.data, sizeof(fsp->h_ext.data));
memcpy(rule->filter.user_mask, fsp->m_ext.data, sizeof(fsp->m_ext.data));
-
- /* VLAN etype matching is only valid using flex filter */
- if ((fsp->flow_type & FLOW_EXT) && fsp->h_ext.vlan_etype) {
- rule->filter.vlan_etype = fsp->h_ext.vlan_etype;
- rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_ETYPE;
- }
}
+
+ /* When multiple filter options or user data or vlan etype is set, use a
+ * flex filter.
+ */
+ if ((rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA) ||
+ (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_ETYPE) ||
+ (rule->filter.match_flags & (rule->filter.match_flags - 1)))
+ rule->flex = true;
+ else
+ rule->flex = false;
}
/**
@@ -1264,11 +1274,6 @@ static int igc_ethtool_check_nfc_rule(struct igc_adapter *adapter,
return -EINVAL;
}
- if (flags & (flags - 1)) {
- netdev_dbg(dev, "Rule with multiple matches not supported\n");
- return -EOPNOTSUPP;
- }
-
list_for_each_entry(tmp, &adapter->nfc_rule_list, list) {
if (!memcmp(&rule->filter, &tmp->filter,
sizeof(rule->filter)) &&
@@ -3385,14 +3385,8 @@ static int igc_enable_nfc_rule(struct igc_adapter *adapter,
{
int err;
- /* Check for user data first: When user data is set, the only option is
- * to use a flex filter. When more options are set (ethertype, vlan tci,
- * ...) construct a flex filter matching all of that.
- */
- if (rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA) {
- err = igc_add_flex_filter(adapter, rule);
- if (err)
- return err;
+ if (rule->flex) {
+ return igc_add_flex_filter(adapter, rule);
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
@@ -3431,8 +3425,10 @@ static int igc_enable_nfc_rule(struct igc_adapter *adapter,
static void igc_disable_nfc_rule(struct igc_adapter *adapter,
const struct igc_nfc_rule *rule)
{
- if (rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA)
+ if (rule->flex) {
igc_del_flex_filter(adapter, rule->filter.flex_index);
+ return;
+ }
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
igc_del_etype_filter(adapter, rule->filter.etype);