diff options
author | Frank Pavlic <pavlic@de.ibm.com> | 2005-05-12 14:37:53 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-05-15 18:06:17 -0400 |
commit | d801145d910cc4a0fb418dda1dee227cec993cbd (patch) | |
tree | 423eda6277d89e89348907e185a49523debb0389 /drivers/s390/net | |
parent | 5e39f2933f6707fc824b5e419dcac8ced67a57b6 (diff) |
[PATCH] s390: qeth bug fixes
[patch 7/10] s390: qeth bug fixes.
From: Frank Pavlic <pavlic@de.ibm.com>
qeth network driver changes:
- Removed redundant code, use the same qeth_fill_buffer_frag
for TSO path either
- Using skb->frags solely is not correct since skb->data still
points to the beginning of the whole data, even when it is
a small portion we have to fill the qdio buffer with it.
Signed-off-by: Frank Pavlic <pavlic@de.ibm.com>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/qeth.h | 13 | ||||
-rw-r--r-- | drivers/s390/net/qeth_eddp.c | 15 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 49 | ||||
-rw-r--r-- | drivers/s390/net/qeth_tso.c | 49 | ||||
-rw-r--r-- | drivers/s390/net/qeth_tso.h | 71 |
5 files changed, 86 insertions, 111 deletions
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index a341041a6cf7..501b87e6875a 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "qeth_mpc.h" | 25 | #include "qeth_mpc.h" |
26 | 26 | ||
27 | #define VERSION_QETH_H "$Revision: 1.135 $" | 27 | #define VERSION_QETH_H "$Revision: 1.136 $" |
28 | 28 | ||
29 | #ifdef CONFIG_QETH_IPV6 | 29 | #ifdef CONFIG_QETH_IPV6 |
30 | #define QETH_VERSION_IPV6 ":IPv6" | 30 | #define QETH_VERSION_IPV6 ":IPv6" |
@@ -866,6 +866,17 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) | |||
866 | return hdr; | 866 | return hdr; |
867 | } | 867 | } |
868 | 868 | ||
869 | static inline int | ||
870 | qeth_get_skb_data_len(struct sk_buff *skb) | ||
871 | { | ||
872 | int len = skb->len; | ||
873 | int i; | ||
874 | |||
875 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) | ||
876 | len -= skb_shinfo(skb)->frags[i].size; | ||
877 | return len; | ||
878 | } | ||
879 | |||
869 | inline static int | 880 | inline static int |
870 | qeth_get_hlen(__u8 link_type) | 881 | qeth_get_hlen(__u8 link_type) |
871 | { | 882 | { |
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 7ee1c06ed68a..45aa4a962daf 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $) | 3 | * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $) |
4 | * | 4 | * |
5 | * Enhanced Device Driver Packing (EDDP) support for the qeth driver. | 5 | * Enhanced Device Driver Packing (EDDP) support for the qeth driver. |
6 | * | 6 | * |
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Author(s): Thomas Spatzier <tspat@de.ibm.com> | 9 | * Author(s): Thomas Spatzier <tspat@de.ibm.com> |
10 | * | 10 | * |
11 | * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $ | 11 | * $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $ |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
@@ -202,17 +202,6 @@ out: | |||
202 | return flush_cnt; | 202 | return flush_cnt; |
203 | } | 203 | } |
204 | 204 | ||
205 | static inline int | ||
206 | qeth_get_skb_data_len(struct sk_buff *skb) | ||
207 | { | ||
208 | int len = skb->len; | ||
209 | int i; | ||
210 | |||
211 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) | ||
212 | len -= skb_shinfo(skb)->frags[i].size; | ||
213 | return len; | ||
214 | } | ||
215 | |||
216 | static inline void | 205 | static inline void |
217 | qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, | 206 | qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, |
218 | struct qeth_eddp_data *eddp) | 207 | struct qeth_eddp_data *eddp) |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 607b92542df6..17e8d16fa06c 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $) | 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.207 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * | 6 | * |
@@ -12,7 +12,7 @@ | |||
12 | * Frank Pavlic (pavlic@de.ibm.com) and | 12 | * Frank Pavlic (pavlic@de.ibm.com) and |
13 | * Thomas Spatzier <tspat@de.ibm.com> | 13 | * Thomas Spatzier <tspat@de.ibm.com> |
14 | * | 14 | * |
15 | * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $ | 15 | * $Revision: 1.207 $ $Date: 2005/04/01 21:40:40 $ |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
@@ -80,7 +80,7 @@ qeth_eyecatcher(void) | |||
80 | #include "qeth_eddp.h" | 80 | #include "qeth_eddp.h" |
81 | #include "qeth_tso.h" | 81 | #include "qeth_tso.h" |
82 | 82 | ||
83 | #define VERSION_QETH_C "$Revision: 1.206 $" | 83 | #define VERSION_QETH_C "$Revision: 1.207 $" |
84 | static const char *version = "qeth S/390 OSA-Express driver"; | 84 | static const char *version = "qeth S/390 OSA-Express driver"; |
85 | 85 | ||
86 | /** | 86 | /** |
@@ -3894,47 +3894,6 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | |||
3894 | } | 3894 | } |
3895 | 3895 | ||
3896 | static inline void | 3896 | static inline void |
3897 | __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, | ||
3898 | int *next_element_to_fill) | ||
3899 | { | ||
3900 | int length = skb->len; | ||
3901 | struct skb_frag_struct *frag; | ||
3902 | int fragno; | ||
3903 | unsigned long addr; | ||
3904 | int element; | ||
3905 | int first_lap = 1; | ||
3906 | |||
3907 | fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */ | ||
3908 | element = *next_element_to_fill + fragno; | ||
3909 | while (length > 0) { | ||
3910 | if (fragno > 0) { | ||
3911 | frag = &skb_shinfo(skb)->frags[fragno - 1]; | ||
3912 | addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + | ||
3913 | frag->page_offset; | ||
3914 | buffer->element[element].addr = (char *)addr; | ||
3915 | buffer->element[element].length = frag->size; | ||
3916 | length -= frag->size; | ||
3917 | if (first_lap) | ||
3918 | buffer->element[element].flags = | ||
3919 | SBAL_FLAGS_LAST_FRAG; | ||
3920 | else | ||
3921 | buffer->element[element].flags = | ||
3922 | SBAL_FLAGS_MIDDLE_FRAG; | ||
3923 | } else { | ||
3924 | buffer->element[element].addr = skb->data; | ||
3925 | buffer->element[element].length = length; | ||
3926 | length = 0; | ||
3927 | buffer->element[element].flags = | ||
3928 | SBAL_FLAGS_FIRST_FRAG; | ||
3929 | } | ||
3930 | element--; | ||
3931 | fragno--; | ||
3932 | first_lap = 0; | ||
3933 | } | ||
3934 | *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; | ||
3935 | } | ||
3936 | |||
3937 | static inline void | ||
3938 | __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, | 3897 | __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, |
3939 | int *next_element_to_fill) | 3898 | int *next_element_to_fill) |
3940 | { | 3899 | { |
@@ -3991,7 +3950,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
3991 | __qeth_fill_buffer(skb, buffer, | 3950 | __qeth_fill_buffer(skb, buffer, |
3992 | (int *)&buf->next_element_to_fill); | 3951 | (int *)&buf->next_element_to_fill); |
3993 | else | 3952 | else |
3994 | __qeth_fill_buffer_frag(skb, buffer, | 3953 | __qeth_fill_buffer_frag(skb, buffer, 0, |
3995 | (int *)&buf->next_element_to_fill); | 3954 | (int *)&buf->next_element_to_fill); |
3996 | 3955 | ||
3997 | if (!queue->do_pack) { | 3956 | if (!queue->do_pack) { |
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c index c91976274e7b..4e58f19cb71c 100644 --- a/drivers/s390/net/qeth_tso.c +++ b/drivers/s390/net/qeth_tso.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $) | 2 | * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.7 $) |
3 | * | 3 | * |
4 | * Header file for qeth TCP Segmentation Offload support. | 4 | * Header file for qeth TCP Segmentation Offload support. |
5 | * | 5 | * |
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> | 8 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> |
9 | * | 9 | * |
10 | * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $ | 10 | * $Revision: 1.7 $ $Date: 2005/04/01 21:40:41 $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -144,38 +144,6 @@ qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue) | |||
144 | return flush_cnt; | 144 | return flush_cnt; |
145 | } | 145 | } |
146 | 146 | ||
147 | static inline void | ||
148 | __qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf, | ||
149 | struct sk_buff *skb) | ||
150 | { | ||
151 | struct skb_frag_struct *frag; | ||
152 | struct qdio_buffer *buffer; | ||
153 | int fragno, cnt, element; | ||
154 | unsigned long addr; | ||
155 | |||
156 | QETH_DBF_TEXT(trace, 6, "tsfilfrg"); | ||
157 | |||
158 | /*initialize variables ...*/ | ||
159 | fragno = skb_shinfo(skb)->nr_frags; | ||
160 | buffer = buf->buffer; | ||
161 | element = buf->next_element_to_fill; | ||
162 | /*fill buffer elements .....*/ | ||
163 | for (cnt = 0; cnt < fragno; cnt++) { | ||
164 | frag = &skb_shinfo(skb)->frags[cnt]; | ||
165 | addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + | ||
166 | frag->page_offset; | ||
167 | buffer->element[element].addr = (char *)addr; | ||
168 | buffer->element[element].length = frag->size; | ||
169 | if (cnt < (fragno - 1)) | ||
170 | buffer->element[element].flags = | ||
171 | SBAL_FLAGS_MIDDLE_FRAG; | ||
172 | else | ||
173 | buffer->element[element].flags = | ||
174 | SBAL_FLAGS_LAST_FRAG; | ||
175 | element++; | ||
176 | } | ||
177 | buf->next_element_to_fill = element; | ||
178 | } | ||
179 | 147 | ||
180 | static inline int | 148 | static inline int |
181 | qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, | 149 | qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, |
@@ -205,19 +173,22 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, | |||
205 | buffer->element[element].length = hdr_len; | 173 | buffer->element[element].length = hdr_len; |
206 | buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; | 174 | buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; |
207 | buf->next_element_to_fill++; | 175 | buf->next_element_to_fill++; |
208 | 176 | /*check if we have frags ...*/ | |
209 | if (skb_shinfo(skb)->nr_frags > 0) { | 177 | if (skb_shinfo(skb)->nr_frags > 0) { |
210 | __qeth_tso_fill_buffer_frag(buf, skb); | 178 | skb->len = length; |
179 | skb->data = data; | ||
180 | __qeth_fill_buffer_frag(skb, buffer,1, | ||
181 | (int *)&buf->next_element_to_fill); | ||
211 | goto out; | 182 | goto out; |
212 | } | 183 | } |
213 | 184 | ||
214 | /*start filling buffer entries ...*/ | 185 | /*... if not, use this */ |
215 | element++; | 186 | element++; |
216 | while (length > 0) { | 187 | while (length > 0) { |
217 | /* length_here is the remaining amount of data in this page */ | 188 | /* length_here is the remaining amount of data in this page */ |
218 | length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); | 189 | length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); |
219 | if (length < length_here) | 190 | if (length < length_here) |
220 | length_here = length; | 191 | length_here = length; |
221 | buffer->element[element].addr = data; | 192 | buffer->element[element].addr = data; |
222 | buffer->element[element].length = length_here; | 193 | buffer->element[element].length = length_here; |
223 | length -= length_here; | 194 | length -= length_here; |
@@ -230,9 +201,9 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, | |||
230 | data += length_here; | 201 | data += length_here; |
231 | element++; | 202 | element++; |
232 | } | 203 | } |
233 | /*set the buffer to primed ...*/ | ||
234 | buf->next_element_to_fill = element; | 204 | buf->next_element_to_fill = element; |
235 | out: | 205 | out: |
206 | /*prime buffer now ...*/ | ||
236 | atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); | 207 | atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); |
237 | return 1; | 208 | return 1; |
238 | } | 209 | } |
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 83504dee3f57..ff585ae49b6c 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $) | 2 | * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.5 $) |
3 | * | 3 | * |
4 | * Header file for qeth TCP Segmentation Offload support. | 4 | * Header file for qeth TCP Segmentation Offload support. |
5 | * | 5 | * |
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> | 8 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> |
9 | * | 9 | * |
10 | * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $ | 10 | * $Revision: 1.5 $ $Date: 2005/04/01 21:40:41 $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #ifndef __QETH_TSO_H__ | 13 | #ifndef __QETH_TSO_H__ |
@@ -37,22 +37,67 @@ struct qeth_hdr_tso { | |||
37 | } __attribute__ ((packed)); | 37 | } __attribute__ ((packed)); |
38 | 38 | ||
39 | /*some helper functions*/ | 39 | /*some helper functions*/ |
40 | |||
41 | static inline int | 40 | static inline int |
42 | qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) | 41 | qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) |
43 | { | 42 | { |
44 | int elements_needed = 0; | 43 | int elements_needed = 0; |
45 | 44 | ||
46 | if (skb_shinfo(skb)->nr_frags > 0) | 45 | if (skb_shinfo(skb)->nr_frags > 0) |
47 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); | 46 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); |
48 | if (elements_needed == 0 ) | 47 | if (elements_needed == 0 ) |
49 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) | 48 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) |
50 | + skb->len) >> PAGE_SHIFT); | 49 | + skb->len) >> PAGE_SHIFT); |
51 | if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ | 50 | if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ |
52 | PRINT_ERR("qeth_do_send_packet: invalid size of " | 51 | PRINT_ERR("qeth_do_send_packet: invalid size of " |
53 | "IP packet. Discarded."); | 52 | "IP packet. Discarded."); |
54 | return 0; | 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; | ||
55 | } | 99 | } |
56 | return elements_needed; | 100 | *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; |
57 | } | 101 | } |
102 | |||
58 | #endif /* __QETH_TSO_H__ */ | 103 | #endif /* __QETH_TSO_H__ */ |