[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>
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 @@
 } __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;
-	}
-	return elements_needed;
+        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;
+	}
+	*next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
+}
+
 #endif /* __QETH_TSO_H__ */