[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"
|
#include "qeth_mpc.h"
|
||||||
|
|
||||||
#define VERSION_QETH_H "$Revision: 1.135 $"
|
#define VERSION_QETH_H "$Revision: 1.136 $"
|
||||||
|
|
||||||
#ifdef CONFIG_QETH_IPV6
|
#ifdef CONFIG_QETH_IPV6
|
||||||
#define QETH_VERSION_IPV6 ":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;
|
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
|
inline static int
|
||||||
qeth_get_hlen(__u8 link_type)
|
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.
|
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
|
||||||
*
|
*
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
|
* 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>
|
#include <linux/config.h>
|
||||||
|
@ -202,17 +202,6 @@ out:
|
||||||
return flush_cnt;
|
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
|
static inline void
|
||||||
qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
|
qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
|
||||||
struct qeth_eddp_data *eddp)
|
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
|
* Linux on zSeries OSA Express and HiperSockets support
|
||||||
*
|
*
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* Frank Pavlic (pavlic@de.ibm.com) and
|
* Frank Pavlic (pavlic@de.ibm.com) and
|
||||||
* Thomas Spatzier <tspat@de.ibm.com>
|
* 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
|
* 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
|
* 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_eddp.h"
|
||||||
#include "qeth_tso.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";
|
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
|
static inline void
|
||||||
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
|
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
|
||||||
int *next_element_to_fill)
|
int *next_element_to_fill)
|
||||||
|
@ -3991,7 +3950,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
|
||||||
__qeth_fill_buffer(skb, buffer,
|
__qeth_fill_buffer(skb, buffer,
|
||||||
(int *)&buf->next_element_to_fill);
|
(int *)&buf->next_element_to_fill);
|
||||||
else
|
else
|
||||||
__qeth_fill_buffer_frag(skb, buffer,
|
__qeth_fill_buffer_frag(skb, buffer, 0,
|
||||||
(int *)&buf->next_element_to_fill);
|
(int *)&buf->next_element_to_fill);
|
||||||
|
|
||||||
if (!queue->do_pack) {
|
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.
|
* Header file for qeth TCP Segmentation Offload support.
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
|
* 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;
|
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
|
static inline int
|
||||||
qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
|
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].length = hdr_len;
|
||||||
buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
|
buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
|
||||||
buf->next_element_to_fill++;
|
buf->next_element_to_fill++;
|
||||||
|
/*check if we have frags ...*/
|
||||||
if (skb_shinfo(skb)->nr_frags > 0) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*start filling buffer entries ...*/
|
/*... if not, use this */
|
||||||
element++;
|
element++;
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
/* length_here is the remaining amount of data in this page */
|
/* length_here is the remaining amount of data in this page */
|
||||||
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
|
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
|
||||||
if (length < length_here)
|
if (length < length_here)
|
||||||
length_here = length;
|
length_here = length;
|
||||||
buffer->element[element].addr = data;
|
buffer->element[element].addr = data;
|
||||||
buffer->element[element].length = length_here;
|
buffer->element[element].length = length_here;
|
||||||
length -= length_here;
|
length -= length_here;
|
||||||
|
@ -230,9 +201,9 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
|
||||||
data += length_here;
|
data += length_here;
|
||||||
element++;
|
element++;
|
||||||
}
|
}
|
||||||
/*set the buffer to primed ...*/
|
|
||||||
buf->next_element_to_fill = element;
|
buf->next_element_to_fill = element;
|
||||||
out:
|
out:
|
||||||
|
/*prime buffer now ...*/
|
||||||
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
|
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
|
||||||
return 1;
|
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.
|
* Header file for qeth TCP Segmentation Offload support.
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
|
* 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__
|
#ifndef __QETH_TSO_H__
|
||||||
|
@ -37,22 +37,67 @@ struct qeth_hdr_tso {
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/*some helper functions*/
|
/*some helper functions*/
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
|
qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int elements_needed = 0;
|
int elements_needed = 0;
|
||||||
|
|
||||||
if (skb_shinfo(skb)->nr_frags > 0)
|
if (skb_shinfo(skb)->nr_frags > 0)
|
||||||
elements_needed = (skb_shinfo(skb)->nr_frags + 1);
|
elements_needed = (skb_shinfo(skb)->nr_frags + 1);
|
||||||
if (elements_needed == 0 )
|
if (elements_needed == 0 )
|
||||||
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
|
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
|
||||||
+ skb->len) >> PAGE_SHIFT);
|
+ skb->len) >> PAGE_SHIFT);
|
||||||
if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
|
if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
|
||||||
PRINT_ERR("qeth_do_send_packet: invalid size of "
|
PRINT_ERR("qeth_do_send_packet: invalid size of "
|
||||||
"IP packet. Discarded.");
|
"IP packet. Discarded.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return elements_needed;
|
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__ */
|
#endif /* __QETH_TSO_H__ */
|
||||||
|
|
Loading…
Reference in New Issue