diff options
-rw-r--r-- | drivers/net/ethernet/sfc/tx.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 61bc0ed718e3..d9dbebc9f819 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c | |||
@@ -631,7 +631,7 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) | |||
631 | * @dma_flags: TX buffer flags for DMA mapping - %EFX_TX_BUF_MAP_SINGLE or 0 | 631 | * @dma_flags: TX buffer flags for DMA mapping - %EFX_TX_BUF_MAP_SINGLE or 0 |
632 | * @protocol: Network protocol (after any VLAN header) | 632 | * @protocol: Network protocol (after any VLAN header) |
633 | * @header_len: Number of bytes of header | 633 | * @header_len: Number of bytes of header |
634 | * @full_packet_size: Number of bytes to put in each outgoing segment | 634 | * @ip_base_len: IPv4 tot_len or IPv6 payload_len, before TCP payload |
635 | * | 635 | * |
636 | * The state used during segmentation. It is put into this data structure | 636 | * The state used during segmentation. It is put into this data structure |
637 | * just to make it easy to pass into inline functions. | 637 | * just to make it easy to pass into inline functions. |
@@ -652,7 +652,7 @@ struct tso_state { | |||
652 | 652 | ||
653 | __be16 protocol; | 653 | __be16 protocol; |
654 | unsigned header_len; | 654 | unsigned header_len; |
655 | int full_packet_size; | 655 | unsigned int ip_base_len; |
656 | }; | 656 | }; |
657 | 657 | ||
658 | 658 | ||
@@ -830,12 +830,14 @@ static void tso_start(struct tso_state *st, const struct sk_buff *skb) | |||
830 | */ | 830 | */ |
831 | st->header_len = ((tcp_hdr(skb)->doff << 2u) | 831 | st->header_len = ((tcp_hdr(skb)->doff << 2u) |
832 | + PTR_DIFF(tcp_hdr(skb), skb->data)); | 832 | + PTR_DIFF(tcp_hdr(skb), skb->data)); |
833 | st->full_packet_size = st->header_len + skb_shinfo(skb)->gso_size; | ||
834 | 833 | ||
835 | if (st->protocol == htons(ETH_P_IP)) | 834 | if (st->protocol == htons(ETH_P_IP)) { |
835 | st->ip_base_len = st->header_len - ETH_HDR_LEN(skb); | ||
836 | st->ipv4_id = ntohs(ip_hdr(skb)->id); | 836 | st->ipv4_id = ntohs(ip_hdr(skb)->id); |
837 | else | 837 | } else { |
838 | st->ip_base_len = tcp_hdr(skb)->doff << 2u; | ||
838 | st->ipv4_id = 0; | 839 | st->ipv4_id = 0; |
840 | } | ||
839 | st->seqnum = ntohl(tcp_hdr(skb)->seq); | 841 | st->seqnum = ntohl(tcp_hdr(skb)->seq); |
840 | 842 | ||
841 | EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg); | 843 | EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg); |
@@ -966,15 +968,16 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue, | |||
966 | st->seqnum += skb_shinfo(skb)->gso_size; | 968 | st->seqnum += skb_shinfo(skb)->gso_size; |
967 | if (st->out_len > skb_shinfo(skb)->gso_size) { | 969 | if (st->out_len > skb_shinfo(skb)->gso_size) { |
968 | /* This packet will not finish the TSO burst. */ | 970 | /* This packet will not finish the TSO burst. */ |
969 | ip_length = st->full_packet_size - ETH_HDR_LEN(skb); | 971 | st->packet_space = skb_shinfo(skb)->gso_size; |
970 | tsoh_th->fin = 0; | 972 | tsoh_th->fin = 0; |
971 | tsoh_th->psh = 0; | 973 | tsoh_th->psh = 0; |
972 | } else { | 974 | } else { |
973 | /* This packet will be the last in the TSO burst. */ | 975 | /* This packet will be the last in the TSO burst. */ |
974 | ip_length = st->header_len - ETH_HDR_LEN(skb) + st->out_len; | 976 | st->packet_space = st->out_len; |
975 | tsoh_th->fin = tcp_hdr(skb)->fin; | 977 | tsoh_th->fin = tcp_hdr(skb)->fin; |
976 | tsoh_th->psh = tcp_hdr(skb)->psh; | 978 | tsoh_th->psh = tcp_hdr(skb)->psh; |
977 | } | 979 | } |
980 | ip_length = st->ip_base_len + st->packet_space; | ||
978 | 981 | ||
979 | if (st->protocol == htons(ETH_P_IP)) { | 982 | if (st->protocol == htons(ETH_P_IP)) { |
980 | struct iphdr *tsoh_iph = | 983 | struct iphdr *tsoh_iph = |
@@ -989,14 +992,13 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue, | |||
989 | struct ipv6hdr *tsoh_iph = | 992 | struct ipv6hdr *tsoh_iph = |
990 | (struct ipv6hdr *)(header + SKB_IPV6_OFF(skb)); | 993 | (struct ipv6hdr *)(header + SKB_IPV6_OFF(skb)); |
991 | 994 | ||
992 | tsoh_iph->payload_len = htons(ip_length - sizeof(*tsoh_iph)); | 995 | tsoh_iph->payload_len = htons(ip_length); |
993 | } | 996 | } |
994 | 997 | ||
995 | rc = efx_tso_put_header(tx_queue, buffer, header); | 998 | rc = efx_tso_put_header(tx_queue, buffer, header); |
996 | if (unlikely(rc)) | 999 | if (unlikely(rc)) |
997 | return rc; | 1000 | return rc; |
998 | 1001 | ||
999 | st->packet_space = skb_shinfo(skb)->gso_size; | ||
1000 | ++tx_queue->tso_packets; | 1002 | ++tx_queue->tso_packets; |
1001 | 1003 | ||
1002 | return 0; | 1004 | return 0; |