diff options
author | Divy Le Ray <divy@chelsio.com> | 2007-11-27 16:30:09 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-12-01 16:32:31 -0500 |
commit | 7832ee034b6ef78aab020c9ec1348544cd65ccbd (patch) | |
tree | 9a4fedc9bf3b6b9c31f35a50f3d7aa0deab358d4 | |
parent | bd0ceaab86d3f0e3916b3b7868cfe20de490eebc (diff) |
cxgb - fix T2 GSO
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>
-rwxr-xr-x[-rw-r--r--] | drivers/net/chelsio/cxgb2.c | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/net/chelsio/sge.c | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/net/chelsio/sge.h | 1 |
3 files changed, 18 insertions, 20 deletions
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 2dbf8dc116c6..2461f91b0996 100644..100755 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c | |||
@@ -401,7 +401,8 @@ static char stats_strings[][ETH_GSTRING_LEN] = { | |||
401 | "TxTso", | 401 | "TxTso", |
402 | "RxVlan", | 402 | "RxVlan", |
403 | "TxVlan", | 403 | "TxVlan", |
404 | 404 | "TxNeedHeadroom", | |
405 | |||
405 | /* Interrupt stats */ | 406 | /* Interrupt stats */ |
406 | "rx drops", | 407 | "rx drops", |
407 | "pure_rsps", | 408 | "pure_rsps", |
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 443666292a5c..e8b1036672ae 100644..100755 --- 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, | |||
991 | ss->tx_packets += st->tx_packets; | 991 | ss->tx_packets += st->tx_packets; |
992 | ss->tx_cso += st->tx_cso; | 992 | ss->tx_cso += st->tx_cso; |
993 | ss->tx_tso += st->tx_tso; | 993 | ss->tx_tso += st->tx_tso; |
994 | ss->tx_need_hdrroom += st->tx_need_hdrroom; | ||
994 | ss->vlan_xtract += st->vlan_xtract; | 995 | ss->vlan_xtract += st->vlan_xtract; |
995 | ss->vlan_insert += st->vlan_insert; | 996 | ss->vlan_insert += st->vlan_insert; |
996 | } | 997 | } |
@@ -1848,7 +1849,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1848 | { | 1849 | { |
1849 | struct adapter *adapter = dev->priv; | 1850 | struct adapter *adapter = dev->priv; |
1850 | struct sge *sge = adapter->sge; | 1851 | struct sge *sge = adapter->sge; |
1851 | struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id()); | 1852 | struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], |
1853 | smp_processor_id()); | ||
1852 | struct cpl_tx_pkt *cpl; | 1854 | struct cpl_tx_pkt *cpl; |
1853 | struct sk_buff *orig_skb = skb; | 1855 | struct sk_buff *orig_skb = skb; |
1854 | int ret; | 1856 | int ret; |
@@ -1856,6 +1858,18 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1856 | if (skb->protocol == htons(ETH_P_CPL5)) | 1858 | if (skb->protocol == htons(ETH_P_CPL5)) |
1857 | goto send; | 1859 | goto send; |
1858 | 1860 | ||
1861 | /* | ||
1862 | * We are using a non-standard hard_header_len. | ||
1863 | * Allocate more header room in the rare cases it is not big enough. | ||
1864 | */ | ||
1865 | if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { | ||
1866 | skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso)); | ||
1867 | ++st->tx_need_hdrroom; | ||
1868 | dev_kfree_skb_any(orig_skb); | ||
1869 | if (!skb) | ||
1870 | return NETDEV_TX_OK; | ||
1871 | } | ||
1872 | |||
1859 | if (skb_shinfo(skb)->gso_size) { | 1873 | if (skb_shinfo(skb)->gso_size) { |
1860 | int eth_type; | 1874 | int eth_type; |
1861 | struct cpl_tx_pkt_lso *hdr; | 1875 | struct cpl_tx_pkt_lso *hdr; |
@@ -1889,24 +1903,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1889 | return NETDEV_TX_OK; | 1903 | return NETDEV_TX_OK; |
1890 | } | 1904 | } |
1891 | 1905 | ||
1892 | /* | ||
1893 | * We are using a non-standard hard_header_len and some kernel | ||
1894 | * components, such as pktgen, do not handle it right. | ||
1895 | * Complain when this happens but try to fix things up. | ||
1896 | */ | ||
1897 | if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { | ||
1898 | pr_debug("%s: headroom %d header_len %d\n", dev->name, | ||
1899 | skb_headroom(skb), dev->hard_header_len); | ||
1900 | |||
1901 | if (net_ratelimit()) | ||
1902 | printk(KERN_ERR "%s: inadequate headroom in " | ||
1903 | "Tx packet\n", dev->name); | ||
1904 | skb = skb_realloc_headroom(skb, sizeof(*cpl)); | ||
1905 | dev_kfree_skb_any(orig_skb); | ||
1906 | if (!skb) | ||
1907 | return NETDEV_TX_OK; | ||
1908 | } | ||
1909 | |||
1910 | if (!(adapter->flags & UDP_CSUM_CAPABLE) && | 1906 | if (!(adapter->flags & UDP_CSUM_CAPABLE) && |
1911 | skb->ip_summed == CHECKSUM_PARTIAL && | 1907 | skb->ip_summed == CHECKSUM_PARTIAL && |
1912 | ip_hdr(skb)->protocol == IPPROTO_UDP) { | 1908 | ip_hdr(skb)->protocol == IPPROTO_UDP) { |
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 713d9c55f24d..285bbb272ed5 100644..100755 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h | |||
@@ -64,6 +64,7 @@ struct sge_port_stats { | |||
64 | u64 tx_tso; /* # of TSO requests */ | 64 | u64 tx_tso; /* # of TSO requests */ |
65 | u64 vlan_xtract; /* # of VLAN tag extractions */ | 65 | u64 vlan_xtract; /* # of VLAN tag extractions */ |
66 | u64 vlan_insert; /* # of VLAN tag insertions */ | 66 | u64 vlan_insert; /* # of VLAN tag insertions */ |
67 | u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */ | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | struct sk_buff; | 70 | struct sk_buff; |