Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Sep 2008 13:18:07 +0900
From:      Pyun YongHyeon <pyunyh@gmail.com>
To:        "Arno J. Klaassen" <arno@heho.snv.jussieu.fr>
Cc:        stable@freebsd.org, net@freebsd.org
Subject:   Re: 7.1-PRERELEASE : bad network performance (nfe0)
Message-ID:  <20080930041807.GC59136@cdnetworks.co.kr>
In-Reply-To: <wpy71bavmf.fsf@heho.snv.jussieu.fr>
References:  <wptzc1gu9v.fsf@heho.snv.jussieu.fr> <20080929043134.GD54819@cdnetworks.co.kr> <wpy71bavmf.fsf@heho.snv.jussieu.fr>

next in thread | previous in thread | raw e-mail | index | archive | help

--jho1yZJdad60DJr+
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Sep 29, 2008 at 04:12:56PM +0200, Arno J. Klaassen wrote:

[...]

 > > 
 > > AFAIK it seems that you're the first one that reports poor
 > > performance issue of MCP65.
 > 
 > 
 > someone must be ;) no kiddin, I am not convinced this is (only)
 > a driver issue (cf. "bad NFS/UDP performance" thread on -hackers).
 > 
 > I just have no experience on this notebook, so I can't say " it worked
 > great before" and my only other 7-stable-amd64 I have does not
 > show the probs, having a cheap re0 *and* being UP.
 > 
 > 
 > > MCP65 has no checksum offload/TSO
 > > capability so nfe(4) never try to take advantage of the hardware
 > > capability. So you should have no checksum offload/TSO related
 > > issue here. 
 > > Also note, checking network performance with scp(1) wouldn't
 > > show real numbers as scp(1) may involve other system activities.
 > > Use one of network benchmark programs in ports(e.g.
 > > benchmarks/netperf) to measure network performance.
 > 
 > quite funny (even taken with lots of salt since the LAN is used
 > for "normal work" as well in parallel, but differences are
 > rather significant) :
 > 
 > I test to same server (7-stable-amd64 from Jun  7 (using
 > nfe0 as well btw, but another chip), either from a
 > 6-stable-x86 (Jul 14, sk0) or the notebook (7-stable-x64 below), using
 > 
 >  for i in <SOME-TESTS>  ; do
 >     echo $i; /usr/local/bin/netperf -H push -i 4,2 -I 95,10 -t $i;  echo;
 >  done
 > 
 > streaming results are OK for both :
 > 
 > TCP_STREAM
 >               Throughput  
 >               10^6bits/sec  
 > 
 > 6-stable-x86  349.57   
 > 7-stable-x64  939.47 
 > 
 > UDP_STREAM
 >               Throughput
 >               10^6bits/sec
 > 
 > 6-stable-x86  388.45
 > 7-stable-x64  947.89    
 > 
 > 
 > However, the "request/respones" tests are awfull for my notebook 
 > (test repeated on the notebook for the sake of conviction) :
 > 
 > TCP_RR
 >               Trans.
 >               Rate          
 >               per sec        
 > 
 > 6-stable-x86  9801.58                
 > 7-stable-x64   137.61
 > 7-stable-x64    89.35
 > 7-stable-x64   102.29
 > 
 > TCP_CRR
 >               Trans.
 >               Rate                                        
 >               per sec   
 > 
 > 6-stable-x86  4520.98   
 > 7-stable-x64     7.00
 > 7-stable-x64     8.10
 > 7-stable-x64    18.49
 > 
 > 
 > UDP_RR
 >               Trans.
 >               Rate                                        
 >               per sec   
 > 
 > 6-stable-x86  9473.20   
 > 7-stable-x64     9.60
 > 7-stable-x64     0.90
 > 7-stable-x64     0.10
 > 
 > 
 > I can send you complete results if wanted.
 >  

Based on poor TCP_RR numbers I wonder how you can get such a high
TCP_STREAM numbers.

 > > Other possible cause of issue could be link speed/duplex mismatch
 > > or excessive MAC control frames(e.g. pause frames). Does nfe(4)
 > > agree on resolved speed/duplex with link partner?
 > 
 > 
 > yes (1000baseTX <full-duplex>)
 > 
 > > If they all agree on resolved speed/duplex, would you check number
 > > of pause frames sent/received from link partner? Even though MCP65
 > > supports hardware MAC statistics for pause frames nfe(4) has no
 > > support code yet so you may have to resort to managed switch that
 > > can show Tx/Rx statistics of each port.
 > 
 > aargh; I do have a Netgear GS724TS around where I can connect it to.
 > This thing should be manageable, but give me some time to
 > find out how ....
 > 

Or try attached patch. Use "sysctl dev.nfe.0.stats" to get
statistics.

-- 
Regards,
Pyun YongHyeon

--jho1yZJdad60DJr+
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="nfe.mib.patch"

Index: sys/dev/nfe/if_nfe.c
===================================================================
--- sys/dev/nfe/if_nfe.c	(revision 183480)
+++ sys/dev/nfe/if_nfe.c	(working copy)
@@ -122,6 +122,9 @@
 
 static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
 static int sysctl_hw_nfe_proc_limit(SYSCTL_HANDLER_ARGS);
+static void nfe_sysctl_node(struct nfe_softc *);
+static void nfe_stats_clear(struct nfe_softc *);
+static void nfe_stats_update(struct nfe_softc *);
 
 #ifdef NFE_DEBUG
 static int nfedebug = 0;
@@ -245,6 +248,22 @@
 	    "NVIDIA nForce MCP73 Networking Adapter"},
 	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN4,
 	    "NVIDIA nForce MCP73 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN1,
