public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] [UPDATED] ixgbe: add LRO support
@ 2008-06-11 22:14 Jeff Kirsher
  2008-06-11 22:15 ` [PATCH 2/2] MAINTAINERS Jeff Kirsher
  2008-06-11 22:20 ` [PATCH 1/2] [UPDATED] ixgbe: add LRO support Randy Dunlap
  0 siblings, 2 replies; 4+ messages in thread
From: Jeff Kirsher @ 2008-06-11 22:14 UTC (permalink / raw)
  To: jeff; +Cc: netdev, linux-kernel, davem, e1000-dev


Support for in-kernel LRO with the ability to enable/disable via ethtool
based on comments from Ben Hutchings.

Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
---

 drivers/net/ixgbe/ixgbe.h         |    9 +++
 drivers/net/ixgbe/ixgbe_ethtool.c |   11 ++++
 drivers/net/ixgbe/ixgbe_main.c    |  111 ++++++++++++++++++++++++++++++-------
 3 files changed, 110 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index d981134..956914a 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/inet_lro.h>
 
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
@@ -100,6 +101,9 @@
 #define IXGBE_TX_FLAGS_VLAN_MASK	0xffff0000
 #define IXGBE_TX_FLAGS_VLAN_SHIFT	16
 
+#define IXGBE_MAX_LRO_DESCRIPTORS       8
+#define IXGBE_MAX_LRO_AGGREGATE         32
+
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
@@ -150,6 +154,8 @@ struct ixgbe_ring {
 	/* cpu for tx queue */
 	int cpu;
 #endif
+	struct net_lro_mgr lro_mgr;
+	bool lro_used;
 	struct ixgbe_queue_stats stats;
 	u8 v_idx; /* maps directly to the index for this ring in the hardware
 		   * vector array, can also be used for finding the bit in EICR
@@ -287,6 +293,9 @@ struct ixgbe_adapter {
 
 	unsigned long state;
 	u64 tx_busy;
+	u64 lro_aggregated;
+	u64 lro_flushed;
+	u64 lro_no_desc;
 };
 
 enum ixbge_state_t {
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 4e46377..12990b1 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -90,6 +90,8 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
 	{"rx_header_split", IXGBE_STAT(rx_hdr_split)},
 	{"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
 	{"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
+	{"lro_aggregated", IXGBE_STAT(lro_aggregated)},
+	{"lro_flushed", IXGBE_STAT(lro_flushed)},
 };
 
 #define IXGBE_QUEUE_STATS_LEN \
@@ -787,6 +789,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
 	int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
 	int j, k;
 	int i;
+	u64 aggregated = 0, flushed = 0, no_desc = 0;
 
 	ixgbe_update_stats(adapter);
 	for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
@@ -801,11 +804,17 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
 		i += k;
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
+		aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated;
+		flushed += adapter->rx_ring[j].lro_mgr.stats.flushed;
+		no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc;
 		queue_stat = (u64 *)&adapter->rx_ring[j].stats;
 		for (k = 0; k < stat_count; k++)
 			data[i + k] = queue_stat[k];
 		i += k;
 	}
+	adapter->lro_aggregated = aggregated;
+	adapter->lro_flushed = flushed;
+	adapter->lro_no_desc = no_desc;
 }
 
 static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
@@ -973,6 +982,8 @@ static struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_ethtool_stats      = ixgbe_get_ethtool_stats,
 	.get_coalesce           = ixgbe_get_coalesce,
 	.set_coalesce           = ixgbe_set_coalesce,
+	.get_flags              = ethtool_op_get_flags,
+	.set_flags              = ethtool_op_set_flags,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 7b85922..04c6482 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -389,24 +389,39 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
  * ixgbe_receive_skb - Send a completed packet up the stack
  * @adapter: board private structure
  * @skb: packet to send up
- * @is_vlan: packet has a VLAN tag
- * @tag: VLAN tag from descriptor
+ * @status: hardware indication of status of receive
+ * @rx_ring: rx descriptor ring (for a specific queue) to setup
+ * @rx_desc: rx descriptor
  **/
 static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
-			      struct sk_buff *skb, bool is_vlan,
-			      u16 tag)
+			      struct sk_buff *skb, u8 status,
+			      struct ixgbe_ring *ring,
+                              union ixgbe_adv_rx_desc *rx_desc)
 {
-	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-		if (adapter->vlgrp && is_vlan)
-			vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
-		else
-			netif_receive_skb(skb);
-	} else {
+	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
+	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
+	if (adapter->netdev->features & NETIF_F_LRO &&
+	    skb->ip_summed == CHECKSUM_UNNECESSARY) {
 		if (adapter->vlgrp && is_vlan)
-			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
+			lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
+			                             adapter->vlgrp, tag,
+			                             rx_desc);
 		else
-			netif_rx(skb);
+			lro_receive_skb(&ring->lro_mgr, skb, rx_desc);
+		ring->lro_used = true;
+	} else {
+		if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
+			if (adapter->vlgrp && is_vlan)
+				vlan_nw_accel_receive_skb(skb, adapter->vlgrp, tag);
+			else
+				netif_receive_skb(skb);
+		} else {
+			if (adapter->vlgrp && is_vlan)
+				vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
+			else
+				netif_rx(skb);
+		}
 	}
 }
 
