netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next 00/10][pull request] Intel Wired LAN Driver Updates
@ 2013-02-08 10:39 Jeff Kirsher
  2013-02-08 10:39 ` [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled Jeff Kirsher
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann

This series contains updates to igb and ixgbe.  Most of the changes
are against igb, except for one patch against ixgbe.

There are 3 igb fixes from Carolyn which were reported by Dan
Carpenter which resolve issues found in the get_i2c_client().  Alex
does some cleanup of the igb driver to match similar functionality
in ixgbe on transmit.  Alex also makes it so that we can enable the use
of build_skb for cases where jumbo frames are disabled.  The advantage
to this is that we do not have to perform a memcpy to populate the header
and as a result we see a significant performance improvement.

Akeem provides 4 patches to initialize function pointers and do a
re-factoring of the function pointers in igb_get_variants() to assist
with driver debugging.

The ixgbe patch comes from Emil to reshuffle the switch/case structure
of the flag assignment to allow for the flags to be set for each MAC
type separately. This is needed for new hardware that does not have feature
parity with older hardware.

The following are changes since commit b285109dde7b873b5dc671ef1b3ae3090f4bc72f:
  Merge branch 'tg3'
and are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master

Akeem G. Abodunrin (4):
  igb: Initialize PHY function pointers
  igb: Initialize NVM function pointers
  igb: Intialize MAC function pointers
  igb: Refractoring function pointers in igb_get_invariants function

Alexander Duyck (2):
  igb: Support using build_skb in the case that jumbo frames are
    disabled
  igb: Update igb to use a path similar to ixgbe to determine when to
    stop Tx

Carolyn Wyborny (3):
  igb: Fix for improper exit in igb_get_i2c_client
  igb: Fix for improper allocation flag in igb_get_i2c_client
  igb: Fix for sparse warning in igb_get_i2c_client

Emil Tantilov (1):
  ixgbe: refactor initialization of feature flags

 drivers/net/ethernet/intel/igb/e1000_82575.c  | 488 ++++++++++++++------------
 drivers/net/ethernet/intel/igb/igb.h          |  21 +-
 drivers/net/ethernet/intel/igb/igb_main.c     | 230 +++++++++---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  58 +--
 4 files changed, 497 insertions(+), 300 deletions(-)

-- 
1.7.11.7

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

* [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 02/10] igb: Fix for improper exit in igb_get_i2c_client Jeff Kirsher
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher

From: Alexander Duyck <alexander.h.duyck@intel.com>

This change makes it so that we can enable the use of build_skb for cases
where jumbo frames are disabled.  The advantage to this is that we do not
have to perform a memcpy to populate the header and as a result we see a
significant performance improvement.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb.h      |   8 ++
 drivers/net/ethernet/intel/igb/igb_main.c | 187 ++++++++++++++++++++++++------
 2 files changed, 161 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 4b78053..afdb8bb 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -275,10 +275,18 @@ struct igb_q_vector {
 enum e1000_ring_flags_t {
 	IGB_RING_FLAG_RX_SCTP_CSUM,
 	IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
+	IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
 	IGB_RING_FLAG_TX_CTX_IDX,
 	IGB_RING_FLAG_TX_DETECT_HANG
 };
 
+#define ring_uses_build_skb(ring) \
+	test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define set_ring_build_skb_enabled(ring) \
+	set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define clear_ring_build_skb_enabled(ring) \
+	clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+
 #define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
 
 #define IGB_RX_DESC(R, i)	    \
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 1aaf193..b070a97 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3354,6 +3354,20 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
 	wr32(E1000_RXDCTL(reg_idx), rxdctl);
 }
 
+static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
+				  struct igb_ring *rx_ring)
+{
+#define IGB_MAX_BUILD_SKB_SIZE \
+	(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) - \
+	 (NET_SKB_PAD + NET_IP_ALIGN + IGB_TS_HDR_LEN))
+
+	/* set build_skb flag */
+	if (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE)
+		set_ring_build_skb_enabled(rx_ring);
+	else
+		clear_ring_build_skb_enabled(rx_ring);
+}
+
 /**
  * igb_configure_rx - Configure receive Unit after Reset
  * @adapter: board private structure
@@ -3373,8 +3387,11 @@ static void igb_configure_rx(struct igb_adapter *adapter)
 
 	/* Setup the HW Rx Head and Tail Descriptor Pointers and
 	 * the Base and Length of the Rx Descriptor Ring */
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		igb_configure_rx_ring(adapter, adapter->rx_ring[i]);
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct igb_ring *rx_ring = adapter->rx_ring[i];
+		igb_set_rx_buffer_len(adapter, rx_ring);
+		igb_configure_rx_ring(adapter, rx_ring);
+	}
 }
 
 /**
@@ -6097,6 +6114,41 @@ static void igb_reuse_rx_page(struct igb_ring *rx_ring,
 					 DMA_FROM_DEVICE);
 }
 
+static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
+				  struct page *page,
+				  unsigned int truesize)
+{
+	/* avoid re-using remote pages */
+	if (unlikely(page_to_nid(page) != numa_node_id()))
+		return false;
+
+#if (PAGE_SIZE < 8192)
+	/* if we are only owner of page we can reuse it */
+	if (unlikely(page_count(page) != 1))
+		return false;
+
+	/* flip page offset to other buffer */
+	rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+
+	/* since we are the only owner of the page and we need to
+	 * increment it, just set the value to 2 in order to avoid
+	 * an unnecessary locked operation
+	 */
+	atomic_set(&page->_count, 2);
+#else
+	/* move offset up to the next cache line */
+	rx_buffer->page_offset += truesize;
+
+	if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
+		return false;
+
+	/* bump ref count on page before it is given to the stack */
+	get_page(page);
+#endif
+
+	return true;
+}
+
 /**
  * igb_add_rx_frag - Add contents of Rx buffer to sk_buff
  * @rx_ring: rx descriptor ring to transact packets on
@@ -6119,6 +6171,11 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
 {
 	struct page *page = rx_buffer->page;
 	unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+#if (PAGE_SIZE < 8192)
+	unsigned int truesize = IGB_RX_BUFSZ;
+#else
+	unsigned int truesize = ALIGN(size, L1_CACHE_BYTES);
+#endif
 
 	if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) {
 		unsigned char *va = page_address(page) + rx_buffer->page_offset;
@@ -6141,38 +6198,88 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
 	}
 
 	skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
-			rx_buffer->page_offset, size, IGB_RX_BUFSZ);
+			rx_buffer->page_offset, size, truesize);
 
-	/* avoid re-using remote pages */
-	if (unlikely(page_to_nid(page) != numa_node_id()))
-		return false;
+	return igb_can_reuse_rx_page(rx_buffer, page, truesize);
+}
 
+static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
+					   union e1000_adv_rx_desc *rx_desc)
+{
+	struct igb_rx_buffer *rx_buffer;
+	struct sk_buff *skb;
+	struct page *page;
+	void *page_addr;
+	unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
 #if (PAGE_SIZE < 8192)
-	/* if we are only owner of page we can reuse it */
-	if (unlikely(page_count(page) != 1))
-		return false;
+	unsigned int truesize = IGB_RX_BUFSZ;
+#else
+	unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+				SKB_DATA_ALIGN(NET_SKB_PAD +
+					       NET_IP_ALIGN +
+					       size);
+#endif
 
-	/* flip page offset to other buffer */
-	rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+	/* If we spanned a buffer we have a huge mess so test for it */
+	BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)));
 
-	/*
-	 * since we are the only owner of the page and we need to
-	 * increment it, just set the value to 2 in order to avoid
-	 * an unnecessary locked operation
-	 */
-	atomic_set(&page->_count, 2);
-#else
-	/* move offset up to the next cache line */
-	rx_buffer->page_offset += SKB_DATA_ALIGN(size);
+	/* Guarantee this function can be used by verifying buffer sizes */
+	BUILD_BUG_ON(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) < (NET_SKB_PAD +
+							NET_IP_ALIGN +
+							IGB_TS_HDR_LEN +
+							ETH_FRAME_LEN +
+							ETH_FCS_LEN));
 
-	if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
-		return false;
+	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+	page = rx_buffer->page;
+	prefetchw(page);
 
-	/* bump ref count on page before it is given to the stack */
-	get_page(page);
+	page_addr = page_address(page) + rx_buffer->page_offset;
+
+	/* prefetch first cache line of first page */
+	prefetch(page_addr + NET_SKB_PAD + NET_IP_ALIGN);
+#if L1_CACHE_BYTES < 128
+	prefetch(page_addr + L1_CACHE_BYTES + NET_SKB_PAD + NET_IP_ALIGN);
 #endif
 
-	return true;
+	/* build an skb to around the page buffer */
+	skb = build_skb(page_addr, truesize);
+	if (unlikely(!skb)) {
+		rx_ring->rx_stats.alloc_failed++;
+		return NULL;
+	}
+
+	/* we are reusing so sync this buffer for CPU use */
+	dma_sync_single_range_for_cpu(rx_ring->dev,
+				      rx_buffer->dma,
+				      rx_buffer->page_offset,
+				      IGB_RX_BUFSZ,
+				      DMA_FROM_DEVICE);
+
+	/* update pointers within the skb to store the data */
+	skb_reserve(skb, NET_IP_ALIGN + NET_SKB_PAD);
+	__skb_put(skb, size);
+
+	/* pull timestamp out of packet data */
+	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+		igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
+		__skb_pull(skb, IGB_TS_HDR_LEN);
+	}
+
+	if (igb_can_reuse_rx_page(rx_buffer, page, truesize)) {
+		/* hand second half of page back to the ring */
+		igb_reuse_rx_page(rx_ring, rx_buffer);
+	} else {
+		/* we are not reusing the buffer so unmap it */
+		dma_unmap_page(rx_ring->dev, rx_buffer->dma,
+			       PAGE_SIZE, DMA_FROM_DEVICE);
+	}
+
+	/* clear contents of buffer_info */
+	rx_buffer->dma = 0;
+	rx_buffer->page = NULL;
+
+	return skb;
 }
 
 static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
@@ -6184,13 +6291,6 @@ static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
 
 	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
 
-	/*
-	 * This memory barrier is needed to keep us from reading
-	 * any other fields out of the rx_desc until we know the
-	 * RXD_STAT_DD bit is set
-	 */
-	rmb();
-
 	page = rx_buffer->page;
 	prefetchw(page);
 
@@ -6590,8 +6690,17 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
 		if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
 			break;
 
+		/* This memory barrier is needed to keep us from reading
+		 * any other fields out of the rx_desc until we know the
+		 * RXD_STAT_DD bit is set
+		 */
+		rmb();
+
 		/* retrieve a buffer from the ring */
-		skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
+		if (ring_uses_build_skb(rx_ring))
+			skb = igb_build_rx_buffer(rx_ring, rx_desc);
+		else
+			skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
 
 		/* exit if we failed to retrieve a buffer */
 		if (!skb)
@@ -6678,6 +6787,14 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
 	return true;
 }
 
+static inline unsigned int igb_rx_offset(struct igb_ring *rx_ring)
+{
+	if (ring_uses_build_skb(rx_ring))
+		return NET_SKB_PAD + NET_IP_ALIGN;
+	else
+		return 0;
+}
+
 /**
  * igb_alloc_rx_buffers - Replace used receive buffers; packet split
  * @adapter: address of board private structure
@@ -6704,7 +6821,9 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
 		 * Refresh the desc even if buffer_addrs didn't change
 		 * because each write-back erases this info.
 		 */
-		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
+		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma +
+						     bi->page_offset +
+						     igb_rx_offset(rx_ring));
 
 		rx_desc++;
 		bi++;
-- 
1.7.11.7

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

* [net-next 02/10] igb: Fix for improper exit in igb_get_i2c_client
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
  2013-02-08 10:39 ` [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 03/10] igb: Fix for improper allocation flag " Jeff Kirsher
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