+	    "NVIDIA nForce MCP77 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN2,
+	    "NVIDIA nForce MCP77 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN3,
+	    "NVIDIA nForce MCP77 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN4,
+	    "NVIDIA nForce MCP77 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN1,
+	    "NVIDIA nForce MCP79 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN2,
+	    "NVIDIA nForce MCP79 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN3,
+	    "NVIDIA nForce MCP79 Networking Adapter"},
+	{PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN4,
+	    "NVIDIA nForce MCP79 Networking Adapter"},
 	{0, 0, NULL}
 };
 
@@ -438,18 +457,19 @@
 		break;
 	case PCI_PRODUCT_NVIDIA_MCP51_LAN1:
 	case PCI_PRODUCT_NVIDIA_MCP51_LAN2:
-		sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT;
+		sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT | NFE_MIB_V1;
 		break;
 	case PCI_PRODUCT_NVIDIA_CK804_LAN1:
 	case PCI_PRODUCT_NVIDIA_CK804_LAN2:
 	case PCI_PRODUCT_NVIDIA_MCP04_LAN1:
 	case PCI_PRODUCT_NVIDIA_MCP04_LAN2:
-		sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM;
+		sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM |
+		    NFE_MIB_V1;
 		break;
 	case PCI_PRODUCT_NVIDIA_MCP55_LAN1:
 	case PCI_PRODUCT_NVIDIA_MCP55_LAN2:
 		sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM |
-		    NFE_HW_VLAN | NFE_PWR_MGMT | NFE_TX_FLOW_CTRL;
+		    NFE_HW_VLAN | NFE_PWR_MGMT | NFE_TX_FLOW_CTRL | NFE_MIB_V2;
 		break;
 
 	case PCI_PRODUCT_NVIDIA_MCP61_LAN1:
@@ -465,14 +485,26 @@
 	case PCI_PRODUCT_NVIDIA_MCP73_LAN3:
 	case PCI_PRODUCT_NVIDIA_MCP73_LAN4:
 		sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT |
-		    NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL;
+		    NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL | NFE_MIB_V2;
 		break;
