]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/s390/net/qeth_eddp.c
[PATCH] s390: qeth bug fixes
[linux-2.6.git] / drivers / s390 / net / qeth_eddp.c
index 7ee1c06ed68a841af7ac49eeaa1d616681845b67..f94f1f25eec60a8e57ba9d311a90c47b2df58594 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $)
+ * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
  *
  * 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.13 $         $Date: 2005/05/04 20:19:18 $
  *
  */
 #include <linux/config.h>
@@ -85,7 +85,7 @@ void
 qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
 {
        struct qeth_eddp_context_reference *ref;
-
+       
        QETH_DBF_TEXT(trace, 6, "eddprctx");
        while (!list_empty(&buf->ctx_list)){
                ref = list_entry(buf->ctx_list.next,
@@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
                                           "buffer!\n");
                                goto out;
                        }
-               }
+               }               
                /* check if the whole next skb fits into current buffer */
                if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
                                        buf->next_element_to_fill)
@@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
                         * and increment ctx's refcnt */
                        must_refcnt = 1;
                        continue;
-               }
+               }       
                if (must_refcnt){
                        must_refcnt = 0;
                        if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -202,40 +202,29 @@ 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)
+                             struct qeth_eddp_data *eddp, int data_len)
 {
        u8 *page;
        int page_remainder;
        int page_offset;
-       int hdr_len;
+       int pkt_len;
        struct qeth_eddp_element *element;
 
        QETH_DBF_TEXT(trace, 5, "eddpcrsh");
        page = ctx->pages[ctx->offset >> PAGE_SHIFT];
        page_offset = ctx->offset % PAGE_SIZE;
        element = &ctx->elements[ctx->num_elements];
-       hdr_len = eddp->nhl + eddp->thl;
+       pkt_len = eddp->nhl + eddp->thl + data_len;
        /* FIXME: layer2 and VLAN !!! */
        if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
-               hdr_len += ETH_HLEN;
+               pkt_len += ETH_HLEN;
        if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
-               hdr_len += VLAN_HLEN;
-       /* does complete header fit in current page ? */
+               pkt_len += VLAN_HLEN;
+       /* does complete packet fit in current page ? */
        page_remainder = PAGE_SIZE - page_offset;
-       if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){
+       if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
                /* no -> go to start of next page */
                ctx->offset += page_remainder;
                page = ctx->pages[ctx->offset >> PAGE_SHIFT];
@@ -281,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
        int left_in_frag;
        int copy_len;
        u8 *src;
-
+       
        QETH_DBF_TEXT(trace, 5, "eddpcdtc");
        if (skb_shinfo(eddp->skb)->nr_frags == 0) {
                memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -292,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
                while (len > 0) {
                        if (eddp->frag < 0) {
                                /* we're in skb->data */
-                               left_in_frag = qeth_get_skb_data_len(eddp->skb)
+                               left_in_frag = (eddp->skb->len - eddp->skb->data_len)
                                                - eddp->skb_offset;
                                src = eddp->skb->data + eddp->skb_offset;
                        } else {
@@ -424,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
        struct tcphdr *tcph;
        int data_len;
        u32 hcsum;
-
+       
        QETH_DBF_TEXT(trace, 5, "eddpftcp");
        eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
        tcph = eddp->skb->h.th;
@@ -464,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                else
                        hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
                /* fill the next segment into the context */
-               qeth_eddp_create_segment_hdrs(ctx, eddp);
+               qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
                qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
                if (eddp->skb_offset >= eddp->skb->len)
                        break;
@@ -474,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                eddp->th.tcp.h.seq += data_len;
        }
 }
-
+                          
 static inline int
 qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                           struct sk_buff *skb, struct qeth_hdr *qhdr)
 {
        struct qeth_eddp_data *eddp = NULL;
-
+       
        QETH_DBF_TEXT(trace, 5, "eddpficx");
        /* create our segmentation headers and copy original headers */
        if (skb->protocol == ETH_P_IP)
@@ -520,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
                         int hdr_len)
 {
        int skbs_per_page;
-
+       
        QETH_DBF_TEXT(trace, 5, "eddpcanp");
        /* can we put multiple skbs in one page? */
        skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -600,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
                             struct qeth_hdr *qhdr)
 {
        struct qeth_eddp_context *ctx = NULL;
-
+       
        QETH_DBF_TEXT(trace, 5, "creddpct");
        if (skb->protocol == ETH_P_IP)
                ctx = qeth_eddp_create_context_generic(card, skb,