diff mbox

igb: Record hardware RX overruns in net_stats

Message ID 1241643595.2234.9.camel@localhost.localdomain
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Jesper Dangaard Brouer May 6, 2009, 8:59 p.m. UTC
On Wed, 2009-05-06 at 15:09 +0200, Jesper Dangaard Brouer wrote:
> > In the SRRCTL registers, there is a DROP_EN bit, bit 31.  If this 
> > bit is set to 1b for the queue in question, then the packet will be 
> > dropped when there are no buffers in the packet buffer.  This does
> not 
> > mean the FIFO is full or has been overrun, it just means there's no
> more
> > descriptors available in the Rx ring for that queue.  In this case,
> RNBC 
> > is incremented, MPC is not.
> 
> My experience is that if DROP_EN bit is *set*. Then I cannot find the
> drop count anywhere... not in RNBC and not in MPC ... and I can still
> see the drops with my netfilter module mp2t.
> 
> ethtool -S eth21 | egrep 'rx_no_buffer_count|rx_miss'
>      rx_no_buffer_count: 0
>      rx_missed_errors: 0
> 
> I'm guessing that the drop counters are now in the per queue RQDPC
> register (Receive Queue Drop Packet Count), but reading that is not
> implemented in the driver. 

Just did a quick implemenation in the driver, see draft patch below (not
ready for inclusion yet!).

An my guess was correct, the drops count is stored per queue in RQDPC.
The only really anoying thing is that this counter is only 12 bit, thus
overruns can occur quickly.  (This reminds me of my drop count
implemenation for Sun niu driver.  This counter has less bits that the 
Sun counter, but at least it automatically clears on reads)

I'll post some more clean patches tomorrow...

Comments

Waskiewicz Jr, Peter P May 6, 2009, 9:24 p.m. UTC | #1
On Wed, 6 May 2009, Jesper Dangaard Brouer wrote:

> On Wed, 2009-05-06 at 15:09 +0200, Jesper Dangaard Brouer wrote:
> > > In the SRRCTL registers, there is a DROP_EN bit, bit 31.  If this 
> > > bit is set to 1b for the queue in question, then the packet will be 
> > > dropped when there are no buffers in the packet buffer.  This does
> > not 
> > > mean the FIFO is full or has been overrun, it just means there's no
> > more
> > > descriptors available in the Rx ring for that queue.  In this case,
> > RNBC 
> > > is incremented, MPC is not.
> > 
> > My experience is that if DROP_EN bit is *set*. Then I cannot find the
> > drop count anywhere... not in RNBC and not in MPC ... and I can still
> > see the drops with my netfilter module mp2t.
> > 
> > ethtool -S eth21 | egrep 'rx_no_buffer_count|rx_miss'
> >      rx_no_buffer_count: 0
> >      rx_missed_errors: 0
> > 
> > I'm guessing that the drop counters are now in the per queue RQDPC
> > register (Receive Queue Drop Packet Count), but reading that is not
> > implemented in the driver. 
> 
> Just did a quick implemenation in the driver, see draft patch below (not
> ready for inclusion yet!).
> 
> An my guess was correct, the drops count is stored per queue in RQDPC.
> The only really anoying thing is that this counter is only 12 bit, thus
> overruns can occur quickly.  (This reminds me of my drop count
> implemenation for Sun niu driver.  This counter has less bits that the 
> Sun counter, but at least it automatically clears on reads)
> 
> I'll post some more clean patches tomorrow...

Ok, so 82576 is much more like 82599 with the queue counters, but 
different enough to be annoying.  Yes, I'm seeing this in the data manual 
for 82576.  Honestly, we have too many damn counters for packet 
accounting.  I'm very happy you're getting what you wanted now.  Your 
patch looks reasonable to me; please let us know if you have any other 
questions about the part that we might be able to help with.

Cheers,
-PJ Waskiewicz
--
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
diff mbox

Patch

diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 0bd7728..85683e2 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -165,6 +165,8 @@  enum {
 				    : (0x0C018 + ((_n) * 0x40)))
 #define E1000_RXDCTL(_n)  ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) \
 				    : (0x0C028 + ((_n) * 0x40)))
+#define E1000_RQDPC(_n)   ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) \
+				    : (0x0C030 + ((_n) * 0x40)))
 #define E1000_TDBAL(_n)   ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) \
 				    : (0x0E000 + ((_n) * 0x40)))
 #define E1000_TDBAH(_n)   ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) \
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 4e8464b..4a16ac0 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -140,6 +140,7 @@  struct igb_buffer {
 struct igb_queue_stats {
 	u64 packets;
 	u64 bytes;
+	u64 drops;
 };
 
 struct igb_ring {
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 27eae49..b0d3100 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1998,12 +1998,16 @@  static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 			p += ETH_GSTRING_LEN;
 			sprintf(p, "tx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
+			sprintf(p, "tx_queue_%u_drops", i);
+			p += ETH_GSTRING_LEN;
 		}
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			sprintf(p, "rx_queue_%u_packets", i);
 			p += ETH_GSTRING_LEN;
 			sprintf(p, "rx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
+			sprintf(p, "rx_queue_%u_drops", i);
+			p += ETH_GSTRING_LEN;
 		}
 /*		BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */
 		break;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 183235d..20190bb 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -3494,6 +3494,7 @@  void igb_update_stats(struct igb_adapter *adapter)
 	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
 	u16 phy_tmp;
+	int i;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
@@ -3583,6 +3584,11 @@  void igb_update_stats(struct igb_adapter *adapter)
 	adapter->net_stats.multicast = adapter->stats.mprc;
 	adapter->net_stats.collisions = adapter->stats.colc;
 
+	/* Read out drops stats per RX queue */
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		adapter->rx_ring[i].rx_stats.drops += rd32(E1000_RQDPC(i));
+	}
+
 	/* Rx Errors */
 
 	/* RLEC on some newer hardware can be incorrect so build