aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_eddp.c
diff options
context:
space:
mode:
authorFrank Pavlic <pavlic@de.ibm.com>2005-05-12 14:39:09 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-15 18:06:17 -0400
commit05e08a2a297371564020f76d1bf8b3a931d5e1ed (patch)
tree0aac8cafdec747a792c46dff1b934db642b0a054 /drivers/s390/net/qeth_eddp.c
parent9a4558193662e933588ee53e0202c103a68c9366 (diff)
[PATCH] s390: qeth bug fixes
[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>
Diffstat (limited to 'drivers/s390/net/qeth_eddp.c')
-rw-r--r--drivers/s390/net/qeth_eddp.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 45aa4a962daf..f94f1f25eec6 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * 2 *
3 * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $) 3 * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
4 * 4 *
5 * Enhanced Device Driver Packing (EDDP) support for the qeth driver. 5 * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
6 * 6 *
@@ -8,7 +8,7 @@
8 * 8 *
9 * Author(s): Thomas Spatzier <tspat@de.ibm.com> 9 * Author(s): Thomas Spatzier <tspat@de.ibm.com>
10 * 10 *
11 * $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $ 11 * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
12 * 12 *
13 */ 13 */
14#include <linux/config.h> 14#include <linux/config.h>
@@ -85,7 +85,7 @@ void
85qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) 85qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
86{ 86{
87 struct qeth_eddp_context_reference *ref; 87 struct qeth_eddp_context_reference *ref;
88 88
89 QETH_DBF_TEXT(trace, 6, "eddprctx"); 89 QETH_DBF_TEXT(trace, 6, "eddprctx");
90 while (!list_empty(&buf->ctx_list)){ 90 while (!list_empty(&buf->ctx_list)){
91 ref = list_entry(buf->ctx_list.next, 91 ref = list_entry(buf->ctx_list.next,
@@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
139 "buffer!\n"); 139 "buffer!\n");
140 goto out; 140 goto out;
141 } 141 }
142 } 142 }
143 /* check if the whole next skb fits into current buffer */ 143 /* check if the whole next skb fits into current buffer */
144 if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) - 144 if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
145 buf->next_element_to_fill) 145 buf->next_element_to_fill)
@@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
152 * and increment ctx's refcnt */ 152 * and increment ctx's refcnt */
153 must_refcnt = 1; 153 must_refcnt = 1;
154 continue; 154 continue;
155 } 155 }
156 if (must_refcnt){ 156 if (must_refcnt){
157 must_refcnt = 0; 157 must_refcnt = 0;
158 if (qeth_eddp_buf_ref_context(buf, ctx)){ 158 if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -204,27 +204,27 @@ out:
204 204
205static inline void 205static inline void
206qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, 206qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
207 struct qeth_eddp_data *eddp) 207 struct qeth_eddp_data *eddp, int data_len)
208{ 208{
209 u8 *page; 209 u8 *page;
210 int page_remainder; 210 int page_remainder;
211 int page_offset; 211 int page_offset;
212 int hdr_len; 212 int pkt_len;
213 struct qeth_eddp_element *element; 213 struct qeth_eddp_element *element;
214 214
215 QETH_DBF_TEXT(trace, 5, "eddpcrsh"); 215 QETH_DBF_TEXT(trace, 5, "eddpcrsh");
216 page = ctx->pages[ctx->offset >> PAGE_SHIFT]; 216 page = ctx->pages[ctx->offset >> PAGE_SHIFT];
217 page_offset = ctx->offset % PAGE_SIZE; 217 page_offset = ctx->offset % PAGE_SIZE;
218 element = &ctx->elements[ctx->num_elements]; 218 element = &ctx->elements[ctx->num_elements];
219 hdr_len = eddp->nhl + eddp->thl; 219 pkt_len = eddp->nhl + eddp->thl + data_len;
220 /* FIXME: layer2 and VLAN !!! */ 220 /* FIXME: layer2 and VLAN !!! */
221 if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) 221 if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
222 hdr_len += ETH_HLEN; 222 pkt_len += ETH_HLEN;
223 if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) 223 if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
224 hdr_len += VLAN_HLEN; 224 pkt_len += VLAN_HLEN;
225 /* does complete header fit in current page ? */ 225 /* does complete packet fit in current page ? */
226 page_remainder = PAGE_SIZE - page_offset; 226 page_remainder = PAGE_SIZE - page_offset;
227 if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){ 227 if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
228 /* no -> go to start of next page */ 228 /* no -> go to start of next page */
229 ctx->offset += page_remainder; 229 ctx->offset += page_remainder;
230 page = ctx->pages[ctx->offset >> PAGE_SHIFT]; 230 page = ctx->pages[ctx->offset >> PAGE_SHIFT];
@@ -270,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
270 int left_in_frag; 270 int left_in_frag;
271 int copy_len; 271 int copy_len;
272 u8 *src; 272 u8 *src;
273 273
274 QETH_DBF_TEXT(trace, 5, "eddpcdtc"); 274 QETH_DBF_TEXT(trace, 5, "eddpcdtc");
275 if (skb_shinfo(eddp->skb)->nr_frags == 0) { 275 if (skb_shinfo(eddp->skb)->nr_frags == 0) {
276 memcpy(dst, eddp->skb->data + eddp->skb_offset, len); 276 memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -281,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
281 while (len > 0) { 281 while (len > 0) {
282 if (eddp->frag < 0) { 282 if (eddp->frag < 0) {
283 /* we're in skb->data */ 283 /* we're in skb->data */
284 left_in_frag = qeth_get_skb_data_len(eddp->skb) 284 left_in_frag = (eddp->skb->len - eddp->skb->data_len)
285 - eddp->skb_offset; 285 - eddp->skb_offset;
286 src = eddp->skb->data + eddp->skb_offset; 286 src = eddp->skb->data + eddp->skb_offset;
287 } else { 287 } else {
@@ -413,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
413 struct tcphdr *tcph; 413 struct tcphdr *tcph;
414 int data_len; 414 int data_len;
415 u32 hcsum; 415 u32 hcsum;
416 416
417 QETH_DBF_TEXT(trace, 5, "eddpftcp"); 417 QETH_DBF_TEXT(trace, 5, "eddpftcp");
418 eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; 418 eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
419 tcph = eddp->skb->h.th; 419 tcph = eddp->skb->h.th;
@@ -453,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
453 else 453 else
454 hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); 454 hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
455 /* fill the next segment into the context */ 455 /* fill the next segment into the context */
456 qeth_eddp_create_segment_hdrs(ctx, eddp); 456 qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
457 qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum); 457 qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
458 if (eddp->skb_offset >= eddp->skb->len) 458 if (eddp->skb_offset >= eddp->skb->len)
459 break; 459 break;
@@ -463,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
463 eddp->th.tcp.h.seq += data_len; 463 eddp->th.tcp.h.seq += data_len;
464 } 464 }
465} 465}
466 466
467static inline int 467static inline int
468qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, 468qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
469 struct sk_buff *skb, struct qeth_hdr *qhdr) 469 struct sk_buff *skb, struct qeth_hdr *qhdr)
470{ 470{
471 struct qeth_eddp_data *eddp = NULL; 471 struct qeth_eddp_data *eddp = NULL;
472 472
473 QETH_DBF_TEXT(trace, 5, "eddpficx"); 473 QETH_DBF_TEXT(trace, 5, "eddpficx");
474 /* create our segmentation headers and copy original headers */ 474 /* create our segmentation headers and copy original headers */
475 if (skb->protocol == ETH_P_IP) 475 if (skb->protocol == ETH_P_IP)
@@ -509,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
509 int hdr_len) 509 int hdr_len)
510{ 510{
511 int skbs_per_page; 511 int skbs_per_page;
512 512
513 QETH_DBF_TEXT(trace, 5, "eddpcanp"); 513 QETH_DBF_TEXT(trace, 5, "eddpcanp");
514 /* can we put multiple skbs in one page? */ 514 /* can we put multiple skbs in one page? */
515 skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); 515 skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -589,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
589 struct qeth_hdr *qhdr) 589 struct qeth_hdr *qhdr)
590{ 590{
591 struct qeth_eddp_context *ctx = NULL; 591 struct qeth_eddp_context *ctx = NULL;
592 592
593 QETH_DBF_TEXT(trace, 5, "creddpct"); 593 QETH_DBF_TEXT(trace, 5, "creddpct");
594 if (skb->protocol == ETH_P_IP) 594 if (skb->protocol == ETH_P_IP)
595 ctx = qeth_eddp_create_context_generic(card, skb, 595 ctx = qeth_eddp_create_context_generic(card, skb,