@@ -546,8 +561,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
 	struct sk_buff *skb;
 	unsigned int i;
 	u32 upper_len, len, staterr;
-	u16 hdr_info, vlan_tag;
-	bool is_vlan, cleaned = false;
+	u16 hdr_info;
+	bool cleaned = false;
 	int cleaned_count = 0;
 	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
 
@@ -556,8 +571,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
 	rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
 	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 	rx_buffer_info = &rx_ring->rx_buffer_info[i];
-	is_vlan = (staterr & IXGBE_RXD_STAT_VP);
-	vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
 	while (staterr & IXGBE_RXD_STAT_DD) {
 		if (*work_done >= work_to_do)
@@ -635,7 +648,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
 		total_rx_packets++;
 
 		skb->protocol = eth_type_trans(skb, netdev);
-		ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag);
+		ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
 		netdev->last_rx = jiffies;
 
 next_desc:
@@ -652,8 +665,11 @@ next_desc:
 		rx_buffer_info = next_buffer;
 
 		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
-		is_vlan = (staterr & IXGBE_RXD_STAT_VP);
-		vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
+	}
+
+	if (rx_ring->lro_used) {
+		lro_flush_all(&rx_ring->lro_mgr);
+		rx_ring->lro_used = false;
 	}
 
 	rx_ring->next_to_clean = i;
@@ -1382,6 +1398,33 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 
 #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT			2
 /**
+ * ixgbe_get_skb_hdr - helper function for LRO header processing
+ * @skb: pointer to sk_buff to be added to LRO packet
+ * @iphdr: pointer to tcp header structure
+ * @tcph: pointer to tcp header structure
+ * @hdr_flags: pointer to header flags
+ * @priv: private data
+ **/
+static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
+                             u64 *hdr_flags, void *priv)
+{
+	union ixgbe_adv_rx_desc *rx_desc = priv;
+
+	/* Verify that this is a valid IPv4 TCP packet */
+	if (!(rx_desc->wb.lower.lo_dword.pkt_info &
+	    (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)))
+		return -1;
+
+	/* Set network headers */
+	skb_reset_network_header(skb);
+	skb_set_transport_header(skb, ip_hdrlen(skb));
+	*iphdr = ip_hdr(skb);
+	*tcph = tcp_hdr(skb);
+	*hdr_flags = LRO_IPV4 | LRO_TCP;
+	return 0;
+}
+
+/**
  * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset
  * @adapter: board private structure
  *
@@ -1470,6 +1513,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 		adapter->rx_ring[i].tail = IXGBE_RDT(i);
 	}
 
+	/* Intitial LRO Settings */
+	adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
+	adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
+	adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
+	adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
+	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+		adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
+	adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
+	adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
+	adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 		/* Fill out redirection table */
 		for (i = 0, j = 0; i < 128; i++, j++) {
@@ -2489,12 +2543,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
 	struct pci_dev *pdev = adapter->pdev;
 	int size;
 
+	size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
+	rxdr->lro_mgr.lro_arr = vmalloc(size);
+	if (!rxdr->lro_mgr.lro_arr)
+		return -ENOMEM;
+	memset(rxdr->lro_mgr.lro_arr, 0, size);
+
 	size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
 	rxdr->rx_buffer_info = vmalloc(size);
 	if (!rxdr->rx_buffer_info) {
 		DPRINTK(PROBE, ERR,
 			"vmalloc allocation failed for the rx desc ring\n");
-		return -ENOMEM;
+		goto alloc_failed;
 	}
 	memset(rxdr->rx_buffer_info, 0, size);
 
@@ -2508,13 +2568,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
 		DPRINTK(PROBE, ERR,
 			"Memory allocation failed for the rx desc ring\n");
 		vfree(rxdr->rx_buffer_info);
-		return -ENOMEM;
+		goto alloc_failed;
 	}
 
 	rxdr->next_to_clean = 0;
 	rxdr->next_to_use = 0;
 
 	return 0;
