[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>
This commit is contained in:
parent
5e39f2933f
commit
d801145d91
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
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__ */
|
||||
|
|
Loading…
Reference in New Issue