+	case PCI_PRODUCT_NVIDIA_MCP77_LAN1:
+	case PCI_PRODUCT_NVIDIA_MCP77_LAN2:
+	case PCI_PRODUCT_NVIDIA_MCP77_LAN3:
+	case PCI_PRODUCT_NVIDIA_MCP77_LAN4:
+	case PCI_PRODUCT_NVIDIA_MCP79_LAN1:
+	case PCI_PRODUCT_NVIDIA_MCP79_LAN2:
+	case PCI_PRODUCT_NVIDIA_MCP79_LAN3:
+	case PCI_PRODUCT_NVIDIA_MCP79_LAN4:
+		sc->nfe_flags |= NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_PWR_MGMT |
+		    NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL | NFE_MIB_V3;
+		break;
 	case PCI_PRODUCT_NVIDIA_MCP65_LAN1:
 	case PCI_PRODUCT_NVIDIA_MCP65_LAN2:
 	case PCI_PRODUCT_NVIDIA_MCP65_LAN3:
 	case PCI_PRODUCT_NVIDIA_MCP65_LAN4:
 		sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR |
-		    NFE_PWR_MGMT | NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL;
+		    NFE_PWR_MGMT | NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL |
+		    NFE_MIB_V2;
 		break;
 	}
 
@@ -519,25 +551,9 @@
 		goto fail;
 
 	nfe_alloc_jrx_ring(sc, &sc->jrxq);
+	/* Create sysctl node. */
+	nfe_sysctl_node(sc);
 
-	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-	    OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW,
-	    &sc->nfe_process_limit, 0, sysctl_hw_nfe_proc_limit, "I",
-	    "max number of Rx events to process");
-
-	sc->nfe_process_limit = NFE_PROC_DEFAULT;
-	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
-	    "process_limit", &sc->nfe_process_limit);
-	if (error == 0) {
-		if (sc->nfe_process_limit < NFE_PROC_MIN ||
-		    sc->nfe_process_limit > NFE_PROC_MAX) {
-			device_printf(dev, "process_limit value out of range; "
-			    "using default: %d\n", NFE_PROC_DEFAULT);
-			sc->nfe_process_limit = NFE_PROC_DEFAULT;
-		}
-	}
-
 	ifp->if_softc = sc;
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_mtu = ETHERMTU;
@@ -902,6 +918,8 @@
 	if (sc->nfe_link != 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
 		txctl |= NFE_TX_START;
 		rxctl |= NFE_RX_START;
+		/* Got a link, clear hardware stats. */
+		nfe_stats_clear(sc);
 	} else {
 		txctl &= ~NFE_TX_START;
 		rxctl &= ~NFE_RX_START;
@@ -2823,6 +2841,8 @@
 			tdata->m = NULL;
 		}
 	}
+	/* Update hardware stats. */
+	nfe_stats_update(sc);
 }
 
 
@@ -2874,6 +2894,7 @@
 
 	mii = device_get_softc(sc->nfe_miibus);
 	mii_tick(mii);
+	nfe_stats_update(sc);
 	nfe_watchdog(ifp);
 	callout_reset(&sc->nfe_stat_ch, hz, nfe_tick, sc);
 }
@@ -2981,3 +3002,199 @@
 	return (sysctl_int_range(oidp, arg1, arg2, req, NFE_PROC_MIN,
 	    NFE_PROC_MAX));
 }
