aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_l3_main.c
diff options
context:
space:
mode:
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);