aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igb
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-07-08 18:12:13 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-07-11 01:20:32 -0400
commitd3352520273426e4c16e91d189aa8aa7ee5e96c5 (patch)
tree963c396cdc698b853acfe100080efbe41719013e /drivers/net/igb
parentbf36c1a0040cc6ccd63cdd1cec25d2085f2df964 (diff)
igb: add support for in kernel LRO
This patch adds support for the use of the inet_lro module to provide software LRO support. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/igb')
-rw-r--r--drivers/net/igb/e1000_82575.h2
-rw-r--r--drivers/net/igb/igb.h16
-rw-r--r--drivers/net/igb/igb_ethtool.c17
-rw-r--r--drivers/net/igb/igb_main.c112
4 files changed, 138 insertions, 9 deletions
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index d273236c7764..2f848e578a24 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -99,6 +99,8 @@ union e1000_adv_rx_desc {
99/* RSS Hash results */ 99/* RSS Hash results */
100 100
101/* RSS Packet Types as indicated in the receive descriptor */ 101/* RSS Packet Types as indicated in the receive descriptor */
102#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
103#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */
102 104
103/* Transmit Descriptor - Advanced */ 105/* Transmit Descriptor - Advanced */
104union e1000_adv_tx_desc { 106union e1000_adv_tx_desc {
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index f41b9996d2ed..c25ca17d3228 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -36,6 +36,12 @@
36 36
37struct igb_adapter; 37struct igb_adapter;
38 38
39#ifdef CONFIG_IGB_LRO
40#include <linux/inet_lro.h>
41#define MAX_LRO_AGGR 32
42#define MAX_LRO_DESCRIPTORS 8
43#endif
44
39/* Interrupt defines */ 45/* Interrupt defines */
40#define IGB_MAX_TX_CLEAN 72 46#define IGB_MAX_TX_CLEAN 72
41 47
@@ -167,6 +173,10 @@ struct igb_ring {
167 int no_itr_adjust; 173 int no_itr_adjust;
168 struct igb_queue_stats rx_stats; 174 struct igb_queue_stats rx_stats;
169 struct napi_struct napi; 175 struct napi_struct napi;
176#ifdef CONFIG_IGB_LRO
177 struct net_lro_mgr lro_mgr;
178 bool lro_used;
179#endif
170 }; 180 };
171 }; 181 };
172 182
@@ -278,6 +288,12 @@ struct igb_adapter {
278#ifdef CONFIG_NETDEVICES_MULTIQUEUE 288#ifdef CONFIG_NETDEVICES_MULTIQUEUE
279 struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; 289 struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES];
280#endif /* CONFIG_NETDEVICES_MULTIQUEUE */ 290#endif /* CONFIG_NETDEVICES_MULTIQUEUE */
291#ifdef CONFIG_IGB_LRO
292 unsigned int lro_max_aggr;
293 unsigned int lro_aggregated;
294 unsigned int lro_flushed;
295 unsigned int lro_no_desc;
296#endif
281}; 297};
282 298
283#define IGB_FLAG_HAS_MSI (1 << 0) 299#define IGB_FLAG_HAS_MSI (1 << 0)
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index ef209b5cd390..7db183093768 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -93,6 +93,11 @@ static const struct igb_stats igb_gstrings_stats[] = {
93 { "tx_smbus", IGB_STAT(stats.mgptc) }, 93 { "tx_smbus", IGB_STAT(stats.mgptc) },
94 { "rx_smbus", IGB_STAT(stats.mgprc) }, 94 { "rx_smbus", IGB_STAT(stats.mgprc) },
95 { "dropped_smbus", IGB_STAT(stats.mgpdc) }, 95 { "dropped_smbus", IGB_STAT(stats.mgpdc) },
96#ifdef CONFIG_IGB_LRO
97 { "lro_aggregated", IGB_STAT(lro_aggregated) },
98 { "lro_flushed", IGB_STAT(lro_flushed) },
99 { "lro_no_desc", IGB_STAT(lro_no_desc) },
100#endif
96}; 101};
97 102
98#define IGB_QUEUE_STATS_LEN \ 103#define IGB_QUEUE_STATS_LEN \
@@ -1917,6 +1922,18 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
1917 int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64); 1922 int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64);
1918 int j; 1923 int j;
1919 int i; 1924 int i;
1925#ifdef CONFIG_IGB_LRO
1926 int aggregated = 0, flushed = 0, no_desc = 0;
1927
1928 for (i = 0; i < adapter->num_rx_queues; i++) {
1929 aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated;
1930 flushed += adapter->rx_ring[i].lro_mgr.stats.flushed;
1931 no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc;
1932 }
1933 adapter->lro_aggregated = aggregated;
1934 adapter->lro_flushed = flushed;
1935 adapter->lro_no_desc = no_desc;
1936#endif
1920 1937
1921 igb_update_stats(adapter); 1938 igb_update_stats(adapter);
1922 for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { 1939 for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 660a78653287..89416ebda9ef 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -116,6 +116,9 @@ static bool igb_clean_tx_irq(struct igb_ring *);
116static int igb_poll(struct napi_struct *, int); 116static int igb_poll(struct napi_struct *, int);
117static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int); 117static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int);
118static void igb_alloc_rx_buffers_adv(struct igb_ring *, int); 118static void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
119#ifdef CONFIG_IGB_LRO
120static int igb_get_skb_hdr(struct sk_buff *skb, void **, void **, u64 *, void *);
121#endif
119static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); 122static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
120static void igb_tx_timeout(struct net_device *); 123static void igb_tx_timeout(struct net_device *);
121static void igb_reset_task(struct work_struct *); 124static void igb_reset_task(struct work_struct *);
@@ -1134,6 +1137,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
1134 netdev->features |= NETIF_F_TSO; 1137 netdev->features |= NETIF_F_TSO;
1135 netdev->features |= NETIF_F_TSO6; 1138 netdev->features |= NETIF_F_TSO6;
1136 1139
1140#ifdef CONFIG_IGB_LRO
1141 netdev->features |= NETIF_F_LRO;
1142#endif
1143
1137 netdev->vlan_features |= NETIF_F_TSO; 1144 netdev->vlan_features |= NETIF_F_TSO;
1138 netdev->vlan_features |= NETIF_F_TSO6; 1145 netdev->vlan_features |= NETIF_F_TSO6;
1139 netdev->vlan_features |= NETIF_F_HW_CSUM; 1146 netdev->vlan_features |= NETIF_F_HW_CSUM;
@@ -1705,6 +1712,14 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
1705 struct pci_dev *pdev = adapter->pdev; 1712 struct pci_dev *pdev = adapter->pdev;
1706 int size, desc_len; 1713 int size, desc_len;
1707 1714
1715#ifdef CONFIG_IGB_LRO
1716 size = sizeof(struct net_lro_desc) * MAX_LRO_DESCRIPTORS;
1717 rx_ring->lro_mgr.lro_arr = vmalloc(size);
1718 if (!rx_ring->lro_mgr.lro_arr)
1719 goto err;
1720 memset(rx_ring->lro_mgr.lro_arr, 0, size);
1721#endif
1722
1708 size = sizeof(struct igb_buffer) * rx_ring->count; 1723 size = sizeof(struct igb_buffer) * rx_ring->count;
1709 rx_ring->buffer_info = vmalloc(size); 1724 rx_ring->buffer_info = vmalloc(size);
1710 if (!rx_ring->buffer_info) 1725 if (!rx_ring->buffer_info)
@@ -1731,6 +1746,10 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
1731 return 0; 1746 return 0;
1732 1747
1733err: 1748err:
1749#ifdef CONFIG_IGB_LRO
1750 vfree(rx_ring->lro_mgr.lro_arr);
1751 rx_ring->lro_mgr.lro_arr = NULL;
1752#endif
1734 vfree(rx_ring->buffer_info); 1753 vfree(rx_ring->buffer_info);
1735 dev_err(&adapter->pdev->dev, "Unable to allocate memory for " 1754 dev_err(&adapter->pdev->dev, "Unable to allocate memory for "
1736 "the receive descriptor ring\n"); 1755 "the receive descriptor ring\n");
@@ -1894,6 +1913,16 @@ static void igb_configure_rx(struct igb_adapter *adapter)
1894 rxdctl |= IGB_RX_HTHRESH << 8; 1913 rxdctl |= IGB_RX_HTHRESH << 8;
1895 rxdctl |= IGB_RX_WTHRESH << 16; 1914 rxdctl |= IGB_RX_WTHRESH << 16;
1896 wr32(E1000_RXDCTL(i), rxdctl); 1915 wr32(E1000_RXDCTL(i), rxdctl);
1916#ifdef CONFIG_IGB_LRO
1917 /* Intitial LRO Settings */
1918 ring->lro_mgr.max_aggr = MAX_LRO_AGGR;
1919 ring->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
1920 ring->lro_mgr.get_skb_header = igb_get_skb_hdr;
1921 ring->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1922 ring->lro_mgr.dev = adapter->netdev;
1923 ring->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
1924 ring->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
1925#endif
1897 } 1926 }
1898 1927
1899 if (adapter->num_rx_queues > 1) { 1928 if (adapter->num_rx_queues > 1) {
@@ -2085,6 +2114,11 @@ static void igb_free_rx_resources(struct igb_ring *rx_ring)
2085 vfree(rx_ring->buffer_info); 2114 vfree(rx_ring->buffer_info);
2086 rx_ring->buffer_info = NULL; 2115 rx_ring->buffer_info = NULL;
2087 2116
2117#ifdef CONFIG_IGB_LRO
2118 vfree(rx_ring->lro_mgr.lro_arr);
2119 rx_ring->lro_mgr.lro_arr = NULL;
2120#endif
2121
2088 pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); 2122 pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
2089 2123
2090 rx_ring->desc = NULL; 2124 rx_ring->desc = NULL;
@@ -3735,22 +3769,75 @@ done_cleaning:
3735 return retval; 3769 return retval;
3736} 3770}
3737 3771
3772#ifdef CONFIG_IGB_LRO
3773 /**
3774 * igb_get_skb_hdr - helper function for LRO header processing
3775 * @skb: pointer to sk_buff to be added to LRO packet
3776 * @iphdr: pointer to ip header structure
3777 * @tcph: pointer to tcp header structure
3778 * @hdr_flags: pointer to header flags
3779 * @priv: pointer to the receive descriptor for the current sk_buff
3780 **/
3781static int igb_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
3782 u64 *hdr_flags, void *priv)
3783{
3784 union e1000_adv_rx_desc *rx_desc = priv;
3785 u16 pkt_type = rx_desc->wb.lower.lo_dword.pkt_info &
3786 (E1000_RXDADV_PKTTYPE_IPV4 | E1000_RXDADV_PKTTYPE_TCP);
3787
3788 /* Verify that this is a valid IPv4 TCP packet */
3789 if (pkt_type != (E1000_RXDADV_PKTTYPE_IPV4 |
3790 E1000_RXDADV_PKTTYPE_TCP))
3791 return -1;
3792
3793 /* Set network headers */
3794 skb_reset_network_header(skb);
3795 skb_set_transport_header(skb, ip_hdrlen(skb));
3796 *iphdr = ip_hdr(skb);
3797 *tcph = tcp_hdr(skb);
3798 *hdr_flags = LRO_IPV4 | LRO_TCP;
3799
3800 return 0;
3801
3802}
3803#endif /* CONFIG_IGB_LRO */
3738 3804
3739/** 3805/**
3740 * igb_receive_skb - helper function to handle rx indications 3806 * igb_receive_skb - helper function to handle rx indications
3741 * @adapter: board private structure 3807 * @ring: pointer to receive ring receving this packet
3742 * @status: descriptor status field as written by hardware 3808 * @status: descriptor status field as written by hardware
3743 * @vlan: descriptor vlan field as written by hardware (no le/be conversion) 3809 * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
3744 * @skb: pointer to sk_buff to be indicated to stack 3810 * @skb: pointer to sk_buff to be indicated to stack
3745 **/ 3811 **/
3746static void igb_receive_skb(struct igb_adapter *adapter, u8 status, __le16 vlan, 3812static void igb_receive_skb(struct igb_ring *ring, u8 status,
3747 struct sk_buff *skb) 3813 union e1000_adv_rx_desc * rx_desc,
3814 struct sk_buff *skb)
3748{ 3815{
3749 if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) 3816 struct igb_adapter * adapter = ring->adapter;
3750 vlan_hwaccel_receive_skb(skb, adapter->vlgrp, 3817 bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP));
3751 le16_to_cpu(vlan)); 3818
3752 else 3819#ifdef CONFIG_IGB_LRO
3753 netif_receive_skb(skb); 3820 if (adapter->netdev->features & NETIF_F_LRO &&
3821 skb->ip_summed == CHECKSUM_UNNECESSARY) {
3822 if (vlan_extracted)
3823 lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
3824 adapter->vlgrp,
3825 le16_to_cpu(rx_desc->wb.upper.vlan),
3826 rx_desc);
3827 else
3828 lro_receive_skb(&ring->lro_mgr,skb, rx_desc);
3829 ring->lro_used = 1;
3830 } else {
3831#endif
3832 if (vlan_extracted)
3833 vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
3834 le16_to_cpu(rx_desc->wb.upper.vlan));
3835 else
3836
3837 netif_receive_skb(skb);
3838#ifdef CONFIG_IGB_LRO
3839 }
3840#endif
3754} 3841}
3755 3842
3756 3843
@@ -3883,7 +3970,7 @@ send_up:
3883 3970
3884 skb->protocol = eth_type_trans(skb, netdev); 3971 skb->protocol = eth_type_trans(skb, netdev);
3885 3972
3886 igb_receive_skb(adapter, staterr, rx_desc->wb.upper.vlan, skb); 3973 igb_receive_skb(rx_ring, staterr, rx_desc, skb);
3887 3974
3888 netdev->last_rx = jiffies; 3975 netdev->last_rx = jiffies;
3889 3976
@@ -3906,6 +3993,13 @@ next_desc:
3906 rx_ring->next_to_clean = i; 3993 rx_ring->next_to_clean = i;
3907 cleaned_count = IGB_DESC_UNUSED(rx_ring); 3994 cleaned_count = IGB_DESC_UNUSED(rx_ring);
3908 3995
3996#ifdef CONFIG_IGB_LRO
3997 if (rx_ring->lro_used) {
3998 lro_flush_all(&rx_ring->lro_mgr);
3999 rx_ring->lro_used = 0;
4000 }
4001#endif
4002
3909 if (cleaned_count) 4003 if (cleaned_count)
3910 igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); 4004 igb_alloc_rx_buffers_adv(rx_ring, cleaned_count);
3911 4005