diff options
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 59 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/filter.c | 196 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/filter.h | 6 |
3 files changed, 214 insertions, 47 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index f887f65e4189..83191151b650 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c | |||
@@ -808,11 +808,16 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) | |||
808 | return efx_reset(efx, rc); | 808 | return efx_reset(efx, rc); |
809 | } | 809 | } |
810 | 810 | ||
811 | /* MAC address mask including only MC flag */ | ||
812 | static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; | ||
813 | |||
811 | static int efx_ethtool_get_class_rule(struct efx_nic *efx, | 814 | static int efx_ethtool_get_class_rule(struct efx_nic *efx, |
812 | struct ethtool_rx_flow_spec *rule) | 815 | struct ethtool_rx_flow_spec *rule) |
813 | { | 816 | { |
814 | struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec; | 817 | struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec; |
815 | struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec; | 818 | struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec; |
819 | struct ethhdr *mac_entry = &rule->h_u.ether_spec; | ||
820 | struct ethhdr *mac_mask = &rule->m_u.ether_spec; | ||
816 | struct efx_filter_spec spec; | 821 | struct efx_filter_spec spec; |
817 | u16 vid; | 822 | u16 vid; |
818 | u8 proto; | 823 | u8 proto; |
@@ -828,11 +833,18 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, | |||
828 | else | 833 | else |
829 | rule->ring_cookie = spec.dmaq_id; | 834 | rule->ring_cookie = spec.dmaq_id; |
830 | 835 | ||
831 | rc = efx_filter_get_eth_local(&spec, &vid, | 836 | if (spec.type == EFX_FILTER_MC_DEF || spec.type == EFX_FILTER_UC_DEF) { |
832 | rule->h_u.ether_spec.h_dest); | 837 | rule->flow_type = ETHER_FLOW; |
838 | memcpy(mac_mask->h_dest, mac_addr_mc_mask, ETH_ALEN); | ||
839 | if (spec.type == EFX_FILTER_MC_DEF) | ||
840 | memcpy(mac_entry->h_dest, mac_addr_mc_mask, ETH_ALEN); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | rc = efx_filter_get_eth_local(&spec, &vid, mac_entry->h_dest); | ||
833 | if (rc == 0) { | 845 | if (rc == 0) { |
834 | rule->flow_type = ETHER_FLOW; | 846 | rule->flow_type = ETHER_FLOW; |
835 | memset(rule->m_u.ether_spec.h_dest, ~0, ETH_ALEN); | 847 | memset(mac_mask->h_dest, ~0, ETH_ALEN); |
836 | if (vid != EFX_FILTER_VID_UNSPEC) { | 848 | if (vid != EFX_FILTER_VID_UNSPEC) { |
837 | rule->flow_type |= FLOW_EXT; | 849 | rule->flow_type |= FLOW_EXT; |
838 | rule->h_ext.vlan_tci = htons(vid); | 850 | rule->h_ext.vlan_tci = htons(vid); |
@@ -1001,27 +1013,40 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, | |||
1001 | } | 1013 | } |
1002 | 1014 | ||
1003 | case ETHER_FLOW | FLOW_EXT: | 1015 | case ETHER_FLOW | FLOW_EXT: |
1004 | /* Must match all or none of VID */ | 1016 | case ETHER_FLOW: { |
1005 | if (rule->m_ext.vlan_tci != htons(0xfff) && | 1017 | u16 vlan_tag_mask = (rule->flow_type & FLOW_EXT ? |
1006 | rule->m_ext.vlan_tci != 0) | 1018 | ntohs(rule->m_ext.vlan_tci) : 0); |
1007 | return -EINVAL; | 1019 | |
1008 | case ETHER_FLOW: | 1020 | /* Must not match on source address or Ethertype */ |
1009 | /* Must match all of destination */ | ||
1010 | if (!is_broadcast_ether_addr(mac_mask->h_dest)) | ||
1011 | return -EINVAL; | ||
1012 | /* and nothing else */ | ||
1013 | if (!is_zero_ether_addr(mac_mask->h_source) || | 1021 | if (!is_zero_ether_addr(mac_mask->h_source) || |
1014 | mac_mask->h_proto) | 1022 | mac_mask->h_proto) |
1015 | return -EINVAL; | 1023 | return -EINVAL; |
1016 | 1024 | ||
1017 | rc = efx_filter_set_eth_local( | 1025 | /* Is it a default UC or MC filter? */ |
1018 | &spec, | 1026 | if (!compare_ether_addr(mac_mask->h_dest, mac_addr_mc_mask) && |
1019 | (rule->flow_type & FLOW_EXT && rule->m_ext.vlan_tci) ? | 1027 | vlan_tag_mask == 0) { |
1020 | ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC, | 1028 | if (is_multicast_ether_addr(mac_entry->h_dest)) |
1021 | mac_entry->h_dest); | 1029 | rc = efx_filter_set_mc_def(&spec); |
1030 | else | ||
1031 | rc = efx_filter_set_uc_def(&spec); | ||
1032 | } | ||
1033 | /* Otherwise, it must match all of destination and all | ||
1034 | * or none of VID. | ||
1035 | */ | ||
1036 | else if (is_broadcast_ether_addr(mac_mask->h_dest) && | ||
1037 | (vlan_tag_mask == 0xfff || vlan_tag_mask == 0)) { | ||
1038 | rc = efx_filter_set_eth_local( | ||
1039 | &spec, | ||
1040 | vlan_tag_mask ? | ||
1041 | ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC, | ||
1042 | mac_entry->h_dest); | ||
1043 | } else { | ||
1044 | rc = -EINVAL; | ||
1045 | } | ||
1022 | if (rc) | 1046 | if (rc) |
1023 | return rc; | 1047 | return rc; |
1024 | break; | 1048 | break; |
1049 | } | ||
1025 | 1050 | ||
1026 | default: | 1051 | default: |
1027 | return -EINVAL; | 1052 | return -EINVAL; |
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c index 1fbbbee7b1ae..92517ea42715 100644 --- a/drivers/net/ethernet/sfc/filter.c +++ b/drivers/net/ethernet/sfc/filter.c | |||
@@ -35,9 +35,16 @@ | |||
35 | enum efx_filter_table_id { | 35 | enum efx_filter_table_id { |
36 | EFX_FILTER_TABLE_RX_IP = 0, | 36 | EFX_FILTER_TABLE_RX_IP = 0, |
37 | EFX_FILTER_TABLE_RX_MAC, | 37 | EFX_FILTER_TABLE_RX_MAC, |
38 | EFX_FILTER_TABLE_RX_DEF, | ||
38 | EFX_FILTER_TABLE_COUNT, | 39 | EFX_FILTER_TABLE_COUNT, |
39 | }; | 40 | }; |
40 | 41 | ||
42 | enum efx_filter_index { | ||
43 | EFX_FILTER_INDEX_UC_DEF, | ||
44 | EFX_FILTER_INDEX_MC_DEF, | ||
45 | EFX_FILTER_SIZE_RX_DEF, | ||
46 | }; | ||
47 | |||
41 | struct efx_filter_table { | 48 | struct efx_filter_table { |
42 | enum efx_filter_table_id id; | 49 | enum efx_filter_table_id id; |
43 | u32 offset; /* address of table relative to BAR */ | 50 | u32 offset; /* address of table relative to BAR */ |
@@ -109,7 +116,7 @@ static void efx_filter_table_reset_search_depth(struct efx_filter_table *table) | |||
109 | memset(table->search_depth, 0, sizeof(table->search_depth)); | 116 | memset(table->search_depth, 0, sizeof(table->search_depth)); |
110 | } | 117 | } |
111 | 118 | ||
112 | static void efx_filter_push_rx_limits(struct efx_nic *efx) | 119 | static void efx_filter_push_rx_config(struct efx_nic *efx) |
113 | { | 120 | { |
114 | struct efx_filter_state *state = efx->filter_state; | 121 | struct efx_filter_state *state = efx->filter_state; |
115 | struct efx_filter_table *table; | 122 | struct efx_filter_table *table; |
@@ -143,6 +150,32 @@ static void efx_filter_push_rx_limits(struct efx_nic *efx) | |||
143 | FILTER_CTL_SRCH_FUDGE_WILD); | 150 | FILTER_CTL_SRCH_FUDGE_WILD); |
144 | } | 151 | } |
145 | 152 | ||
153 | table = &state->table[EFX_FILTER_TABLE_RX_DEF]; | ||
154 | if (table->size) { | ||
155 | EFX_SET_OWORD_FIELD( | ||
156 | filter_ctl, FRF_CZ_UNICAST_NOMATCH_Q_ID, | ||
157 | table->spec[EFX_FILTER_INDEX_UC_DEF].dmaq_id); | ||
158 | EFX_SET_OWORD_FIELD( | ||
159 | filter_ctl, FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED, | ||
160 | !!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags & | ||
161 | EFX_FILTER_FLAG_RX_RSS)); | ||
162 | EFX_SET_OWORD_FIELD( | ||
163 | filter_ctl, FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE, | ||
164 | !!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags & | ||
165 | EFX_FILTER_FLAG_RX_OVERRIDE_IP)); | ||
166 | EFX_SET_OWORD_FIELD( | ||
167 | filter_ctl, FRF_CZ_MULTICAST_NOMATCH_Q_ID, | ||
168 | table->spec[EFX_FILTER_INDEX_MC_DEF].dmaq_id); | ||
169 | EFX_SET_OWORD_FIELD( | ||
170 | filter_ctl, FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED, | ||
171 | !!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags & | ||
172 | EFX_FILTER_FLAG_RX_RSS)); | ||
173 | EFX_SET_OWORD_FIELD( | ||
174 | filter_ctl, FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE, | ||
175 | !!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags & | ||
176 | EFX_FILTER_FLAG_RX_OVERRIDE_IP)); | ||
177 | } | ||
178 | |||
146 | efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL); | 179 | efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL); |
147 | } | 180 | } |
148 | 181 | ||
@@ -319,6 +352,52 @@ int efx_filter_set_eth_local(struct efx_filter_spec *spec, | |||
319 | return 0; | 352 | return 0; |
320 | } | 353 | } |
321 | 354 | ||
355 | /** | ||
356 | * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast | ||
357 | * @spec: Specification to initialise | ||
358 | */ | ||
359 | int efx_filter_set_uc_def(struct efx_filter_spec *spec) | ||
360 | { | ||
361 | EFX_BUG_ON_PARANOID(!(spec->flags & | ||
362 | (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX))); | ||
363 | |||
364 | if (spec->type != EFX_FILTER_UNSPEC) | ||
365 | return -EINVAL; | ||
366 | |||
367 | spec->type = EFX_FILTER_UC_DEF; | ||
368 | memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */ | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast | ||
374 | * @spec: Specification to initialise | ||
375 | */ | ||
376 | int efx_filter_set_mc_def(struct efx_filter_spec *spec) | ||
377 | { | ||
378 | EFX_BUG_ON_PARANOID(!(spec->flags & | ||
379 | (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX))); | ||
380 | |||
381 | if (spec->type != EFX_FILTER_UNSPEC) | ||
382 | return -EINVAL; | ||
383 | |||
384 | spec->type = EFX_FILTER_MC_DEF; | ||
385 | memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */ | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static void efx_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx) | ||
390 | { | ||
391 | struct efx_filter_state *state = efx->filter_state; | ||
392 | struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_DEF]; | ||
393 | struct efx_filter_spec *spec = &table->spec[filter_idx]; | ||
394 | |||
395 | efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL, | ||
396 | EFX_FILTER_FLAG_RX_RSS, 0); | ||
397 | spec->type = EFX_FILTER_UC_DEF + filter_idx; | ||
398 | table->used_bitmap[0] |= 1 << filter_idx; | ||
399 | } | ||
400 | |||
322 | int efx_filter_get_eth_local(const struct efx_filter_spec *spec, | 401 | int efx_filter_get_eth_local(const struct efx_filter_spec *spec, |
323 | u16 *vid, u8 *addr) | 402 | u16 *vid, u8 *addr) |
324 | { | 403 | { |
@@ -366,6 +445,13 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec) | |||
366 | break; | 445 | break; |
367 | } | 446 | } |
368 | 447 | ||
448 | case EFX_FILTER_TABLE_RX_DEF: | ||
449 | /* One filter spec per type */ | ||
450 | BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0); | ||
451 | BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF != | ||
452 | EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF); | ||
453 | return spec->type - EFX_FILTER_UC_DEF; | ||
454 | |||
369 | case EFX_FILTER_TABLE_RX_MAC: { | 455 | case EFX_FILTER_TABLE_RX_MAC: { |
370 | bool is_wild = spec->type == EFX_FILTER_MAC_WILD; | 456 | bool is_wild = spec->type == EFX_FILTER_MAC_WILD; |
371 | EFX_POPULATE_OWORD_8( | 457 | EFX_POPULATE_OWORD_8( |
@@ -448,23 +534,40 @@ static int efx_filter_search(struct efx_filter_table *table, | |||
448 | * MAC filters without overriding behaviour. | 534 | * MAC filters without overriding behaviour. |
449 | */ | 535 | */ |
450 | 536 | ||
537 | #define EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP 0 | ||
538 | #define EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP 1 | ||
539 | #define EFX_FILTER_MATCH_PRI_NORMAL_BASE 2 | ||
540 | |||
451 | #define EFX_FILTER_INDEX_WIDTH 13 | 541 | #define EFX_FILTER_INDEX_WIDTH 13 |
452 | #define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1) | 542 | #define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1) |
453 | 543 | ||
454 | static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id, | 544 | static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id, |
455 | unsigned int index, u8 flags) | 545 | unsigned int index, u8 flags) |
456 | { | 546 | { |
457 | return (table_id == EFX_FILTER_TABLE_RX_MAC && | 547 | unsigned int match_pri = EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id; |
458 | flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ? | 548 | |
459 | index : | 549 | if (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) { |
460 | (table_id + 1) << EFX_FILTER_INDEX_WIDTH | index; | 550 | if (table_id == EFX_FILTER_TABLE_RX_MAC) |
551 | match_pri = EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP; | ||
552 | else if (table_id == EFX_FILTER_TABLE_RX_DEF) | ||
553 | match_pri = EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP; | ||
554 | } | ||
555 | |||
556 | return match_pri << EFX_FILTER_INDEX_WIDTH | index; | ||
461 | } | 557 | } |
462 | 558 | ||
463 | static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id) | 559 | static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id) |
464 | { | 560 | { |
465 | return (id <= EFX_FILTER_INDEX_MASK) ? | 561 | unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH; |
466 | EFX_FILTER_TABLE_RX_MAC : | 562 | |
467 | (id >> EFX_FILTER_INDEX_WIDTH) - 1; | 563 | switch (match_pri) { |
564 | case EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP: | ||
565 | return EFX_FILTER_TABLE_RX_MAC; | ||
566 | case EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP: | ||
567 | return EFX_FILTER_TABLE_RX_DEF; | ||
568 | default: | ||
569 | return match_pri - EFX_FILTER_MATCH_PRI_NORMAL_BASE; | ||
570 | } | ||
468 | } | 571 | } |
469 | 572 | ||
470 | static inline unsigned int efx_filter_id_index(u32 id) | 573 | static inline unsigned int efx_filter_id_index(u32 id) |
@@ -474,23 +577,27 @@ static inline unsigned int efx_filter_id_index(u32 id) | |||
474 | 577 | ||
475 | static inline u8 efx_filter_id_flags(u32 id) | 578 | static inline u8 efx_filter_id_flags(u32 id) |
476 | { | 579 | { |
477 | return (id <= EFX_FILTER_INDEX_MASK) ? | 580 | unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH; |
478 | EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP : | 581 | |
479 | EFX_FILTER_FLAG_RX; | 582 | if (match_pri < EFX_FILTER_MATCH_PRI_NORMAL_BASE) |
583 | return EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP; | ||
584 | else | ||
585 | return EFX_FILTER_FLAG_RX; | ||
480 | } | 586 | } |
481 | 587 | ||
482 | u32 efx_filter_get_rx_id_limit(struct efx_nic *efx) | 588 | u32 efx_filter_get_rx_id_limit(struct efx_nic *efx) |
483 | { | 589 | { |
484 | struct efx_filter_state *state = efx->filter_state; | 590 | struct efx_filter_state *state = efx->filter_state; |
591 | unsigned int table_id = EFX_FILTER_TABLE_RX_DEF; | ||
485 | 592 | ||
486 | if (state->table[EFX_FILTER_TABLE_RX_MAC].size != 0) | 593 | do { |
487 | return ((EFX_FILTER_TABLE_RX_MAC + 1) << EFX_FILTER_INDEX_WIDTH) | 594 | if (state->table[table_id].size != 0) |
488 | + state->table[EFX_FILTER_TABLE_RX_MAC].size; | 595 | return ((EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id) |
489 | else if (state->table[EFX_FILTER_TABLE_RX_IP].size != 0) | 596 | << EFX_FILTER_INDEX_WIDTH) + |
490 | return ((EFX_FILTER_TABLE_RX_IP + 1) << EFX_FILTER_INDEX_WIDTH) | 597 | state->table[table_id].size; |
491 | + state->table[EFX_FILTER_TABLE_RX_IP].size; | 598 | } while (table_id--); |
492 | else | 599 | |
493 | return 0; | 600 | return 0; |
494 | } | 601 | } |
495 | 602 | ||
496 | /** | 603 | /** |
@@ -548,12 +655,17 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, | |||
548 | } | 655 | } |
549 | *saved_spec = *spec; | 656 | *saved_spec = *spec; |
550 | 657 | ||
551 | if (table->search_depth[spec->type] < depth) { | 658 | if (table->id == EFX_FILTER_TABLE_RX_DEF) { |
552 | table->search_depth[spec->type] = depth; | 659 | efx_filter_push_rx_config(efx); |
553 | efx_filter_push_rx_limits(efx); | 660 | } else { |
554 | } | 661 | if (table->search_depth[spec->type] < depth) { |
662 | table->search_depth[spec->type] = depth; | ||
663 | efx_filter_push_rx_config(efx); | ||
664 | } | ||
555 | 665 | ||
556 | efx_writeo(efx, &filter, table->offset + table->step * filter_idx); | 666 | efx_writeo(efx, &filter, |
667 | table->offset + table->step * filter_idx); | ||
668 | } | ||
557 | 669 | ||
558 | netif_vdbg(efx, hw, efx->net_dev, | 670 | netif_vdbg(efx, hw, efx->net_dev, |
559 | "%s: filter type %d index %d rxq %u set", | 671 | "%s: filter type %d index %d rxq %u set", |
@@ -571,7 +683,11 @@ static void efx_filter_table_clear_entry(struct efx_nic *efx, | |||
571 | { | 683 | { |
572 | static efx_oword_t filter; | 684 | static efx_oword_t filter; |
573 | 685 | ||
574 | if (test_bit(filter_idx, table->used_bitmap)) { | 686 | if (table->id == EFX_FILTER_TABLE_RX_DEF) { |
687 | /* RX default filters must always exist */ | ||
688 | efx_filter_reset_rx_def(efx, filter_idx); | ||
689 | efx_filter_push_rx_config(efx); | ||
690 | } else if (test_bit(filter_idx, table->used_bitmap)) { | ||
575 | __clear_bit(filter_idx, table->used_bitmap); | 691 | __clear_bit(filter_idx, table->used_bitmap); |
576 | --table->used; | 692 | --table->used; |
577 | memset(&table->spec[filter_idx], 0, sizeof(table->spec[0])); | 693 | memset(&table->spec[filter_idx], 0, sizeof(table->spec[0])); |
@@ -617,7 +733,8 @@ int efx_filter_remove_id_safe(struct efx_nic *efx, | |||
617 | spin_lock_bh(&state->lock); | 733 | spin_lock_bh(&state->lock); |
618 | 734 | ||
619 | if (test_bit(filter_idx, table->used_bitmap) && | 735 | if (test_bit(filter_idx, table->used_bitmap) && |
620 | spec->priority == priority && spec->flags == filter_flags) { | 736 | spec->priority == priority && |
737 | !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) { | ||
621 | efx_filter_table_clear_entry(efx, table, filter_idx); | 738 | efx_filter_table_clear_entry(efx, table, filter_idx); |
622 | if (table->used == 0) | 739 | if (table->used == 0) |
623 | efx_filter_table_reset_search_depth(table); | 740 | efx_filter_table_reset_search_depth(table); |
@@ -668,7 +785,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx, | |||
668 | spin_lock_bh(&state->lock); | 785 | spin_lock_bh(&state->lock); |
669 | 786 | ||
670 | if (test_bit(filter_idx, table->used_bitmap) && | 787 | if (test_bit(filter_idx, table->used_bitmap) && |
671 | spec->priority == priority && spec->flags == filter_flags) { | 788 | spec->priority == priority && |
789 | !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) { | ||
672 | *spec_buf = *spec; | 790 | *spec_buf = *spec; |
673 | rc = 0; | 791 | rc = 0; |
674 | } else { | 792 | } else { |
@@ -722,7 +840,7 @@ u32 efx_filter_count_rx_used(struct efx_nic *efx, | |||
722 | spin_lock_bh(&state->lock); | 840 | spin_lock_bh(&state->lock); |
723 | 841 | ||
724 | for (table_id = EFX_FILTER_TABLE_RX_IP; | 842 | for (table_id = EFX_FILTER_TABLE_RX_IP; |
725 | table_id <= EFX_FILTER_TABLE_RX_MAC; | 843 | table_id <= EFX_FILTER_TABLE_RX_DEF; |
726 | table_id++) { | 844 | table_id++) { |
727 | table = &state->table[table_id]; | 845 | table = &state->table[table_id]; |
728 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { | 846 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { |
@@ -750,7 +868,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx, | |||
750 | spin_lock_bh(&state->lock); | 868 | spin_lock_bh(&state->lock); |
751 | 869 | ||
752 | for (table_id = EFX_FILTER_TABLE_RX_IP; | 870 | for (table_id = EFX_FILTER_TABLE_RX_IP; |
753 | table_id <= EFX_FILTER_TABLE_RX_MAC; | 871 | table_id <= EFX_FILTER_TABLE_RX_DEF; |
754 | table_id++) { | 872 | table_id++) { |
755 | table = &state->table[table_id]; | 873 | table = &state->table[table_id]; |
756 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { | 874 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { |
@@ -785,6 +903,11 @@ void efx_restore_filters(struct efx_nic *efx) | |||
785 | 903 | ||
786 | for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { | 904 | for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { |
787 | table = &state->table[table_id]; | 905 | table = &state->table[table_id]; |
906 | |||
907 | /* Check whether this is a regular register table */ | ||
908 | if (table->step == 0) | ||
909 | continue; | ||
910 | |||
788 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { | 911 | for (filter_idx = 0; filter_idx < table->size; filter_idx++) { |
789 | if (!test_bit(filter_idx, table->used_bitmap)) | 912 | if (!test_bit(filter_idx, table->used_bitmap)) |
790 | continue; | 913 | continue; |
@@ -794,7 +917,7 @@ void efx_restore_filters(struct efx_nic *efx) | |||
794 | } | 917 | } |
795 | } | 918 | } |
796 | 919 | ||
797 | efx_filter_push_rx_limits(efx); | 920 | efx_filter_push_rx_config(efx); |
798 | 921 | ||
799 | spin_unlock_bh(&state->lock); | 922 | spin_unlock_bh(&state->lock); |
800 | } | 923 | } |
@@ -833,6 +956,10 @@ int efx_probe_filters(struct efx_nic *efx) | |||
833 | table->offset = FR_CZ_RX_MAC_FILTER_TBL0; | 956 | table->offset = FR_CZ_RX_MAC_FILTER_TBL0; |
834 | table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS; | 957 | table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS; |
835 | table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP; | 958 | table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP; |
959 | |||
960 | table = &state->table[EFX_FILTER_TABLE_RX_DEF]; | ||
961 | table->id = EFX_FILTER_TABLE_RX_DEF; | ||
962 | table->size = EFX_FILTER_SIZE_RX_DEF; | ||
836 | } | 963 | } |
837 | 964 | ||
838 | for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { | 965 | for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { |
@@ -849,6 +976,15 @@ int efx_probe_filters(struct efx_nic *efx) | |||
849 | goto fail; | 976 | goto fail; |
850 | } | 977 | } |
851 | 978 | ||
979 | if (state->table[EFX_FILTER_TABLE_RX_DEF].size) { | ||
980 | /* RX default filters must always exist */ | ||
981 | unsigned i; | ||
982 | for (i = 0; i < EFX_FILTER_SIZE_RX_DEF; i++) | ||
983 | efx_filter_reset_rx_def(efx, i); | ||
984 | } | ||
985 | |||
986 | efx_filter_push_rx_config(efx); | ||
987 | |||
852 | return 0; | 988 | return 0; |
853 | 989 | ||
854 | fail: | 990 | fail: |
diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h index 3d4108cd90ca..451997841dc9 100644 --- a/drivers/net/ethernet/sfc/filter.h +++ b/drivers/net/ethernet/sfc/filter.h | |||
@@ -20,6 +20,8 @@ | |||
20 | * @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port) | 20 | * @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port) |
21 | * @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID | 21 | * @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID |
22 | * @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address | 22 | * @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address |
23 | * @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast | ||
24 | * @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast | ||
23 | * @EFX_FILTER_UNSPEC: Match type is unspecified | 25 | * @EFX_FILTER_UNSPEC: Match type is unspecified |
24 | * | 26 | * |
25 | * Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types. | 27 | * Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types. |
@@ -31,6 +33,8 @@ enum efx_filter_type { | |||
31 | EFX_FILTER_UDP_WILD, | 33 | EFX_FILTER_UDP_WILD, |
32 | EFX_FILTER_MAC_FULL = 4, | 34 | EFX_FILTER_MAC_FULL = 4, |
33 | EFX_FILTER_MAC_WILD, | 35 | EFX_FILTER_MAC_WILD, |
36 | EFX_FILTER_UC_DEF = 8, | ||
37 | EFX_FILTER_MC_DEF, | ||
34 | EFX_FILTER_TYPE_COUNT, /* number of specific types */ | 38 | EFX_FILTER_TYPE_COUNT, /* number of specific types */ |
35 | EFX_FILTER_UNSPEC = 0xf, | 39 | EFX_FILTER_UNSPEC = 0xf, |
36 | }; | 40 | }; |
@@ -117,6 +121,8 @@ extern int efx_filter_set_eth_local(struct efx_filter_spec *spec, | |||
117 | u16 vid, const u8 *addr); | 121 | u16 vid, const u8 *addr); |
118 | extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec, | 122 | extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec, |
119 | u16 *vid, u8 *addr); | 123 | u16 *vid, u8 *addr); |
124 | extern int efx_filter_set_uc_def(struct efx_filter_spec *spec); | ||
125 | extern int efx_filter_set_mc_def(struct efx_filter_spec *spec); | ||
120 | enum { | 126 | enum { |
121 | EFX_FILTER_VID_UNSPEC = 0xffff, | 127 | EFX_FILTER_VID_UNSPEC = 0xffff, |
122 | }; | 128 | }; |