+
+
+#define	NFE_SYSCTL_STAT_ADD32(c, h, n, p, d)	\
+	    SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
+#define	NFE_SYSCTL_STAT_ADD64(c, h, n, p, d)	\
+	    SYSCTL_ADD_QUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d)
+
+static void
+nfe_sysctl_node(struct nfe_softc *sc)
+{
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid_list *child, *parent;
+	struct sysctl_oid *tree;
+	struct nfe_hw_stats *stats;
+	int error;
+
+	stats = &sc->nfe_stats;
+	ctx = device_get_sysctl_ctx(sc->nfe_dev);
+	child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->nfe_dev));
+	SYSCTL_ADD_PROC(ctx, child,
+	    OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW,
+	    &sc->nfe_process_limit, 0, sysctl_hw_nfe_proc_limit, "I",
+	    "max number of Rx events to process");
+
+	sc->nfe_process_limit = NFE_PROC_DEFAULT;
+	error = resource_int_value(device_get_name(sc->nfe_dev),
+	    device_get_unit(sc->nfe_dev), "process_limit",
+	    &sc->nfe_process_limit);
+	if (error == 0) {
+		if (sc->nfe_process_limit < NFE_PROC_MIN ||
+		    sc->nfe_process_limit > NFE_PROC_MAX) {
+			device_printf(sc->nfe_dev,
+			    "process_limit value out of range; "
+			    "using default: %d\n", NFE_PROC_DEFAULT);
+			sc->nfe_process_limit = NFE_PROC_DEFAULT;
+		}
+	}
+
+	if ((sc->nfe_flags & (NFE_MIB_V1 | NFE_MIB_V2 | NFE_MIB_V3)) == 0)
+		return;
+
+	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
+	    NULL, "NFE statistics");
+	parent = SYSCTL_CHILDREN(tree);
+
+	/* Rx statistics. */
+	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD,
+	    NULL, "Tx MAC statistics");
+	child = SYSCTL_CHILDREN(tree);
+	NFE_SYSCTL_STAT_ADD64(ctx, child, "octets",
+	    &stats->tx_octets, "Octets");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "zero_rexmits",
+	    &stats->tx_zero_rexmits, "Zero Retransmits");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "one_rexmits",
+	    &stats->tx_one_rexmits, "One Retransmits");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "multi_rexmits",
+	    &stats->tx_multi_rexmits, "Multiple Retransmits");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "late_cols",
+	    &stats->tx_late_cols, "Late Collisions");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "fifo_underuns",
+	    &stats->tx_fifo_underuns, "FIFO Underruns");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "carrier_losts",
+	    &stats->tx_carrier_losts, "Carrier Losts");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "excess_deferrals",
+	    &stats->tx_excess_deferals, "Excess Deferrals");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "retry_errors",
+	    &stats->tx_retry_errors, "Retry Errors");
+	if ((sc->nfe_flags & NFE_MIB_V2) != 0) {
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "deferrals",
+		    &stats->tx_deferals, "Deferrals");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "frames",
+		    &stats->tx_frames, "Frames");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "pause",
+		    &stats->tx_pause, "Pause Frames");
+	}
+	if ((sc->nfe_flags & NFE_MIB_V3) != 0) {
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "unicast",
+		    &stats->tx_deferals, "Unicast Frames");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "multicast",
+		    &stats->tx_frames, "Multicast Frames");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "broadcast",
+		    &stats->tx_pause, "Broadcast Frames");
+	}
+
+	/* Rx statistics. */
+	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD,
+	    NULL, "Rx MAC statistics");
+	child = SYSCTL_CHILDREN(tree);
+
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "frame_errors",
+	    &stats->rx_frame_errors, "Framing Errors");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "extra_bytes",
+	    &stats->rx_extra_bytes, "Extra Bytes");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "late_cols",
+	    &stats->rx_late_cols, "Late Collisions");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "runts",
+	    &stats->rx_runts, "Runts");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "jumbos",
+	    &stats->rx_jumbos, "Jumbos");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "fifo_overuns",
+	    &stats->rx_fifo_overuns, "FIFO Overruns");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "crc_errors",
+	    &stats->rx_crc_errors, "CRC Errors");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "fae",
+	    &stats->rx_fae, "Frame Alignment Errors");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "len_errors",
+	    &stats->rx_len_errors, "Length Errors");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "unicast",
+	    &stats->rx_unicast, "Unicast Frames");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "multicast",
+	    &stats->rx_multicast, "Multicast Frames");
+	NFE_SYSCTL_STAT_ADD32(ctx, child, "brocadcast",
+	    &stats->rx_broadcast, "Broadcast Frames");
+	if ((sc->nfe_flags & NFE_MIB_V2) != 0) {
+		NFE_SYSCTL_STAT_ADD64(ctx, child, "octets",
+		    &stats->rx_octets, "Octets");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "pause",
+		    &stats->rx_pause, "Pause frames");
+		NFE_SYSCTL_STAT_ADD32(ctx, child, "drops",
+		    &stats->rx_drops, "Drop frames");
+	}
+}
+
+#undef NFE_SYSCTL_STAT_ADD32
+#undef NFE_SYSCTL_STAT_ADD64
+
+static void
+nfe_stats_clear(struct nfe_softc *sc)
+{
+	int i, mib_cnt;
+
+	if ((sc->nfe_flags & NFE_MIB_V1) != 0)
+		mib_cnt = NFE_NUM_MIB_STATV1;
+	else if ((sc->nfe_flags & (NFE_MIB_V2 | NFE_MIB_V3)) != 0)
+		mib_cnt = NFE_NUM_MIB_STATV2;
+	else
+		return;
+
+	for (i = 0; i < mib_cnt; i += sizeof(uint32_t))
+		NFE_READ(sc, NFE_TX_OCTET + i);
+
+	if ((sc->nfe_flags & NFE_MIB_V3) != 0) {
+		NFE_READ(sc, NFE_TX_UNICAST);
+		NFE_READ(sc, NFE_TX_MULTICAST);
+		NFE_READ(sc, NFE_TX_BROADCAST);
+	}
+}
+
+static void
+nfe_stats_update(struct nfe_softc *sc)
+{
+	struct nfe_hw_stats *stats;
+
+	NFE_LOCK_ASSERT(sc);
+
+	if ((sc->nfe_flags & (NFE_MIB_V1 | NFE_MIB_V2 | NFE_MIB_V3)) == 0)
+		return;
+
+	stats = &sc->nfe_stats;
+	stats->tx_octets += NFE_READ(sc, NFE_TX_OCTET);
+	stats->tx_zero_rexmits += NFE_READ(sc, NFE_TX_ZERO_REXMIT);
+	stats->tx_one_rexmits += NFE_READ(sc, NFE_TX_ONE_REXMIT);
+	stats->tx_multi_rexmits += NFE_READ(sc, NFE_TX_MULTI_REXMIT);
+	stats->tx_late_cols += NFE_READ(sc, NFE_TX_LATE_COL);
+	stats->tx_fifo_underuns += NFE_READ(sc, NFE_TX_FIFO_UNDERUN);
+	stats->tx_carrier_losts += NFE_READ(sc, NFE_TX_CARRIER_LOST);
+	stats->tx_excess_deferals += NFE_READ(sc, NFE_TX_EXCESS_DEFERRAL);
+	stats->tx_retry_errors += NFE_READ(sc, NFE_TX_RETRY_ERROR);
+	stats->rx_frame_errors += NFE_READ(sc, NFE_RX_FRAME_ERROR);
+	stats->rx_extra_bytes += NFE_READ(sc, NFE_RX_EXTRA_BYTES);
+	stats->rx_late_cols += NFE_READ(sc, NFE_RX_LATE_COL);
+	stats->rx_runts += NFE_READ(sc, NFE_RX_RUNT);
+	stats->rx_jumbos += NFE_READ(sc, NFE_RX_JUMBO);
+	stats->rx_fifo_overuns += NFE_READ(sc, NFE_RX_FIFO_OVERUN);
+	stats->rx_crc_errors += NFE_READ(sc, NFE_RX_CRC_ERROR);
+	stats->rx_fae += NFE_READ(sc, NFE_RX_FAE);
+	stats->rx_len_errors += NFE_READ(sc, NFE_RX_LEN_ERROR);
+	stats->rx_unicast += NFE_READ(sc, NFE_RX_UNICAST);
+	stats->rx_multicast += NFE_READ(sc, NFE_RX_MULTICAST);
+	stats->rx_broadcast += NFE_READ(sc, NFE_RX_BROADCAST);
+
+	if ((sc->nfe_flags & NFE_MIB_V2) != 0) {
+		stats->tx_deferals += NFE_READ(sc, NFE_TX_DEFERAL);
+		stats->tx_frames += NFE_READ(sc, NFE_TX_FRAME);
+		stats->rx_octets += NFE_READ(sc, NFE_RX_OCTET);
+		stats->tx_pause += NFE_READ(sc, NFE_TX_PAUSE);
+		stats->rx_pause += NFE_READ(sc, NFE_RX_PAUSE);
+		stats->rx_drops += NFE_READ(sc, NFE_RX_DROP);
+	}
+
+	if ((sc->nfe_flags & NFE_MIB_V3) != 0) {
+		stats->tx_unicast += NFE_READ(sc, NFE_TX_UNICAST);
+		stats->tx_multicast += NFE_READ(sc, NFE_TX_MULTICAST);
+		stats->rx_broadcast += NFE_READ(sc, NFE_TX_BROADCAST);
+	}
+}
Index: sys/dev/nfe/if_nfereg.h
===================================================================
--- sys/dev/nfe/if_nfereg.h	(revision 183480)
+++ sys/dev/nfe/if_nfereg.h	(working copy)
@@ -51,7 +51,7 @@
 #define	NFE_MSI_MAP0		0x020
 #define	NFE_MSI_MAP1		0x024
 #define	NFE_MSI_IRQ_MASK	0x030