This patch fixes an issue where we check for irq's disabled then exit after
explicitly disabling them with spin_lock_irqsave.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <arron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_main.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index b070a97..d84f28c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -7750,12 +7750,7 @@ igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
 		}
 	}
 
-	/* no client_list found, create a new one as long as
-	 * irqs are not disabled
-	 */
-	if (unlikely(irqs_disabled()))
-		goto exit;
-
+	/* no client_list found, create a new one */
 	client_list = kzalloc(sizeof(*client_list), GFP_KERNEL);
 	if (client_list == NULL)
 		goto exit;
-- 
1.7.11.7

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

* [net-next 03/10] igb: Fix for improper allocation flag in igb_get_i2c_client
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
  2013-02-08 10:39 ` [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled Jeff Kirsher
  2013-02-08 10:39 ` [net-next 02/10] igb: Fix for improper exit in igb_get_i2c_client Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 04/10] igb: Fix for sparse warning " Jeff Kirsher
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

This patch fixes the allocation function in igb_get_i2c_client to use
GFP_ATOMIC instead of GFP_KERNEL because we have a spinlock.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index d84f28c..c19a35c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -7751,7 +7751,7 @@ igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
 	}
 
 	/* no client_list found, create a new one */
-	client_list = kzalloc(sizeof(*client_list), GFP_KERNEL);
+	client_list = kzalloc(sizeof(*client_list), GFP_ATOMIC);
 	if (client_list == NULL)
 		goto exit;
 
-- 
1.7.11.7

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

