aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_l3_main.c
diff options
context:
space:
mode:
authorFrank Blaschka <frank.blaschka@de.ibm.com>2008-08-01 10:39:13 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-08-01 10:39:31 -0400
commit683d718a893575a88c551ad71ea2c382eedbf67e (patch)
tree4255357a683d412120a083326da968e996c7cf00 /drivers/s390/net/qeth_l3_main.c
parenta4b526b3ba6353cd89a38e41da48ed83b0ead16f (diff)
[S390] qeth: preallocated qeth header for hiper socket
For hiper socket devices this patch will economize the reallocation of the tx skb data segment by allocating separate memory for the qdio transport information (qeth header). Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r--drivers/s390/net/qeth_l3_main.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 3e1d13857350..dd72c3c20165 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2604,6 +2604,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2604 int tx_bytes = skb->len; 2604 int tx_bytes = skb->len;
2605 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; 2605 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
2606 struct qeth_eddp_context *ctx = NULL; 2606 struct qeth_eddp_context *ctx = NULL;
2607 int data_offset = -1;
2607 2608
2608 if ((card->info.type == QETH_CARD_TYPE_IQD) && 2609 if ((card->info.type == QETH_CARD_TYPE_IQD) &&
2609 (skb->protocol != htons(ETH_P_IPV6)) && 2610 (skb->protocol != htons(ETH_P_IPV6)) &&
@@ -2624,14 +2625,28 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2624 card->perf_stats.outbound_start_time = qeth_get_micros(); 2625 card->perf_stats.outbound_start_time = qeth_get_micros();
2625 } 2626 }
2626 2627
2627 /* create a clone with writeable headroom */ 2628 if (skb_is_gso(skb))
2628 new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) + 2629 large_send = card->options.large_send;
2629 VLAN_HLEN); 2630
2630 if (!new_skb) 2631 if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
2631 goto tx_drop; 2632 (skb_shinfo(skb)->nr_frags == 0)) {
2633 new_skb = skb;
2634 data_offset = ETH_HLEN;
2635 hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
2636 if (!hdr)
2637 goto tx_drop;
2638 elements_needed++;
2639 } else {
2640 /* create a clone with writeable headroom */
2641 new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)
2642 + VLAN_HLEN);
2643 if (!new_skb)
2644 goto tx_drop;
2645 }
2632 2646
2633 if (card->info.type == QETH_CARD_TYPE_IQD) { 2647 if (card->info.type == QETH_CARD_TYPE_IQD) {
2634 skb_pull(new_skb, ETH_HLEN); 2648 if (data_offset < 0)
2649 skb_pull(new_skb, ETH_HLEN);
2635 } else { 2650 } else {
2636 if (new_skb->protocol == htons(ETH_P_IP)) { 2651 if (new_skb->protocol == htons(ETH_P_IP)) {
2637 if (card->dev->type == ARPHRD_IEEE802_TR) 2652 if (card->dev->type == ARPHRD_IEEE802_TR)
@@ -2657,9 +2672,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2657 2672
2658 netif_stop_queue(dev); 2673 netif_stop_queue(dev);
2659 2674
2660 if (skb_is_gso(new_skb))
2661 large_send = card->options.large_send;
2662
2663 /* fix hardware limitation: as long as we do not have sbal 2675 /* fix hardware limitation: as long as we do not have sbal
2664 * chaining we can not send long frag lists so we temporary 2676 * chaining we can not send long frag lists so we temporary
2665 * switch to EDDP 2677 * switch to EDDP
@@ -2677,9 +2689,16 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2677 qeth_tso_fill_header(card, hdr, new_skb); 2689 qeth_tso_fill_header(card, hdr, new_skb);
2678 elements_needed++; 2690 elements_needed++;
2679 } else { 2691 } else {
2680 hdr = (struct qeth_hdr *)skb_push(new_skb, 2692 if (data_offset < 0) {
2693 hdr = (struct qeth_hdr *)skb_push(new_skb,
2681 sizeof(struct qeth_hdr)); 2694 sizeof(struct qeth_hdr));
2682 qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type); 2695 qeth_l3_fill_header(card, hdr, new_skb, ipv,
2696 cast_type);
2697 } else {
2698 qeth_l3_fill_header(card, hdr, new_skb, ipv,
2699 cast_type);
2700 hdr->hdr.l3.length = new_skb->len - data_offset;
2701 }
2683 } 2702 }
2684 2703
2685 if (large_send == QETH_LARGE_SEND_EDDP) { 2704 if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -2695,8 +2714,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2695 } else { 2714 } else {
2696 int elems = qeth_get_elements_no(card, (void *)hdr, new_skb, 2715 int elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
2697 elements_needed); 2716 elements_needed);
2698 if (!elems) 2717 if (!elems) {
2718 if (data_offset >= 0)
2719 kmem_cache_free(qeth_core_header_cache, hdr);
2699 goto tx_drop; 2720 goto tx_drop;
2721 }
2700 elements_needed += elems; 2722 elements_needed += elems;
2701 } 2723 }
2702 2724
@@ -2709,7 +2731,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2709 elements_needed, ctx); 2731 elements_needed, ctx);
2710 else 2732 else
2711 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, 2733 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
2712 elements_needed, ctx); 2734 elements_needed, ctx, data_offset, 0);
2713 2735
2714 if (!rc) { 2736 if (!rc) {
2715 card->stats.tx_packets++; 2737 card->stats.tx_packets++;
@@ -2737,6 +2759,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2737 if (ctx != NULL) 2759 if (ctx != NULL)
2738 qeth_eddp_put_context(ctx); 2760 qeth_eddp_put_context(ctx);
2739 2761
2762 if (data_offset >= 0)
2763 kmem_cache_free(qeth_core_header_cache, hdr);
2764
2740 if (rc == -EBUSY) { 2765 if (rc == -EBUSY) {
2741 if (new_skb != skb) 2766 if (new_skb != skb)
2742 dev_kfree_skb_any(new_skb); 2767 dev_kfree_skb_any(new_skb);