1 #include <linux/export.h> 2 #include <net/ip.h> 3 #include <net/tso.h> 4 #include <asm/unaligned.h> 5 6 /* Calculate expected number of TX descriptors */ 7 int tso_count_descs(struct sk_buff *skb) 8 { 9 /* The Marvell Way */ 10 return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags; 11 } 12 EXPORT_SYMBOL(tso_count_descs); 13 14 void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, 15 int size, bool is_last) 16 { 17 struct iphdr *iph; 18 struct tcphdr *tcph; 19 int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); 20 int mac_hdr_len = skb_network_offset(skb); 21 22 memcpy(hdr, skb->data, hdr_len); 23 iph = (struct iphdr *)(hdr + mac_hdr_len); 24 iph->id = htons(tso->ip_id); 25 iph->tot_len = htons(size + hdr_len - mac_hdr_len); 26 tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb)); 27 put_unaligned_be32(tso->tcp_seq, &tcph->seq); 28 tso->ip_id++; 29 30 if (!is_last) { 31 /* Clear all special flags for not last packet */ 32 tcph->psh = 0; 33 tcph->fin = 0; 34 tcph->rst = 0; 35 } 36 } 37 EXPORT_SYMBOL(tso_build_hdr); 38 39 void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) 40 { 41 tso->tcp_seq += size; 42 tso->size -= size; 43 tso->data += size; 44 45 if ((tso->size == 0) && 46 (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) { 47 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx]; 48 49 /* Move to next segment */ 50 tso->size = frag->size; 51 tso->data = page_address(frag->page.p) + frag->page_offset; 52 tso->next_frag_idx++; 53 } 54 } 55 EXPORT_SYMBOL(tso_build_data); 56 57 void tso_start(struct sk_buff *skb, struct tso_t *tso) 58 { 59 int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); 60 61 tso->ip_id = ntohs(ip_hdr(skb)->id); 62 tso->tcp_seq = ntohl(tcp_hdr(skb)->seq); 63 tso->next_frag_idx = 0; 64 65 /* Build first data */ 66 tso->size = skb_headlen(skb) - hdr_len; 67 tso->data = skb->data + hdr_len; 68 if ((tso->size == 0) && 69 (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) { 70 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx]; 71 72 /* Move to next segment */ 73 tso->size = frag->size; 74 tso->data = page_address(frag->page.p) + frag->page_offset; 75 tso->next_frag_idx++; 76 } 77 } 78 EXPORT_SYMBOL(tso_start); 79