]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - drivers/s390/net/qeth_tso.h
[PATCH] s390: qeth bug fixes
[linux-3.10.git] / drivers / s390 / net / qeth_tso.h
1 /*
2  * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.5 $)
3  *
4  * Header file for qeth TCP Segmentation Offload support.
5  *
6  * Copyright 2004 IBM Corporation
7  *
8  *    Author(s): Frank Pavlic <pavlic@de.ibm.com>
9  *
10  *    $Revision: 1.5 $   $Date: 2005/04/01 21:40:41 $
11  *
12  */
13 #ifndef __QETH_TSO_H__
14 #define __QETH_TSO_H__
15
16
17 extern int
18 qeth_tso_send_packet(struct qeth_card *, struct sk_buff *,
19                      struct qeth_qdio_out_q *, int , int);
20
21 struct qeth_hdr_ext_tso {
22         __u16 hdr_tot_len;
23         __u8  imb_hdr_no;
24         __u8  reserved;
25         __u8  hdr_type;
26         __u8  hdr_version;
27         __u16 hdr_len;
28         __u32 payload_len;
29         __u16 mss;
30         __u16 dg_hdr_len;
31         __u8  padding[16];
32 } __attribute__ ((packed));
33
34 struct qeth_hdr_tso {
35         struct qeth_hdr hdr;    /*hdr->hdr.l3.xxx*/
36         struct qeth_hdr_ext_tso ext;
37 } __attribute__ ((packed));
38
39 /*some helper functions*/
40 static inline int
41 qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
42 {
43         int elements_needed = 0;
44
45         if (skb_shinfo(skb)->nr_frags > 0)
46                 elements_needed = (skb_shinfo(skb)->nr_frags + 1);
47         if (elements_needed == 0 )
48                 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
49                                         + skb->len) >> PAGE_SHIFT);
50         if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
51                 PRINT_ERR("qeth_do_send_packet: invalid size of "
52                           "IP packet. Discarded.");
53                 return 0;
54         }
55         return elements_needed;
56 }
57
58 static inline void
59 __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
60                         int is_tso, int *next_element_to_fill)
61 {
62         int length = skb->len;
63         struct skb_frag_struct *frag;
64         int fragno;
65         unsigned long addr;
66         int element;
67         int first_lap = 1;
68
69         fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
70         element = *next_element_to_fill + fragno;
71         while (length > 0) {
72                 if (fragno > 0) {
73                         frag = &skb_shinfo(skb)->frags[fragno - 1];
74                         addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
75                                 frag->page_offset;
76                         buffer->element[element].addr = (char *)addr;
77                         buffer->element[element].length = frag->size;
78                         length -= frag->size;
79                         if (first_lap)
80                                 buffer->element[element].flags =
81                                     SBAL_FLAGS_LAST_FRAG;
82                         else
83                                 buffer->element[element].flags =
84                                     SBAL_FLAGS_MIDDLE_FRAG;
85                 } else {
86                         buffer->element[element].addr = skb->data;
87                         buffer->element[element].length = length;
88                         length = 0;
89                         if (is_tso)
90                                 buffer->element[element].flags =
91                                         SBAL_FLAGS_MIDDLE_FRAG;
92                         else
93                                 buffer->element[element].flags =
94                                         SBAL_FLAGS_FIRST_FRAG;
95                 }
96                 element--;
97                 fragno--;
98                 first_lap = 0;
99         }
100         *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
101 }
102
103 #endif /* __QETH_TSO_H__ */