From d71c0dc4e961e74143a644f248fc1a39cabf6586 Mon Sep 17 00:00:00 2001 From: Michael Chan <mchan@broadcom.com> Date: Sun, 11 May 2014 20:22:53 -0700 Subject: [PATCH 1/3] tg3: Don't modify ip header fields when doing GSO tg3 uses GSO as workaround if the hardware cannot perform TSO on certain packets. We should not modify the ip header fields if we do GSO on the packet. It happens to work by accident because GSO recalculates the IP checksum and IP total length. Also fix the tg3_start_xmit comment to reflect that this is the only xmit function for all devices. Signed-off-by: Prashant Sreedharan <prashant@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/broadcom/tg3.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e5d95c5ce1ad..bdfd08bcfe57 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7871,9 +7871,7 @@ tg3_tso_bug_end: return NETDEV_TX_OK; } -/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and - * support TG3_FLAG_HW_TSO_1 or firmware TSO only. - */ +/* hard_start_xmit for all devices */ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); @@ -7927,14 +7925,14 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; if (!skb_is_gso_v6(skb)) { + if (unlikely((ETH_HLEN + hdr_len) > 80) && + tg3_flag(tp, TSO_BUG)) + return tg3_tso_bug(tp, skb); + iph->check = 0; iph->tot_len = htons(mss + hdr_len); } - if (unlikely((ETH_HLEN + hdr_len) > 80) && - tg3_flag(tp, TSO_BUG)) - return tg3_tso_bug(tp, skb); - base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); From d3f6f3a1d818410c17445bce4f4caab52eb102f1 Mon Sep 17 00:00:00 2001 From: Michael Chan <mchan@broadcom.com> Date: Sun, 11 May 2014 20:22:54 -0700 Subject: [PATCH 2/3] tg3: Prevent page allocation failure during TSO workaround If any TSO fragment hits hardware bug conditions (e.g. 4G boundary), the driver will workaround by calling skb_copy() to copy to a linear SKB. Users have reported page allocation failures as the TSO packet can be up to 64K. Copying such a large packet is also very inefficient. We fix this by using existing tg3_tso_bug() to transmit the packet using GSO. Signed-off-by: Prashant Sreedharan <prashant@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/broadcom/tg3.c | 33 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bdfd08bcfe57..36b2b51facb9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7882,6 +7882,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) struct tg3_napi *tnapi; struct netdev_queue *txq; unsigned int last; + struct iphdr *iph = NULL; + struct tcphdr *tcph = NULL; + __sum16 tcp_csum = 0, ip_csum = 0; + __be16 ip_tot_len = 0; txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); tnapi = &tp->napi[skb_get_queue_mapping(skb)]; @@ -7913,7 +7917,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) mss = skb_shinfo(skb)->gso_size; if (mss) { - struct iphdr *iph; u32 tcp_opt_len, hdr_len; if (skb_cow_head(skb, 0)) @@ -7929,6 +7932,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tg3_flag(tp, TSO_BUG)) return tg3_tso_bug(tp, skb); + ip_csum = iph->check; + ip_tot_len = iph->tot_len; iph->check = 0; iph->tot_len = htons(mss + hdr_len); } @@ -7936,16 +7941,18 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); + tcph = tcp_hdr(skb); + tcp_csum = tcph->check; + if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) { - tcp_hdr(skb)->check = 0; + tcph->check = 0; base_flags &= ~TXD_FLAG_TCPUDP_CSUM; - } else - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + } else { + tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + } if (tg3_flag(tp, HW_TSO_3)) { mss |= (hdr_len & 0xc) << 12; @@ -8045,6 +8052,18 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (would_hit_hwbug) { tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); + if (mss) { + /* If it's a TSO packet, do GSO instead of + * allocating and copying to a large linear SKB + */ + if (ip_tot_len) { + iph->check = ip_csum; + iph->tot_len = ip_tot_len; + } + tcph->check = tcp_csum; + return tg3_tso_bug(tp, skb); + } + /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ From de750e4c4bf36b8a14401527e6541e8620ea6267 Mon Sep 17 00:00:00 2001 From: Michael Chan <mchan@broadcom.com> Date: Sun, 11 May 2014 20:22:55 -0700 Subject: [PATCH 3/3] tg3: Update copyright and version to 3.137 Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/broadcom/tg3.c | 6 +++--- drivers/net/ethernet/broadcom/tg3.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 36b2b51facb9..ccd90156aebc 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2013 Broadcom Corporation. + * Copyright (C) 2005-2014 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, @@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 136 +#define TG3_MIN_NUM 137 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "Jan 03, 2014" +#define DRV_MODULE_RELDATE "May 11, 2014" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 04321e5a356e..461accaf0aa4 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2007-2013 Broadcom Corporation. + * Copyright (C) 2007-2014 Broadcom Corporation. */ #ifndef _T3_H