* [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (2 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 03/10] igb: Fix for improper allocation flag " Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-11 17:05   ` Ben Hutchings
  2013-02-08 10:39 ` [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx Jeff Kirsher
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

This patch changes definition of i2c_client in igb_get_i2c_client to static
to prevent sparse warning.

Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index c19a35c..ebf8384 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -7732,7 +7732,7 @@ igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
 {
 	ulong flags;
 	struct igb_i2c_client_list *client_list;
-	struct i2c_client *client = NULL;
+	static struct i2c_client *client;
 	struct i2c_board_info client_info = {
 		I2C_BOARD_INFO("igb", 0x00),
 	};
-- 
1.7.11.7

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

* [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (3 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 04/10] igb: Fix for sparse warning " Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 12:26   ` Eric Dumazet
  2013-02-08 10:39 ` [net-next 06/10] igb: Initialize PHY function pointers Jeff Kirsher
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher

From: Alexander Duyck <alexander.h.duyck@intel.com>

After reviewing the igb and ixgbe code I realized there are a few issues in
how the code is structured.  Specifically we are not checking the size of the
buffers being used in transmits and we are not using the same value to
determine when to stop or start a Tx queue.  As such the code is prone to be
buggy.

This patch makes it so that we have one value DESC_NEEDED that we will use for
starting and stopping the queue.  In addition we will check the size of
buffers being used when setting up a transmit so as to avoid a possible buffer
overrun if we were to receive a frame with a block of data larger than 32K in
skb->data.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb.h      | 13 +++++++++++--
 drivers/net/ethernet/intel/igb/igb_main.c | 32 ++++++++++++++++++-------------
 2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index afdb8bb..d27edbc 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -139,8 +139,6 @@ struct vf_data_storage {
 #define IGB_RX_HDR_LEN		IGB_RXBUFFER_256
 #define IGB_RX_BUFSZ		IGB_RXBUFFER_2048
 
-/* How many Tx Descriptors do we need to call netif_wake_queue ? */
-#define IGB_TX_QUEUE_WAKE	16
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
 #define IGB_RX_BUFFER_WRITE	16	/* Must be power of 2 */
 
@@ -169,6 +167,17 @@ enum igb_tx_flags {
 #define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
 #define IGB_TX_FLAGS_VLAN_SHIFT	16
 
+/*
+ * The largest size we can write to the descriptor is 65535.  In order to
+ * maintain a power of two alignment we have to limit ourselves to 32K.
+ */
+#define IGB_MAX_TXD_PWR	15
+#define IGB_MAX_DATA_PER_TXD	(1 << IGB_MAX_TXD_PWR)
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
+#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
+
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct igb_tx_buffer {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ebf8384..e69dd4f 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -4434,13 +4434,6 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
 	tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
 }
 
-/*
- * The largest size we can write to the descriptor is 65535.  In order to
- * maintain a power of two alignment we have to limit ourselves to 32K.
- */
-#define IGB_MAX_TXD_PWR	15
-#define IGB_MAX_DATA_PER_TXD	(1<<IGB_MAX_TXD_PWR)
-
 static void igb_tx_map(struct igb_ring *tx_ring,
 		       struct igb_tx_buffer *first,
 		       const u8 hdr_len)
@@ -4609,15 +4602,27 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
 	struct igb_tx_buffer *first;
 	int tso;
 	u32 tx_flags = 0;
+#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
+	unsigned short f;
+#endif
+	u16 count = TXD_USE_COUNT(skb_headlen(skb));
 	__be16 protocol = vlan_get_protocol(skb);
 	u8 hdr_len = 0;
 
-	/* need: 1 descriptor per page,
+	/*
+	 * need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD,
+	 *       + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD,
 	 *       + 2 desc gap to keep tail from touching head,
-	 *       + 1 desc for skb->data,
 	 *       + 1 desc for context descriptor,
-	 * otherwise try next time */
-	if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
+	 * otherwise try next time
+	 */
+#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
+	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+#else
+	count += skb_shinfo(skb)->nr_frags;
+#endif
+	if (igb_maybe_stop_tx(tx_ring, count + 3)) {
 		/* this is a hard error */
 		return NETDEV_TX_BUSY;
 	}
@@ -4659,7 +4664,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
 	igb_tx_map(tx_ring, first, hdr_len);
 
 	/* Make sure there is space in the ring for the next send. */
-	igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4);
+	igb_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
 	return NETDEV_TX_OK;
 
@@ -6063,9 +6068,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 		}
 	}
 
+#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
 	if (unlikely(total_packets &&
 		     netif_carrier_ok(tx_ring->netdev) &&
-		     igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) {
+		     igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
-- 
1.7.11.7

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

* [net-next 06/10] igb: Initialize PHY function pointers
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (4 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 07/10] igb: Initialize NVM " Jeff Kirsher
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Akeem G. Abodunrin, netdev, gospo, sassmann, Jeff Kirsher

From: "Akeem G. Abodunrin" <akeem.g.abodunrin@intel.com>

This patch initializes PHY function pointers for device configuration.

Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/e1000_82575.c | 112 +++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 54a7c20..fc69414 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -111,6 +111,118 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw)
 	return ext_mdio;
 }
 
+/**
+ *  igb_init_phy_params_82575 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 igb_init_phy_params_82575(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val = 0;
+	u32 ctrl_ext;
+
+	if (hw->phy.media_type != e1000_media_type_copper) {
+		phy->type = e1000_phy_none;
+		goto out;
+	}
+
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 100;
+
+	ctrl_ext = rd32(E1000_CTRL_EXT);
+
+	if (igb_sgmii_active_82575(hw)) {
+		phy->ops.reset = igb_phy_hw_reset_sgmii_82575;
+		ctrl_ext |= E1000_CTRL_I2C_ENA;
+	} else {
+		phy->ops.reset = igb_phy_hw_reset;
+		ctrl_ext &= ~E1000_CTRL_I2C_ENA;
+	}
+
+	wr32(E1000_CTRL_EXT, ctrl_ext);
+	igb_reset_mdicnfg_82580(hw);
+
+	if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) {
+		phy->ops.read_reg = igb_read_phy_reg_sgmii_82575;
+		phy->ops.write_reg = igb_write_phy_reg_sgmii_82575;
+	} else {
+		switch (hw->mac.type) {
+		case e1000_82580:
+		case e1000_i350:
+			phy->ops.read_reg = igb_read_phy_reg_82580;
+			phy->ops.write_reg = igb_write_phy_reg_82580;
+			break;
+		case e1000_i210:
+		case e1000_i211:
+			phy->ops.read_reg = igb_read_phy_reg_gs40g;
+			phy->ops.write_reg = igb_write_phy_reg_gs40g;
+			break;
+		default:
+			phy->ops.read_reg = igb_read_phy_reg_igp;
+			phy->ops.write_reg = igb_write_phy_reg_igp;
+		}
+	}
+
+	/* set lan id */
+	hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >>
+			E1000_STATUS_FUNC_SHIFT;
+
+	/* Set phy->phy_addr and phy->id. */
+	ret_val = igb_get_phy_id_82575(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* Verify phy id and set remaining function pointers */
+	switch (phy->id) {
+	case I347AT4_E_PHY_ID:
+	case M88E1112_E_PHY_ID:
+	case M88E1111_I_PHY_ID:
+		phy->type		= e1000_phy_m88;
+		phy->ops.get_phy_info	= igb_get_phy_info_m88;
+		if (phy->id == I347AT4_E_PHY_ID ||
+		    phy->id == M88E1112_E_PHY_ID)
+			phy->ops.get_cable_length =
+					 igb_get_cable_length_m88_gen2;
+		else
+			phy->ops.get_cable_length = igb_get_cable_length_m88;
+		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
+		break;
+	case IGP03E1000_E_PHY_ID:
+		phy->type = e1000_phy_igp_3;
+		phy->ops.get_phy_info = igb_get_phy_info_igp;
+		phy->ops.get_cable_length = igb_get_cable_length_igp_2;
+		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp;
+		phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82575;
+		phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state;
+		break;
+	case I82580_I_PHY_ID:
+	case I350_I_PHY_ID:
+		phy->type = e1000_phy_82580;
+		phy->ops.force_speed_duplex =
+					 igb_phy_force_speed_duplex_82580;
+		phy->ops.get_cable_length = igb_get_cable_length_82580;
+		phy->ops.get_phy_info = igb_get_phy_info_82580;
+		phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+		phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+		break;
+	case I210_I_PHY_ID:
+		phy->type		= e1000_phy_i210;
+		phy->ops.check_polarity	= igb_check_polarity_m88;
+		phy->ops.get_phy_info	= igb_get_phy_info_m88;
+		phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
+		phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+		phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
+		break;
+	default:
+		ret_val = -E1000_ERR_PHY;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-- 
1.7.11.7

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

* [net-next 07/10] igb: Initialize NVM function pointers
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (5 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 06/10] igb: Initialize PHY function pointers Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 08/10] igb: Intialize MAC " Jeff Kirsher
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Akeem G. Abodunrin, netdev, gospo, sassmann, Jeff Kirsher

From: "Akeem G. Abodunrin" <akeem.g.abodunrin@intel.com>

This patch initializes NVM function pointers for device configuration.

Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/e1000_82575.c | 109 +++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index fc69414..e59fc9b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -223,6 +223,115 @@ out:
 	return ret_val;
 }
 
+/**
+ *  igb_init_nvm_params_82575 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+s32 igb_init_nvm_params_82575(struct e1000_hw *hw)
+{
+	struct e1000_nvm_info *nvm = &hw->nvm;
+	u32 eecd = rd32(E1000_EECD);
+	u16 size;
+
+	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+		     E1000_EECD_SIZE_EX_SHIFT);
+	/* Added to a constant, "size" becomes the left-shift value
+	 * for setting word_size.
+	 */
+	size += NVM_WORD_SIZE_BASE_SHIFT;
+
+	/* Just in case size is out of range, cap it to the largest
+	 * EEPROM size supported
+	 */
+	if (size > 15)
+		size = 15;
+
+	nvm->word_size = 1 << size;
+	if (hw->mac.type < e1000_i210) {
+		nvm->opcode_bits = 8;
+		nvm->delay_usec = 1;
+
+		switch (nvm->override) {
+		case e1000_nvm_override_spi_large:
+			nvm->page_size = 32;
+			nvm->address_bits = 16;
+			break;
+		case e1000_nvm_override_spi_small:
+			nvm->page_size = 8;
+			nvm->address_bits = 8;
+			break;
+		default:
+			nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+			nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
+					    16 : 8;
+			break;
+		}
+		if (nvm->word_size == (1 << 15))
+			nvm->page_size = 128;
+
+		nvm->type = e1000_nvm_eeprom_spi;
+	} else {
+		nvm->type = e1000_nvm_flash_hw;
+	}
+
+	/* NVM Function Pointers */
+	switch (hw->mac.type) {
+	case e1000_82580:
+		nvm->ops.validate = igb_validate_nvm_checksum_82580;
+		nvm->ops.update = igb_update_nvm_checksum_82580;
+		nvm->ops.acquire = igb_acquire_nvm_82575;
+		nvm->ops.release = igb_release_nvm_82575;
+		if (nvm->word_size < (1 << 15))
+			nvm->ops.read = igb_read_nvm_eerd;
+		else
+			nvm->ops.read = igb_read_nvm_spi;
+		nvm->ops.write = igb_write_nvm_spi;
+		break;
+	case e1000_i350:
+		nvm->ops.validate = igb_validate_nvm_checksum_i350;
+		nvm->ops.update = igb_update_nvm_checksum_i350;
+		nvm->ops.acquire = igb_acquire_nvm_82575;
+		nvm->ops.release = igb_release_nvm_82575;
+		if (nvm->word_size < (1 << 15))
+			nvm->ops.read = igb_read_nvm_eerd;
+		else
+			nvm->ops.read = igb_read_nvm_spi;
+		nvm->ops.write = igb_write_nvm_spi;
+		break;
+	case e1000_i210:
+		nvm->ops.validate = igb_validate_nvm_checksum_i210;
+		nvm->ops.update   = igb_update_nvm_checksum_i210;
+		nvm->ops.acquire = igb_acquire_nvm_i210;
+		nvm->ops.release = igb_release_nvm_i210;
+		nvm->ops.read    = igb_read_nvm_srrd_i210;
+		nvm->ops.write   = igb_write_nvm_srwr_i210;
+		nvm->ops.valid_led_default = igb_valid_led_default_i210;
+		break;
+	case e1000_i211:
+		nvm->ops.acquire  = igb_acquire_nvm_i210;
+		nvm->ops.release  = igb_release_nvm_i210;
+		nvm->ops.read     = igb_read_nvm_i211;
+		nvm->ops.valid_led_default = igb_valid_led_default_i210;
+		nvm->ops.validate = NULL;
+		nvm->ops.update   = NULL;
+		nvm->ops.write    = NULL;
+		break;
+	default:
+		nvm->ops.validate = igb_validate_nvm_checksum;
+		nvm->ops.update = igb_update_nvm_checksum;
+		nvm->ops.acquire = igb_acquire_nvm_82575;
+		nvm->ops.release = igb_release_nvm_82575;
+		if (nvm->word_size < (1 << 15))
+			nvm->ops.read = igb_read_nvm_eerd;
+		else
+			nvm->ops.read = igb_read_nvm_spi;
+		nvm->ops.write = igb_write_nvm_spi;
+		break;
+	}
+
+	return 0;
+}
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-- 
1.7.11.7

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

* [net-next 08/10] igb: Intialize MAC function pointers
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (6 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 07/10] igb: Initialize NVM " Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 09/10] igb: Refractoring function pointers in igb_get_invariants function Jeff Kirsher
  2013-02-08 10:39 ` [net-next 10/10] ixgbe: refactor initialization of feature flags Jeff Kirsher
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Akeem G. Abodunrin, netdev, gospo, sassmann, Jeff Kirsher

From: "Akeem G. Abodunrin" <akeem.g.abodunrin@intel.com>

This patch initializes MAC function pointers for device configuration.

Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/e1000_82575.c | 61 ++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index e59fc9b..8604013 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -332,6 +332,67 @@ s32 igb_init_nvm_params_82575(struct e1000_hw *hw)
 	return 0;
 }
 
