aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
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
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')
-rw-r--r--drivers/s390/net/qeth_core.h5
-rw-r--r--drivers/s390/net/qeth_core_main.c59
-rw-r--r--drivers/s390/net/qeth_l2_main.c50
-rw-r--r--drivers/s390/net/qeth_l3_main.c51
4 files changed, 126 insertions, 39 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 1895dbb553cd..80971c21ea1a 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -419,6 +419,7 @@ struct qeth_qdio_out_buffer {
419 int next_element_to_fill; 419 int next_element_to_fill;
420 struct sk_buff_head skb_list; 420 struct sk_buff_head skb_list;
421 struct list_head ctx_list; 421 struct list_head ctx_list;
422 int is_header[16];
422}; 423};
423 424
424struct qeth_card; 425struct qeth_card;
@@ -785,7 +786,7 @@ void qeth_core_remove_osn_attributes(struct device *);
785 786
786/* exports for qeth discipline device drivers */ 787/* exports for qeth discipline device drivers */
787extern struct qeth_card_list_struct qeth_core_card_list; 788extern struct qeth_card_list_struct qeth_core_card_list;
788 789extern struct kmem_cache *qeth_core_header_cache;
789extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS]; 790extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
790 791
791void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int); 792void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
@@ -843,7 +844,7 @@ int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
843int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); 844int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
844int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, 845int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
845 struct sk_buff *, struct qeth_hdr *, int, 846 struct sk_buff *, struct qeth_hdr *, int,
846 struct qeth_eddp_context *); 847 struct qeth_eddp_context *, int, int);
847int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, 848int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
848 struct sk_buff *, struct qeth_hdr *, 849 struct sk_buff *, struct qeth_hdr *,
849 int, struct qeth_eddp_context *); 850 int, struct qeth_eddp_context *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index cebb25e36e82..7a5549919717 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -48,6 +48,8 @@ EXPORT_SYMBOL_GPL(qeth_dbf);
48 48
49struct qeth_card_list_struct qeth_core_card_list; 49struct qeth_card_list_struct qeth_core_card_list;
50EXPORT_SYMBOL_GPL(qeth_core_card_list); 50EXPORT_SYMBOL_GPL(qeth_core_card_list);
51struct kmem_cache *qeth_core_header_cache;
52EXPORT_SYMBOL_GPL(qeth_core_header_cache);
51 53
52static struct device *qeth_core_root_dev; 54static struct device *qeth_core_root_dev;
53static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY; 55static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
@@ -933,6 +935,10 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
933 } 935 }
934 qeth_eddp_buf_release_contexts(buf); 936 qeth_eddp_buf_release_contexts(buf);
935 for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { 937 for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
938 if (buf->buffer->element[i].addr && buf->is_header[i])
939 kmem_cache_free(qeth_core_header_cache,
940 buf->buffer->element[i].addr);
941 buf->is_header[i] = 0;
936 buf->buffer->element[i].length = 0; 942 buf->buffer->element[i].length = 0;
937 buf->buffer->element[i].addr = NULL; 943 buf->buffer->element[i].addr = NULL;
938 buf->buffer->element[i].flags = 0; 944 buf->buffer->element[i].flags = 0;
@@ -3002,8 +3008,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3002 if (skb_shinfo(skb)->nr_frags > 0) 3008 if (skb_shinfo(skb)->nr_frags > 0)
3003 elements_needed = (skb_shinfo(skb)->nr_frags + 1); 3009 elements_needed = (skb_shinfo(skb)->nr_frags + 1);
3004 if (elements_needed == 0) 3010 if (elements_needed == 0)
3005 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) 3011 elements_needed = 1 + (((((unsigned long) skb->data) %
3006 + skb->len) >> PAGE_SHIFT); 3012 PAGE_SIZE) + skb->len) >> PAGE_SHIFT);
3007 if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { 3013 if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
3008 QETH_DBF_MESSAGE(2, "Invalid size of IP packet " 3014 QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
3009 "(Number=%d / Length=%d). Discarded.\n", 3015 "(Number=%d / Length=%d). Discarded.\n",
@@ -3015,7 +3021,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3015EXPORT_SYMBOL_GPL(qeth_get_elements_no); 3021EXPORT_SYMBOL_GPL(qeth_get_elements_no);
3016 3022
3017static inline void __qeth_fill_buffer(struct sk_buff *skb, 3023static inline void __qeth_fill_buffer(struct sk_buff *skb,
3018 struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill) 3024 struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill,
3025 int offset)
3019{ 3026{
3020 int length = skb->len; 3027 int length = skb->len;
3021 int length_here; 3028 int length_here;
@@ -3027,6 +3034,11 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
3027 data = skb->data; 3034 data = skb->data;
3028 first_lap = (is_tso == 0 ? 1 : 0); 3035 first_lap = (is_tso == 0 ? 1 : 0);
3029 3036
3037 if (offset >= 0) {
3038 data = skb->data + offset;
3039 first_lap = 0;
3040 }
3041
3030 while (length > 0) { 3042 while (length > 0) {
3031 /* length_here is the remaining amount of data in this page */ 3043 /* length_here is the remaining amount of data in this page */
3032 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); 3044 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
@@ -3058,22 +3070,22 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
3058} 3070}
3059 3071
3060static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, 3072static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3061 struct qeth_qdio_out_buffer *buf, struct sk_buff *skb) 3073 struct qeth_qdio_out_buffer *buf, struct sk_buff *skb,
3074 struct qeth_hdr *hdr, int offset, int hd_len)
3062{ 3075{
3063 struct qdio_buffer *buffer; 3076 struct qdio_buffer *buffer;
3064 struct qeth_hdr_tso *hdr;
3065 int flush_cnt = 0, hdr_len, large_send = 0; 3077 int flush_cnt = 0, hdr_len, large_send = 0;
3066 3078
3067 buffer = buf->buffer; 3079 buffer = buf->buffer;
3068 atomic_inc(&skb->users); 3080 atomic_inc(&skb->users);
3069 skb_queue_tail(&buf->skb_list, skb); 3081 skb_queue_tail(&buf->skb_list, skb);
3070 3082
3071 hdr = (struct qeth_hdr_tso *) skb->data;
3072 /*check first on TSO ....*/ 3083 /*check first on TSO ....*/
3073 if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) { 3084 if (hdr->hdr.l3.id == QETH_HEADER_TYPE_TSO) {
3074 int element = buf->next_element_to_fill; 3085 int element = buf->next_element_to_fill;
3075 3086
3076 hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; 3087 hdr_len = sizeof(struct qeth_hdr_tso) +
3088 ((struct qeth_hdr_tso *)hdr)->ext.dg_hdr_len;
3077 /*fill first buffer entry only with header information */ 3089 /*fill first buffer entry only with header information */
3078 buffer->element[element].addr = skb->data; 3090 buffer->element[element].addr = skb->data;
3079 buffer->element[element].length = hdr_len; 3091 buffer->element[element].length = hdr_len;
@@ -3083,9 +3095,20 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3083 skb->len -= hdr_len; 3095 skb->len -= hdr_len;
3084 large_send = 1; 3096 large_send = 1;
3085 } 3097 }
3098
3099 if (offset >= 0) {
3100 int element = buf->next_element_to_fill;
3101 buffer->element[element].addr = hdr;
3102 buffer->element[element].length = sizeof(struct qeth_hdr) +
3103 hd_len;
3104 buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
3105 buf->is_header[element] = 1;
3106 buf->next_element_to_fill++;
3107 }
3108
3086 if (skb_shinfo(skb)->nr_frags == 0) 3109 if (skb_shinfo(skb)->nr_frags == 0)
3087 __qeth_fill_buffer(skb, buffer, large_send, 3110 __qeth_fill_buffer(skb, buffer, large_send,
3088 (int *)&buf->next_element_to_fill); 3111 (int *)&buf->next_element_to_fill, offset);
3089 else 3112 else
3090 __qeth_fill_buffer_frag(skb, buffer, large_send, 3113 __qeth_fill_buffer_frag(skb, buffer, large_send,
3091 (int *)&buf->next_element_to_fill); 3114 (int *)&buf->next_element_to_fill);
@@ -3115,7 +3138,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3115int qeth_do_send_packet_fast(struct qeth_card *card, 3138int qeth_do_send_packet_fast(struct qeth_card *card,
3116 struct qeth_qdio_out_q *queue, struct sk_buff *skb, 3139 struct qeth_qdio_out_q *queue, struct sk_buff *skb,
3117 struct qeth_hdr *hdr, int elements_needed, 3140 struct qeth_hdr *hdr, int elements_needed,
3118 struct qeth_eddp_context *ctx) 3141 struct qeth_eddp_context *ctx, int offset, int hd_len)
3119{ 3142{
3120 struct qeth_qdio_out_buffer *buffer; 3143 struct qeth_qdio_out_buffer *buffer;
3121 int buffers_needed = 0; 3144 int buffers_needed = 0;
@@ -3148,7 +3171,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
3148 } 3171 }
3149 atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); 3172 atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
3150 if (ctx == NULL) { 3173 if (ctx == NULL) {
3151 qeth_fill_buffer(queue, buffer, skb); 3174 qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
3152 qeth_flush_buffers(queue, index, 1); 3175 qeth_flush_buffers(queue, index, 1);
3153 } else { 3176 } else {
3154 flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index); 3177 flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
@@ -3224,7 +3247,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
3224 } 3247 }
3225 } 3248 }
3226 if (ctx == NULL) 3249 if (ctx == NULL)
3227 tmp = qeth_fill_buffer(queue, buffer, skb); 3250 tmp = qeth_fill_buffer(queue, buffer, skb, hdr, -1, 0);
3228 else { 3251 else {
3229 tmp = qeth_eddp_fill_buffer(queue, ctx, 3252 tmp = qeth_eddp_fill_buffer(queue, ctx,
3230 queue->next_buf_to_fill); 3253 queue->next_buf_to_fill);
@@ -4443,8 +4466,17 @@ static int __init qeth_core_init(void)
4443 rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0; 4466 rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
4444 if (rc) 4467 if (rc)
4445 goto register_err; 4468 goto register_err;
4446 return 0;
4447 4469
4470 qeth_core_header_cache = kmem_cache_create("qeth_hdr",
4471 sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL);
4472 if (!qeth_core_header_cache) {
4473 rc = -ENOMEM;
4474 goto slab_err;
4475 }
4476
4477 return 0;
4478slab_err:
4479 s390_root_dev_unregister(qeth_core_root_dev);
4448register_err: 4480register_err:
4449 driver_remove_file(&qeth_core_ccwgroup_driver.driver, 4481 driver_remove_file(&qeth_core_ccwgroup_driver.driver,
4450 &driver_attr_group); 4482 &driver_attr_group);
@@ -4466,6 +4498,7 @@ static void __exit qeth_core_exit(void)
4466 &driver_attr_group); 4498 &driver_attr_group);
4467 ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); 4499 ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
4468 ccw_driver_unregister(&qeth_ccw_driver); 4500 ccw_driver_unregister(&qeth_ccw_driver);
4501 kmem_cache_destroy(qeth_core_header_cache);
4469 qeth_unregister_dbf_views(); 4502 qeth_unregister_dbf_views();
4470 PRINT_INFO("core functions removed\n"); 4503 PRINT_INFO("core functions removed\n");
4471} 4504}
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,
243static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, 243static 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);
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);