+
+alloc_failed:
+	vfree(rxdr->lro_mgr.lro_arr);
+	rxdr->lro_mgr.lro_arr = NULL;
+	return -ENOMEM;
 }
 
 /**
@@ -2565,6 +2630,9 @@ static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
 {
 	struct pci_dev *pdev = adapter->pdev;
 
+	vfree(rx_ring->lro_mgr.lro_arr);
+	rx_ring->lro_mgr.lro_arr = NULL;
+
 	ixgbe_clean_rx_ring(adapter, rx_ring);
 
 	vfree(rx_ring->rx_buffer_info);
@@ -3517,6 +3585,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
 
+	netdev->features |= NETIF_F_LRO;
 	netdev->features |= NETIF_F_TSO;
 
 	netdev->features |= NETIF_F_TSO6;


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] MAINTAINERS
  2008-06-11 22:14 [PATCH 1/2] [UPDATED] ixgbe: add LRO support Jeff Kirsher
@ 2008-06-11 22:15 ` Jeff Kirsher
  2008-06-11 22:20 ` [PATCH 1/2] [UPDATED] ixgbe: add LRO support Randy Dunlap
  1 sibling, 0 replies; 4+ messages in thread
From: Jeff Kirsher @ 2008-06-11 22:15 UTC (permalink / raw)
  To: jeff; +Cc: netdev, linux-kernel, davem, e1000-dev

Add PJ Waskiewicz to the list of maintainers for Intel 10/100/1000/10GbE
adapters.

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
---

 MAINTAINERS |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index f5583dc..b87e0e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2118,6 +2118,8 @@ P:	Jesse Brandeburg
 M:	jesse.brandeburg@intel.com
 P:	Bruce Allan
 M:	bruce.w.allan@intel.com
+P:	PJ Waskiewicz
+M:	peter.p.waskiewicz.jr@intel.com
 P:	John Ronciak
 M:	john.ronciak@intel.com
 L:	e1000-devel@lists.sourceforge.net


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] [UPDATED] ixgbe: add LRO support
  2008-06-11 22:14 [PATCH 1/2] [UPDATED] ixgbe: add LRO support Jeff Kirsher
  2008-06-11 22:15 ` [PATCH 2/2] MAINTAINERS Jeff Kirsher
@ 2008-06-11 22:20 ` Randy Dunlap
  2008-06-12 16:13   ` Malli
  1 sibling, 1 reply; 4+ messages in thread
From: Randy Dunlap @ 2008-06-11 22:20 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: jeff, netdev, linux-kernel, davem, e1000-dev

On Wed, 11 Jun 2008 15:14:17 -0700 Jeff Kirsher wrote:

> 
> Support for in-kernel LRO with the ability to enable/disable via ethtool
> based on comments from Ben Hutchings.
> 
> Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> Signed-off-by: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
> ---
> 
>  drivers/net/ixgbe/ixgbe.h         |    9 +++
>  drivers/net/ixgbe/ixgbe_ethtool.c |   11 ++++
>  drivers/net/ixgbe/ixgbe_main.c    |  111 ++++++++++++++++++++++++++++++-------
>  3 files changed, 110 insertions(+), 21 deletions(-)

Is there also a patch to drivers/net/Kconfig that makes IXGBE depend on INET?
You can't just assume that the lro_* functions are always there....


> diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
> index d981134..956914a 100644
> --- a/drivers/net/ixgbe/ixgbe.h
> +++ b/drivers/net/ixgbe/ixgbe.h
> @@ -32,6 +32,7 @@
>  #include <linux/types.h>
>  #include <linux/pci.h>
>  #include <linux/netdevice.h>
> +#include <linux/inet_lro.h>
>  
>  #include "ixgbe_type.h"
>  #include "ixgbe_common.h"
> @@ -100,6 +101,9 @@
>  #define IXGBE_TX_FLAGS_VLAN_MASK	0xffff0000
>  #define IXGBE_TX_FLAGS_VLAN_SHIFT	16
>  
> +#define IXGBE_MAX_LRO_DESCRIPTORS       8
> +#define IXGBE_MAX_LRO_AGGREGATE         32
> +
>  /* wrapper around a pointer to a socket buffer,
>   * so a DMA handle can be stored along with the buffer */
>  struct ixgbe_tx_buffer {
> @@ -150,6 +154,8 @@ struct ixgbe_ring {
>  	/* cpu for tx queue */
>  	int cpu;
>  #endif
> +	struct net_lro_mgr lro_mgr;
> +	bool lro_used;
>  	struct ixgbe_queue_stats stats;
>  	u8 v_idx; /* maps directly to the index for this ring in the hardware
>  		   * vector array, can also be used for finding the bit in EICR
> @@ -287,6 +293,9 @@ struct ixgbe_adapter {
>  
>  	unsigned long state;
>  	u64 tx_busy;
> +	u64 lro_aggregated;
> +	u64 lro_flushed;
> +	u64 lro_no_desc;
>  };
>  
>  enum ixbge_state_t {
> diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
> index 4e46377..12990b1 100644
> --- a/drivers/net/ixgbe/ixgbe_ethtool.c
> +++ b/drivers/net/ixgbe/ixgbe_ethtool.c
> @@ -90,6 +90,8 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
>  	{"rx_header_split", IXGBE_STAT(rx_hdr_split)},
>  	{"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
>  	{"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
> +	{"lro_aggregated", IXGBE_STAT(lro_aggregated)},
> +	{"lro_flushed", IXGBE_STAT(lro_flushed)},
>  };
>  
>  #define IXGBE_QUEUE_STATS_LEN \
> @@ -787,6 +789,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
>  	int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
>  	int j, k;
>  	int i;
> +	u64 aggregated = 0, flushed = 0, no_desc = 0;
>  
>  	ixgbe_update_stats(adapter);
>  	for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
> @@ -801,11 +804,17 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
>  		i += k;
>  	}
>  	for (j = 0; j < adapter->num_rx_queues; j++) {
> +		aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated;
> +		flushed += adapter->rx_ring[j].lro_mgr.stats.flushed;
> +		no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc;
>  		queue_stat = (u64 *)&adapter->rx_ring[j].stats;
>  		for (k = 0; k < stat_count; k++)
>  			data[i + k] = queue_stat[k];
>  		i += k;
>  	}
> +	adapter->lro_aggregated = aggregated;
> +	adapter->lro_flushed = flushed;
> +	adapter->lro_no_desc = no_desc;
>  }
>  
>  static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
> @@ -973,6 +982,8 @@ static struct ethtool_ops ixgbe_ethtool_ops = {
>  	.get_ethtool_stats      = ixgbe_get_ethtool_stats,
>  	.get_coalesce           = ixgbe_get_coalesce,
>  	.set_coalesce           = ixgbe_set_coalesce,
> +	.get_flags              = ethtool_op_get_flags,
> +	.set_flags              = ethtool_op_set_flags,
>  };
>  
>  void ixgbe_set_ethtool_ops(struct net_device *netdev)
> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
> index 7b85922..04c6482 100644
> --- a/drivers/net/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ixgbe/ixgbe_main.c
> @@ -389,24 +389,39 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
>   * ixgbe_receive_skb - Send a completed packet up the stack
>   * @adapter: board private structure
>   * @skb: packet to send up
> - * @is_vlan: packet has a VLAN tag
> - * @tag: VLAN tag from descriptor
> + * @status: hardware indication of status of receive
> + * @rx_ring: rx descriptor ring (for a specific queue) to setup
> + * @rx_desc: rx descriptor
>   **/
>  static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
> -			      struct sk_buff *skb, bool is_vlan,
> -			      u16 tag)
> +			      struct sk_buff *skb, u8 status,
> +			      struct ixgbe_ring *ring,
> +                              union ixgbe_adv_rx_desc *rx_desc)
>  {
> -	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
> -		if (adapter->vlgrp && is_vlan)
> -			vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
> -		else
> -			netif_receive_skb(skb);
> -	} else {
> +	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
> +	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
>  
> +	if (adapter->netdev->features & NETIF_F_LRO &&
> +	    skb->ip_summed == CHECKSUM_UNNECESSARY) {
>  		if (adapter->vlgrp && is_vlan)
> -			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
> +			lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
> +			                             adapter->vlgrp, tag,
> +			                             rx_desc);
>  		else
> -			netif_rx(skb);
> +			lro_receive_skb(&ring->lro_mgr, skb, rx_desc);
> +		ring->lro_used = true;
> +	} else {
> +		if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
> +			if (adapter->vlgrp && is_vlan)
> +				vlan_nw_accel_receive_skb(skb, adapter->vlgrp, tag);
> +			else
> +				netif_receive_skb(skb);
> +		} else {
> +			if (adapter->vlgrp && is_vlan)
> +				vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
> +			else
> +				netif_rx(skb);
> +		}
>  	}
>  }
>  
> @@ -546,8 +561,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>  	struct sk_buff *skb;
>  	unsigned int i;
>  	u32 upper_len, len, staterr;
> -	u16 hdr_info, vlan_tag;
> -	bool is_vlan, cleaned = false;
> +	u16 hdr_info;
> +	bool cleaned = false;
>  	int cleaned_count = 0;
>  	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
>  
> @@ -556,8 +571,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>  	rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
>  	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
>  	rx_buffer_info = &rx_ring->rx_buffer_info[i];
> -	is_vlan = (staterr & IXGBE_RXD_STAT_VP);
> -	vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
>  
>  	while (staterr & IXGBE_RXD_STAT_DD) {
>  		if (*work_done >= work_to_do)
> @@ -635,7 +648,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>  		total_rx_packets++;
>  
>  		skb->protocol = eth_type_trans(skb, netdev);
> -		ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag);
> +		ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
>  		netdev->last_rx = jiffies;
>  
>  next_desc:
> @@ -652,8 +665,11 @@ next_desc:
>  		rx_buffer_info = next_buffer;
>  
>  		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
> -		is_vlan = (staterr & IXGBE_RXD_STAT_VP);
> -		vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
> +	}
> +
> +	if (rx_ring->lro_used) {
> +		lro_flush_all(&rx_ring->lro_mgr);
> +		rx_ring->lro_used = false;
>  	}
>  
>  	rx_ring->next_to_clean = i;
> @@ -1382,6 +1398,33 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
>  
>  #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT			2
>  /**
> + * ixgbe_get_skb_hdr - helper function for LRO header processing
> + * @skb: pointer to sk_buff to be added to LRO packet
> + * @iphdr: pointer to tcp header structure
> + * @tcph: pointer to tcp header structure
> + * @hdr_flags: pointer to header flags
> + * @priv: private data
> + **/
> +static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
> +                             u64 *hdr_flags, void *priv)
> +{
> +	union ixgbe_adv_rx_desc *rx_desc = priv;
> +
> +	/* Verify that this is a valid IPv4 TCP packet */
> +	if (!(rx_desc->wb.lower.lo_dword.pkt_info &
> +	    (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)))
> +		return -1;
> +
> +	/* Set network headers */
> +	skb_reset_network_header(skb);
> +	skb_set_transport_header(skb, ip_hdrlen(skb));
> +	*iphdr = ip_hdr(skb);
> +	*tcph = tcp_hdr(skb);
> +	*hdr_flags = LRO_IPV4 | LRO_TCP;
> +	return 0;
> +}
> +
> +/**
>   * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset
>   * @adapter: board private structure
>   *
> @@ -1470,6 +1513,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
>  		adapter->rx_ring[i].tail = IXGBE_RDT(i);
>  	}
>  
> +	/* Intitial LRO Settings */
> +	adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
> +	adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
> +	adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
> +	adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
> +	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
> +		adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
> +	adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
> +	adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
> +	adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
> +
>  	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
>  		/* Fill out redirection table */
>  		for (i = 0, j = 0; i < 128; i++, j++) {
> @@ -2489,12 +2543,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
>  	struct pci_dev *pdev = adapter->pdev;
>  	int size;
>  
> +	size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
> +	rxdr->lro_mgr.lro_arr = vmalloc(size);
> +	if (!rxdr->lro_mgr.lro_arr)
> +		return -ENOMEM;
> +	memset(rxdr->lro_mgr.lro_arr, 0, size);
> +
>  	size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
>  	rxdr->rx_buffer_info = vmalloc(size);
>  	if (!rxdr->rx_buffer_info) {
>  		DPRINTK(PROBE, ERR,
>  			"vmalloc allocation failed for the rx desc ring\n");
> -		return -ENOMEM;
> +		goto alloc_failed;
>  	}
>  	memset(rxdr->rx_buffer_info, 0, size);
>  
> @@ -2508,13 +2568,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
>  		DPRINTK(PROBE, ERR,
>  			"Memory allocation failed for the rx desc ring\n");
>  		vfree(rxdr->rx_buffer_info);
> -		return -ENOMEM;
> +		goto alloc_failed;
>  	}
>  
>  	rxdr->next_to_clean = 0;
>  	rxdr->next_to_use = 0;
>  
>  	return 0;
> +
> +alloc_failed:
> +	vfree(rxdr->lro_mgr.lro_arr);
> +	rxdr->lro_mgr.lro_arr = NULL;
> +	return -ENOMEM;
>  }
>  
>  /**
> @@ -2565,6 +2630,9 @@ static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
>  {
>  	struct pci_dev *pdev = adapter->pdev;
>  
> +	vfree(rx_ring->lro_mgr.lro_arr);
> +	rx_ring->lro_mgr.lro_arr = NULL;
> +
>  	ixgbe_clean_rx_ring(adapter, rx_ring);
>  
>  	vfree(rx_ring->rx_buffer_info);
> @@ -3517,6 +3585,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
>  			   NETIF_F_HW_VLAN_RX |
>  			   NETIF_F_HW_VLAN_FILTER;
>  
> +	netdev->features |= NETIF_F_LRO;
>  	netdev->features |= NETIF_F_TSO;
>  
>  	netdev->features |= NETIF_F_TSO6;

---
~Randy

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] [UPDATED] ixgbe: add LRO support
  2008-06-11 22:20 ` [PATCH 1/2] [UPDATED] ixgbe: add LRO support Randy Dunlap
@ 2008-06-12 16:13   ` Malli
  0 siblings, 0 replies; 4+ messages in thread
From: Malli @ 2008-06-12 16:13 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Jeff Kirsher, jeff, netdev, linux-kernel, davem, e1000-dev

Thanks Randy. Yes we'll update the patches with drivers/net/Kconfig changes.

On Wed, Jun 11, 2008 at 3:20 PM, Randy Dunlap <randy.dunlap@oracle.com> wrote:
> On Wed, 11 Jun 2008 15:14:17 -0700 Jeff Kirsher wrote:
>
>>
>> Support for in-kernel LRO with the ability to enable/disable via ethtool
>> based on comments from Ben Hutchings.
>>
>> Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> Signed-off-by: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
>> ---
>>
>>  drivers/net/ixgbe/ixgbe.h         |    9 +++
>>  drivers/net/ixgbe/ixgbe_ethtool.c |   11 ++++
>>  drivers/net/ixgbe/ixgbe_main.c    |  111 ++++++++++++++++++++++++++++++-------
>>  3 files changed, 110 insertions(+), 21 deletions(-)
>
> Is there also a patch to drivers/net/Kconfig that makes IXGBE depend on INET?
> You can't just assume that the lro_* functions are always there....
>
>
>> diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
>> index d981134..956914a 100644
>> --- a/drivers/net/ixgbe/ixgbe.h
>> +++ b/drivers/net/ixgbe/ixgbe.h
>> @@ -32,6 +32,7 @@
>>  #include <linux/types.h>
>>  #include <linux/pci.h>
>>  #include <linux/netdevice.h>
>> +#include <linux/inet_lro.h>
>>
>>  #include "ixgbe_type.h"
>>  #include "ixgbe_common.h"
>> @@ -100,6 +101,9 @@
>>  #define IXGBE_TX_FLAGS_VLAN_MASK     0xffff0000
>>  #define IXGBE_TX_FLAGS_VLAN_SHIFT    16
>>
>> +#define IXGBE_MAX_LRO_DESCRIPTORS       8
>> +#define IXGBE_MAX_LRO_AGGREGATE         32
>> +
>>  /* wrapper around a pointer to a socket buffer,
>>   * so a DMA handle can be stored along with the buffer */
>>  struct ixgbe_tx_buffer {
>> @@ -150,6 +154,8 @@ struct ixgbe_ring {
>>       /* cpu for tx queue */
>>       int cpu;
>>  #endif
>> +     struct net_lro_mgr lro_mgr;
>> +     bool lro_used;
>>       struct ixgbe_queue_stats stats;
>>       u8 v_idx; /* maps directly to the index for this ring in the hardware
>>                  * vector array, can also be used for finding the bit in EICR
>> @@ -287,6 +293,9 @@ struct ixgbe_adapter {
>>
>>       unsigned long state;
>>       u64 tx_busy;
>> +     u64 lro_aggregated;
>> +     u64 lro_flushed;
>> +     u64 lro_no_desc;
>>  };
>>
>>  enum ixbge_state_t {
>> diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
>> index 4e46377..12990b1 100644
>> --- a/drivers/net/ixgbe/ixgbe_ethtool.c
>> +++ b/drivers/net/ixgbe/ixgbe_ethtool.c
>> @@ -90,6 +90,8 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
>>       {"rx_header_split", IXGBE_STAT(rx_hdr_split)},
>>       {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
>>       {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
>> +     {"lro_aggregated", IXGBE_STAT(lro_aggregated)},
>> +     {"lro_flushed", IXGBE_STAT(lro_flushed)},
>>  };
>>
>>  #define IXGBE_QUEUE_STATS_LEN \
>> @@ -787,6 +789,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
>>       int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
>>       int j, k;
>>       int i;
>> +     u64 aggregated = 0, flushed = 0, no_desc = 0;
>>
>>       ixgbe_update_stats(adapter);
>>       for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
>> @@ -801,11 +804,17 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
>>               i += k;
>>       }
>>       for (j = 0; j < adapter->num_rx_queues; j++) {
>> +             aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated;
>> +             flushed += adapter->rx_ring[j].lro_mgr.stats.flushed;
>> +             no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc;
>>               queue_stat = (u64 *)&adapter->rx_ring[j].stats;
>>               for (k = 0; k < stat_count; k++)
>>                       data[i + k] = queue_stat[k];
>>               i += k;
>>       }
>> +     adapter->lro_aggregated = aggregated;
>> +     adapter->lro_flushed = flushed;
>> +     adapter->lro_no_desc = no_desc;
>>  }
>>
>>  static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
>> @@ -973,6 +982,8 @@ static struct ethtool_ops ixgbe_ethtool_ops = {
>>       .get_ethtool_stats      = ixgbe_get_ethtool_stats,
>>       .get_coalesce           = ixgbe_get_coalesce,
>>       .set_coalesce           = ixgbe_set_coalesce,
>> +     .get_flags              = ethtool_op_get_flags,
>> +     .set_flags              = ethtool_op_set_flags,
>>  };
>>
>>  void ixgbe_set_ethtool_ops(struct net_device *netdev)
>> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
>> index 7b85922..04c6482 100644
>> --- a/drivers/net/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ixgbe/ixgbe_main.c
>> @@ -389,24 +389,39 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
>>   * ixgbe_receive_skb - Send a completed packet up the stack
>>   * @adapter: board private structure
>>   * @skb: packet to send up
>> - * @is_vlan: packet has a VLAN tag
>> - * @tag: VLAN tag from descriptor
>> + * @status: hardware indication of status of receive
>> + * @rx_ring: rx descriptor ring (for a specific queue) to setup
>> + * @rx_desc: rx descriptor
>>   **/
>>  static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
>> -                           struct sk_buff *skb, bool is_vlan,
>> -                           u16 tag)
>> +                           struct sk_buff *skb, u8 status,
>> +                           struct ixgbe_ring *ring,
>> +                              union ixgbe_adv_rx_desc *rx_desc)
>>  {
>> -     if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
>> -             if (adapter->vlgrp && is_vlan)
>> -                     vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
>> -             else
>> -                     netif_receive_skb(skb);
>> -     } else {
>> +     bool is_vlan = (status & IXGBE_RXD_STAT_VP);
>> +     u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
>>
>> +     if (adapter->netdev->features & NETIF_F_LRO &&
>> +         skb->ip_summed == CHECKSUM_UNNECESSARY) {
>>               if (adapter->vlgrp && is_vlan)
>> -                     vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
>> +                     lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
>> +                                                  adapter->vlgrp, tag,
>> +                                                  rx_desc);
>>               else
>> -                     netif_rx(skb);
>> +                     lro_receive_skb(&ring->lro_mgr, skb, rx_desc);
>> +             ring->lro_used = true;
>> +     } else {
>> +             if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
>> +                     if (adapter->vlgrp && is_vlan)
>> +                             vlan_nw_accel_receive_skb(skb, adapter->vlgrp, tag);
>> +                     else
>> +                             netif_receive_skb(skb);
>> +             } else {
>> +                     if (adapter->vlgrp && is_vlan)
>> +                             vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
>> +                     else
>> +                             netif_rx(skb);
>> +             }
>>       }
>>  }
>>
>> @@ -546,8 +561,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>>       struct sk_buff *skb;
>>       unsigned int i;
>>       u32 upper_len, len, staterr;
>> -     u16 hdr_info, vlan_tag;
>> -     bool is_vlan, cleaned = false;
>> +     u16 hdr_info;
>> +     bool cleaned = false;
>>       int cleaned_count = 0;
>>       unsigned int total_rx_bytes = 0, total_rx_packets = 0;
>>
>> @@ -556,8 +571,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>>       rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
>>       staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
>>       rx_buffer_info = &rx_ring->rx_buffer_info[i];
>> -     is_vlan = (staterr & IXGBE_RXD_STAT_VP);
>> -     vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
>>
>>       while (staterr & IXGBE_RXD_STAT_DD) {
>>               if (*work_done >= work_to_do)
>> @@ -635,7 +648,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
>>               total_rx_packets++;
>>
>>               skb->protocol = eth_type_trans(skb, netdev);
>> -             ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag);
>> +             ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
>>               netdev->last_rx = jiffies;
>>
>>  next_desc:
>> @@ -652,8 +665,11 @@ next_desc:
>>               rx_buffer_info = next_buffer;
>>
>>               staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
>> -             is_vlan = (staterr & IXGBE_RXD_STAT_VP);
>> -             vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
>> +     }
>> +
>> +     if (rx_ring->lro_used) {
>> +             lro_flush_all(&rx_ring->lro_mgr);
>> +             rx_ring->lro_used = false;
>>       }
>>
>>       rx_ring->next_to_clean = i;
>> @@ -1382,6 +1398,33 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
>>
>>  #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT                      2
>>  /**
>> + * ixgbe_get_skb_hdr - helper function for LRO header processing
>> + * @skb: pointer to sk_buff to be added to LRO packet
>> + * @iphdr: pointer to tcp header structure
>> + * @tcph: pointer to tcp header structure
>> + * @hdr_flags: pointer to header flags
>> + * @priv: private data
>> + **/
>> +static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
>> +                             u64 *hdr_flags, void *priv)
>> +{
>> +     union ixgbe_adv_rx_desc *rx_desc = priv;
>> +
>> +     /* Verify that this is a valid IPv4 TCP packet */
>> +     if (!(rx_desc->wb.lower.lo_dword.pkt_info &
>> +         (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)))
>> +             return -1;
>> +
>> +     /* Set network headers */
>> +     skb_reset_network_header(skb);
>> +     skb_set_transport_header(skb, ip_hdrlen(skb));
>> +     *iphdr = ip_hdr(skb);
>> +     *tcph = tcp_hdr(skb);
>> +     *hdr_flags = LRO_IPV4 | LRO_TCP;
>> +     return 0;
>> +}
>> +
>> +/**
>>   * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset
>>   * @adapter: board private structure
>>   *
>> @@ -1470,6 +1513,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
>>               adapter->rx_ring[i].tail = IXGBE_RDT(i);
>>       }
>>
>> +     /* Intitial LRO Settings */
>> +     adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
>> +     adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
>> +     adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
>> +     adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
>> +     if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
>> +             adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
>> +     adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
>> +     adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
>> +     adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
>> +
>>       if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
>>               /* Fill out redirection table */
>>               for (i = 0, j = 0; i < 128; i++, j++) {
>> @@ -2489,12 +2543,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
>>       struct pci_dev *pdev = adapter->pdev;
>>       int size;
>>
>> +     size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
>> +     rxdr->lro_mgr.lro_arr = vmalloc(size);
>> +     if (!rxdr->lro_mgr.lro_arr)
>> +             return -ENOMEM;
>> +     memset(rxdr->lro_mgr.lro_arr, 0, size);
>> +
>>       size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
>>       rxdr->rx_buffer_info = vmalloc(size);
>>       if (!rxdr->rx_buffer_info) {
>>               DPRINTK(PROBE, ERR,
>>                       "vmalloc allocation failed for the rx desc ring\n");
>> -             return -ENOMEM;
>> +             goto alloc_failed;
>>       }
>>       memset(rxdr->rx_buffer_info, 0, size);
>>
>> @@ -2508,13 +2568,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
>>               DPRINTK(PROBE, ERR,
>>                       "Memory allocation failed for the rx desc ring\n");
>>               vfree(rxdr->rx_buffer_info);
>> -             return -ENOMEM;
>> +             goto alloc_failed;
>>       }
>>
>>       rxdr->next_to_clean = 0;
>>       rxdr->next_to_use = 0;
>>
>>       return 0;
>> +
>> +alloc_failed:
>> +     vfree(rxdr->lro_mgr.lro_arr);
>> +     rxdr->lro_mgr.lro_arr = NULL;
>> +     return -ENOMEM;
>>  }
>>
>>  /**
>> @@ -2565,6 +2630,9 @@ static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
>>  {
>>       struct pci_dev *pdev = adapter->pdev;
>>
>> +     vfree(rx_ring->lro_mgr.lro_arr);
>> +     rx_ring->lro_mgr.lro_arr = NULL;
>> +
>>       ixgbe_clean_rx_ring(adapter, rx_ring);
>>
>>       vfree(rx_ring->rx_buffer_info);
>> @@ -3517,6 +3585,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
>>                          NETIF_F_HW_VLAN_RX |
>>                          NETIF_F_HW_VLAN_FILTER;
>>
>> +     netdev->features |= NETIF_F_LRO;
>>       netdev->features |= NETIF_F_TSO;
>>
>>       netdev->features |= NETIF_F_TSO6;
>
> ---
> ~Randy
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-06-12 16:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-11 22:14 [PATCH 1/2] [UPDATED] ixgbe: add LRO support Jeff Kirsher
2008-06-11 22:15 ` [PATCH 2/2] MAINTAINERS Jeff Kirsher
2008-06-11 22:20 ` [PATCH 1/2] [UPDATED] ixgbe: add LRO support Randy Dunlap
2008-06-12 16:13   ` Malli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox