aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net
diff options
context:
space:
mode:
authorFrank Pavlic <pavlic@de.ibm.com>2005-05-12 20:37:53 +0200
committerJeff Garzik <jgarzik@pobox.com>2005-05-15 18:06:17 -0400
commitd801145d910cc4a0fb418dda1dee227cec993cbd (patch)
tree423eda6277d89e89348907e185a49523debb0389 /drivers/s390/net
parent5e39f2933f6707fc824b5e419dcac8ced67a57b6 (diff)
downloadkernel_samsung_crespo-d801145d910cc4a0fb418dda1dee227cec993cbd.zip
kernel_samsung_crespo-d801145d910cc4a0fb418dda1dee227cec993cbd.tar.gz
kernel_samsung_crespo-d801145d910cc4a0fb418dda1dee227cec993cbd.tar.bz2
[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.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 a341041..501b87e 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.135 $"
+#define VERSION_QETH_H "$Revision: 1.136 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -866,6 +866,17 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
return hdr;
}
+static inline int
+qeth_get_skb_data_len(struct sk_buff *skb)
+{
+ int len = skb->len;
+ int i;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
+ len -= skb_shinfo(skb)->frags[i].size;
+ return len;
+}
+
inline static int
qeth_get_hlen(__u8 link_type)
{
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 7ee1c06..45aa4a9 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $)
+ * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $)
*
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
*
@@ -8,7 +8,7 @@
*
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $
*
*/
#include <linux/config.h>
@@ -202,17 +202,6 @@ out:
return flush_cnt;
}
-static inline int
-qeth_get_skb_data_len(struct sk_buff *skb)
-{
- int len = skb->len;
- int i;
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
- len -= skb_shinfo(skb)->frags[i].size;
- return len;
-}
-
static inline void
qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
struct qeth_eddp_data *eddp)
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 607b925..17e8d16 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.207 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.207 $ $Date: 2005/04/01 21:40:40 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -80,7 +80,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.206 $"
+#define VERSION_QETH_C "$Revision: 1.207 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -3894,47 +3894,6 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
static inline void
-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
- int *next_element_to_fill)
-{
- int length = skb->len;
- struct skb_frag_struct *frag;
- int fragno;
- unsigned long addr;
- int element;
- int first_lap = 1;
-
- fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
- element = *next_element_to_fill + fragno;
- while (length > 0) {
- if (fragno > 0) {
- frag = &skb_shinfo(skb)->frags[fragno - 1];
- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
- frag->page_offset;
- buffer->element[element].addr = (char *)addr;
- buffer->element[element].length = frag->size;
- length -= frag->size;
- if (first_lap)
- buffer->element[element].flags =
- SBAL_FLAGS_LAST_FRAG;
- else
- buffer->element[element].flags =
- SBAL_FLAGS_MIDDLE_FRAG;
- } else {
- buffer->element[element].addr = skb->data;
- buffer->element[element].length = length;
- length = 0;
- buffer->element[element].flags =
- SBAL_FLAGS_FIRST_FRAG;
- }
- element--;
- fragno--;
- first_lap = 0;
- }
- *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
-}
-
-static inline void
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
int *next_element_to_fill)
{
@@ -3991,7 +3950,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
__qeth_fill_buffer(skb, buffer,
(int *)&buf->next_element_to_fill);
else
- __qeth_fill_buffer_frag(skb, buffer,
+ __qeth_fill_buffer_frag(skb, buffer, 0,
(int *)&buf->next_element_to_fill);
if (!queue->do_pack) {
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c
index c919762..4e58f19 100644
--- a/drivers/s390/net/qeth_tso.c
+++ b/drivers/s390/net/qeth_tso.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $)
+ * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.7 $)
*
* Header file for qeth TCP Segmentation Offload support.
*
@@ -7,7 +7,7 @@
*
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
*
- * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.7 $ $Date: 2005/04/01 21:40:41 $
*
*/
@@ -144,38 +144,6 @@ qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue)
return flush_cnt;
}
-static inline void
-__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf,
- struct sk_buff *skb)
-{
- struct skb_frag_struct *frag;
- struct qdio_buffer *buffer;
- int fragno, cnt, element;
- unsigned long addr;
-
- QETH_DBF_TEXT(trace, 6, "tsfilfrg");
-
- /*initialize variables ...*/
- fragno = skb_shinfo(skb)->nr_frags;
- buffer = buf->buffer;
- element = buf->next_element_to_fill;
- /*fill buffer elements .....*/
- for (cnt = 0; cnt < fragno; cnt++) {
- frag = &skb_shinfo(skb)->frags[cnt];
- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
- frag->page_offset;
- buffer->element[element].addr = (char *)addr;
- buffer->element[element].length = frag->size;
- if (cnt < (fragno - 1))
- buffer->element[element].flags =
- SBAL_FLAGS_MIDDLE_FRAG;
- else
- buffer->element[element].flags =
- SBAL_FLAGS_LAST_FRAG;
- element++;
- }
- buf->next_element_to_fill = element;
-}
static inline int
qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
@@ -205,19 +173,22 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
buffer->element[element].length = hdr_len;
buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
buf->next_element_to_fill++;
-
+ /*check if we have frags ...*/
if (skb_shinfo(skb)->nr_frags > 0) {
- __qeth_tso_fill_buffer_frag(buf, skb);
+ skb->len = length;
+ skb->data = data;
+ __qeth_fill_buffer_frag(skb, buffer,1,
+ (int *)&buf->next_element_to_fill);
goto out;
}
- /*start filling buffer entries ...*/
+ /*... if not, use this */
element++;
while (length > 0) {
/* length_here is the remaining amount of data in this page */
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
if (length < length_here)
- length_here = length;
+ length_here = length;
buffer->element[element].addr = data;
buffer->element[element].length = length_here;
length -= length_here;
@@ -230,9 +201,9 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
data += length_here;
element++;
}
- /*set the buffer to primed ...*/
buf->next_element_to_fill = element;
out:
+ /*prime buffer now ...*/
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
return 1;
}
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 83504de..ff585ae 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $)
+ * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.5 $)
*
* Header file for qeth TCP Segmentation Offload support.
*
@@ -7,7 +7,7 @@
*
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
*
- * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.5 $ $Date: 2005/04/01 21:40:41 $
*
*/
#ifndef __QETH_TSO_H__
@@ -37,22 +37,67 @@ struct qeth_hdr_tso {
} __attribute__ ((packed));
/*some helper functions*/
-
static inline int
qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
{
int elements_needed = 0;
- if (skb_shinfo(skb)->nr_frags > 0)
- elements_needed = (skb_shinfo(skb)->nr_frags + 1);
- if (elements_needed == 0 )
- elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
- + skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
- PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
- return 0;
+ if (skb_shinfo(skb)->nr_frags > 0)
+ elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+ if (elements_needed == 0 )
+ elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ + skb->len) >> PAGE_SHIFT);
+ if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ PRINT_ERR("qeth_do_send_packet: invalid size of "
+ "IP packet. Discarded.");
+ return 0;
+ }
+ return elements_needed;
+}
+
+static inline void
+__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+ int is_tso, int *next_element_to_fill)
+{
+ int length = skb->len;
+ struct skb_frag_struct *frag;
+ int fragno;
+ unsigned long addr;
+ int element;
+ int first_lap = 1;
+
+ fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
+ element = *next_element_to_fill + fragno;
+ while (length > 0) {
+ if (fragno > 0) {
+ frag = &skb_shinfo(skb)->frags[fragno - 1];
+ addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+ frag->page_offset;
+ buffer->element[element].addr = (char *)addr;
+ buffer->element[element].length = frag->size;
+ length -= frag->size;
+ if (first_lap)
+ buffer->element[element].flags =
+ SBAL_FLAGS_LAST_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ } else {
+ buffer->element[element].addr = skb->data;
+ buffer->element[element].length = length;
+ length = 0;
+ if (is_tso)
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_FIRST_FRAG;
+ }
+ element--;
+ fragno--;
+ first_lap = 0;
}
- return elements_needed;
+ *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
}
+
#endif /* __QETH_TSO_H__ */