diff options
author | Michael Chan <mchan@broadcom.com> | 2014-05-11 23:22:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-13 18:38:51 -0400 |
commit | d3f6f3a1d818410c17445bce4f4caab52eb102f1 (patch) | |
tree | 19370e26092b97714c595cee5b71f90f303fd0db | |
parent | d71c0dc4e961e74143a644f248fc1a39cabf6586 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 33 |
1 files 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) | |||
7882 | struct tg3_napi *tnapi; | 7882 | struct tg3_napi *tnapi; |
7883 | struct netdev_queue *txq; | 7883 | struct netdev_queue *txq; |
7884 | unsigned int last; | 7884 | unsigned int last; |
7885 | struct iphdr *iph = NULL; | ||
7886 | struct tcphdr *tcph = NULL; | ||
7887 | __sum16 tcp_csum = 0, ip_csum = 0; | ||
7888 | __be16 ip_tot_len = 0; | ||
7885 | 7889 | ||
7886 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | 7890 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
7887 | tnapi = &tp->napi[skb_get_queue_mapping(skb)]; | 7891 | 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) | |||
7913 | 7917 | ||
7914 | mss = skb_shinfo(skb)->gso_size; | 7918 | mss = skb_shinfo(skb)->gso_size; |
7915 | if (mss) { | 7919 | if (mss) { |
7916 | struct iphdr *iph; | ||
7917 | u32 tcp_opt_len, hdr_len; | 7920 | u32 tcp_opt_len, hdr_len; |
7918 | 7921 | ||
7919 | if (skb_cow_head(skb, 0)) | 7922 | 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) | |||
7929 | tg3_flag(tp, TSO_BUG)) | 7932 | tg3_flag(tp, TSO_BUG)) |
7930 | return tg3_tso_bug(tp, skb); | 7933 | return tg3_tso_bug(tp, skb); |
7931 | 7934 | ||
7935 | ip_csum = iph->check; | ||
7936 | ip_tot_len = iph->tot_len; | ||
7932 | iph->check = 0; | 7937 | iph->check = 0; |
7933 | iph->tot_len = htons(mss + hdr_len); | 7938 | iph->tot_len = htons(mss + hdr_len); |
7934 | } | 7939 | } |
@@ -7936,16 +7941,18 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
7936 | base_flags |= (TXD_FLAG_CPU_PRE_DMA | | 7941 | base_flags |= (TXD_FLAG_CPU_PRE_DMA | |
7937 | TXD_FLAG_CPU_POST_DMA); | 7942 | TXD_FLAG_CPU_POST_DMA); |
7938 | 7943 | ||
7944 | tcph = tcp_hdr(skb); | ||
7945 | tcp_csum = tcph->check; | ||
7946 | |||
7939 | if (tg3_flag(tp, HW_TSO_1) || | 7947 | if (tg3_flag(tp, HW_TSO_1) || |
7940 | tg3_flag(tp, HW_TSO_2) || | 7948 | tg3_flag(tp, HW_TSO_2) || |
7941 | tg3_flag(tp, HW_TSO_3)) { | 7949 | tg3_flag(tp, HW_TSO_3)) { |
7942 | tcp_hdr(skb)->check = 0; | 7950 | tcph->check = 0; |
7943 | base_flags &= ~TXD_FLAG_TCPUDP_CSUM; | 7951 | base_flags &= ~TXD_FLAG_TCPUDP_CSUM; |
7944 | } else | 7952 | } else { |
7945 | tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, | 7953 | tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, |
7946 | iph->daddr, 0, | 7954 | 0, IPPROTO_TCP, 0); |
7947 | IPPROTO_TCP, | 7955 | } |
7948 | 0); | ||
7949 | 7956 | ||
7950 | if (tg3_flag(tp, HW_TSO_3)) { | 7957 | if (tg3_flag(tp, HW_TSO_3)) { |
7951 | mss |= (hdr_len & 0xc) << 12; | 7958 | mss |= (hdr_len & 0xc) << 12; |
@@ -8045,6 +8052,18 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
8045 | if (would_hit_hwbug) { | 8052 | if (would_hit_hwbug) { |
8046 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); | 8053 | tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); |
8047 | 8054 | ||
8055 | if (mss) { | ||
8056 | /* If it's a TSO packet, do GSO instead of | ||
8057 | * allocating and copying to a large linear SKB | ||
8058 | */ | ||
8059 | if (ip_tot_len) { | ||
8060 | iph->check = ip_csum; | ||
8061 | iph->tot_len = ip_tot_len; | ||
8062 | } | ||
8063 | tcph->check = tcp_csum; | ||
8064 | return tg3_tso_bug(tp, skb); | ||
8065 | } | ||
8066 | |||
8048 | /* If the workaround fails due to memory/mapping | 8067 | /* If the workaround fails due to memory/mapping |
8049 | * failure, silently drop this packet. | 8068 | * failure, silently drop this packet. |
8050 | */ | 8069 | */ |