From a65398194ac8b78523a0a0cad03aaa6b3b115d2e Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Thu, 19 Dec 2024 11:19:23 +0800 Subject: [PATCH 1/3] net: wangxun: fix tx csum by soft except tcp udp sctp wangxun inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBCASR CVE: NA ------------------------------- when l4 protocol is not tcp, udp, or sctp, compute csum by software.otherwise, it will cause tx hang. Fixes: a5961b4bc6ce ("openeuler: net: ngbe: add ngbe module support") Fixes: a493f74ade8f ("net: txgbe: Add support for Netswift 10G NIC") Signed-off-by: Duanqiang Wen --- drivers/net/ethernet/netswift/ngbe/ngbe_main.c | 4 +++- drivers/net/ethernet/netswift/txgbe/txgbe_main.c | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c index 41e1300e6de1..931f21eca373 100644 --- a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c @@ -5432,6 +5432,7 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, u32 type_tucmd; if (skb->ip_summed != CHECKSUM_PARTIAL) { +csum_failed: if (!(first->tx_flags & NGBE_TX_FLAGS_HW_VLAN) && !(first->tx_flags & NGBE_TX_FLAGS_CC)) return; @@ -5534,7 +5535,8 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, NGBE_TXD_L4LEN_SHIFT; break; default: - break; + skb_checksum_help(skb); + goto csum_failed; } /* update TX checksum flag */ diff --git a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c index fb08d2f0d19f..39b19321709d 100644 --- a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c @@ -6350,12 +6350,11 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, u32 vlan_macip_lens = 0; u32 mss_l4len_idx = 0; u32 tunhdr_eiplen_tunlen = 0; - u8 tun_prot = 0; - u32 type_tucmd; if (skb->ip_summed != CHECKSUM_PARTIAL) { +csum_failed: if (!(first->tx_flags & TXGBE_TX_FLAGS_HW_VLAN) && !(first->tx_flags & TXGBE_TX_FLAGS_CC)) return; @@ -6447,7 +6446,6 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, switch (l4_prot) { case IPPROTO_TCP: - mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) << TXGBE_TXD_L4LEN_SHIFT; break; @@ -6460,7 +6458,8 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, TXGBE_TXD_L4LEN_SHIFT; break; default: - break; + skb_checksum_help(skb); + goto csum_failed; } /* update TX checksum flag */ -- Gitee From abd5078bcd21063944ed133282ee3fafdc92092c Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Thu, 19 Dec 2024 14:33:12 +0800 Subject: [PATCH 2/3] net: wangxun: fix resolving ipv6 pakets extension header errors wangxun inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBCASR CVE: NA ---------------------- fix bug of all Outer ipv6 packets with extension header, and fix bug of IP over IP with ipvX/ipv6 mode. Fixes: a5961b4bc6ce ("openeuler: net: ngbe: add ngbe module support") Fixes: a493f74ade8f ("net: txgbe: Add support for Netswift 10G NIC") Signed-off-by: Duanqiang Wen --- .../net/ethernet/netswift/ngbe/ngbe_main.c | 87 +++++++++++-------- .../net/ethernet/netswift/txgbe/txgbe_main.c | 85 +++++++++--------- 2 files changed, 97 insertions(+), 75 deletions(-) diff --git a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c index 931f21eca373..5d1f454bf85e 100644 --- a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c @@ -5141,36 +5141,6 @@ static void ngbe_service_task(struct work_struct *work) ngbe_service_event_complete(adapter); } -static u8 get_ipv6_proto(struct sk_buff *skb, int offset) -{ - struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset); - u8 nexthdr = hdr->nexthdr; - - offset += sizeof(struct ipv6hdr); - - while (ipv6_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - if (nexthdr == NEXTHDR_NONE) - break; - - hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr); - if (!hp) - break; - - if (nexthdr == NEXTHDR_FRAGMENT) - break; - else if (nexthdr == NEXTHDR_AUTH) - offset += ipv6_authlen(hp); - else - offset += ipv6_optlen(hp); - - nexthdr = hp->nexthdr; - } - - return nexthdr; -} - union network_header { struct iphdr *ipv4; struct ipv6hdr *ipv6; @@ -5183,6 +5153,9 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f u8 tun_prot = 0; u8 l4_prot = 0; u8 ptype = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; if (skb->encapsulation) { union network_header hdr; @@ -5195,7 +5168,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f ptype = NGBE_PTYPE_TUN_IPV4; break; case htons(ETH_P_IPV6): - tun_prot = get_ipv6_proto(skb, skb_network_offset(skb)); + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); + if (tun_prot == NEXTHDR_FRAGMENT) goto encap_frag; ptype = NGBE_PTYPE_TUN_IPV6; @@ -5204,7 +5183,8 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f goto exit; } - if (tun_prot == IPPROTO_IPIP) { + if (tun_prot == IPPROTO_IPIP || + tun_prot == IPPROTO_IPV6) { hdr.raw = (void *)inner_ip_hdr(skb); ptype |= NGBE_PTYPE_PKT_IPIP; } else if (tun_prot == IPPROTO_UDP) { @@ -5222,8 +5202,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f } break; case 6: - l4_prot = get_ipv6_proto(skb, - skb_inner_network_offset(skb)); + l4_hdr = skb_inner_transport_header(skb); + exthdr = skb_inner_network_header(skb) + sizeof(struct ipv6hdr); + l4_prot = inner_ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); + ptype |= NGBE_PTYPE_PKT_IPV6; if (l4_prot == NEXTHDR_FRAGMENT) { ptype |= NGBE_PTYPE_TYP_IPFRAG; @@ -5246,7 +5231,13 @@ static struct ngbe_dec_ptype encode_tx_desc_ptype(const struct ngbe_tx_buffer *f break; #ifdef NETIF_F_IPV6_CSUM case htons(ETH_P_IPV6): - l4_prot = get_ipv6_proto(skb, skb_network_offset(skb)); + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + l4_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); + ptype = NGBE_PTYPE_PKT_IP | NGBE_PTYPE_PKT_IPV6; if (l4_prot == NEXTHDR_FRAGMENT) { ptype |= NGBE_PTYPE_TYP_IPFRAG; @@ -5308,9 +5299,12 @@ static int ngbe_tso(struct ngbe_ring *tx_ring, struct iphdr *iph; u32 tunhdr_eiplen_tunlen = 0; u8 tun_prot = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; bool enc = skb->encapsulation; - struct ipv6hdr *ipv6h; + struct ipv6hdr *ipv6h; if (skb->ip_summed != CHECKSUM_PARTIAL) return 0; @@ -5373,7 +5367,12 @@ static int ngbe_tso(struct ngbe_ring *tx_ring, first->tx_flags |= NGBE_TX_FLAGS_OUTER_IPV4; break; case htons(ETH_P_IPV6): + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); break; default: break; @@ -5398,6 +5397,7 @@ static int ngbe_tso(struct ngbe_ring *tx_ring, NGBE_TXD_TUNNEL_LEN_SHIFT); break; case IPPROTO_IPIP: + case IPPROTO_IPV6: tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - (char *)ip_hdr(skb)) >> 2) << NGBE_TXD_OUTER_IPLEN_SHIFT; @@ -5440,6 +5440,10 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, NGBE_TXD_MACLEN_SHIFT; } else { u8 l4_prot = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; + union { struct iphdr *ipv4; struct ipv6hdr *ipv6; @@ -5460,7 +5464,13 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, tun_prot = ip_hdr(skb)->protocol; break; case htons(ETH_P_IPV6): + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); + break; default: if (unlikely(net_ratelimit())) { @@ -5490,6 +5500,7 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, NGBE_TXD_TUNNEL_LEN_SHIFT); break; case IPPROTO_IPIP: + case IPPROTO_IPV6: tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb)- (char *)ip_hdr(skb)) >> 2) << @@ -5515,7 +5526,11 @@ static void ngbe_tx_csum(struct ngbe_ring *tx_ring, case 6: vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + exthdr = network_hdr.raw + sizeof(struct ipv6hdr); l4_prot = network_hdr.ipv6->nexthdr; + if (transport_hdr.raw != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); break; default: break; diff --git a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c index 39b19321709d..336f128eddd8 100644 --- a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c @@ -6022,37 +6022,6 @@ static void txgbe_service_task(struct work_struct *work) txgbe_service_event_complete(adapter); } -static u8 get_ipv6_proto(struct sk_buff *skb, int offset) -{ - struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset); - u8 nexthdr = hdr->nexthdr; - - offset += sizeof(struct ipv6hdr); - - while (ipv6_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - if (nexthdr == NEXTHDR_NONE) - break; - - hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr); - if (!hp) - break; - - if (nexthdr == NEXTHDR_FRAGMENT) { - break; - } else if (nexthdr == NEXTHDR_AUTH) { - offset += ipv6_authlen(hp); - } else { - offset += ipv6_optlen(hp); - } - - nexthdr = hp->nexthdr; - } - - return nexthdr; -} - union network_header { struct iphdr *ipv4; struct ipv6hdr *ipv6; @@ -6062,11 +6031,12 @@ union network_header { static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first) { struct sk_buff *skb = first->skb; - u8 tun_prot = 0; - u8 l4_prot = 0; u8 ptype = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; if (skb->encapsulation) { union network_header hdr; @@ -6079,7 +6049,12 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first) ptype = TXGBE_PTYPE_TUN_IPV4; break; case __constant_htons(ETH_P_IPV6): - tun_prot = get_ipv6_proto(skb, skb_network_offset(skb)); + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); if (tun_prot == NEXTHDR_FRAGMENT) goto encap_frag; ptype = TXGBE_PTYPE_TUN_IPV6; @@ -6088,7 +6063,8 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first) goto exit; } - if (tun_prot == IPPROTO_IPIP) { + if (tun_prot == IPPROTO_IPIP || + tun_prot == IPPROTO_IPV6) { hdr.raw = (void *)inner_ip_hdr(skb); ptype |= TXGBE_PTYPE_PKT_IPIP; } else if (tun_prot == IPPROTO_UDP) { @@ -6135,8 +6111,12 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first) } break; case 6: - l4_prot = get_ipv6_proto(skb, - skb_inner_network_offset(skb)); + l4_hdr = skb_inner_transport_header(skb); + exthdr = skb_inner_network_header(skb) + sizeof(struct ipv6hdr); + l4_prot = inner_ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); ptype |= TXGBE_PTYPE_PKT_IPV6; if (l4_prot == NEXTHDR_FRAGMENT) { ptype |= TXGBE_PTYPE_TYP_IPFRAG; @@ -6160,7 +6140,13 @@ static txgbe_dptype encode_tx_desc_ptype(const struct txgbe_tx_buffer *first) break; #ifdef NETIF_F_IPV6_CSUM case __constant_htons(ETH_P_IPV6): - l4_prot = get_ipv6_proto(skb, skb_network_offset(skb)); + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + l4_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); + ptype = TXGBE_PTYPE_PKT_IP | TXGBE_PTYPE_PKT_IPV6; if (l4_prot == NEXTHDR_FRAGMENT) { ptype |= TXGBE_PTYPE_TYP_IPFRAG; @@ -6222,8 +6208,10 @@ static int txgbe_tso(struct txgbe_ring *tx_ring, struct tcphdr *tcph; struct iphdr *iph; u32 tunhdr_eiplen_tunlen = 0; - u8 tun_prot = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; bool enc = skb->encapsulation; struct ipv6hdr *ipv6h; @@ -6296,7 +6284,12 @@ static int txgbe_tso(struct txgbe_ring *tx_ring, first->tx_flags |= TXGBE_TX_FLAGS_OUTER_IPV4; break; case __constant_htons(ETH_P_IPV6): + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); break; default: break; @@ -6321,6 +6314,7 @@ static int txgbe_tso(struct txgbe_ring *tx_ring, TXGBE_TXD_TUNNEL_LEN_SHIFT); break; case IPPROTO_IPIP: + case IPPROTO_IPV6: tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb)- (char *)ip_hdr(skb)) >> 2) << TXGBE_TXD_OUTER_IPLEN_SHIFT; @@ -6362,6 +6356,9 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, TXGBE_TXD_MACLEN_SHIFT; } else { u8 l4_prot = 0; + unsigned char *exthdr; + unsigned char *l4_hdr; + __be16 frag_off; union { struct iphdr *ipv4; @@ -6383,7 +6380,12 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, tun_prot = ip_hdr(skb)->protocol; break; case __constant_htons(ETH_P_IPV6): + l4_hdr = skb_transport_header(skb); + exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); tun_prot = ipv6_hdr(skb)->nexthdr; + if (l4_hdr != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &tun_prot, &frag_off); break; default: if (unlikely(net_ratelimit())) { @@ -6413,6 +6415,7 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, TXGBE_TXD_TUNNEL_LEN_SHIFT); break; case IPPROTO_IPIP: + case IPPROTO_IPV6: tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb)- (char *)ip_hdr(skb)) >> 2) << @@ -6438,7 +6441,11 @@ static void txgbe_tx_csum(struct txgbe_ring *tx_ring, case 6: vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + exthdr = network_hdr.raw + sizeof(struct ipv6hdr); l4_prot = network_hdr.ipv6->nexthdr; + if (transport_hdr.raw != exthdr) + ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_prot, &frag_off); break; default: break; -- Gitee From f91e04dd675c805615e399fadccfc69561d42682 Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Thu, 19 Dec 2024 17:35:58 +0800 Subject: [PATCH 3/3] net: wangxun: change netdev uc addr num maxmium wangxun inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBCASR CVE: NA ------------------------------ txgbe has 128 entries in mac table, so we will add new uticast addr to mac table when netdev_uc_addr is less than 128. Otherwise if netdev_uc_addr is more than 128, we will open promisc mode to promise packets can be received. ngbe has 32 entries in mac table, so we will add new unicast addr to mac table when netdev_uc_addr is less than 32. Otherwise if netdev_uc_addr is more than 32, we will open promisc mode to promise packets can be received. Signed-off-by: Duanqiang Wen --- drivers/net/ethernet/netswift/ngbe/ngbe.h | 4 +-- .../net/ethernet/netswift/ngbe/ngbe_main.c | 30 +++++++++++++++---- drivers/net/ethernet/netswift/txgbe/txgbe.h | 4 +-- .../net/ethernet/netswift/txgbe/txgbe_main.c | 28 +++++++++++++---- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/netswift/ngbe/ngbe.h b/drivers/net/ethernet/netswift/ngbe/ngbe.h index cb3b414fc217..7ce3d3e320ca 100644 --- a/drivers/net/ethernet/netswift/ngbe/ngbe.h +++ b/drivers/net/ethernet/netswift/ngbe/ngbe.h @@ -858,9 +858,9 @@ int ngbe_get_settings(struct net_device *netdev, int ngbe_write_uc_addr_list(struct net_device *netdev, int pool); void ngbe_full_sync_mac_table(struct ngbe_adapter *adapter); int ngbe_add_mac_filter(struct ngbe_adapter *adapter, - u8 *addr, u16 pool); + const u8 *addr, u16 pool); int ngbe_del_mac_filter(struct ngbe_adapter *adapter, - u8 *addr, u16 pool); + const u8 *addr, u16 pool); int ngbe_available_rars(struct ngbe_adapter *adapter); void ngbe_vlan_mode(struct net_device *netdev, u32 features); diff --git a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c index 5d1f454bf85e..9a17ab1367e7 100644 --- a/drivers/net/ethernet/netswift/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/netswift/ngbe/ngbe_main.c @@ -2784,7 +2784,7 @@ static void ngbe_mac_set_default_filter(struct ngbe_adapter *adapter, NGBE_PSR_MAC_SWC_AD_H_AV); } -int ngbe_add_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool) +int ngbe_add_mac_filter(struct ngbe_adapter *adapter, const u8 *addr, u16 pool) { struct ngbe_hw *hw = &adapter->hw; u32 i; @@ -2820,7 +2820,7 @@ static void ngbe_flush_sw_mac_table(struct ngbe_adapter *adapter) ngbe_sync_mac_table(adapter); } -int ngbe_del_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool) +int ngbe_del_mac_filter(struct ngbe_adapter *adapter, const u8 *addr, u16 pool) { /* search table for addr, if found, set to 0 and sync */ u32 i; @@ -2843,6 +2843,25 @@ int ngbe_del_mac_filter(struct ngbe_adapter *adapter, u8 *addr, u16 pool) return -ENOMEM; } +static int ngbe_uc_sync(struct net_device *netdev, const unsigned char *addr) +{ + struct ngbe_adapter *adapter = netdev_priv(netdev); + int ret; + + ret = ngbe_add_mac_filter(adapter, addr, VMDQ_P(0)); + + return min_t(int, ret, 0); +} + +static int ngbe_uc_unsync(struct net_device *netdev, const unsigned char *addr) +{ + struct ngbe_adapter *adapter = netdev_priv(netdev); + + ngbe_del_mac_filter(adapter, addr, VMDQ_P(0)); + + return 0; +} + /** * ngbe_write_uc_addr_list - write unicast addresses to RAR table * @netdev: network interface device structure @@ -2938,10 +2957,11 @@ void ngbe_set_rx_mode(struct net_device *netdev) * sufficient space to store all the addresses then enable * unicast promiscuous mode */ - count = ngbe_write_uc_addr_list(netdev, VMDQ_P(0)); - if (count < 0) { + if (__dev_uc_sync(netdev, ngbe_uc_sync, ngbe_uc_unsync)) { vmolr &= ~NGBE_PSR_VM_L2CTL_ROPE; - vmolr |= NGBE_PSR_VM_L2CTL_UPE; + fctrl |= NGBE_PSR_CTL_UPE; + e_dev_warn("uc count is %d, available mac entry is %d, enable promisc mode\n", + netdev_uc_count(netdev), ngbe_available_rars(adapter)); } /* Write addresses to the MTA, if the attempt fails diff --git a/drivers/net/ethernet/netswift/txgbe/txgbe.h b/drivers/net/ethernet/netswift/txgbe/txgbe.h index f010162fad2d..7af14d7b0c41 100644 --- a/drivers/net/ethernet/netswift/txgbe/txgbe.h +++ b/drivers/net/ethernet/netswift/txgbe/txgbe.h @@ -1078,9 +1078,9 @@ int txgbe_get_settings(struct net_device *netdev, int txgbe_write_uc_addr_list(struct net_device *netdev, int pool); void txgbe_full_sync_mac_table(struct txgbe_adapter *adapter); int txgbe_add_mac_filter(struct txgbe_adapter *adapter, - u8 *addr, u16 pool); + const u8 *addr, u16 pool); int txgbe_del_mac_filter(struct txgbe_adapter *adapter, - u8 *addr, u16 pool); + const u8 *addr, u16 pool); int txgbe_available_rars(struct txgbe_adapter *adapter); void txgbe_vlan_mode(struct net_device *, u32); diff --git a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c index 336f128eddd8..b623613d9948 100644 --- a/drivers/net/ethernet/netswift/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/netswift/txgbe/txgbe_main.c @@ -3220,7 +3220,7 @@ static void txgbe_mac_set_default_filter(struct txgbe_adapter *adapter, TXGBE_PSR_MAC_SWC_AD_H_AV); } -int txgbe_add_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool) +int txgbe_add_mac_filter(struct txgbe_adapter *adapter, const u8 *addr, u16 pool) { struct txgbe_hw *hw = &adapter->hw; u32 i; @@ -3267,7 +3267,7 @@ static void txgbe_flush_sw_mac_table(struct txgbe_adapter *adapter) txgbe_sync_mac_table(adapter); } -int txgbe_del_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool) +int txgbe_del_mac_filter(struct txgbe_adapter *adapter, const u8 *addr, u16 pool) { /* search table for addr, if found, set to 0 and sync */ u32 i; @@ -3303,6 +3303,25 @@ int txgbe_del_mac_filter(struct txgbe_adapter *adapter, u8 *addr, u16 pool) return -ENOMEM; } +static int txgbe_uc_sync(struct net_device *netdev, const unsigned char *addr) +{ + struct txgbe_adapter *adapter = netdev_priv(netdev); + int ret; + + ret = txgbe_add_mac_filter(adapter, addr, VMDQ_P(0)); + + return min_t(int, ret, 0); +} + +static int txgbe_uc_unsync(struct net_device *netdev, const unsigned char *addr) +{ + struct txgbe_adapter *adapter = netdev_priv(netdev); + + txgbe_del_mac_filter(adapter, addr, VMDQ_P(0)); + + return 0; +} + /** * txgbe_write_uc_addr_list - write unicast addresses to RAR table * @netdev: network interface device structure @@ -3426,10 +3445,9 @@ void txgbe_set_rx_mode(struct net_device *netdev) * sufficient space to store all the addresses then enable * unicast promiscuous mode */ - count = txgbe_write_uc_addr_list(netdev, VMDQ_P(0)); - if (count < 0) { + if (__dev_uc_sync(netdev, txgbe_uc_sync, txgbe_uc_unsync)) { vmolr &= ~TXGBE_PSR_VM_L2CTL_ROPE; - vmolr |= TXGBE_PSR_VM_L2CTL_UPE; + fctrl |= TXGBE_PSR_CTL_UPE; } /* -- Gitee