Skip to content

Commit

Permalink
[PATCH] s390: qeth bug fixes
Browse files Browse the repository at this point in the history
[patch 10/10] s390: qeth bug fixes.

From: Frank Pavlic <pavlic@de.ibm.com>

qeth network driver related changes:
 - due to OSA hardware changes in TCP Segmentation Offload
   support we are able now to pack TSO packets too.
   This fits perfectly in design of qeth buffer handling and
   sending data respectively.
 - remove skb_realloc_headroom from the sending path since
   hard_header_len value provides enough headroom now.
 - device recovery behaviour improvement
 - bug fixed in Enhanced Device Driver Packing functionality

Signed-off-by: Frank Pavlic <pavlic@de.ibm.com>
  • Loading branch information
Frank Pavlic authored and Jeff Garzik committed May 15, 2005
1 parent 9a45581 commit 05e08a2
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 404 deletions.
2 changes: 1 addition & 1 deletion drivers/s390/net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
obj-$(CONFIG_LCS) += lcs.o cu3088.o
obj-$(CONFIG_CLAW) += claw.o cu3088.o
qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o
qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
qeth-$(CONFIG_PROC_FS) += qeth_proc.o
obj-$(CONFIG_QETH) += qeth.o
41 changes: 25 additions & 16 deletions drivers/s390/net/qeth.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include "qeth_mpc.h"

#define VERSION_QETH_H "$Revision: 1.137 $"
#define VERSION_QETH_H "$Revision: 1.139 $"

#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
Expand Down Expand Up @@ -370,6 +370,25 @@ struct qeth_hdr {
} hdr;
} __attribute__ ((packed));

/*TCP Segmentation Offload header*/
struct qeth_hdr_ext_tso {
__u16 hdr_tot_len;
__u8 imb_hdr_no;
__u8 reserved;
__u8 hdr_type;
__u8 hdr_version;
__u16 hdr_len;
__u32 payload_len;
__u16 mss;
__u16 dg_hdr_len;
__u8 padding[16];
} __attribute__ ((packed));

struct qeth_hdr_tso {
struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
struct qeth_hdr_ext_tso ext;
} __attribute__ ((packed));


/* flags for qeth_hdr.flags */
#define QETH_HDR_PASSTHRU 0x10
Expand Down Expand Up @@ -867,16 +886,6 @@ 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)
Expand All @@ -885,19 +894,19 @@ qeth_get_hlen(__u8 link_type)
switch (link_type) {
case QETH_LINK_TYPE_HSTR:
case QETH_LINK_TYPE_LANE_TR:
return sizeof(struct qeth_hdr) + TR_HLEN;
return sizeof(struct qeth_hdr_tso) + TR_HLEN;
default:
#ifdef CONFIG_QETH_VLAN
return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN;
return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
#else
return sizeof(struct qeth_hdr) + ETH_HLEN;
return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
#endif
}
#else /* CONFIG_QETH_IPV6 */
#ifdef CONFIG_QETH_VLAN
return sizeof(struct qeth_hdr) + VLAN_HLEN;
return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
#else
return sizeof(struct qeth_hdr);
return sizeof(struct qeth_hdr_tso);
#endif
#endif /* CONFIG_QETH_IPV6 */
}
Expand Down
40 changes: 20 additions & 20 deletions drivers/s390/net/qeth_eddp.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
*
* linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $)
* linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
*
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
*
* Copyright 2004 IBM Corporation
*
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
* $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $
* $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
*
*/
#include <linux/config.h>
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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)){
Expand Down Expand Up @@ -204,27 +204,27 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,

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];
Expand Down Expand Up @@ -270,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);
Expand All @@ -281,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 {
Expand Down Expand Up @@ -413,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;
Expand Down Expand Up @@ -453,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;
Expand All @@ -463,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)
Expand Down Expand Up @@ -509,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);
Expand Down Expand Up @@ -589,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,
Expand Down
Loading

0 comments on commit 05e08a2

Please sign in to comment.