summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2007-12-18 15:12:44 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-08 12:01:36 -0800
commitb6f3568f83d38355314f42e5159648c09b5ece87 (patch)
tree56e80b46474c8dbed3929dd0df534d9115dc4ba5
parent5213946fb2ba61721aa933f9a565b0d2ee93687d (diff)
cxgb: fix T2 GSO
patch 7832ee034b6ef78aab020c9ec1348544cd65ccbd in mainline. The patch ensures that a GSO skb has enough headroom to push an encapsulating cpl_tx_pkt_lso header. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/chelsio/cxgb2.c1
-rw-r--r--drivers/net/chelsio/sge.c34
-rw-r--r--drivers/net/chelsio/sge.h1
3 files changed, 17 insertions, 19 deletions
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 231ce43b97cf..0d0aa55a0879 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -397,6 +397,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"TxTso",
"RxVlan",
"TxVlan",
+ "TxNeedHeadroom",
/* Interrupt stats */
"rx drops",
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index c016bd72bc09..cdac18507b37 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -991,6 +991,7 @@ void t1_sge_get_port_stats(const struct sge *sge, int port,
ss->tx_packets += st->tx_packets;
ss->tx_cso += st->tx_cso;
ss->tx_tso += st->tx_tso;
+ ss->tx_need_hdrroom += st->tx_need_hdrroom;
ss->vlan_xtract += st->vlan_xtract;
ss->vlan_insert += st->vlan_insert;
}
@@ -1851,7 +1852,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct adapter *adapter = dev->priv;
struct sge *sge = adapter->sge;
- struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id());
+ struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port],
+ smp_processor_id());
struct cpl_tx_pkt *cpl;
struct sk_buff *orig_skb = skb;
int ret;
@@ -1859,6 +1861,18 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->protocol == htons(ETH_P_CPL5))
goto send;
+ /*
+ * We are using a non-standard hard_header_len.
+ * Allocate more header room in the rare cases it is not big enough.
+ */
+ if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
+ skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso));
+ ++st->tx_need_hdrroom;
+ dev_kfree_skb_any(orig_skb);
+ if (!skb)
+ return NETDEV_TX_OK;
+ }
+
if (skb_shinfo(skb)->gso_size) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
@@ -1892,24 +1906,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
- /*
- * We are using a non-standard hard_header_len and some kernel
- * components, such as pktgen, do not handle it right.
- * Complain when this happens but try to fix things up.
- */
- if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
- pr_debug("%s: headroom %d header_len %d\n", dev->name,
- skb_headroom(skb), dev->hard_header_len);
-
- if (net_ratelimit())
- printk(KERN_ERR "%s: inadequate headroom in "
- "Tx packet\n", dev->name);
- skb = skb_realloc_headroom(skb, sizeof(*cpl));
- dev_kfree_skb_any(orig_skb);
- if (!skb)
- return NETDEV_TX_OK;
- }
-
if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
skb->ip_summed == CHECKSUM_PARTIAL &&
ip_hdr(skb)->protocol == IPPROTO_UDP) {
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index d132a0ef2a22..94b87767f9df 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -64,6 +64,7 @@ struct sge_port_stats {
u64 tx_tso; /* # of TSO requests */
u64 vlan_xtract; /* # of VLAN tag extractions */
u64 vlan_insert; /* # of VLAN tag insertions */
+ u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */
};
struct sk_buff;