-#define	NFE_MAC_RESET		0x03c
+#define	NFE_MAC_RESET		0x034
 #define	NFE_MISC1		0x080
 #define	NFE_TX_CTL		0x084
 #define	NFE_TX_STATUS		0x088
@@ -87,11 +87,41 @@
 #define	NFE_PHY_SPEED		0x18c
 #define	NFE_PHY_CTL		0x190
 #define	NFE_PHY_DATA		0x194
+#define	NFE_TX_UNICAST		0x1a0
+#define	NFE_TX_MULTICAST	0x1a4
+#define	NFE_TX_BROADCAST	0x1a8
 #define	NFE_WOL_CTL		0x200
 #define	NFE_PATTERN_CRC		0x204
 #define	NFE_PATTERN_MASK	0x208
 #define	NFE_PWR_CAP		0x268
 #define	NFE_PWR_STATE		0x26c
+#define	NFE_TX_OCTET		0x280
+#define	NFE_TX_ZERO_REXMIT	0x284
+#define	NFE_TX_ONE_REXMIT	0x288
+#define	NFE_TX_MULTI_REXMIT	0x28c
+#define	NFE_TX_LATE_COL		0x290
+#define	NFE_TX_FIFO_UNDERUN	0x294
+#define	NFE_TX_CARRIER_LOST	0x298
+#define	NFE_TX_EXCESS_DEFERRAL	0x29c
+#define	NFE_TX_RETRY_ERROR	0x2a0
+#define	NFE_RX_FRAME_ERROR	0x2a4
+#define	NFE_RX_EXTRA_BYTES	0x2a8
+#define	NFE_RX_LATE_COL		0x2ac
+#define	NFE_RX_RUNT		0x2b0
+#define	NFE_RX_JUMBO		0x2b4
+#define	NFE_RX_FIFO_OVERUN	0x2b8
+#define	NFE_RX_CRC_ERROR	0x2bc
+#define	NFE_RX_FAE		0x2c0
+#define	NFE_RX_LEN_ERROR	0x2c4
+#define	NFE_RX_UNICAST		0x2c8
+#define	NFE_RX_MULTICAST	0x2cc
+#define	NFE_RX_BROADCAST	0x2d0
+#define	NFE_TX_DEFERAL		0x2d4
+#define	NFE_TX_FRAME		0x2d8
+#define	NFE_RX_OCTET		0x2dc
+#define	NFE_TX_PAUSE		0x2e0
+#define	NFE_RX_PAUSE		0x2e4
+#define	NFE_RX_DROP		0x2e8
 #define	NFE_VTAG_CTL		0x300
 #define	NFE_MSIX_MAP0		0x3e0
 #define	NFE_MSIX_MAP1		0x3e4