+/**
+ *  igb_init_mac_params_82575 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
+{
+	struct e1000_mac_info *mac = &hw->mac;
+	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	switch (mac->type) {
+	case e1000_82576:
+		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
+		break;
+	case e1000_82580:
+		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+		break;
+	case e1000_i350:
+		mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+		break;
+	default:
+		mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
+		break;
+	}
+	/* reset */
+	if (mac->type >= e1000_82580)
+		mac->ops.reset_hw = igb_reset_hw_82580;
+	else
+		mac->ops.reset_hw = igb_reset_hw_82575;
+
+	if (mac->type >= e1000_i210) {
+		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210;
+		mac->ops.release_swfw_sync = igb_release_swfw_sync_i210;
+
+	} else {
+		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575;
+		mac->ops.release_swfw_sync = igb_release_swfw_sync_82575;
+	}
+
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+	/* Set if manageability features are enabled. */
+	mac->arc_subsystem_valid =
+		(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
+			? true : false;
+	/* enable EEE on i350 parts and later parts */
+	if (mac->type >= e1000_i350)
+		dev_spec->eee_disable = false;
+	else
+		dev_spec->eee_disable = true;
+	/* physical interface link setup */
+	mac->ops.setup_physical_interface =
+		(hw->phy.media_type == e1000_media_type_copper)
+			? igb_setup_copper_link_82575
+			: igb_setup_serdes_link_82575;
+
+	return 0;
+}
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-- 
1.7.11.7

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

* [net-next 09/10] igb: Refractoring function pointers in igb_get_invariants function
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (7 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 08/10] igb: Intialize MAC " Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  2013-02-08 10:39 ` [net-next 10/10] ixgbe: refactor initialization of feature flags Jeff Kirsher
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Akeem G. Abodunrin, netdev, gospo, sassmann, Jeff Kirsher

From: "Akeem G. Abodunrin" <akeem.g.abodunrin@intel.com>

This patch simplifies igb_get_invariants function by moving all implemented
function pointers in this function to individual separate functions,
based on their functionalities, this would make debugging much easier.

Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/e1000_82575.c | 262 ++-------------------------
 1 file changed, 11 insertions(+), 251 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 8604013..84e7e09 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -395,13 +395,9 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
 
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
-	struct e1000_phy_info *phy = &hw->phy;
-	struct e1000_nvm_info *nvm = &hw->nvm;
 	struct e1000_mac_info *mac = &hw->mac;
 	struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575;
-	u32 eecd;
 	s32 ret_val;
-	u16 size;
 	u32 ctrl_ext = 0;
 
 	switch (hw->device_id) {
@@ -462,7 +458,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 	 * SerDes mode on the 82575. There can be an external PHY attached
 	 * on the SGMII interface. For this, we'll set sgmii_active to true.
 	 */
-	phy->media_type = e1000_media_type_copper;
+	hw->phy.media_type = e1000_media_type_copper;
 	dev_spec->sgmii_active = false;
 
 	ctrl_ext = rd32(E1000_CTRL_EXT);
@@ -478,154 +474,15 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 		break;
 	}
 
