diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-30 18:40:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-30 18:40:17 -0400 |
commit | e37a72de84d27ee8bc0e7dbb5c2f1774ed306dbb (patch) | |
tree | f9da35cbd79b52a5bd08d4a0f960bde6af741da0 | |
parent | 93fdf10d4c28edaa1b9f80e7f9c3002359186d00 (diff) | |
parent | f83ef8c0b58dac17211a4c0b6df0e2b1bd6637b1 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[IPV6]: Added GSO support for TCPv6
[NET]: Generalise TSO-specific bits from skb_setup_caps
[IPV6]: Added GSO support for TCPv6
[IPV6]: Remove redundant length check on input
[NETFILTER]: SCTP conntrack: fix crash triggered by packet without chunks
[TG3]: Update version and reldate
[TG3]: Add TSO workaround using GSO
[TG3]: Turn on hw fix for ASF problems
[TG3]: Add rx BD workaround
[TG3]: Add tg3_netif_stop() in vlan functions
[TCP]: Reset gso_segs if packet is dodgy
-rw-r--r-- | drivers/net/s2io.c | 15 | ||||
-rw-r--r-- | drivers/net/tg3.c | 107 | ||||
-rw-r--r-- | drivers/net/tg3.h | 5 | ||||
-rw-r--r-- | include/linux/netdevice.h | 17 | ||||
-rw-r--r-- | include/linux/skbuff.h | 6 | ||||
-rw-r--r-- | include/net/ip6_route.h | 2 | ||||
-rw-r--r-- | include/net/protocol.h | 6 | ||||
-rw-r--r-- | include/net/sock.h | 13 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | include/net/tcp_ecn.h | 4 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_sctp.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 17 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 9 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 2 | ||||
-rw-r--r-- | net/ipv6/exthdrs.c | 4 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 7 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 4 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 62 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 7 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_sctp.c | 2 |
23 files changed, 236 insertions, 65 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 25d289eaaa20..001344c0763e 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -3959,7 +3959,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3959 | txdp->Control_2 = 0; | 3959 | txdp->Control_2 = 0; |
3960 | #ifdef NETIF_F_TSO | 3960 | #ifdef NETIF_F_TSO |
3961 | mss = skb_shinfo(skb)->gso_size; | 3961 | mss = skb_shinfo(skb)->gso_size; |
3962 | if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) { | 3962 | if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { |
3963 | txdp->Control_1 |= TXD_TCP_LSO_EN; | 3963 | txdp->Control_1 |= TXD_TCP_LSO_EN; |
3964 | txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); | 3964 | txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); |
3965 | } | 3965 | } |
@@ -3979,7 +3979,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3979 | } | 3979 | } |
3980 | 3980 | ||
3981 | frg_len = skb->len - skb->data_len; | 3981 | frg_len = skb->len - skb->data_len; |
3982 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) { | 3982 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { |
3983 | int ufo_size; | 3983 | int ufo_size; |
3984 | 3984 | ||
3985 | ufo_size = skb_shinfo(skb)->gso_size; | 3985 | ufo_size = skb_shinfo(skb)->gso_size; |
@@ -4008,7 +4008,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4008 | txdp->Host_Control = (unsigned long) skb; | 4008 | txdp->Host_Control = (unsigned long) skb; |
4009 | txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); | 4009 | txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); |
4010 | 4010 | ||
4011 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) | 4011 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) |
4012 | txdp->Control_1 |= TXD_UFO_EN; | 4012 | txdp->Control_1 |= TXD_UFO_EN; |
4013 | 4013 | ||
4014 | frg_cnt = skb_shinfo(skb)->nr_frags; | 4014 | frg_cnt = skb_shinfo(skb)->nr_frags; |
@@ -4023,12 +4023,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4023 | (sp->pdev, frag->page, frag->page_offset, | 4023 | (sp->pdev, frag->page, frag->page_offset, |
4024 | frag->size, PCI_DMA_TODEVICE); | 4024 | frag->size, PCI_DMA_TODEVICE); |
4025 | txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); | 4025 | txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); |
4026 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) | 4026 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) |
4027 | txdp->Control_1 |= TXD_UFO_EN; | 4027 | txdp->Control_1 |= TXD_UFO_EN; |
4028 | } | 4028 | } |
4029 | txdp->Control_1 |= TXD_GATHER_CODE_LAST; | 4029 | txdp->Control_1 |= TXD_GATHER_CODE_LAST; |
4030 | 4030 | ||
4031 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) | 4031 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) |
4032 | frg_cnt++; /* as Txd0 was used for inband header */ | 4032 | frg_cnt++; /* as Txd0 was used for inband header */ |
4033 | 4033 | ||
4034 | tx_fifo = mac_control->tx_FIFO_start[queue]; | 4034 | tx_fifo = mac_control->tx_FIFO_start[queue]; |
@@ -4042,7 +4042,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4042 | if (mss) | 4042 | if (mss) |
4043 | val64 |= TX_FIFO_SPECIAL_FUNC; | 4043 | val64 |= TX_FIFO_SPECIAL_FUNC; |
4044 | #endif | 4044 | #endif |
4045 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) | 4045 | if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) |
4046 | val64 |= TX_FIFO_SPECIAL_FUNC; | 4046 | val64 |= TX_FIFO_SPECIAL_FUNC; |
4047 | writeq(val64, &tx_fifo->List_Control); | 4047 | writeq(val64, &tx_fifo->List_Control); |
4048 | 4048 | ||
@@ -7020,6 +7020,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
7020 | #ifdef NETIF_F_TSO | 7020 | #ifdef NETIF_F_TSO |
7021 | dev->features |= NETIF_F_TSO; | 7021 | dev->features |= NETIF_F_TSO; |
7022 | #endif | 7022 | #endif |
7023 | #ifdef NETIF_F_TSO6 | ||
7024 | dev->features |= NETIF_F_TSO6; | ||
7025 | #endif | ||
7023 | if (sp->device_type & XFRAME_II_DEVICE) { | 7026 | if (sp->device_type & XFRAME_II_DEVICE) { |
7024 | dev->features |= NETIF_F_UFO; | 7027 | dev->features |= NETIF_F_UFO; |
7025 | dev->features |= NETIF_F_HW_CSUM; | 7028 | dev->features |= NETIF_F_HW_CSUM; |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6bea2b89a915..953255e92633 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -68,8 +68,8 @@ | |||
68 | 68 | ||
69 | #define DRV_MODULE_NAME "tg3" | 69 | #define DRV_MODULE_NAME "tg3" |
70 | #define PFX DRV_MODULE_NAME ": " | 70 | #define PFX DRV_MODULE_NAME ": " |
71 | #define DRV_MODULE_VERSION "3.60" | 71 | #define DRV_MODULE_VERSION "3.61" |
72 | #define DRV_MODULE_RELDATE "June 17, 2006" | 72 | #define DRV_MODULE_RELDATE "June 29, 2006" |
73 | 73 | ||
74 | #define TG3_DEF_MAC_MODE 0 | 74 | #define TG3_DEF_MAC_MODE 0 |
75 | #define TG3_DEF_RX_MODE 0 | 75 | #define TG3_DEF_RX_MODE 0 |
@@ -3194,7 +3194,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) | |||
3194 | */ | 3194 | */ |
3195 | static int tg3_rx(struct tg3 *tp, int budget) | 3195 | static int tg3_rx(struct tg3 *tp, int budget) |
3196 | { | 3196 | { |
3197 | u32 work_mask; | 3197 | u32 work_mask, rx_std_posted = 0; |
3198 | u32 sw_idx = tp->rx_rcb_ptr; | 3198 | u32 sw_idx = tp->rx_rcb_ptr; |
3199 | u16 hw_idx; | 3199 | u16 hw_idx; |
3200 | int received; | 3200 | int received; |
@@ -3221,6 +3221,7 @@ static int tg3_rx(struct tg3 *tp, int budget) | |||
3221 | mapping); | 3221 | mapping); |
3222 | skb = tp->rx_std_buffers[desc_idx].skb; | 3222 | skb = tp->rx_std_buffers[desc_idx].skb; |
3223 | post_ptr = &tp->rx_std_ptr; | 3223 | post_ptr = &tp->rx_std_ptr; |
3224 | rx_std_posted++; | ||
3224 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { | 3225 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { |
3225 | dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], | 3226 | dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], |
3226 | mapping); | 3227 | mapping); |
@@ -3308,6 +3309,15 @@ static int tg3_rx(struct tg3 *tp, int budget) | |||
3308 | 3309 | ||
3309 | next_pkt: | 3310 | next_pkt: |
3310 | (*post_ptr)++; | 3311 | (*post_ptr)++; |
3312 | |||
3313 | if (unlikely(rx_std_posted >= tp->rx_std_max_post)) { | ||
3314 | u32 idx = *post_ptr % TG3_RX_RING_SIZE; | ||
3315 | |||
3316 | tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + | ||
3317 | TG3_64BIT_REG_LOW, idx); | ||
3318 | work_mask &= ~RXD_OPAQUE_RING_STD; | ||
3319 | rx_std_posted = 0; | ||
3320 | } | ||
3311 | next_pkt_nopost: | 3321 | next_pkt_nopost: |
3312 | sw_idx++; | 3322 | sw_idx++; |
3313 | sw_idx %= TG3_RX_RCB_RING_SIZE(tp); | 3323 | sw_idx %= TG3_RX_RCB_RING_SIZE(tp); |
@@ -3869,6 +3879,40 @@ out_unlock: | |||
3869 | return NETDEV_TX_OK; | 3879 | return NETDEV_TX_OK; |
3870 | } | 3880 | } |
3871 | 3881 | ||
3882 | #if TG3_TSO_SUPPORT != 0 | ||
3883 | static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *); | ||
3884 | |||
3885 | /* Use GSO to workaround a rare TSO bug that may be triggered when the | ||
3886 | * TSO header is greater than 80 bytes. | ||
3887 | */ | ||
3888 | static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) | ||
3889 | { | ||
3890 | struct sk_buff *segs, *nskb; | ||
3891 | |||
3892 | /* Estimate the number of fragments in the worst case */ | ||
3893 | if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { | ||
3894 | netif_stop_queue(tp->dev); | ||
3895 | return NETDEV_TX_BUSY; | ||
3896 | } | ||
3897 | |||
3898 | segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO); | ||
3899 | if (unlikely(IS_ERR(segs))) | ||
3900 | goto tg3_tso_bug_end; | ||
3901 | |||
3902 | do { | ||
3903 | nskb = segs; | ||
3904 | segs = segs->next; | ||
3905 | nskb->next = NULL; | ||
3906 | tg3_start_xmit_dma_bug(nskb, tp->dev); | ||
3907 | } while (segs); | ||
3908 | |||
3909 | tg3_tso_bug_end: | ||
3910 | dev_kfree_skb(skb); | ||
3911 | |||
3912 | return NETDEV_TX_OK; | ||
3913 | } | ||
3914 | #endif | ||
3915 | |||
3872 | /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and | 3916 | /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and |
3873 | * support TG3_FLG2_HW_TSO_1 or firmware TSO only. | 3917 | * support TG3_FLG2_HW_TSO_1 or firmware TSO only. |
3874 | */ | 3918 | */ |
@@ -3905,7 +3949,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) | |||
3905 | mss = 0; | 3949 | mss = 0; |
3906 | if (skb->len > (tp->dev->mtu + ETH_HLEN) && | 3950 | if (skb->len > (tp->dev->mtu + ETH_HLEN) && |
3907 | (mss = skb_shinfo(skb)->gso_size) != 0) { | 3951 | (mss = skb_shinfo(skb)->gso_size) != 0) { |
3908 | int tcp_opt_len, ip_tcp_len; | 3952 | int tcp_opt_len, ip_tcp_len, hdr_len; |
3909 | 3953 | ||
3910 | if (skb_header_cloned(skb) && | 3954 | if (skb_header_cloned(skb) && |
3911 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | 3955 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { |
@@ -3916,11 +3960,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) | |||
3916 | tcp_opt_len = ((skb->h.th->doff - 5) * 4); | 3960 | tcp_opt_len = ((skb->h.th->doff - 5) * 4); |
3917 | ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); | 3961 | ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); |
3918 | 3962 | ||
3963 | hdr_len = ip_tcp_len + tcp_opt_len; | ||
3964 | if (unlikely((ETH_HLEN + hdr_len) > 80) && | ||
3965 | (tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG)) | ||
3966 | return (tg3_tso_bug(tp, skb)); | ||
3967 | |||
3919 | base_flags |= (TXD_FLAG_CPU_PRE_DMA | | 3968 | base_flags |= (TXD_FLAG_CPU_PRE_DMA | |
3920 | TXD_FLAG_CPU_POST_DMA); | 3969 | TXD_FLAG_CPU_POST_DMA); |
3921 | 3970 | ||
3922 | skb->nh.iph->check = 0; | 3971 | skb->nh.iph->check = 0; |
3923 | skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); | 3972 | skb->nh.iph->tot_len = htons(mss + hdr_len); |
3924 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { | 3973 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { |
3925 | skb->h.th->check = 0; | 3974 | skb->h.th->check = 0; |
3926 | base_flags &= ~TXD_FLAG_TCPUDP_CSUM; | 3975 | base_flags &= ~TXD_FLAG_TCPUDP_CSUM; |
@@ -5980,7 +6029,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
5980 | } | 6029 | } |
5981 | 6030 | ||
5982 | /* Setup replenish threshold. */ | 6031 | /* Setup replenish threshold. */ |
5983 | tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); | 6032 | val = tp->rx_pending / 8; |
6033 | if (val == 0) | ||
6034 | val = 1; | ||
6035 | else if (val > tp->rx_std_max_post) | ||
6036 | val = tp->rx_std_max_post; | ||
6037 | |||
6038 | tw32(RCVBDI_STD_THRESH, val); | ||
5984 | 6039 | ||
5985 | /* Initialize TG3_BDINFO's at: | 6040 | /* Initialize TG3_BDINFO's at: |
5986 | * RCVDBDI_STD_BD: standard eth size rx ring | 6041 | * RCVDBDI_STD_BD: standard eth size rx ring |
@@ -6140,8 +6195,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
6140 | #endif | 6195 | #endif |
6141 | 6196 | ||
6142 | /* Receive/send statistics. */ | 6197 | /* Receive/send statistics. */ |
6143 | if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && | 6198 | if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { |
6144 | (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { | 6199 | val = tr32(RCVLPC_STATS_ENABLE); |
6200 | val &= ~RCVLPC_STATSENAB_DACK_FIX; | ||
6201 | tw32(RCVLPC_STATS_ENABLE, val); | ||
6202 | } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && | ||
6203 | (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { | ||
6145 | val = tr32(RCVLPC_STATS_ENABLE); | 6204 | val = tr32(RCVLPC_STATS_ENABLE); |
6146 | val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; | 6205 | val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; |
6147 | tw32(RCVLPC_STATS_ENABLE, val); | 6206 | tw32(RCVLPC_STATS_ENABLE, val); |
@@ -8737,6 +8796,9 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | |||
8737 | { | 8796 | { |
8738 | struct tg3 *tp = netdev_priv(dev); | 8797 | struct tg3 *tp = netdev_priv(dev); |
8739 | 8798 | ||
8799 | if (netif_running(dev)) | ||
8800 | tg3_netif_stop(tp); | ||
8801 | |||
8740 | tg3_full_lock(tp, 0); | 8802 | tg3_full_lock(tp, 0); |
8741 | 8803 | ||
8742 | tp->vlgrp = grp; | 8804 | tp->vlgrp = grp; |
@@ -8745,16 +8807,25 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | |||
8745 | __tg3_set_rx_mode(dev); | 8807 | __tg3_set_rx_mode(dev); |
8746 | 8808 | ||
8747 | tg3_full_unlock(tp); | 8809 | tg3_full_unlock(tp); |
8810 | |||
8811 | if (netif_running(dev)) | ||
8812 | tg3_netif_start(tp); | ||
8748 | } | 8813 | } |
8749 | 8814 | ||
8750 | static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | 8815 | static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) |
8751 | { | 8816 | { |
8752 | struct tg3 *tp = netdev_priv(dev); | 8817 | struct tg3 *tp = netdev_priv(dev); |
8753 | 8818 | ||
8819 | if (netif_running(dev)) | ||
8820 | tg3_netif_stop(tp); | ||
8821 | |||
8754 | tg3_full_lock(tp, 0); | 8822 | tg3_full_lock(tp, 0); |
8755 | if (tp->vlgrp) | 8823 | if (tp->vlgrp) |
8756 | tp->vlgrp->vlan_devices[vid] = NULL; | 8824 | tp->vlgrp->vlan_devices[vid] = NULL; |
8757 | tg3_full_unlock(tp); | 8825 | tg3_full_unlock(tp); |
8826 | |||
8827 | if (netif_running(dev)) | ||
8828 | tg3_netif_start(tp); | ||
8758 | } | 8829 | } |
8759 | #endif | 8830 | #endif |
8760 | 8831 | ||
@@ -10159,8 +10230,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10159 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { | 10230 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { |
10160 | tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; | 10231 | tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; |
10161 | tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; | 10232 | tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; |
10162 | } else | 10233 | } else { |
10163 | tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1; | 10234 | tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | |
10235 | TG3_FLG2_HW_TSO_1_BUG; | ||
10236 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == | ||
10237 | ASIC_REV_5750 && | ||
10238 | tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2) | ||
10239 | tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG; | ||
10240 | } | ||
10164 | } | 10241 | } |
10165 | 10242 | ||
10166 | if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && | 10243 | if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && |
@@ -10532,6 +10609,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10532 | (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) | 10609 | (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) |
10533 | tp->rx_offset = 0; | 10610 | tp->rx_offset = 0; |
10534 | 10611 | ||
10612 | tp->rx_std_max_post = TG3_RX_RING_SIZE; | ||
10613 | |||
10614 | /* Increment the rx prod index on the rx std ring by at most | ||
10615 | * 8 for these chips to workaround hw errata. | ||
10616 | */ | ||
10617 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || | ||
10618 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || | ||
10619 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) | ||
10620 | tp->rx_std_max_post = 8; | ||
10621 | |||
10535 | /* By default, disable wake-on-lan. User can change this | 10622 | /* By default, disable wake-on-lan. User can change this |
10536 | * using ETHTOOL_SWOL. | 10623 | * using ETHTOOL_SWOL. |
10537 | */ | 10624 | */ |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 8209da5dd15f..ba2c98711c88 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -125,6 +125,7 @@ | |||
125 | #define CHIPREV_ID_5750_A0 0x4000 | 125 | #define CHIPREV_ID_5750_A0 0x4000 |
126 | #define CHIPREV_ID_5750_A1 0x4001 | 126 | #define CHIPREV_ID_5750_A1 0x4001 |
127 | #define CHIPREV_ID_5750_A3 0x4003 | 127 | #define CHIPREV_ID_5750_A3 0x4003 |
128 | #define CHIPREV_ID_5750_C2 0x4202 | ||
128 | #define CHIPREV_ID_5752_A0_HW 0x5000 | 129 | #define CHIPREV_ID_5752_A0_HW 0x5000 |
129 | #define CHIPREV_ID_5752_A0 0x6000 | 130 | #define CHIPREV_ID_5752_A0 0x6000 |
130 | #define CHIPREV_ID_5752_A1 0x6001 | 131 | #define CHIPREV_ID_5752_A1 0x6001 |
@@ -760,6 +761,7 @@ | |||
760 | #define RCVLPC_STATSCTRL_ENABLE 0x00000001 | 761 | #define RCVLPC_STATSCTRL_ENABLE 0x00000001 |
761 | #define RCVLPC_STATSCTRL_FASTUPD 0x00000002 | 762 | #define RCVLPC_STATSCTRL_FASTUPD 0x00000002 |
762 | #define RCVLPC_STATS_ENABLE 0x00002018 | 763 | #define RCVLPC_STATS_ENABLE 0x00002018 |
764 | #define RCVLPC_STATSENAB_DACK_FIX 0x00040000 | ||
763 | #define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 | 765 | #define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 |
764 | #define RCVLPC_STATS_INCMASK 0x0000201c | 766 | #define RCVLPC_STATS_INCMASK 0x0000201c |
765 | /* 0x2020 --> 0x2100 unused */ | 767 | /* 0x2020 --> 0x2100 unused */ |
@@ -2137,6 +2139,7 @@ struct tg3 { | |||
2137 | struct tg3_rx_buffer_desc *rx_std; | 2139 | struct tg3_rx_buffer_desc *rx_std; |
2138 | struct ring_info *rx_std_buffers; | 2140 | struct ring_info *rx_std_buffers; |
2139 | dma_addr_t rx_std_mapping; | 2141 | dma_addr_t rx_std_mapping; |
2142 | u32 rx_std_max_post; | ||
2140 | 2143 | ||
2141 | struct tg3_rx_buffer_desc *rx_jumbo; | 2144 | struct tg3_rx_buffer_desc *rx_jumbo; |
2142 | struct ring_info *rx_jumbo_buffers; | 2145 | struct ring_info *rx_jumbo_buffers; |
@@ -2191,7 +2194,7 @@ struct tg3 { | |||
2191 | #define TG3_FLAG_INIT_COMPLETE 0x80000000 | 2194 | #define TG3_FLAG_INIT_COMPLETE 0x80000000 |
2192 | u32 tg3_flags2; | 2195 | u32 tg3_flags2; |
2193 | #define TG3_FLG2_RESTART_TIMER 0x00000001 | 2196 | #define TG3_FLG2_RESTART_TIMER 0x00000001 |
2194 | /* 0x00000002 available */ | 2197 | #define TG3_FLG2_HW_TSO_1_BUG 0x00000002 |
2195 | #define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 | 2198 | #define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 |
2196 | #define TG3_FLG2_IS_5788 0x00000008 | 2199 | #define TG3_FLG2_IS_5788 0x00000008 |
2197 | #define TG3_FLG2_MAX_RXPEND_64 0x00000010 | 2200 | #define TG3_FLG2_MAX_RXPEND_64 0x00000010 |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index aa2d3c12c4d8..85f99f60deea 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -313,10 +313,12 @@ struct net_device | |||
313 | 313 | ||
314 | /* Segmentation offload features */ | 314 | /* Segmentation offload features */ |
315 | #define NETIF_F_GSO_SHIFT 16 | 315 | #define NETIF_F_GSO_SHIFT 16 |
316 | #define NETIF_F_GSO_MASK 0xffff0000 | ||
316 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) | 317 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) |
317 | #define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) | 318 | #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) |
318 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) | 319 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) |
319 | #define NETIF_F_TSO_ECN (SKB_GSO_TCPV4_ECN << NETIF_F_GSO_SHIFT) | 320 | #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) |
321 | #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) | ||
320 | 322 | ||
321 | #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) | 323 | #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) |
322 | #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) | 324 | #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) |
@@ -991,13 +993,18 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); | |||
991 | 993 | ||
992 | extern void linkwatch_run_queue(void); | 994 | extern void linkwatch_run_queue(void); |
993 | 995 | ||
994 | static inline int skb_gso_ok(struct sk_buff *skb, int features) | 996 | static inline int net_gso_ok(int features, int gso_type) |
995 | { | 997 | { |
996 | int feature = skb_shinfo(skb)->gso_size ? | 998 | int feature = gso_type << NETIF_F_GSO_SHIFT; |
997 | skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0; | ||
998 | return (features & feature) == feature; | 999 | return (features & feature) == feature; |
999 | } | 1000 | } |
1000 | 1001 | ||
1002 | static inline int skb_gso_ok(struct sk_buff *skb, int features) | ||
1003 | { | ||
1004 | return net_gso_ok(features, skb_shinfo(skb)->gso_size ? | ||
1005 | skb_shinfo(skb)->gso_type : 0); | ||
1006 | } | ||
1007 | |||
1001 | static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) | 1008 | static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) |
1002 | { | 1009 | { |
1003 | return !skb_gso_ok(skb, dev->features); | 1010 | return !skb_gso_ok(skb, dev->features); |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 59918be91d0a..57d7d4965f9a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -171,13 +171,15 @@ enum { | |||
171 | 171 | ||
172 | enum { | 172 | enum { |
173 | SKB_GSO_TCPV4 = 1 << 0, | 173 | SKB_GSO_TCPV4 = 1 << 0, |
174 | SKB_GSO_UDPV4 = 1 << 1, | 174 | SKB_GSO_UDP = 1 << 1, |
175 | 175 | ||
176 | /* This indicates the skb is from an untrusted source. */ | 176 | /* This indicates the skb is from an untrusted source. */ |
177 | SKB_GSO_DODGY = 1 << 2, | 177 | SKB_GSO_DODGY = 1 << 2, |
178 | 178 | ||
179 | /* This indicates the tcp segment has CWR set. */ | 179 | /* This indicates the tcp segment has CWR set. */ |
180 | SKB_GSO_TCPV4_ECN = 1 << 3, | 180 | SKB_GSO_TCP_ECN = 1 << 3, |
181 | |||
182 | SKB_GSO_TCPV6 = 1 << 4, | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | /** | 185 | /** |
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index a398ae5e30f9..ab29dafb1a6a 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
@@ -146,7 +146,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, | |||
146 | struct rt6_info *rt = (struct rt6_info *) dst; | 146 | struct rt6_info *rt = (struct rt6_info *) dst; |
147 | 147 | ||
148 | write_lock(&sk->sk_dst_lock); | 148 | write_lock(&sk->sk_dst_lock); |
149 | __sk_dst_set(sk, dst); | 149 | sk_setup_caps(sk, dst); |
150 | np->daddr_cache = daddr; | 150 | np->daddr_cache = daddr; |
151 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; | 151 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
152 | write_unlock(&sk->sk_dst_lock); | 152 | write_unlock(&sk->sk_dst_lock); |
diff --git a/include/net/protocol.h b/include/net/protocol.h index 40b6b9c9973f..a225d6371cb1 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -50,11 +50,17 @@ struct inet6_protocol | |||
50 | struct inet6_skb_parm *opt, | 50 | struct inet6_skb_parm *opt, |
51 | int type, int code, int offset, | 51 | int type, int code, int offset, |
52 | __u32 info); | 52 | __u32 info); |
53 | |||
54 | struct sk_buff *(*gso_segment)(struct sk_buff *skb, | ||
55 | int features); | ||
56 | |||
53 | unsigned int flags; /* INET6_PROTO_xxx */ | 57 | unsigned int flags; /* INET6_PROTO_xxx */ |
54 | }; | 58 | }; |
55 | 59 | ||
56 | #define INET6_PROTO_NOPOLICY 0x1 | 60 | #define INET6_PROTO_NOPOLICY 0x1 |
57 | #define INET6_PROTO_FINAL 0x2 | 61 | #define INET6_PROTO_FINAL 0x2 |
62 | /* This should be set for any extension header which is compatible with GSO. */ | ||
63 | #define INET6_PROTO_GSO_EXTHDR 0x4 | ||
58 | #endif | 64 | #endif |
59 | 65 | ||
60 | /* This is used to register socket interfaces for IP protocols. */ | 66 | /* This is used to register socket interfaces for IP protocols. */ |
diff --git a/include/net/sock.h b/include/net/sock.h index 7136bae48c2f..7b3d6b856946 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -140,6 +140,7 @@ struct sock_common { | |||
140 | * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings | 140 | * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings |
141 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets | 141 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets |
142 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) | 142 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) |
143 | * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) | ||
143 | * @sk_lingertime: %SO_LINGER l_linger setting | 144 | * @sk_lingertime: %SO_LINGER l_linger setting |
144 | * @sk_backlog: always used with the per-socket spinlock held | 145 | * @sk_backlog: always used with the per-socket spinlock held |
145 | * @sk_callback_lock: used with the callbacks in the end of this struct | 146 | * @sk_callback_lock: used with the callbacks in the end of this struct |
@@ -211,6 +212,7 @@ struct sock { | |||
211 | gfp_t sk_allocation; | 212 | gfp_t sk_allocation; |
212 | int sk_sndbuf; | 213 | int sk_sndbuf; |
213 | int sk_route_caps; | 214 | int sk_route_caps; |
215 | int sk_gso_type; | ||
214 | int sk_rcvlowat; | 216 | int sk_rcvlowat; |
215 | unsigned long sk_flags; | 217 | unsigned long sk_flags; |
216 | unsigned long sk_lingertime; | 218 | unsigned long sk_lingertime; |
@@ -1025,15 +1027,20 @@ extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); | |||
1025 | 1027 | ||
1026 | extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); | 1028 | extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); |
1027 | 1029 | ||
1030 | static inline int sk_can_gso(const struct sock *sk) | ||
1031 | { | ||
1032 | return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); | ||
1033 | } | ||
1034 | |||
1028 | static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | 1035 | static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) |
1029 | { | 1036 | { |
1030 | __sk_dst_set(sk, dst); | 1037 | __sk_dst_set(sk, dst); |
1031 | sk->sk_route_caps = dst->dev->features; | 1038 | sk->sk_route_caps = dst->dev->features; |
1032 | if (sk->sk_route_caps & NETIF_F_GSO) | 1039 | if (sk->sk_route_caps & NETIF_F_GSO) |
1033 | sk->sk_route_caps |= NETIF_F_TSO; | 1040 | sk->sk_route_caps |= NETIF_F_GSO_MASK; |
1034 | if (sk->sk_route_caps & NETIF_F_TSO) { | 1041 | if (sk_can_gso(sk)) { |
1035 | if (dst->header_len) | 1042 | if (dst->header_len) |
1036 | sk->sk_route_caps &= ~NETIF_F_TSO; | 1043 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1037 | else | 1044 | else |
1038 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; | 1045 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; |
1039 | } | 1046 | } |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 624921e76332..3cd803b0d7a5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -751,7 +751,7 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | |||
751 | if (in_flight >= tp->snd_cwnd) | 751 | if (in_flight >= tp->snd_cwnd) |
752 | return 1; | 752 | return 1; |
753 | 753 | ||
754 | if (!(sk->sk_route_caps & NETIF_F_TSO)) | 754 | if (!sk_can_gso(sk)) |
755 | return 0; | 755 | return 0; |
756 | 756 | ||
757 | left = tp->snd_cwnd - in_flight; | 757 | left = tp->snd_cwnd - in_flight; |
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h index 7bb366f70934..4629d77173f2 100644 --- a/include/net/tcp_ecn.h +++ b/include/net/tcp_ecn.h | |||
@@ -55,9 +55,7 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp, | |||
55 | if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { | 55 | if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { |
56 | tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; | 56 | tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; |
57 | skb->h.th->cwr = 1; | 57 | skb->h.th->cwr = 1; |
58 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) | 58 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; |
59 | skb_shinfo(skb)->gso_type |= | ||
60 | SKB_GSO_TCPV4_ECN; | ||
61 | } | 59 | } |
62 | } else { | 60 | } else { |
63 | /* ACK or retransmitted segment: clear ECT|CE */ | 61 | /* ACK or retransmitted segment: clear ECT|CE */ |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 0c872fd0849d..ca0e714613fb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -743,7 +743,7 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
743 | if (!err) { | 743 | if (!err) { |
744 | /* specify the length of each IP datagram fragment*/ | 744 | /* specify the length of each IP datagram fragment*/ |
745 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; | 745 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; |
746 | skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; | 746 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
747 | __skb_queue_tail(&sk->sk_write_queue, skb); | 747 | __skb_queue_tail(&sk->sk_write_queue, skb); |
748 | 748 | ||
749 | return 0; | 749 | return 0; |
@@ -1088,7 +1088,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1088 | if ((sk->sk_protocol == IPPROTO_UDP) && | 1088 | if ((sk->sk_protocol == IPPROTO_UDP) && |
1089 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1089 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
1090 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; | 1090 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; |
1091 | skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; | 1091 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | 1094 | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 0416073c5600..2d3612cd5f18 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c | |||
@@ -254,7 +254,7 @@ static int do_basic_checks(struct ip_conntrack *conntrack, | |||
254 | } | 254 | } |
255 | 255 | ||
256 | DEBUGP("Basic checks passed\n"); | 256 | DEBUGP("Basic checks passed\n"); |
257 | return 0; | 257 | return count == 0; |
258 | } | 258 | } |
259 | 259 | ||
260 | static int new_state(enum ip_conntrack_dir dir, | 260 | static int new_state(enum ip_conntrack_dir dir, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a97450e9eb34..804458712d88 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -642,7 +642,7 @@ static inline int select_size(struct sock *sk, struct tcp_sock *tp) | |||
642 | int tmp = tp->mss_cache; | 642 | int tmp = tp->mss_cache; |
643 | 643 | ||
644 | if (sk->sk_route_caps & NETIF_F_SG) { | 644 | if (sk->sk_route_caps & NETIF_F_SG) { |
645 | if (sk->sk_route_caps & NETIF_F_TSO) | 645 | if (sk_can_gso(sk)) |
646 | tmp = 0; | 646 | tmp = 0; |
647 | else { | 647 | else { |
648 | int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); | 648 | int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); |
@@ -2165,13 +2165,19 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2165 | if (!pskb_may_pull(skb, thlen)) | 2165 | if (!pskb_may_pull(skb, thlen)) |
2166 | goto out; | 2166 | goto out; |
2167 | 2167 | ||
2168 | segs = NULL; | ||
2169 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) | ||
2170 | goto out; | ||
2171 | |||
2172 | oldlen = (u16)~skb->len; | 2168 | oldlen = (u16)~skb->len; |
2173 | __skb_pull(skb, thlen); | 2169 | __skb_pull(skb, thlen); |
2174 | 2170 | ||
2171 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | ||
2172 | /* Packet is from an untrusted source, reset gso_segs. */ | ||
2173 | int mss = skb_shinfo(skb)->gso_size; | ||
2174 | |||
2175 | skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; | ||
2176 | |||
2177 | segs = NULL; | ||
2178 | goto out; | ||
2179 | } | ||
2180 | |||
2175 | segs = skb_segment(skb, features); | 2181 | segs = skb_segment(skb, features); |
2176 | if (IS_ERR(segs)) | 2182 | if (IS_ERR(segs)) |
2177 | goto out; | 2183 | goto out; |
@@ -2208,6 +2214,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2208 | out: | 2214 | out: |
2209 | return segs; | 2215 | return segs; |
2210 | } | 2216 | } |
2217 | EXPORT_SYMBOL(tcp_tso_segment); | ||
2211 | 2218 | ||
2212 | extern void __skb_cb_too_small_for_tcp(int, int); | 2219 | extern void __skb_cb_too_small_for_tcp(int, int); |
2213 | extern struct tcp_congestion_ops tcp_reno; | 2220 | extern struct tcp_congestion_ops tcp_reno; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e02a84cf9a53..8355b729fa95 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -241,6 +241,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
241 | goto failure; | 241 | goto failure; |
242 | 242 | ||
243 | /* OK, now commit destination to socket. */ | 243 | /* OK, now commit destination to socket. */ |
244 | sk->sk_gso_type = SKB_GSO_TCPV4; | ||
244 | sk_setup_caps(sk, &rt->u.dst); | 245 | sk_setup_caps(sk, &rt->u.dst); |
245 | 246 | ||
246 | if (!tp->write_seq) | 247 | if (!tp->write_seq) |
@@ -883,6 +884,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
883 | if (!newsk) | 884 | if (!newsk) |
884 | goto exit; | 885 | goto exit; |
885 | 886 | ||
887 | newsk->sk_gso_type = SKB_GSO_TCPV4; | ||
886 | sk_setup_caps(newsk, dst); | 888 | sk_setup_caps(newsk, dst); |
887 | 889 | ||
888 | newtp = tcp_sk(newsk); | 890 | newtp = tcp_sk(newsk); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5a7cb4a9c867..5c08ea20a18d 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -510,8 +510,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) | |||
510 | 510 | ||
511 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) | 511 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) |
512 | { | 512 | { |
513 | if (skb->len <= mss_now || | 513 | if (skb->len <= mss_now || !sk_can_gso(sk)) { |
514 | !(sk->sk_route_caps & NETIF_F_TSO)) { | ||
515 | /* Avoid the costly divide in the normal | 514 | /* Avoid the costly divide in the normal |
516 | * non-TSO case. | 515 | * non-TSO case. |
517 | */ | 516 | */ |
@@ -525,7 +524,7 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned | |||
525 | factor /= mss_now; | 524 | factor /= mss_now; |
526 | skb_shinfo(skb)->gso_segs = factor; | 525 | skb_shinfo(skb)->gso_segs = factor; |
527 | skb_shinfo(skb)->gso_size = mss_now; | 526 | skb_shinfo(skb)->gso_size = mss_now; |
528 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 527 | skb_shinfo(skb)->gso_type = sk->sk_gso_type; |
529 | } | 528 | } |
530 | } | 529 | } |
531 | 530 | ||
@@ -824,9 +823,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) | |||
824 | 823 | ||
825 | mss_now = tp->mss_cache; | 824 | mss_now = tp->mss_cache; |
826 | 825 | ||
827 | if (large_allowed && | 826 | if (large_allowed && sk_can_gso(sk) && !tp->urg_mode) |
828 | (sk->sk_route_caps & NETIF_F_TSO) && | ||
829 | !tp->urg_mode) | ||
830 | doing_tso = 1; | 827 | doing_tso = 1; |
831 | 828 | ||
832 | if (dst) { | 829 | if (dst) { |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index a94c91b407ef..5a0ba58b86cc 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -659,8 +659,6 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
659 | } | 659 | } |
660 | 660 | ||
661 | ip6_dst_store(sk, dst, NULL); | 661 | ip6_dst_store(sk, dst, NULL); |
662 | sk->sk_route_caps = dst->dev->features & | ||
663 | ~(NETIF_F_IP_CSUM | NETIF_F_TSO); | ||
664 | } | 662 | } |
665 | 663 | ||
666 | return 0; | 664 | return 0; |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index a18d4256372c..9d0ee7f0eeb5 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -179,7 +179,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
179 | 179 | ||
180 | static struct inet6_protocol destopt_protocol = { | 180 | static struct inet6_protocol destopt_protocol = { |
181 | .handler = ipv6_destopt_rcv, | 181 | .handler = ipv6_destopt_rcv, |
182 | .flags = INET6_PROTO_NOPOLICY, | 182 | .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, |
183 | }; | 183 | }; |
184 | 184 | ||
185 | void __init ipv6_destopt_init(void) | 185 | void __init ipv6_destopt_init(void) |
@@ -340,7 +340,7 @@ looped_back: | |||
340 | 340 | ||
341 | static struct inet6_protocol rthdr_protocol = { | 341 | static struct inet6_protocol rthdr_protocol = { |
342 | .handler = ipv6_rthdr_rcv, | 342 | .handler = ipv6_rthdr_rcv, |
343 | .flags = INET6_PROTO_NOPOLICY, | 343 | .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, |
344 | }; | 344 | }; |
345 | 345 | ||
346 | void __init ipv6_rthdr_init(void) | 346 | void __init ipv6_rthdr_init(void) |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 11536db225d7..5c950cc79d80 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -186,8 +186,6 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
186 | } | 186 | } |
187 | 187 | ||
188 | ip6_dst_store(sk, dst, NULL); | 188 | ip6_dst_store(sk, dst, NULL); |
189 | sk->sk_route_caps = dst->dev->features & | ||
190 | ~(NETIF_F_IP_CSUM | NETIF_F_TSO); | ||
191 | } | 189 | } |
192 | 190 | ||
193 | skb->dst = dst_clone(dst); | 191 | skb->dst = dst_clone(dst); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index aceee252503d..df8f051c0fce 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -84,14 +84,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
84 | */ | 84 | */ |
85 | IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; | 85 | IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; |
86 | 86 | ||
87 | if (skb->len < sizeof(struct ipv6hdr)) | 87 | if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) |
88 | goto err; | 88 | goto err; |
89 | 89 | ||
90 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { | ||
91 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | ||
92 | goto drop; | ||
93 | } | ||
94 | |||
95 | hdr = skb->nh.ipv6h; | 90 | hdr = skb->nh.ipv6h; |
96 | 91 | ||
97 | if (hdr->version != 6) | 92 | if (hdr->version != 6) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index aa2b2c3e5076..2c5b44575af0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -229,7 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
229 | skb->priority = sk->sk_priority; | 229 | skb->priority = sk->sk_priority; |
230 | 230 | ||
231 | mtu = dst_mtu(dst); | 231 | mtu = dst_mtu(dst); |
232 | if ((skb->len <= mtu) || ipfragok) { | 232 | if ((skb->len <= mtu) || ipfragok || skb_shinfo(skb)->gso_size) { |
233 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 233 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); |
234 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, | 234 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, |
235 | dst_output); | 235 | dst_output); |
@@ -834,7 +834,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
834 | /* specify the length of each IP datagram fragment*/ | 834 | /* specify the length of each IP datagram fragment*/ |
835 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen - | 835 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen - |
836 | sizeof(struct frag_hdr); | 836 | sizeof(struct frag_hdr); |
837 | skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; | 837 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
838 | ipv6_select_ident(skb, &fhdr); | 838 | ipv6_select_ident(skb, &fhdr); |
839 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | 839 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; |
840 | __skb_queue_tail(&sk->sk_write_queue, skb); | 840 | __skb_queue_tail(&sk->sk_write_queue, skb); |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 97199d6ec79f..c28e5c287447 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -57,9 +57,71 @@ | |||
57 | 57 | ||
58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; | 58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; |
59 | 59 | ||
60 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | ||
61 | { | ||
62 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
63 | struct ipv6hdr *ipv6h; | ||
64 | struct inet6_protocol *ops; | ||
65 | int proto; | ||
66 | |||
67 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | ||
68 | goto out; | ||
69 | |||
70 | ipv6h = skb->nh.ipv6h; | ||
71 | proto = ipv6h->nexthdr; | ||
72 | __skb_pull(skb, sizeof(*ipv6h)); | ||
73 | |||
74 | rcu_read_lock(); | ||
75 | for (;;) { | ||
76 | struct ipv6_opt_hdr *opth; | ||
77 | int len; | ||
78 | |||
79 | if (proto != NEXTHDR_HOP) { | ||
80 | ops = rcu_dereference(inet6_protos[proto]); | ||
81 | |||
82 | if (unlikely(!ops)) | ||
83 | goto unlock; | ||
84 | |||
85 | if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | if (unlikely(!pskb_may_pull(skb, 8))) | ||
90 | goto unlock; | ||
91 | |||
92 | opth = (void *)skb->data; | ||
93 | len = opth->hdrlen * 8 + 8; | ||
94 | |||
95 | if (unlikely(!pskb_may_pull(skb, len))) | ||
96 | goto unlock; | ||
97 | |||
98 | proto = opth->nexthdr; | ||
99 | __skb_pull(skb, len); | ||
100 | } | ||
101 | |||
102 | skb->h.raw = skb->data; | ||
103 | if (likely(ops->gso_segment)) | ||
104 | segs = ops->gso_segment(skb, features); | ||
105 | |||
106 | unlock: | ||
107 | rcu_read_unlock(); | ||
108 | |||
109 | if (unlikely(IS_ERR(segs))) | ||
110 | goto out; | ||
111 | |||
112 | for (skb = segs; skb; skb = skb->next) { | ||
113 | ipv6h = skb->nh.ipv6h; | ||
114 | ipv6h->payload_len = htons(skb->len - skb->mac_len); | ||
115 | } | ||
116 | |||
117 | out: | ||
118 | return segs; | ||
119 | } | ||
120 | |||
60 | static struct packet_type ipv6_packet_type = { | 121 | static struct packet_type ipv6_packet_type = { |
61 | .type = __constant_htons(ETH_P_IPV6), | 122 | .type = __constant_htons(ETH_P_IPV6), |
62 | .func = ipv6_rcv, | 123 | .func = ipv6_rcv, |
124 | .gso_segment = ipv6_gso_segment, | ||
63 | }; | 125 | }; |
64 | 126 | ||
65 | struct ip6_ra_chain *ip6_ra_chain; | 127 | struct ip6_ra_chain *ip6_ra_chain; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 81dbc9c3bf04..5bdcb9002cf7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -269,9 +269,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
269 | ipv6_addr_copy(&np->saddr, saddr); | 269 | ipv6_addr_copy(&np->saddr, saddr); |
270 | inet->rcv_saddr = LOOPBACK4_IPV6; | 270 | inet->rcv_saddr = LOOPBACK4_IPV6; |
271 | 271 | ||
272 | sk->sk_gso_type = SKB_GSO_TCPV6; | ||
272 | ip6_dst_store(sk, dst, NULL); | 273 | ip6_dst_store(sk, dst, NULL); |
273 | sk->sk_route_caps = dst->dev->features & | ||
274 | ~(NETIF_F_IP_CSUM | NETIF_F_TSO); | ||
275 | 274 | ||
276 | icsk->icsk_ext_hdr_len = 0; | 275 | icsk->icsk_ext_hdr_len = 0; |
277 | if (np->opt) | 276 | if (np->opt) |
@@ -929,9 +928,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
929 | * comment in that function for the gory details. -acme | 928 | * comment in that function for the gory details. -acme |
930 | */ | 929 | */ |
931 | 930 | ||
931 | sk->sk_gso_type = SKB_GSO_TCPV6; | ||
932 | ip6_dst_store(newsk, dst, NULL); | 932 | ip6_dst_store(newsk, dst, NULL); |
933 | newsk->sk_route_caps = dst->dev->features & | ||
934 | ~(NETIF_F_IP_CSUM | NETIF_F_TSO); | ||
935 | 933 | ||
936 | newtcp6sk = (struct tcp6_sock *)newsk; | 934 | newtcp6sk = (struct tcp6_sock *)newsk; |
937 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; | 935 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; |
@@ -1605,6 +1603,7 @@ struct proto tcpv6_prot = { | |||
1605 | static struct inet6_protocol tcpv6_protocol = { | 1603 | static struct inet6_protocol tcpv6_protocol = { |
1606 | .handler = tcp_v6_rcv, | 1604 | .handler = tcp_v6_rcv, |
1607 | .err_handler = tcp_v6_err, | 1605 | .err_handler = tcp_v6_err, |
1606 | .gso_segment = tcp_tso_segment, | ||
1608 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 1607 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
1609 | }; | 1608 | }; |
1610 | 1609 | ||
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 0839b701b930..9bd8a7877fd5 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -261,7 +261,7 @@ static int do_basic_checks(struct nf_conn *conntrack, | |||
261 | } | 261 | } |
262 | 262 | ||
263 | DEBUGP("Basic checks passed\n"); | 263 | DEBUGP("Basic checks passed\n"); |
264 | return 0; | 264 | return count == 0; |
265 | } | 265 | } |
266 | 266 | ||
267 | static int new_state(enum ip_conntrack_dir dir, | 267 | static int new_state(enum ip_conntrack_dir dir, |