@@ -182,6 +212,10 @@
 #define	NFE_SEED_100TX		0x00002d00
 #define	NFE_SEED_1000T		0x00007400
 
+#define	NFE_NUM_MIB_STATV1	21
+#define	NFE_NUM_MIB_STATV2	27
+#define	NFE_NUM_MIB_STATV3	30
+
 #define	NFE_MSI_MESSAGES	8
 #define	NFE_MSI_VECTOR_0_ENABLED	0x01
 
@@ -295,6 +329,14 @@
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN2		0x07dd
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN3		0x07de
 #define	PCI_PRODUCT_NVIDIA_MCP73_LAN4		0x07df
+#define	PCI_PRODUCT_NVIDIA_MCP77_LAN1		0x0760
+#define	PCI_PRODUCT_NVIDIA_MCP77_LAN2		0x0761
+#define	PCI_PRODUCT_NVIDIA_MCP77_LAN3		0x0762
+#define	PCI_PRODUCT_NVIDIA_MCP77_LAN4		0x0763
+#define	PCI_PRODUCT_NVIDIA_MCP79_LAN1		0x0ab0
+#define	PCI_PRODUCT_NVIDIA_MCP79_LAN2		0x0ab1
+#define	PCI_PRODUCT_NVIDIA_MCP79_LAN3		0x0ab2
+#define	PCI_PRODUCT_NVIDIA_MCP79_LAN4		0x0ab3
 
 #define	PCI_PRODUCT_NVIDIA_NFORCE3_LAN2	PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1
 #define	PCI_PRODUCT_NVIDIA_NFORCE3_LAN3	PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2
