aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sun
diff options
context:
space:
mode:
authorDavid L Stevens <david.stevens@oracle.com>2015-02-11 08:20:17 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-11 22:41:40 -0500
commitf7d70f74811f5a522885b2962edeccb417e950c7 (patch)
treea67252c41e854d14fdc25772e95da17d55c3851b /drivers/net/ethernet/sun
parent1d6c4cca41840c82e6967a48137f622547244630 (diff)
sunvnet: don't change gso data on clones
This patch unclones an skb for the case where the sunvnet driver needs to change the segmentation size so that it doesn't interfere with TCP SACK's use of them. Signed-off-by: David L Stevens <david.stevens@oracle.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sun')
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 2b10b85d8a08..22e0cad1b4b5 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -1192,23 +1192,16 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb)
1192 skb_pull(skb, maclen); 1192 skb_pull(skb, maclen);
1193 1193
1194 if (port->tso && gso_size < datalen) { 1194 if (port->tso && gso_size < datalen) {
1195 if (skb_unclone(skb, GFP_ATOMIC))
1196 goto out_dropped;
1197
1195 /* segment to TSO size */ 1198 /* segment to TSO size */
1196 skb_shinfo(skb)->gso_size = datalen; 1199 skb_shinfo(skb)->gso_size = datalen;
1197 skb_shinfo(skb)->gso_segs = gso_segs; 1200 skb_shinfo(skb)->gso_segs = gso_segs;
1198
1199 segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
1200
1201 /* restore gso_size & gso_segs */
1202 skb_shinfo(skb)->gso_size = gso_size;
1203 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len - hlen,
1204 gso_size);
1205 } else
1206 segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
1207 if (IS_ERR(segs)) {
1208 dev->stats.tx_dropped++;
1209 dev_kfree_skb_any(skb);
1210 return NETDEV_TX_OK;
1211 } 1201 }
1202 segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
1203 if (IS_ERR(segs))
1204 goto out_dropped;
1212 1205
1213 skb_push(skb, maclen); 1206 skb_push(skb, maclen);
1214 skb_reset_mac_header(skb); 1207 skb_reset_mac_header(skb);
@@ -1246,6 +1239,10 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb)
1246 if (!(status & NETDEV_TX_MASK)) 1239 if (!(status & NETDEV_TX_MASK))
1247 dev_kfree_skb_any(skb); 1240 dev_kfree_skb_any(skb);
1248 return status; 1241 return status;
1242out_dropped:
1243 dev->stats.tx_dropped++;
1244 dev_kfree_skb_any(skb);
1245 return NETDEV_TX_OK;
1249} 1246}
1250 1247
1251static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) 1248static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)