Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d801145d authored by Frank Pavlic's avatar Frank Pavlic Committed by Jeff Garzik
Browse files

[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: default avatarFrank Pavlic <pavlic@de.ibm.com>
parent 5e39f293
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -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)
{
+2 −13
Original line number Diff line number Diff line
/*
 *
 * 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 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
	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)
+4 −45
Original line number Diff line number Diff line
/*
 *
 * 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";

/**
@@ -3893,47 +3893,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) {
+10 −39
Original line number Diff line number Diff line
/*
 * 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,13 +173,16 @@ 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 */
@@ -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;
}
+58 −13
Original line number Diff line number Diff line
/*
 * 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,7 +37,6 @@ 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)
{
@@ -55,4 +54,50 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
        }
        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__ */