aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAndrew Gallatin <gallatin@myri.com>2007-09-17 14:37:42 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:47 -0400
commit1e6e9342d41ff80ced0ad5dfcf084926700cdfc5 (patch)
treef4890526db54f9c8821e2d3e366d116d44b1712a /drivers/net
parentd4dc4ec9d84e0578b9bfbe56a11fafdb7cbac771 (diff)
[MYRI10GE]: Use LRO.
Singed off by: Andrew Gallatin <gallatin@myri.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/myri10ge/myri10ge.c109
2 files changed, 109 insertions, 1 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 61dedfeed62a..40ff9a5269a2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2583,6 +2583,7 @@ config MYRI10GE
2583 depends on PCI 2583 depends on PCI
2584 select FW_LOADER 2584 select FW_LOADER
2585 select CRC32 2585 select CRC32
2586 select INET_LRO
2586 ---help--- 2587 ---help---
2587 This driver supports Myricom Myri-10G Dual Protocol interface in 2588 This driver supports Myricom Myri-10G Dual Protocol interface in
2588 Ethernet mode. If the eeprom on your board is not recent enough, 2589 Ethernet mode. If the eeprom on your board is not recent enough,
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index a30146ea51f0..48b23c592406 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -48,6 +48,7 @@
48#include <linux/etherdevice.h> 48#include <linux/etherdevice.h>
49#include <linux/if_ether.h> 49#include <linux/if_ether.h>
50#include <linux/if_vlan.h> 50#include <linux/if_vlan.h>
51#include <linux/inet_lro.h>
51#include <linux/ip.h> 52#include <linux/ip.h>
52#include <linux/inet.h> 53#include <linux/inet.h>
53#include <linux/in.h> 54#include <linux/in.h>
@@ -62,6 +63,8 @@
62#include <linux/io.h> 63#include <linux/io.h>
63#include <linux/log2.h> 64#include <linux/log2.h>
64#include <net/checksum.h> 65#include <net/checksum.h>
66#include <net/ip.h>
67#include <net/tcp.h>
65#include <asm/byteorder.h> 68#include <asm/byteorder.h>
66#include <asm/io.h> 69#include <asm/io.h>
67#include <asm/processor.h> 70#include <asm/processor.h>
@@ -89,6 +92,8 @@ MODULE_LICENSE("Dual BSD/GPL");
89 92
90#define MYRI10GE_EEPROM_STRINGS_SIZE 256 93#define MYRI10GE_EEPROM_STRINGS_SIZE 256
91#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) 94#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
95#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
96#define MYRI10GE_LRO_MAX_PKTS 64
92 97
93#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) 98#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
94#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff 99#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
@@ -151,6 +156,8 @@ struct myri10ge_rx_done {
151 dma_addr_t bus; 156 dma_addr_t bus;
152 int cnt; 157 int cnt;
153 int idx; 158 int idx;
159 struct net_lro_mgr lro_mgr;
160 struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
154}; 161};
155 162
156struct myri10ge_priv { 163struct myri10ge_priv {
@@ -278,6 +285,14 @@ static int myri10ge_debug = -1; /* defaults above */
278module_param(myri10ge_debug, int, 0); 285module_param(myri10ge_debug, int, 0);
279MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); 286MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
280 287
288static int myri10ge_lro = 1;
289module_param(myri10ge_lro, int, S_IRUGO);
290MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload\n");
291
292static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
293module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
294MODULE_PARM_DESC(myri10ge_lro, "Number of LRO packets to be aggregated\n");
295
281static int myri10ge_fill_thresh = 256; 296static int myri10ge_fill_thresh = 256;
282module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); 297module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
283MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); 298MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
@@ -1021,6 +1036,15 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
1021 remainder -= MYRI10GE_ALLOC_SIZE; 1036 remainder -= MYRI10GE_ALLOC_SIZE;
1022 } 1037 }
1023 1038
1039 if (mgp->csum_flag && myri10ge_lro) {
1040 rx_frags[0].page_offset += MXGEFW_PAD;
1041 rx_frags[0].size -= MXGEFW_PAD;
1042 len -= MXGEFW_PAD;
1043 lro_receive_frags(&mgp->rx_done.lro_mgr, rx_frags,
1044 len, len, (void *)(unsigned long)csum, csum);
1045 return 1;
1046 }
1047
1024 hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; 1048 hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
1025 1049
1026 /* allocate an skb to attach the page(s) to. */ 1050 /* allocate an skb to attach the page(s) to. */
@@ -1136,6 +1160,9 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget)
1136 mgp->stats.rx_packets += rx_packets; 1160 mgp->stats.rx_packets += rx_packets;
1137 mgp->stats.rx_bytes += rx_bytes; 1161 mgp->stats.rx_bytes += rx_bytes;
1138 1162
1163 if (myri10ge_lro)
1164 lro_flush_all(&rx_done->lro_mgr);
1165
1139 /* restock receive rings if needed */ 1166 /* restock receive rings if needed */
1140 if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) 1167 if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh)
1141 myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, 1168 myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
@@ -1373,7 +1400,8 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
1373 "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32", 1400 "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32",
1374 "dropped_unicast_filtered", "dropped_multicast_filtered", 1401 "dropped_unicast_filtered", "dropped_multicast_filtered",
1375 "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", 1402 "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
1376 "dropped_no_big_buffer" 1403 "dropped_no_big_buffer", "LRO aggregated", "LRO flushed",
1404 "LRO avg aggr", "LRO no_desc"
1377}; 1405};
1378 1406
1379#define MYRI10GE_NET_STATS_LEN 21 1407#define MYRI10GE_NET_STATS_LEN 21
@@ -1439,6 +1467,14 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
1439 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun); 1467 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
1440 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer); 1468 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
1441 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer); 1469 data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
1470 data[i++] = mgp->rx_done.lro_mgr.stats.aggregated;
1471 data[i++] = mgp->rx_done.lro_mgr.stats.flushed;
1472 if (mgp->rx_done.lro_mgr.stats.flushed)
1473 data[i++] = mgp->rx_done.lro_mgr.stats.aggregated /
1474 mgp->rx_done.lro_mgr.stats.flushed;
1475 else
1476 data[i++] = 0;
1477 data[i++] = mgp->rx_done.lro_mgr.stats.no_desc;
1442} 1478}
1443 1479
1444static void myri10ge_set_msglevel(struct net_device *netdev, u32 value) 1480static void myri10ge_set_msglevel(struct net_device *netdev, u32 value)
@@ -1712,10 +1748,69 @@ static void myri10ge_free_irq(struct myri10ge_priv *mgp)
1712 pci_disable_msi(pdev); 1748 pci_disable_msi(pdev);
1713} 1749}
1714 1750
1751static int
1752myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
1753 void **ip_hdr, void **tcpudp_hdr,
1754 u64 * hdr_flags, void *priv)
1755{
1756 struct ethhdr *eh;
1757 struct vlan_ethhdr *veh;
1758 struct iphdr *iph;
1759 u8 *va = page_address(frag->page) + frag->page_offset;
1760 unsigned long ll_hlen;
1761 __wsum csum = (__wsum) (unsigned long)priv;
1762
1763 /* find the mac header, aborting if not IPv4 */
1764
1765 eh = (struct ethhdr *)va;
1766 *mac_hdr = eh;
1767 ll_hlen = ETH_HLEN;
1768 if (eh->h_proto != htons(ETH_P_IP)) {
1769 if (eh->h_proto == htons(ETH_P_8021Q)) {
1770 veh = (struct vlan_ethhdr *)va;
1771 if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
1772 return -1;
1773
1774 ll_hlen += VLAN_HLEN;
1775
1776 /*
1777 * HW checksum starts ETH_HLEN bytes into
1778 * frame, so we must subtract off the VLAN
1779 * header's checksum before csum can be used
1780 */
1781 csum = csum_sub(csum, csum_partial(va + ETH_HLEN,
1782 VLAN_HLEN, 0));
1783 } else {
1784 return -1;
1785 }
1786 }
1787 *hdr_flags = LRO_IPV4;
1788
1789 iph = (struct iphdr *)(va + ll_hlen);
1790 *ip_hdr = iph;
1791 if (iph->protocol != IPPROTO_TCP)
1792 return -1;
1793 *hdr_flags |= LRO_TCP;
1794 *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
1795
1796 /* verify the IP checksum */
1797 if (unlikely(ip_fast_csum((u8 *) iph, iph->ihl)))
1798 return -1;
1799
1800 /* verify the checksum */
1801 if (unlikely(csum_tcpudp_magic(iph->saddr, iph->daddr,
1802 ntohs(iph->tot_len) - (iph->ihl << 2),
1803 IPPROTO_TCP, csum)))
1804 return -1;
1805
1806 return 0;
1807}
1808
1715static int myri10ge_open(struct net_device *dev) 1809static int myri10ge_open(struct net_device *dev)
1716{ 1810{
1717 struct myri10ge_priv *mgp; 1811 struct myri10ge_priv *mgp;
1718 struct myri10ge_cmd cmd; 1812 struct myri10ge_cmd cmd;
1813 struct net_lro_mgr *lro_mgr;
1719 int status, big_pow2; 1814 int status, big_pow2;
1720 1815
1721 mgp = netdev_priv(dev); 1816 mgp = netdev_priv(dev);
@@ -1847,6 +1942,18 @@ static int myri10ge_open(struct net_device *dev)
1847 mgp->link_state = htonl(~0U); 1942 mgp->link_state = htonl(~0U);
1848 mgp->rdma_tags_available = 15; 1943 mgp->rdma_tags_available = 15;
1849 1944
1945 lro_mgr = &mgp->rx_done.lro_mgr;
1946 lro_mgr->dev = dev;
1947 lro_mgr->features = LRO_F_NAPI;
1948 lro_mgr->ip_summed = CHECKSUM_COMPLETE;
1949 lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
1950 lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
1951 lro_mgr->lro_arr = mgp->rx_done.lro_desc;
1952 lro_mgr->get_frag_header = myri10ge_get_frag_header;
1953 lro_mgr->max_aggr = myri10ge_lro_max_pkts;
1954 if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
1955 lro_mgr->max_aggr = MAX_SKB_FRAGS;
1956
1850 napi_enable(&mgp->napi); /* must happen prior to any irq */ 1957 napi_enable(&mgp->napi); /* must happen prior to any irq */
1851 1958
1852 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); 1959 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);