[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>
This commit is contained in:
committed by
Martin Schwidefsky
parent
a4b526b3ba
commit
683d718a89
@@ -2604,6 +2604,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
int tx_bytes = skb->len;
|
||||
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
|
||||
struct qeth_eddp_context *ctx = NULL;
|
||||
int data_offset = -1;
|
||||
|
||||
if ((card->info.type == QETH_CARD_TYPE_IQD) &&
|
||||
(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)
|
||||
card->perf_stats.outbound_start_time = qeth_get_micros();
|
||||
}
|
||||
|
||||
/* create a clone with writeable headroom */
|
||||
new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) +
|
||||
VLAN_HLEN);
|
||||
if (!new_skb)
|
||||
goto tx_drop;
|
||||
if (skb_is_gso(skb))
|
||||
large_send = card->options.large_send;
|
||||
|
||||
if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
|
||||
(skb_shinfo(skb)->nr_frags == 0)) {
|
||||
new_skb = skb;
|
||||
data_offset = ETH_HLEN;
|
||||
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
|
||||
if (!hdr)
|
||||
goto tx_drop;
|
||||
elements_needed++;
|
||||
} else {
|
||||
/* create a clone with writeable headroom */
|
||||
new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)
|
||||
+ VLAN_HLEN);
|
||||
if (!new_skb)
|
||||
goto tx_drop;
|
||||
}
|
||||
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD) {
|
||||
skb_pull(new_skb, ETH_HLEN);
|
||||
if (data_offset < 0)
|
||||
skb_pull(new_skb, ETH_HLEN);
|
||||
} else {
|
||||
if (new_skb->protocol == htons(ETH_P_IP)) {
|
||||
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)
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
if (skb_is_gso(new_skb))
|
||||
large_send = card->options.large_send;
|
||||
|
||||
/* fix hardware limitation: as long as we do not have sbal
|
||||
* chaining we can not send long frag lists so we temporary
|
||||
* switch to EDDP
|
||||
@@ -2677,9 +2689,16 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
qeth_tso_fill_header(card, hdr, new_skb);
|
||||
elements_needed++;
|
||||
} else {
|
||||
hdr = (struct qeth_hdr *)skb_push(new_skb,
|
||||
if (data_offset < 0) {
|
||||
hdr = (struct qeth_hdr *)skb_push(new_skb,
|
||||
sizeof(struct qeth_hdr));
|
||||
qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
|
||||
qeth_l3_fill_header(card, hdr, new_skb, ipv,
|
||||
cast_type);
|
||||
} else {
|
||||
qeth_l3_fill_header(card, hdr, new_skb, ipv,
|
||||
cast_type);
|
||||
hdr->hdr.l3.length = new_skb->len - data_offset;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
} else {
|
||||
int elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
|
||||
elements_needed);
|
||||
if (!elems)
|
||||
if (!elems) {
|
||||
if (data_offset >= 0)
|
||||
kmem_cache_free(qeth_core_header_cache, hdr);
|
||||
goto tx_drop;
|
||||
}
|
||||
elements_needed += elems;
|
||||
}
|
||||
|
||||
@@ -2709,7 +2731,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
elements_needed, ctx);
|
||||
else
|
||||
rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
|
||||
elements_needed, ctx);
|
||||
elements_needed, ctx, data_offset, 0);
|
||||
|
||||
if (!rc) {
|
||||
card->stats.tx_packets++;
|
||||
@@ -2737,6 +2759,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (ctx != NULL)
|
||||
qeth_eddp_put_context(ctx);
|
||||
|
||||
if (data_offset >= 0)
|
||||
kmem_cache_free(qeth_core_header_cache, hdr);
|
||||
|
||||
if (rc == -EBUSY) {
|
||||
if (new_skb != skb)
|
||||
dev_kfree_skb_any(new_skb);
|
||||
|
Reference in New Issue
Block a user