-	/* Set mta register count */
-	mac->mta_reg_count = 128;
-	/* Set rar entry count */
-	switch (mac->type) {
-	case e1000_82576:
-		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
-		break;
-	case e1000_82580:
-		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
-		break;
-	case e1000_i350:
-		mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
-		break;
-	default:
-		mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
-		break;
-	}
-	/* reset */
-	if (mac->type >= e1000_82580)
-		mac->ops.reset_hw = igb_reset_hw_82580;
-	else
-		mac->ops.reset_hw = igb_reset_hw_82575;
-
-	if (mac->type >= e1000_i210) {
-		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210;
-		mac->ops.release_swfw_sync = igb_release_swfw_sync_i210;
-	} else {
-		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575;
-		mac->ops.release_swfw_sync = igb_release_swfw_sync_82575;
-	}
-
-	/* Set if part includes ASF firmware */
-	mac->asf_firmware_present = true;
-	/* Set if manageability features are enabled. */
-	mac->arc_subsystem_valid =
-		(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
-			? true : false;
-	/* enable EEE on i350 parts and later parts */
-	if (mac->type >= e1000_i350)
-		dev_spec->eee_disable = false;
-	else
-		dev_spec->eee_disable = true;
-	/* physical interface link setup */
-	mac->ops.setup_physical_interface =
-		(hw->phy.media_type == e1000_media_type_copper)
-			? igb_setup_copper_link_82575
-			: igb_setup_serdes_link_82575;
+	/* mac initialization and operations */
+	ret_val = igb_init_mac_params_82575(hw);
+	if (ret_val)
+		goto out;
 
 	/* NVM initialization */
-	eecd = rd32(E1000_EECD);
-	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
-		     E1000_EECD_SIZE_EX_SHIFT);
-
-	/*
-	 * Added to a constant, "size" becomes the left-shift value
-	 * for setting word_size.
-	 */
-	size += NVM_WORD_SIZE_BASE_SHIFT;
-
-	/*
-	 * Check for invalid size
-	 */
-	if ((hw->mac.type == e1000_82576) && (size > 15)) {
-		pr_notice("The NVM size is not valid, defaulting to 32K\n");
-		size = 15;
-	}
-
-	nvm->word_size = 1 << size;
-	if (hw->mac.type < e1000_i210) {
-		nvm->opcode_bits        = 8;
-		nvm->delay_usec         = 1;
-		switch (nvm->override) {
-		case e1000_nvm_override_spi_large:
-			nvm->page_size    = 32;
-			nvm->address_bits = 16;
-			break;
-		case e1000_nvm_override_spi_small:
-			nvm->page_size    = 8;
-			nvm->address_bits = 8;
-			break;
-		default:
-			nvm->page_size    = eecd
-				& E1000_EECD_ADDR_BITS ? 32 : 8;
-			nvm->address_bits = eecd
-				& E1000_EECD_ADDR_BITS ? 16 : 8;
-			break;
-		}
-		if (nvm->word_size == (1 << 15))
-			nvm->page_size = 128;
-
-		nvm->type = e1000_nvm_eeprom_spi;
-	} else
-		nvm->type = e1000_nvm_flash_hw;
-
-	/* NVM Function Pointers */
-	switch (hw->mac.type) {
-	case e1000_82580:
-		nvm->ops.validate = igb_validate_nvm_checksum_82580;
-		nvm->ops.update = igb_update_nvm_checksum_82580;
-		nvm->ops.acquire = igb_acquire_nvm_82575;
-		nvm->ops.release = igb_release_nvm_82575;
-		if (nvm->word_size < (1 << 15))
-			nvm->ops.read = igb_read_nvm_eerd;
-		else
-			nvm->ops.read = igb_read_nvm_spi;
-		nvm->ops.write = igb_write_nvm_spi;
-		break;
-	case e1000_i350:
-		nvm->ops.validate = igb_validate_nvm_checksum_i350;
-		nvm->ops.update = igb_update_nvm_checksum_i350;
-		nvm->ops.acquire = igb_acquire_nvm_82575;
-		nvm->ops.release = igb_release_nvm_82575;
-		if (nvm->word_size < (1 << 15))
-			nvm->ops.read = igb_read_nvm_eerd;
-		else
-			nvm->ops.read = igb_read_nvm_spi;
-		nvm->ops.write = igb_write_nvm_spi;
-		break;
-	case e1000_i210:
-		nvm->ops.validate = igb_validate_nvm_checksum_i210;
-		nvm->ops.update   = igb_update_nvm_checksum_i210;
-		nvm->ops.acquire = igb_acquire_nvm_i210;
-		nvm->ops.release = igb_release_nvm_i210;
-		nvm->ops.read    = igb_read_nvm_srrd_i210;
-		nvm->ops.write   = igb_write_nvm_srwr_i210;
-		nvm->ops.valid_led_default = igb_valid_led_default_i210;
-		break;
-	case e1000_i211:
-		nvm->ops.acquire  = igb_acquire_nvm_i210;
-		nvm->ops.release  = igb_release_nvm_i210;
-		nvm->ops.read     = igb_read_nvm_i211;
-		nvm->ops.valid_led_default = igb_valid_led_default_i210;
-		nvm->ops.validate = NULL;
-		nvm->ops.update   = NULL;
-		nvm->ops.write    = NULL;
-		break;
-	default:
-		nvm->ops.validate = igb_validate_nvm_checksum;
-		nvm->ops.update = igb_update_nvm_checksum;
-		nvm->ops.acquire = igb_acquire_nvm_82575;
-		nvm->ops.release = igb_release_nvm_82575;
-		if (nvm->word_size < (1 << 15))
-			nvm->ops.read = igb_read_nvm_eerd;
-		else
-			nvm->ops.read = igb_read_nvm_spi;
-		nvm->ops.write = igb_write_nvm_spi;
-		break;
-	}
+	ret_val = igb_init_nvm_params_82575(hw);
+	if (ret_val)
+		goto out;
 
 	/* if part supports SR-IOV then initialize mailbox parameters */
 	switch (mac->type) {
@@ -638,107 +495,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 	}
 
 	/* setup PHY parameters */
-	if (phy->media_type != e1000_media_type_copper) {
-		phy->type = e1000_phy_none;
-		return 0;
-	}
-
-	phy->autoneg_mask        = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-	phy->reset_delay_us      = 100;
-
-	ctrl_ext = rd32(E1000_CTRL_EXT);
-
-	/* PHY function pointers */
-	if (igb_sgmii_active_82575(hw)) {
-		phy->ops.reset      = igb_phy_hw_reset_sgmii_82575;
-		ctrl_ext |= E1000_CTRL_I2C_ENA;
-	} else {
-		phy->ops.reset      = igb_phy_hw_reset;
-		ctrl_ext &= ~E1000_CTRL_I2C_ENA;
-	}
-
-	wr32(E1000_CTRL_EXT, ctrl_ext);
-	igb_reset_mdicnfg_82580(hw);
-
-	if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) {
-		phy->ops.read_reg   = igb_read_phy_reg_sgmii_82575;
-		phy->ops.write_reg  = igb_write_phy_reg_sgmii_82575;
-	} else if ((hw->mac.type == e1000_82580)
-		|| (hw->mac.type == e1000_i350)) {
-		phy->ops.read_reg   = igb_read_phy_reg_82580;
-		phy->ops.write_reg  = igb_write_phy_reg_82580;
-	} else if (hw->phy.type >= e1000_phy_i210) {
-		phy->ops.read_reg   = igb_read_phy_reg_gs40g;
-		phy->ops.write_reg  = igb_write_phy_reg_gs40g;
-	} else {
-		phy->ops.read_reg   = igb_read_phy_reg_igp;
-		phy->ops.write_reg  = igb_write_phy_reg_igp;
-	}
-
-	/* set lan id */
-	hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >>
-	               E1000_STATUS_FUNC_SHIFT;
+	ret_val = igb_init_phy_params_82575(hw);
 
