aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2008-05-21 21:56:26 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-22 06:34:13 -0400
commitb47385bd4f67481a7dbfcf1b4b82e9a67ecb846c (patch)
tree7357a330b671dc2526fd7c467f1799cc612914ce /drivers
parent7385ecf339c504933a98581c2056d83b69b2a82b (diff)
cxgb3 - Add LRO support
Add LRO support. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/cxgb3/adapter.h14
-rw-r--r--drivers/net/cxgb3/common.h1
-rw-r--r--drivers/net/cxgb3/cxgb3_ioctl.h1
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c19
-rw-r--r--drivers/net/cxgb3/sge.c233
-rw-r--r--drivers/net/cxgb3/t3_cpl.h11
7 files changed, 268 insertions, 12 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9f6cc8a56073..daeb23d7fec1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2409,6 +2409,7 @@ config CHELSIO_T3
2409 tristate "Chelsio Communications T3 10Gb Ethernet support" 2409 tristate "Chelsio Communications T3 10Gb Ethernet support"
2410 depends on PCI 2410 depends on PCI
2411 select FW_LOADER 2411 select FW_LOADER
2412 select INET_LRO
2412 help 2413 help
2413 This driver supports Chelsio T3-based gigabit and 10Gb Ethernet 2414 This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
2414 adapters. 2415 adapters.
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 263e4faf45e5..271140433b09 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -42,6 +42,7 @@
42#include <linux/cache.h> 42#include <linux/cache.h>
43#include <linux/mutex.h> 43#include <linux/mutex.h>
44#include <linux/bitops.h> 44#include <linux/bitops.h>
45#include <linux/inet_lro.h>
45#include "t3cdev.h" 46#include "t3cdev.h"
46#include <asm/io.h> 47#include <asm/io.h>
47 48
@@ -173,16 +174,29 @@ enum { /* per port SGE statistics */
173 SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ 174 SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */
174 SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ 175 SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */
175 SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ 176 SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */
177 SGE_PSTAT_LRO_AGGR, /* # of page chunks added to LRO sessions */
178 SGE_PSTAT_LRO_FLUSHED, /* # of flushed LRO sessions */
179 SGE_PSTAT_LRO_NO_DESC, /* # of overflown LRO sessions */
176 180
177 SGE_PSTAT_MAX /* must be last */ 181 SGE_PSTAT_MAX /* must be last */
178}; 182};
179 183
184#define T3_MAX_LRO_SES 8
185#define T3_MAX_LRO_MAX_PKTS 64
186
180struct sge_qset { /* an SGE queue set */ 187struct sge_qset { /* an SGE queue set */
181 struct adapter *adap; 188 struct adapter *adap;
182 struct napi_struct napi; 189 struct napi_struct napi;
183 struct sge_rspq rspq; 190 struct sge_rspq rspq;
184 struct sge_fl fl[SGE_RXQ_PER_SET]; 191 struct sge_fl fl[SGE_RXQ_PER_SET];
185 struct sge_txq txq[SGE_TXQ_PER_SET]; 192 struct sge_txq txq[SGE_TXQ_PER_SET];
193 struct net_lro_mgr lro_mgr;
194 struct net_lro_desc lro_desc[T3_MAX_LRO_SES];
195 struct skb_frag_struct *lro_frag_tbl;
196 int lro_nfrags;
197 int lro_enabled;
198 int lro_frag_len;
199 void *lro_va;
186 struct net_device *netdev; 200 struct net_device *netdev;
187 unsigned long txq_stopped; /* which Tx queues are stopped */ 201 unsigned long txq_stopped; /* which Tx queues are stopped */
188 struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ 202 struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 579bee42a5cb..d444f5881f56 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -351,6 +351,7 @@ struct tp_params {
351 351
352struct qset_params { /* SGE queue set parameters */ 352struct qset_params { /* SGE queue set parameters */
353 unsigned int polling; /* polling/interrupt service for rspq */ 353 unsigned int polling; /* polling/interrupt service for rspq */
354 unsigned int lro; /* large receive offload */
354 unsigned int coalesce_usecs; /* irq coalescing timer */ 355 unsigned int coalesce_usecs; /* irq coalescing timer */
355 unsigned int rspq_size; /* # of entries in response queue */ 356 unsigned int rspq_size; /* # of entries in response queue */
356 unsigned int fl_size; /* # of entries in regular free list */ 357 unsigned int fl_size; /* # of entries in regular free list */
diff --git a/drivers/net/cxgb3/cxgb3_ioctl.h b/drivers/net/cxgb3/cxgb3_ioctl.h
index 0a82fcddf2d8..68200a14065e 100644
--- a/drivers/net/cxgb3/cxgb3_ioctl.h
+++ b/drivers/net/cxgb3/cxgb3_ioctl.h
@@ -90,6 +90,7 @@ struct ch_qset_params {
90 int32_t fl_size[2]; 90 int32_t fl_size[2];
91 int32_t intr_lat; 91 int32_t intr_lat;
92 int32_t polling; 92 int32_t polling;
93 int32_t lro;
93 int32_t cong_thres; 94 int32_t cong_thres;
94}; 95};
95 96
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 3a3127216791..5447f3e60f07 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1212,6 +1212,9 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
1212 "VLANinsertions ", 1212 "VLANinsertions ",
1213 "TxCsumOffload ", 1213 "TxCsumOffload ",
1214 "RxCsumGood ", 1214 "RxCsumGood ",
1215 "LroAggregated ",
1216 "LroFlushed ",
1217 "LroNoDesc ",
1215 "RxDrops ", 1218 "RxDrops ",
1216 1219
1217 "CheckTXEnToggled ", 1220 "CheckTXEnToggled ",
@@ -1340,6 +1343,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
1340 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS); 1343 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS);
1341 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); 1344 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
1342 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); 1345 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
1346 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_AGGR);
1347 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_FLUSHED);
1348 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_NO_DESC);
1343 *data++ = s->rx_cong_drops; 1349 *data++ = s->rx_cong_drops;
1344 1350
1345 *data++ = s->num_toggled; 1351 *data++ = s->num_toggled;
@@ -1558,6 +1564,13 @@ static int set_rx_csum(struct net_device *dev, u32 data)
1558 struct port_info *p = netdev_priv(dev); 1564 struct port_info *p = netdev_priv(dev);
1559 1565
1560 p->rx_csum_offload = data; 1566 p->rx_csum_offload = data;
1567 if (!data) {
1568 struct adapter *adap = p->adapter;
1569 int i;
1570
1571 for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
1572 adap->sge.qs[i].lro_enabled = 0;
1573 }
1561 return 0; 1574 return 0;
1562} 1575}
1563 1576
@@ -1830,6 +1843,11 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
1830 } 1843 }
1831 } 1844 }
1832 } 1845 }
1846 if (t.lro >= 0) {
1847 struct sge_qset *qs = &adapter->sge.qs[t.qset_idx];
1848 q->lro = t.lro;
1849 qs->lro_enabled = t.lro;
1850 }
1833 break; 1851 break;
1834 } 1852 }
1835 case CHELSIO_GET_QSET_PARAMS:{ 1853 case CHELSIO_GET_QSET_PARAMS:{
@@ -1849,6 +1867,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
1849 t.fl_size[0] = q->fl_size; 1867 t.fl_size[0] = q->fl_size;
1850 t.fl_size[1] = q->jumbo_size; 1868 t.fl_size[1] = q->jumbo_size;
1851 t.polling = q->polling; 1869 t.polling = q->polling;
1870 t.lro = q->lro;
1852 t.intr_lat = q->coalesce_usecs; 1871 t.intr_lat = q->coalesce_usecs;
1853 t.cong_thres = q->cong_thres; 1872 t.cong_thres = q->cong_thres;
1854 1873
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 3e91be55e19e..a96331c875e6 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -584,6 +584,8 @@ static void t3_reset_qset(struct sge_qset *q)
584 memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); 584 memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
585 q->txq_stopped = 0; 585 q->txq_stopped = 0;
586 memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); 586 memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer));
587 kfree(q->lro_frag_tbl);
588 q->lro_nfrags = q->lro_frag_len = 0;
587} 589}
588 590
589 591
@@ -796,7 +798,7 @@ recycle:
796 goto recycle; 798 goto recycle;
797 799
798 if (!skb) 800 if (!skb)
799 newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); 801 newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
800 if (unlikely(!newskb)) { 802 if (unlikely(!newskb)) {
801 if (!drop_thres) 803 if (!drop_thres)
802 return NULL; 804 return NULL;
@@ -1868,9 +1870,10 @@ static void restart_tx(struct sge_qset *qs)
1868 * if it was immediate data in a response. 1870 * if it was immediate data in a response.
1869 */ 1871 */
1870static void rx_eth(struct adapter *adap, struct sge_rspq *rq, 1872static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
1871 struct sk_buff *skb, int pad) 1873 struct sk_buff *skb, int pad, int lro)
1872{ 1874{
1873 struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); 1875 struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad);
1876 struct sge_qset *qs = rspq_to_qset(rq);
1874 struct port_info *pi; 1877 struct port_info *pi;
1875 1878
1876 skb_pull(skb, sizeof(*p) + pad); 1879 skb_pull(skb, sizeof(*p) + pad);
@@ -1887,18 +1890,202 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
1887 if (unlikely(p->vlan_valid)) { 1890 if (unlikely(p->vlan_valid)) {
1888 struct vlan_group *grp = pi->vlan_grp; 1891 struct vlan_group *grp = pi->vlan_grp;
1889 1892
1890 rspq_to_qset(rq)->port_stats[SGE_PSTAT_VLANEX]++; 1893 qs->port_stats[SGE_PSTAT_VLANEX]++;
1891 if (likely(grp)) 1894 if (likely(grp))
1892 __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), 1895 if (lro)
1893 rq->polling); 1896 lro_vlan_hwaccel_receive_skb(&qs->lro_mgr, skb,
1897 grp,
1898 ntohs(p->vlan),
1899 p);
1900 else
1901 __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
1902 rq->polling);
1894 else 1903 else
1895 dev_kfree_skb_any(skb); 1904 dev_kfree_skb_any(skb);
1896 } else if (rq->polling) 1905 } else if (rq->polling) {
1897 netif_receive_skb(skb); 1906 if (lro)
1898 else 1907 lro_receive_skb(&qs->lro_mgr, skb, p);
1908 else
1909 netif_receive_skb(skb);
1910 } else
1899 netif_rx(skb); 1911 netif_rx(skb);
1900} 1912}
1901 1913
1914static inline int is_eth_tcp(u32 rss)
1915{
1916 return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE;
1917}
1918
1919/**
1920 * lro_frame_ok - check if an ingress packet is eligible for LRO
1921 * @p: the CPL header of the packet
1922 *
1923 * Returns true if a received packet is eligible for LRO.
1924 * The following conditions must be true:
1925 * - packet is TCP/IP Ethernet II (checked elsewhere)
1926 * - not an IP fragment
1927 * - no IP options
1928 * - TCP/IP checksums are correct
1929 * - the packet is for this host
1930 */
1931static inline int lro_frame_ok(const struct cpl_rx_pkt *p)
1932{
1933 const struct ethhdr *eh = (struct ethhdr *)(p + 1);
1934 const struct iphdr *ih = (struct iphdr *)(eh + 1);
1935
1936 return (*((u8 *)p + 1) & 0x90) == 0x10 && p->csum == htons(0xffff) &&
1937 eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2);
1938}
1939
1940#define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\
1941 TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\
1942 TCP_FLAG_SYN | TCP_FLAG_FIN)
1943#define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\
1944 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)
1945
1946/**
1947 * lro_segment_ok - check if a TCP segment is eligible for LRO
1948 * @tcph: the TCP header of the packet
1949 *
1950 * Returns true if a TCP packet is eligible for LRO. This requires that
1951 * the packet have only the ACK flag set and no TCP options besides
1952 * time stamps.
1953 */
1954static inline int lro_segment_ok(const struct tcphdr *tcph)
1955{
1956 int optlen;
1957
1958 if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK))
1959 return 0;
1960
1961 optlen = (tcph->doff << 2) - sizeof(*tcph);
1962 if (optlen) {
1963 const u32 *opt = (const u32 *)(tcph + 1);
1964
1965 if (optlen != TCPOLEN_TSTAMP_ALIGNED ||
1966 *opt != htonl(TSTAMP_WORD) || !opt[2])
1967 return 0;
1968 }
1969 return 1;
1970}
1971
1972static int t3_get_lro_header(void **eh, void **iph, void **tcph,
1973 u64 *hdr_flags, void *priv)
1974{
1975 const struct cpl_rx_pkt *cpl = priv;
1976
1977 if (!lro_frame_ok(cpl))
1978 return -1;
1979
1980 *eh = (struct ethhdr *)(cpl + 1);
1981 *iph = (struct iphdr *)((struct ethhdr *)*eh + 1);
1982 *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1);
1983
1984 if (!lro_segment_ok(*tcph))
1985 return -1;
1986
1987 *hdr_flags = LRO_IPV4 | LRO_TCP;
1988 return 0;
1989}
1990
1991static int t3_get_skb_header(struct sk_buff *skb,
1992 void **iph, void **tcph, u64 *hdr_flags,
1993 void *priv)
1994{
1995 void *eh;
1996
1997 return t3_get_lro_header(&eh, iph, tcph, hdr_flags, priv);
1998}
1999
2000static int t3_get_frag_header(struct skb_frag_struct *frag, void **eh,
2001 void **iph, void **tcph, u64 *hdr_flags,
2002 void *priv)
2003{
2004 return t3_get_lro_header(eh, iph, tcph, hdr_flags, priv);
2005}
2006
2007/**
2008 * lro_add_page - add a page chunk to an LRO session
2009 * @adap: the adapter
2010 * @qs: the associated queue set
2011 * @fl: the free list containing the page chunk to add
2012 * @len: packet length
2013 * @complete: Indicates the last fragment of a frame
2014 *
2015 * Add a received packet contained in a page chunk to an existing LRO
2016 * session.
2017 */
2018static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
2019 struct sge_fl *fl, int len, int complete)
2020{
2021 struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
2022 struct cpl_rx_pkt *cpl;
2023 struct skb_frag_struct *rx_frag = qs->lro_frag_tbl;
2024 int nr_frags = qs->lro_nfrags, frag_len = qs->lro_frag_len;
2025 int offset = 0;
2026
2027 if (!nr_frags) {
2028 offset = 2 + sizeof(struct cpl_rx_pkt);
2029 qs->lro_va = cpl = sd->pg_chunk.va + 2;
2030 }
2031
2032 fl->credits--;
2033
2034 len -= offset;
2035 pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
2036 fl->buf_size, PCI_DMA_FROMDEVICE);
2037
2038 rx_frag += nr_frags;
2039 rx_frag->page = sd->pg_chunk.page;
2040 rx_frag->page_offset = sd->pg_chunk.offset + offset;
2041 rx_frag->size = len;
2042 frag_len += len;
2043 qs->lro_nfrags++;
2044 qs->lro_frag_len = frag_len;
2045
2046 if (!complete)
2047 return;
2048
2049 qs->lro_nfrags = qs->lro_frag_len = 0;
2050 cpl = qs->lro_va;
2051
2052 if (unlikely(cpl->vlan_valid)) {
2053 struct net_device *dev = qs->netdev;
2054 struct port_info *pi = netdev_priv(dev);
2055 struct vlan_group *grp = pi->vlan_grp;
2056
2057 if (likely(grp != NULL)) {
2058 lro_vlan_hwaccel_receive_frags(&qs->lro_mgr,
2059 qs->lro_frag_tbl,
2060 frag_len, frag_len,
2061 grp, ntohs(cpl->vlan),
2062 cpl, 0);
2063 return;
2064 }
2065 }
2066 lro_receive_frags(&qs->lro_mgr, qs->lro_frag_tbl,
2067 frag_len, frag_len, cpl, 0);
2068}
2069
2070/**
2071 * init_lro_mgr - initialize a LRO manager object
2072 * @lro_mgr: the LRO manager object
2073 */
2074static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr)
2075{
2076 lro_mgr->dev = qs->netdev;
2077 lro_mgr->features = LRO_F_NAPI;
2078 lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
2079 lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
2080 lro_mgr->max_desc = T3_MAX_LRO_SES;
2081 lro_mgr->lro_arr = qs->lro_desc;
2082 lro_mgr->get_frag_header = t3_get_frag_header;
2083 lro_mgr->get_skb_header = t3_get_skb_header;
2084 lro_mgr->max_aggr = T3_MAX_LRO_MAX_PKTS;
2085 if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
2086 lro_mgr->max_aggr = MAX_SKB_FRAGS;
2087}
2088
1902/** 2089/**
1903 * handle_rsp_cntrl_info - handles control information in a response 2090 * handle_rsp_cntrl_info - handles control information in a response
1904 * @qs: the queue set corresponding to the response 2091 * @qs: the queue set corresponding to the response
@@ -2027,7 +2214,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
2027 q->next_holdoff = q->holdoff_tmr; 2214 q->next_holdoff = q->holdoff_tmr;
2028 2215
2029 while (likely(budget_left && is_new_response(r, q))) { 2216 while (likely(budget_left && is_new_response(r, q))) {
2030 int packet_complete, eth, ethpad = 2; 2217 int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled;
2031 struct sk_buff *skb = NULL; 2218 struct sk_buff *skb = NULL;
2032 u32 len, flags = ntohl(r->flags); 2219 u32 len, flags = ntohl(r->flags);
2033 __be32 rss_hi = *(const __be32 *)r, 2220 __be32 rss_hi = *(const __be32 *)r,
@@ -2059,6 +2246,9 @@ no_mem:
2059 } else if ((len = ntohl(r->len_cq)) != 0) { 2246 } else if ((len = ntohl(r->len_cq)) != 0) {
2060 struct sge_fl *fl; 2247 struct sge_fl *fl;
2061 2248
2249 if (eth)
2250 lro = qs->lro_enabled && is_eth_tcp(rss_hi);
2251
2062 fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; 2252 fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
2063 if (fl->use_pages) { 2253 if (fl->use_pages) {
2064 void *addr = fl->sdesc[fl->cidx].pg_chunk.va; 2254 void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
@@ -2068,6 +2258,12 @@ no_mem:
2068 prefetch(addr + L1_CACHE_BYTES); 2258 prefetch(addr + L1_CACHE_BYTES);
2069#endif 2259#endif
2070 __refill_fl(adap, fl); 2260 __refill_fl(adap, fl);
2261 if (lro > 0) {
2262 lro_add_page(adap, qs, fl,
2263 G_RSPD_LEN(len),
2264 flags & F_RSPD_EOP);
2265 goto next_fl;
2266 }
2071 2267
2072 skb = get_packet_pg(adap, fl, q, 2268 skb = get_packet_pg(adap, fl, q,
2073 G_RSPD_LEN(len), 2269 G_RSPD_LEN(len),
@@ -2083,7 +2279,7 @@ no_mem:
2083 q->rx_drops++; 2279 q->rx_drops++;
2084 } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) 2280 } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
2085 __skb_pull(skb, 2); 2281 __skb_pull(skb, 2);
2086 2282next_fl:
2087 if (++fl->cidx == fl->size) 2283 if (++fl->cidx == fl->size)
2088 fl->cidx = 0; 2284 fl->cidx = 0;
2089 } else 2285 } else
@@ -2113,7 +2309,7 @@ no_mem:
2113 2309
2114 if (skb != NULL && packet_complete) { 2310 if (skb != NULL && packet_complete) {
2115 if (eth) 2311 if (eth)
2116 rx_eth(adap, q, skb, ethpad); 2312 rx_eth(adap, q, skb, ethpad, lro);
2117 else { 2313 else {
2118 q->offload_pkts++; 2314 q->offload_pkts++;
2119 /* Preserve the RSS info in csum & priority */ 2315 /* Preserve the RSS info in csum & priority */
@@ -2125,12 +2321,17 @@ no_mem:
2125 } 2321 }
2126 2322
2127 if (flags & F_RSPD_EOP) 2323 if (flags & F_RSPD_EOP)
2128 clear_rspq_bufstate(q); 2324 clear_rspq_bufstate(q);
2129 } 2325 }
2130 --budget_left; 2326 --budget_left;
2131 } 2327 }
2132 2328
2133 deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); 2329 deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
2330 lro_flush_all(&qs->lro_mgr);
2331 qs->port_stats[SGE_PSTAT_LRO_AGGR] = qs->lro_mgr.stats.aggregated;
2332 qs->port_stats[SGE_PSTAT_LRO_FLUSHED] = qs->lro_mgr.stats.flushed;
2333 qs->port_stats[SGE_PSTAT_LRO_NO_DESC] = qs->lro_mgr.stats.no_desc;
2334
2134 if (sleeping) 2335 if (sleeping)
2135 check_ring_db(adap, qs, sleeping); 2336 check_ring_db(adap, qs, sleeping);
2136 2337
@@ -2674,6 +2875,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
2674{ 2875{
2675 int i, avail, ret = -ENOMEM; 2876 int i, avail, ret = -ENOMEM;
2676 struct sge_qset *q = &adapter->sge.qs[id]; 2877 struct sge_qset *q = &adapter->sge.qs[id];
2878 struct net_lro_mgr *lro_mgr = &q->lro_mgr;
2677 2879
2678 init_qset_cntxt(q, id); 2880 init_qset_cntxt(q, id);
2679 init_timer(&q->tx_reclaim_timer); 2881 init_timer(&q->tx_reclaim_timer);
@@ -2754,6 +2956,10 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
2754 q->fl[0].order = FL0_PG_ORDER; 2956 q->fl[0].order = FL0_PG_ORDER;
2755 q->fl[1].order = FL1_PG_ORDER; 2957 q->fl[1].order = FL1_PG_ORDER;
2756 2958
2959 q->lro_frag_tbl = kcalloc(MAX_FRAME_SIZE / FL1_PG_CHUNK_SIZE + 1,
2960 sizeof(struct skb_frag_struct),
2961 GFP_KERNEL);
2962 q->lro_nfrags = q->lro_frag_len = 0;
2757 spin_lock_irq(&adapter->sge.reg_lock); 2963 spin_lock_irq(&adapter->sge.reg_lock);
2758 2964
2759 /* FL threshold comparison uses < */ 2965 /* FL threshold comparison uses < */
@@ -2803,6 +3009,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
2803 q->adap = adapter; 3009 q->adap = adapter;
2804 q->netdev = dev; 3010 q->netdev = dev;
2805 t3_update_qset_coalesce(q, p); 3011 t3_update_qset_coalesce(q, p);
3012
3013 init_lro_mgr(q, lro_mgr);
3014
2806 avail = refill_fl(adapter, &q->fl[0], q->fl[0].size, 3015 avail = refill_fl(adapter, &q->fl[0], q->fl[0].size,
2807 GFP_KERNEL | __GFP_COMP); 3016 GFP_KERNEL | __GFP_COMP);
2808 if (!avail) { 3017 if (!avail) {
diff --git a/drivers/net/cxgb3/t3_cpl.h b/drivers/net/cxgb3/t3_cpl.h
index b7a1a310dfd4..a666c5d51cc0 100644
--- a/drivers/net/cxgb3/t3_cpl.h
+++ b/drivers/net/cxgb3/t3_cpl.h
@@ -174,6 +174,13 @@ enum { /* TCP congestion control algorithms */
174 CONG_ALG_HIGHSPEED 174 CONG_ALG_HIGHSPEED
175}; 175};
176 176
177enum { /* RSS hash type */
178 RSS_HASH_NONE = 0,
179 RSS_HASH_2_TUPLE = 1,
180 RSS_HASH_4_TUPLE = 2,
181 RSS_HASH_TCPV6 = 3
182};
183
177union opcode_tid { 184union opcode_tid {
178 __be32 opcode_tid; 185 __be32 opcode_tid;
179 __u8 opcode; 186 __u8 opcode;
@@ -184,6 +191,10 @@ union opcode_tid {
184#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF) 191#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF)
185#define G_TID(x) ((x) & 0xFFFFFF) 192#define G_TID(x) ((x) & 0xFFFFFF)
186 193
194#define S_HASHTYPE 22
195#define M_HASHTYPE 0x3
196#define G_HASHTYPE(x) (((x) >> S_HASHTYPE) & M_HASHTYPE)
197
187/* tid is assumed to be 24-bits */ 198/* tid is assumed to be 24-bits */
188#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid)) 199#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid))
189 200