aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Pavlic <pavlic@de.ibm.com>2005-05-12 14:37:53 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-15 18:06:17 -0400
commitd801145d910cc4a0fb418dda1dee227cec993cbd (patch)
tree423eda6277d89e89348907e185a49523debb0389
parent5e39f2933f6707fc824b5e419dcac8ced67a57b6 (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>
-rw-r--r--drivers/s390/net/qeth.h13
-rw-r--r--drivers/s390/net/qeth_eddp.c15
-rw-r--r--drivers/s390/net/qeth_main.c49
-rw-r--r--drivers/s390/net/qeth_tso.c49
-rw-r--r--drivers/s390/net/qeth_tso.h71
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
869static inline int
870qeth_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
869inline static int 880inline static int
870qeth_get_hlen(__u8 link_type) 881qeth_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
205static inline int
206qeth_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
216static inline void 205static inline void
217qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, 206qeth_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 $"
84static const char *version = "qeth S/390 OSA-Express driver"; 84static 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
3896static inline void 3896static 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
3937static 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
147static 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
180static inline int 148static inline int
181qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, 149qeth_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;
235out: 205out:
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
41static inline int 40static inline int
42qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) 41qeth_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
58static 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__ */