-	/* Set phy->phy_addr and phy->id. */
-	ret_val = igb_get_phy_id_82575(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Verify phy id and set remaining function pointers */
-	switch (phy->id) {
-	case I347AT4_E_PHY_ID:
-	case M88E1112_E_PHY_ID:
-	case M88E1111_I_PHY_ID:
-		phy->type                   = e1000_phy_m88;
-		phy->ops.get_phy_info       = igb_get_phy_info_m88;
-
-		if (phy->id == I347AT4_E_PHY_ID ||
-		    phy->id == M88E1112_E_PHY_ID)
-			phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
-		else
-			phy->ops.get_cable_length = igb_get_cable_length_m88;
-
-		if (phy->id == I210_I_PHY_ID) {
-			phy->ops.get_cable_length =
-					 igb_get_cable_length_m88_gen2;
-			phy->ops.set_d0_lplu_state =
-					igb_set_d0_lplu_state_82580;
-			phy->ops.set_d3_lplu_state =
-					igb_set_d3_lplu_state_82580;
-		}
-		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
-		break;
-	case IGP03E1000_E_PHY_ID:
-		phy->type                   = e1000_phy_igp_3;
-		phy->ops.get_phy_info       = igb_get_phy_info_igp;
-		phy->ops.get_cable_length   = igb_get_cable_length_igp_2;
-		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp;
-		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82575;
-		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state;
-		break;
-	case I82580_I_PHY_ID:
-	case I350_I_PHY_ID:
-		phy->type                   = e1000_phy_82580;
-		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580;
-		phy->ops.get_cable_length   = igb_get_cable_length_82580;
-		phy->ops.get_phy_info       = igb_get_phy_info_82580;
-		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82580;
-		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state_82580;
-		break;
-	case I210_I_PHY_ID:
-		phy->type                   = e1000_phy_i210;
-		phy->ops.get_phy_info       = igb_get_phy_info_m88;
-		phy->ops.check_polarity     = igb_check_polarity_m88;
-		phy->ops.get_cable_length   = igb_get_cable_length_m88_gen2;
-		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82580;
-		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state_82580;
-		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
-		break;
-	default:
-		return -E1000_ERR_PHY;
-	}
-
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
-- 
1.7.11.7

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

* [net-next 10/10] ixgbe: refactor initialization of feature flags
  2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
                   ` (8 preceding siblings ...)
  2013-02-08 10:39 ` [net-next 09/10] igb: Refractoring function pointers in igb_get_invariants function Jeff Kirsher
@ 2013-02-08 10:39 ` Jeff Kirsher
  9 siblings, 0 replies; 19+ messages in thread
From: Jeff Kirsher @ 2013-02-08 10:39 UTC (permalink / raw)
  To: davem; +Cc: Emil Tantilov, netdev, gospo, sassmann, Jeff Kirsher

From: Emil Tantilov <emil.s.tantilov@intel.com>

This patch reshuffles the switch/case structure of the flag assignment to
allow for the flags to be set for each MAC type separately. This is needed
for new HW that does not have feature parity with older HW.

Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Tested-by: Jack Morgan <jack.morgan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 58 ++++++++++++++++++---------
 1 file changed, 38 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 396e280..693b158 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4479,38 +4479,56 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
 
-	/* Set capability flags */
+	/* Set common capability flags and settings */
 	rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus());
 	adapter->ring_feature[RING_F_RSS].limit = rss;
+	adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
+	adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+	adapter->ring_feature[RING_F_FDIR].limit = IXGBE_MAX_FDIR_INDICES;
+	adapter->max_q_vectors = MAX_Q_VECTORS_82599;
+	adapter->atr_sample_rate = 20;
+	adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
+#ifdef CONFIG_IXGBE_DCA
+	adapter->flags |= IXGBE_FLAG_DCA_CAPABLE;
+#endif
+#ifdef IXGBE_FCOE
+	adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
+	adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+#ifdef CONFIG_IXGBE_DCB
+	/* Default traffic class to use for FCoE */
+	adapter->fcoe.up = IXGBE_FCOE_DEFTC;
+#endif /* CONFIG_IXGBE_DCB */
+#endif /* IXGBE_FCOE */
+
+	/* Set MAC specific capability flags and exceptions */
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
+		adapter->flags2 &= ~IXGBE_FLAG2_RSC_CAPABLE;
+		adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+
 		if (hw->device_id == IXGBE_DEV_ID_82598AT)
 			adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
+
 		adapter->max_q_vectors = MAX_Q_VECTORS_82598;
+		adapter->ring_feature[RING_F_FDIR].limit = 0;
+		adapter->atr_sample_rate = 0;
+		adapter->fdir_pballoc = 0;
+#ifdef IXGBE_FCOE
+		adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
+		adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+#ifdef CONFIG_IXGBE_DCB
+		adapter->fcoe.up = 0;
+#endif /* IXGBE_DCB */
+#endif /* IXGBE_FCOE */
+		break;
+	case ixgbe_mac_82599EB:
+		if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM)
+			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
 		break;
 	case ixgbe_mac_X540:
 		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
 		if (fwsm & IXGBE_FWSM_TS_ENABLED)
 			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
-	case ixgbe_mac_82599EB:
-		adapter->max_q_vectors = MAX_Q_VECTORS_82599;
-		adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
-		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
-		if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM)
-			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
-		/* Flow Director hash filters enabled */
-		adapter->atr_sample_rate = 20;
-		adapter->ring_feature[RING_F_FDIR].limit =
-							 IXGBE_MAX_FDIR_INDICES;
-		adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
-#ifdef IXGBE_FCOE
-		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
-		adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
-#ifdef CONFIG_IXGBE_DCB
-		/* Default traffic class to use for FCoE */
-		adapter->fcoe.up = IXGBE_FCOE_DEFTC;
-#endif
-#endif /* IXGBE_FCOE */
 		break;
 	default:
 		break;
-- 
1.7.11.7

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

* Re: [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
  2013-02-08 10:39 ` [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx Jeff Kirsher
@ 2013-02-08 12:26   ` Eric Dumazet
  2013-02-08 17:11     ` Alexander Duyck
  0 siblings, 1 reply; 19+ messages in thread
From: Eric Dumazet @ 2013-02-08 12:26 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem, Alexander Duyck, netdev, gospo, sassmann

On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> After reviewing the igb and ixgbe code I realized there are a few issues in
> how the code is structured.  Specifically we are not checking the size of the
> buffers being used in transmits and we are not using the same value to
> determine when to stop or start a Tx queue.  As such the code is prone to be
> buggy.
> 
> This patch makes it so that we have one value DESC_NEEDED that we will use for
> starting and stopping the queue.  In addition we will check the size of
> buffers being used when setting up a transmit so as to avoid a possible buffer
> overrun if we were to receive a frame with a block of data larger than 32K in
> skb->data.
> 
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>  drivers/net/ethernet/intel/igb/igb.h      | 13 +++++++++++--
>  drivers/net/ethernet/intel/igb/igb_main.c | 32 ++++++++++++++++++-------------
>  2 files changed, 30 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
> index afdb8bb..d27edbc 100644
> --- a/drivers/net/ethernet/intel/igb/igb.h
> +++ b/drivers/net/ethernet/intel/igb/igb.h
> @@ -139,8 +139,6 @@ struct vf_data_storage {
>  #define IGB_RX_HDR_LEN		IGB_RXBUFFER_256
>  #define IGB_RX_BUFSZ		IGB_RXBUFFER_2048
>  
> -/* How many Tx Descriptors do we need to call netif_wake_queue ? */
> -#define IGB_TX_QUEUE_WAKE	16
>  /* How many Rx Buffers do we bundle into one write to the hardware ? */
>  #define IGB_RX_BUFFER_WRITE	16	/* Must be power of 2 */
>  
> @@ -169,6 +167,17 @@ enum igb_tx_flags {
>  #define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
>  #define IGB_TX_FLAGS_VLAN_SHIFT	16
>  
> +/*
> + * The largest size we can write to the descriptor is 65535.  In order to
> + * maintain a power of two alignment we have to limit ourselves to 32K.
> + */
> +#define IGB_MAX_TXD_PWR	15
> +#define IGB_MAX_DATA_PER_TXD	(1 << IGB_MAX_TXD_PWR)
> +
> +/* Tx Descriptors needed, worst case */
> +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
> +#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
> +
>  /* wrapper around a pointer to a socket buffer,
>   * so a DMA handle can be stored along with the buffer */
>  struct igb_tx_buffer {
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index ebf8384..e69dd4f 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -4434,13 +4434,6 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
>  	tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
>  }
>  
> -/*
> - * The largest size we can write to the descriptor is 65535.  In order to
> - * maintain a power of two alignment we have to limit ourselves to 32K.
> - */
> -#define IGB_MAX_TXD_PWR	15
> -#define IGB_MAX_DATA_PER_TXD	(1<<IGB_MAX_TXD_PWR)
> -
>  static void igb_tx_map(struct igb_ring *tx_ring,
>  		       struct igb_tx_buffer *first,
>  		       const u8 hdr_len)
> @@ -4609,15 +4602,27 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
>  	struct igb_tx_buffer *first;
>  	int tso;
>  	u32 tx_flags = 0;
> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
> +	unsigned short f;
> +#endif
> +	u16 count = TXD_USE_COUNT(skb_headlen(skb));
>  	__be16 protocol = vlan_get_protocol(skb);
>  	u8 hdr_len = 0;
>  
> -	/* need: 1 descriptor per page,
> +	/*
> +	 * need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD,
> +	 *       + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD,
>  	 *       + 2 desc gap to keep tail from touching head,
> -	 *       + 1 desc for skb->data,
>  	 *       + 1 desc for context descriptor,
> -	 * otherwise try next time */
> -	if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
> +	 * otherwise try next time
> +	 */
> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD

This code assumes a frag is at most PAGE_SIZE, but its not true.

> +	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
> +		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
> +#else
> +	count += skb_shinfo(skb)->nr_frags;
> +#endif

Current practical limit is 32768 bytes on x86

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

* Re: [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
  2013-02-08 12:26   ` Eric Dumazet
@ 2013-02-08 17:11     ` Alexander Duyck
  2013-02-08 19:18       ` David Miller
  0 siblings, 1 reply; 19+ messages in thread
From: Alexander Duyck @ 2013-02-08 17:11 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Jeff Kirsher, davem, netdev, gospo, sassmann

On 2/8/2013 4:26 AM, Eric Dumazet wrote:
> On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
>> From: Alexander Duyck <alexander.h.duyck@intel.com>
>>
>> After reviewing the igb and ixgbe code I realized there are a few issues in
>> how the code is structured.  Specifically we are not checking the size of the
>> buffers being used in transmits and we are not using the same value to
>> determine when to stop or start a Tx queue.  As such the code is prone to be
>> buggy.
>>
>> This patch makes it so that we have one value DESC_NEEDED that we will use for
>> starting and stopping the queue.  In addition we will check the size of
>> buffers being used when setting up a transmit so as to avoid a possible buffer
>> overrun if we were to receive a frame with a block of data larger than 32K in
>> skb->data.
>>
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>>   drivers/net/ethernet/intel/igb/igb.h      | 13 +++++++++++--
>>   drivers/net/ethernet/intel/igb/igb_main.c | 32 ++++++++++++++++++-------------
>>   2 files changed, 30 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
>> index afdb8bb..d27edbc 100644
>> --- a/drivers/net/ethernet/intel/igb/igb.h
>> +++ b/drivers/net/ethernet/intel/igb/igb.h
>> @@ -139,8 +139,6 @@ struct vf_data_storage {
>>   #define IGB_RX_HDR_LEN		IGB_RXBUFFER_256
>>   #define IGB_RX_BUFSZ		IGB_RXBUFFER_2048
>>   
>> -/* How many Tx Descriptors do we need to call netif_wake_queue ? */
>> -#define IGB_TX_QUEUE_WAKE	16
>>   /* How many Rx Buffers do we bundle into one write to the hardware ? */
>>   #define IGB_RX_BUFFER_WRITE	16	/* Must be power of 2 */
>>   
>> @@ -169,6 +167,17 @@ enum igb_tx_flags {
>>   #define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
>>   #define IGB_TX_FLAGS_VLAN_SHIFT	16
>>   
>> +/*
>> + * The largest size we can write to the descriptor is 65535.  In order to
>> + * maintain a power of two alignment we have to limit ourselves to 32K.
>> + */
>> +#define IGB_MAX_TXD_PWR	15
>> +#define IGB_MAX_DATA_PER_TXD	(1 << IGB_MAX_TXD_PWR)
>> +
>> +/* Tx Descriptors needed, worst case */
>> +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
>> +#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
>> +
>>   /* wrapper around a pointer to a socket buffer,
>>    * so a DMA handle can be stored along with the buffer */
>>   struct igb_tx_buffer {
>> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
>> index ebf8384..e69dd4f 100644
>> --- a/drivers/net/ethernet/intel/igb/igb_main.c
>> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
>> @@ -4434,13 +4434,6 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
>>   	tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
>>   }
>>   
>> -/*
>> - * The largest size we can write to the descriptor is 65535.  In order to
>> - * maintain a power of two alignment we have to limit ourselves to 32K.
>> - */
>> -#define IGB_MAX_TXD_PWR	15
>> -#define IGB_MAX_DATA_PER_TXD	(1<<IGB_MAX_TXD_PWR)
>> -
>>   static void igb_tx_map(struct igb_ring *tx_ring,
>>   		       struct igb_tx_buffer *first,
>>   		       const u8 hdr_len)
>> @@ -4609,15 +4602,27 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
>>   	struct igb_tx_buffer *first;
>>   	int tso;
>>   	u32 tx_flags = 0;
>> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
>> +	unsigned short f;
>> +#endif
>> +	u16 count = TXD_USE_COUNT(skb_headlen(skb));
>>   	__be16 protocol = vlan_get_protocol(skb);
>>   	u8 hdr_len = 0;
>>   
>> -	/* need: 1 descriptor per page,
>> +	/*
>> +	 * need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD,
>> +	 *       + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD,
>>   	 *       + 2 desc gap to keep tail from touching head,
>> -	 *       + 1 desc for skb->data,
>>   	 *       + 1 desc for context descriptor,
>> -	 * otherwise try next time */
>> -	if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
>> +	 * otherwise try next time
>> +	 */
>> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
> This code assumes a frag is at most PAGE_SIZE, but its not true.
>
>> +	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
>> +		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
>> +#else
>> +	count += skb_shinfo(skb)->nr_frags;
>> +#endif
> Current practical limit is 32768 bytes on x86

For igb the IGB_MAX_DATA_PER_TXD is 32K as well.  So if I am not 
mistaken we should be fine.  The only time we risk exceeding that is if 
we have 64K page size.  It sounds like we may need to work in the ixgbe 
driver though since I believe the limit for it is only 16K per descriptor.

I will also submit an update for this patch that replaces PAGE_SIZE with 
NETDEV_FRAG_PAGE_MAX_SIZE in order to keep the two in sync.

Thanks,

Alex

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

* Re: [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
  2013-02-08 17:11     ` Alexander Duyck
@ 2013-02-08 19:18       ` David Miller
  2013-02-08 20:19         ` Alexander Duyck
  0 siblings, 1 reply; 19+ messages in thread
From: David Miller @ 2013-02-08 19:18 UTC (permalink / raw)
  To: alexander.h.duyck
  Cc: eric.dumazet, jeffrey.t.kirsher, netdev, gospo, sassmann

From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Fri, 08 Feb 2013 09:11:10 -0800

> For igb the IGB_MAX_DATA_PER_TXD is 32K as well.  So if I am not
> mistaken we should be fine.  The only time we risk exceeding that is
> if we have 64K page size.  It sounds like we may need to work in the
> ixgbe driver though since I believe the limit for it is only 16K per
> descriptor.
> 
> I will also submit an update for this patch that replaces PAGE_SIZE
> with NETDEV_FRAG_PAGE_MAX_SIZE in order to keep the two in sync.

I therefore expect a respin of this series from Jeff once the
update of this patch is resolved.

Thanks.

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

* Re: [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
  2013-02-08 19:18       ` David Miller
@ 2013-02-08 20:19         ` Alexander Duyck
  0 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2013-02-08 20:19 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, jeffrey.t.kirsher, netdev, gospo, sassmann

On 2/8/2013 11:18 AM, David Miller wrote:
> From: Alexander Duyck <alexander.h.duyck@intel.com>
> Date: Fri, 08 Feb 2013 09:11:10 -0800
>
>> For igb the IGB_MAX_DATA_PER_TXD is 32K as well.  So if I am not
>> mistaken we should be fine.  The only time we risk exceeding that is
>> if we have 64K page size.  It sounds like we may need to work in the
>> ixgbe driver though since I believe the limit for it is only 16K per
>> descriptor.
>>
>> I will also submit an update for this patch that replaces PAGE_SIZE
>> with NETDEV_FRAG_PAGE_MAX_SIZE in order to keep the two in sync.
> I therefore expect a respin of this series from Jeff once the
> update of this patch is resolved.
>
> Thanks.

I will work with Jeff to get that resolved.  Also I will be submitting 
one patch directly it looks like since NETDEV_FRAG_PAGE_MAX_SIZE turns 
out to be defined in skbuff.c so I will need to pull it into skbuff.h 
most likely.

Thanks,

Alex

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

* Re: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
  2013-02-08 10:39 ` [net-next 04/10] igb: Fix for sparse warning " Jeff Kirsher
@ 2013-02-11 17:05   ` Ben Hutchings
  2013-02-11 17:27     ` Wyborny, Carolyn
                       ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Ben Hutchings @ 2013-02-11 17:05 UTC (permalink / raw)
  To: Jeff Kirsher, Carolyn Wyborny; +Cc: davem, netdev, gospo, sassmann

On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> From: Carolyn Wyborny <carolyn.wyborny@intel.com>
> 
> This patch changes definition of i2c_client in igb_get_i2c_client to static
> to prevent sparse warning.

So, in order to fix the warning:

drivers/net/ethernet/intel/igb/igb_main.c:7611:19: warning: symbol 'igb_get_i2c_client' was not declared. Should it be static?

you don't touch the function declaration, but instead make a local
variable static.  This doesn't fix the warning, but does introduce a
race condition...

Ben.

> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>  drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index c19a35c..ebf8384 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -7732,7 +7732,7 @@ igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
>  {
>  	ulong flags;
>  	struct igb_i2c_client_list *client_list;
> -	struct i2c_client *client = NULL;
> +	static struct i2c_client *client;
>  	struct i2c_board_info client_info = {
>  		I2C_BOARD_INFO("igb", 0x00),
>  	};

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

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

* RE: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
  2013-02-11 17:05   ` Ben Hutchings
@ 2013-02-11 17:27     ` Wyborny, Carolyn
  2013-02-12 17:12     ` Wyborny, Carolyn
  2013-02-12 17:17     ` Wyborny, Carolyn
  2 siblings, 0 replies; 19+ messages in thread
From: Wyborny, Carolyn @ 2013-02-11 17:27 UTC (permalink / raw)
  To: Ben Hutchings, Kirsher, Jeffrey T; +Cc: davem, netdev, gospo, sassmann

> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Ben Hutchings
> Sent: Monday, February 11, 2013 9:06 AM
> To: Kirsher, Jeffrey T; Wyborny, Carolyn
> Cc: davem@davemloft.net; netdev@vger.kernel.org; gospo@redhat.com;
> sassmann@redhat.com
> Subject: Re: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
> 
> On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> > From: Carolyn Wyborny <carolyn.wyborny@intel.com>
> >
> > This patch changes definition of i2c_client in igb_get_i2c_client to
> > static to prevent sparse warning.
> 
> So, in order to fix the warning:
> 
> drivers/net/ethernet/intel/igb/igb_main.c:7611:19: warning: symbol
> 'igb_get_i2c_client' was not declared. Should it be static?
> 
> you don't touch the function declaration, but instead make a local variable
> static.  This doesn't fix the warning, but does introduce a race condition...
> 
> Ben.
> 
> > Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> > Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
> > Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> > Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> > ---
> >  drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/intel/igb/igb_main.c
> > b/drivers/net/ethernet/intel/igb/igb_main.c
> > index c19a35c..ebf8384 100644
> > --- a/drivers/net/ethernet/intel/igb/igb_main.c
> > +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> > @@ -7732,7 +7732,7 @@ igb_get_i2c_client(struct igb_adapter *adapter,
> > u8 dev_addr)  {
> >  	ulong flags;
> >  	struct igb_i2c_client_list *client_list;
> > -	struct i2c_client *client = NULL;
> > +	static struct i2c_client *client;
> >  	struct i2c_board_info client_info = {
> >  		I2C_BOARD_INFO("igb", 0x00),
> >  	};
> 
> --
> Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's
> the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
> 
> --
> 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

Yes, my mistake in taking a quick suggestion without enough evaluation.  I'm in the process of completely redoing this to not allocate clients on the fly which will fully fix this problem and the initial one.

Thanks,

Carolyn

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

* RE: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
  2013-02-11 17:05   ` Ben Hutchings
  2013-02-11 17:27     ` Wyborny, Carolyn
@ 2013-02-12 17:12     ` Wyborny, Carolyn
  2013-02-12 17:17     ` Wyborny, Carolyn
  2 siblings, 0 replies; 19+ messages in thread
From: Wyborny, Carolyn @ 2013-02-12 17:12 UTC (permalink / raw)
  To: Ben Hutchings, Kirsher, Jeffrey T; +Cc: davem, netdev, gospo, sassmann

> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Ben Hutchings
> Sent: Monday, February 11, 2013 9:06 AM
> To: Kirsher, Jeffrey T; Wyborny, Carolyn
> Cc: davem@davemloft.net; netdev@vger.kernel.org; gospo@redhat.com;
> sassmann@redhat.com
> Subject: Re: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
> 
> On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> > From: Carolyn Wyborny <carolyn.wyborny@intel.com>
> >
> > This patch changes definition of i2c_client in igb_get_i2c_client to
> > static to prevent sparse warning.
> 
> So, in order to fix the warning:
> 
> drivers/net/ethernet/intel/igb/igb_main.c:7611:19: warning: symbol
> 'igb_get_i2c_client' was not declared. Should it be static?
[..]

And this was not the warning I was trying to fix with the static change.  The sparse warning was "cast to 
restricted __le64."  Not sure why you are seeing that particular warning, but I will look for it in my next patch on this function.

Thanks,

Carolyn

Carolyn Wyborny 
Linux Development 
Networking Division 
Intel Corporation 



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

* RE: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
  2013-02-11 17:05   ` Ben Hutchings
  2013-02-11 17:27     ` Wyborny, Carolyn
  2013-02-12 17:12     ` Wyborny, Carolyn
@ 2013-02-12 17:17     ` Wyborny, Carolyn
  2 siblings, 0 replies; 19+ messages in thread
From: Wyborny, Carolyn @ 2013-02-12 17:17 UTC (permalink / raw)
  To: Ben Hutchings, Kirsher, Jeffrey T; +Cc: davem, netdev, gospo, sassmann

> -----Original Message-----
> From: Wyborny, Carolyn
> Sent: Tuesday, February 12, 2013 9:13 AM
> To: 'Ben Hutchings'; Kirsher, Jeffrey T
> Cc: davem@davemloft.net; netdev@vger.kernel.org; gospo@redhat.com;
> sassmann@redhat.com
> Subject: RE: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
> 
Please ignore my last email on this. I am working on the sparse error in igb_get_i2c_client as well as a lockdep error that turned up.  Patch will be submitted to our internal test system as soon as possible.

Sorry for the thrash,

Carolyn
Carolyn Wyborny 
Linux Development 
Networking Division 
Intel Corporation 





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

end of thread, other threads:[~2013-02-12 17:17 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
2013-02-08 10:39 ` [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled Jeff Kirsher
2013-02-08 10:39 ` [net-next 02/10] igb: Fix for improper exit in igb_get_i2c_client Jeff Kirsher
2013-02-08 10:39 ` [net-next 03/10] igb: Fix for improper allocation flag " Jeff Kirsher
2013-02-08 10:39 ` [net-next 04/10] igb: Fix for sparse warning " Jeff Kirsher
2013-02-11 17:05   ` Ben Hutchings
2013-02-11 17:27     ` Wyborny, Carolyn
2013-02-12 17:12     ` Wyborny, Carolyn
2013-02-12 17:17     ` Wyborny, Carolyn
2013-02-08 10:39 ` [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx Jeff Kirsher
2013-02-08 12:26   ` Eric Dumazet
2013-02-08 17:11     ` Alexander Duyck
2013-02-08 19:18       ` David Miller
2013-02-08 20:19         ` Alexander Duyck
2013-02-08 10:39 ` [net-next 06/10] igb: Initialize PHY function pointers Jeff Kirsher
2013-02-08 10:39 ` [net-next 07/10] igb: Initialize NVM " Jeff Kirsher
2013-02-08 10:39 ` [net-next 08/10] igb: Intialize MAC " Jeff Kirsher
2013-02-08 10:39 ` [net-next 09/10] igb: Refractoring function pointers in igb_get_invariants function Jeff Kirsher
2013-02-08 10:39 ` [net-next 10/10] ixgbe: refactor initialization of feature flags Jeff Kirsher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).