Index: sys/dev/nfe/if_nfevar.h
===================================================================
--- sys/dev/nfe/if_nfevar.h	(revision 183480)
+++ sys/dev/nfe/if_nfevar.h	(working copy)
@@ -70,6 +70,39 @@
 	int			jnext;
 };
 
+struct nfe_hw_stats {
+	uint64_t		tx_octets;
+	uint32_t		tx_zero_rexmits;
+	uint32_t		tx_one_rexmits;
+	uint32_t		tx_multi_rexmits;
+	uint32_t		tx_late_cols;
+	uint32_t		tx_fifo_underuns;
+	uint32_t		tx_carrier_losts;
+	uint32_t		tx_excess_deferals;
+	uint32_t		tx_retry_errors;
+	uint32_t		rx_frame_errors;
+	uint32_t		rx_extra_bytes;
+	uint32_t		rx_late_cols;
+	uint32_t		rx_runts;
+	uint32_t		rx_jumbos;
+	uint32_t		rx_fifo_overuns;
+	uint32_t		rx_crc_errors;
+	uint32_t		rx_fae;
+	uint32_t		rx_len_errors;
+	uint32_t		rx_unicast;
+	uint32_t		rx_multicast;
+	uint32_t		rx_broadcast;
+	uint32_t		tx_deferals;
+	uint32_t		tx_frames;
+	uint64_t		rx_octets;
+	uint32_t		tx_pause;
+	uint32_t		rx_pause;
+	uint32_t		rx_drops;
+	uint32_t		tx_unicast;
+	uint32_t		tx_multicast;
+	uint32_t		tx_broadcast;
+};
+
 struct nfe_softc {
 	struct ifnet		*nfe_ifp;
 	device_t		nfe_dev;
@@ -96,10 +129,14 @@
 #define	NFE_PWR_MGMT		0x0010
 #define	NFE_CORRECT_MACADDR	0x0020
 #define	NFE_TX_FLOW_CTRL	0x0040
+#define	NFE_MIB_V1		0x0080
+#define	NFE_MIB_V2		0x0100
+#define	NFE_MIB_V3		0x0200
 	int			nfe_jumbo_disable;
 	uint32_t		rxtxctl;
 	uint8_t			mii_phyaddr;
 	uint8_t			eaddr[ETHER_ADDR_LEN];
+	struct nfe_hw_stats	nfe_stats;
 	struct taskqueue	*nfe_tq;
 	struct task		nfe_int_task;
 	struct task		nfe_tx_task;

--jho1yZJdad60DJr+--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080930041807.GC59136>