diff options
author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2008-08-01 10:39:13 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-08-01 10:39:31 -0400 |
commit | 683d718a893575a88c551ad71ea2c382eedbf67e (patch) | |
tree | 4255357a683d412120a083326da968e996c7cf00 /drivers/s390/net/qeth_l2_main.c | |
parent | a4b526b3ba6353cd89a38e41da48ed83b0ead16f (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_l2_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index a8b069cd9a4c..b3cee032f578 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -243,8 +243,7 @@ static void qeth_l2_get_packet_type(struct qeth_card *card, | |||
243 | static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | 243 | static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, |
244 | struct sk_buff *skb, int ipv, int cast_type) | 244 | struct sk_buff *skb, int ipv, int cast_type) |
245 | { | 245 | { |
246 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)((skb->data) + | 246 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); |
247 | QETH_HEADER_SIZE); | ||
248 | 247 | ||
249 | memset(hdr, 0, sizeof(struct qeth_hdr)); | 248 | memset(hdr, 0, sizeof(struct qeth_hdr)); |
250 | hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; | 249 | hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; |
@@ -621,6 +620,9 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
621 | int tx_bytes = skb->len; | 620 | int tx_bytes = skb->len; |
622 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 621 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
623 | struct qeth_eddp_context *ctx = NULL; | 622 | struct qeth_eddp_context *ctx = NULL; |
623 | int data_offset = -1; | ||
624 | int elements_needed = 0; | ||
625 | int hd_len = 0; | ||
624 | 626 | ||
625 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { | 627 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { |
626 | card->stats.tx_carrier_errors++; | 628 | card->stats.tx_carrier_errors++; |
@@ -643,13 +645,32 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
643 | if (card->info.type == QETH_CARD_TYPE_OSN) | 645 | if (card->info.type == QETH_CARD_TYPE_OSN) |
644 | hdr = (struct qeth_hdr *)skb->data; | 646 | hdr = (struct qeth_hdr *)skb->data; |
645 | else { | 647 | else { |
646 | /* create a clone with writeable headroom */ | 648 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && |
647 | new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr)); | 649 | (skb_shinfo(skb)->nr_frags == 0)) { |
648 | if (!new_skb) | 650 | new_skb = skb; |
649 | goto tx_drop; | 651 | data_offset = ETH_HLEN; |
650 | hdr = (struct qeth_hdr *)skb_push(new_skb, | 652 | hd_len = ETH_HLEN; |
653 | hdr = kmem_cache_alloc(qeth_core_header_cache, | ||
654 | GFP_ATOMIC); | ||
655 | if (!hdr) | ||
656 | goto tx_drop; | ||
657 | elements_needed++; | ||
658 | skb_reset_mac_header(new_skb); | ||
659 | qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type); | ||
660 | hdr->hdr.l2.pkt_length = new_skb->len; | ||
661 | memcpy(((char *)hdr) + sizeof(struct qeth_hdr), | ||
662 | skb_mac_header(new_skb), ETH_HLEN); | ||
663 | } else { | ||
664 | /* create a clone with writeable headroom */ | ||
665 | new_skb = skb_realloc_headroom(skb, | ||
666 | sizeof(struct qeth_hdr)); | ||
667 | if (!new_skb) | ||
668 | goto tx_drop; | ||
669 | hdr = (struct qeth_hdr *)skb_push(new_skb, | ||
651 | sizeof(struct qeth_hdr)); | 670 | sizeof(struct qeth_hdr)); |
652 | qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type); | 671 | skb_set_mac_header(new_skb, sizeof(struct qeth_hdr)); |
672 | qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type); | ||
673 | } | ||
653 | } | 674 | } |
654 | 675 | ||
655 | if (large_send == QETH_LARGE_SEND_EDDP) { | 676 | if (large_send == QETH_LARGE_SEND_EDDP) { |
@@ -660,9 +681,13 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
660 | goto tx_drop; | 681 | goto tx_drop; |
661 | } | 682 | } |
662 | } else { | 683 | } else { |
663 | elements = qeth_get_elements_no(card, (void *)hdr, new_skb, 0); | 684 | elements = qeth_get_elements_no(card, (void *)hdr, new_skb, |
664 | if (!elements) | 685 | elements_needed); |
686 | if (!elements) { | ||
687 | if (data_offset >= 0) | ||
688 | kmem_cache_free(qeth_core_header_cache, hdr); | ||
665 | goto tx_drop; | 689 | goto tx_drop; |
690 | } | ||
666 | } | 691 | } |
667 | 692 | ||
668 | if ((large_send == QETH_LARGE_SEND_NO) && | 693 | if ((large_send == QETH_LARGE_SEND_NO) && |
@@ -674,7 +699,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
674 | elements, ctx); | 699 | elements, ctx); |
675 | else | 700 | else |
676 | rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, | 701 | rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, |
677 | elements, ctx); | 702 | elements, ctx, data_offset, hd_len); |
678 | if (!rc) { | 703 | if (!rc) { |
679 | card->stats.tx_packets++; | 704 | card->stats.tx_packets++; |
680 | card->stats.tx_bytes += tx_bytes; | 705 | card->stats.tx_bytes += tx_bytes; |
@@ -701,6 +726,9 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
701 | if (ctx != NULL) | 726 | if (ctx != NULL) |
702 | qeth_eddp_put_context(ctx); | 727 | qeth_eddp_put_context(ctx); |
703 | 728 | ||
729 | if (data_offset >= 0) | ||
730 | kmem_cache_free(qeth_core_header_cache, hdr); | ||
731 | |||
704 | if (rc == -EBUSY) { | 732 | if (rc == -EBUSY) { |
705 | if (new_skb != skb) | 733 | if (new_skb != skb) |
706 | dev_kfree_skb_any(new_skb); | 734 | dev_kfree_skb_any(new_skb); |