qeth_tso.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * linux/drivers/s390/net/qeth_tso.h
  3. *
  4. * Header file for qeth TCP Segmentation Offload support.
  5. *
  6. * Copyright 2004 IBM Corporation
  7. *
  8. * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  9. *
  10. */
  11. #ifndef __QETH_TSO_H__
  12. #define __QETH_TSO_H__
  13. #include <linux/skbuff.h>
  14. #include <linux/tcp.h>
  15. #include <linux/ip.h>
  16. #include <linux/ipv6.h>
  17. #include <net/ip6_checksum.h>
  18. #include "qeth.h"
  19. #include "qeth_mpc.h"
  20. static inline struct qeth_hdr_tso *
  21. qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
  22. {
  23. QETH_DBF_TEXT(trace, 5, "tsoprsk");
  24. return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
  25. }
  26. /**
  27. * fill header for a TSO packet
  28. */
  29. static inline void
  30. qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
  31. {
  32. struct qeth_hdr_tso *hdr;
  33. struct tcphdr *tcph;
  34. struct iphdr *iph;
  35. QETH_DBF_TEXT(trace, 5, "tsofhdr");
  36. hdr = (struct qeth_hdr_tso *) skb->data;
  37. iph = ip_hdr(skb);
  38. tcph = tcp_hdr(skb);
  39. /*fix header to TSO values ...*/
  40. hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
  41. /*set values which are fix for the first approach ...*/
  42. hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
  43. hdr->ext.imb_hdr_no = 1;
  44. hdr->ext.hdr_type = 1;
  45. hdr->ext.hdr_version = 1;
  46. hdr->ext.hdr_len = 28;
  47. /*insert non-fix values */
  48. hdr->ext.mss = skb_shinfo(skb)->gso_size;
  49. hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
  50. hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
  51. sizeof(struct qeth_hdr_tso));
  52. }
  53. /**
  54. * change some header values as requested by hardware
  55. */
  56. static inline void
  57. qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
  58. {
  59. struct iphdr *iph = ip_hdr(skb);
  60. struct ipv6hdr *ip6h = ipv6_hdr(skb);
  61. struct tcphdr *tcph = tcp_hdr(skb);
  62. tcph->check = 0;
  63. if (skb->protocol == ETH_P_IPV6) {
  64. ip6h->payload_len = 0;
  65. tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
  66. 0, IPPROTO_TCP, 0);
  67. return;
  68. }
  69. /*OSA want us to set these values ...*/
  70. tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
  71. 0, IPPROTO_TCP, 0);
  72. iph->tot_len = 0;
  73. iph->check = 0;
  74. }
  75. static inline int
  76. qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
  77. int ipv, int cast_type)
  78. {
  79. struct qeth_hdr_tso *hdr;
  80. QETH_DBF_TEXT(trace, 5, "tsoprep");
  81. hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
  82. if (hdr == NULL) {
  83. QETH_DBF_TEXT(trace, 4, "tsoperr");
  84. return -ENOMEM;
  85. }
  86. memset(hdr, 0, sizeof(struct qeth_hdr_tso));
  87. /*fill first 32 bytes of qdio header as used
  88. *FIXME: TSO has two struct members
  89. * with different names but same size
  90. * */
  91. qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
  92. qeth_tso_fill_header(card, skb);
  93. qeth_tso_set_tcpip_header(card, skb);
  94. return 0;
  95. }
  96. static inline void
  97. __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
  98. int is_tso, int *next_element_to_fill)
  99. {
  100. struct skb_frag_struct *frag;
  101. int fragno;
  102. unsigned long addr;
  103. int element, cnt, dlen;
  104. fragno = skb_shinfo(skb)->nr_frags;
  105. element = *next_element_to_fill;
  106. dlen = 0;
  107. if (is_tso)
  108. buffer->element[element].flags =
  109. SBAL_FLAGS_MIDDLE_FRAG;
  110. else
  111. buffer->element[element].flags =
  112. SBAL_FLAGS_FIRST_FRAG;
  113. if ( (dlen = (skb->len - skb->data_len)) ) {
  114. buffer->element[element].addr = skb->data;
  115. buffer->element[element].length = dlen;
  116. element++;
  117. }
  118. for (cnt = 0; cnt < fragno; cnt++) {
  119. frag = &skb_shinfo(skb)->frags[cnt];
  120. addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
  121. frag->page_offset;
  122. buffer->element[element].addr = (char *)addr;
  123. buffer->element[element].length = frag->size;
  124. if (cnt < (fragno - 1))
  125. buffer->element[element].flags =
  126. SBAL_FLAGS_MIDDLE_FRAG;
  127. else
  128. buffer->element[element].flags =
  129. SBAL_FLAGS_LAST_FRAG;
  130. element++;
  131. }
  132. *next_element_to_fill = element;
  133. }
  134. #endif /* __QETH_TSO_H__ */