svn commit: r209309 - stable/8/sys/dev/e1000
Jack F Vogel
jfv at FreeBSD.org
Fri Jun 18 17:22:09 UTC 2010
Author: jfv
Date: Fri Jun 18 17:22:08 2010
New Revision: 209309
URL: http://svn.freebsd.org/changeset/base/209309
Log:
MFC of E1000 drivers:
Stability fixes from M.Tuexen
Cool stats changes from gnn
Changes for POLL friendliness from John Baldwin
Thanks everyone!
MFC to RELENG8.1 asap
Modified:
stable/8/sys/dev/e1000/if_em.c
stable/8/sys/dev/e1000/if_igb.c
stable/8/sys/dev/e1000/if_igb.h
stable/8/sys/dev/e1000/if_lem.c
Modified: stable/8/sys/dev/e1000/if_em.c
==============================================================================
--- stable/8/sys/dev/e1000/if_em.c Fri Jun 18 16:36:57 2010 (r209308)
+++ stable/8/sys/dev/e1000/if_em.c Fri Jun 18 17:22:08 2010 (r209309)
@@ -230,8 +230,9 @@ static void em_free_receive_buffers(stru
static void em_enable_intr(struct adapter *);
static void em_disable_intr(struct adapter *);
static void em_update_stats_counters(struct adapter *);
+static void em_add_hw_stats(struct adapter *adapter);
static bool em_txeof(struct tx_ring *);
-static int em_rxeof(struct rx_ring *, int);
+static bool em_rxeof(struct rx_ring *, int, int *);
#ifndef __NO_STRICT_ALIGNMENT
static int em_fixup_rx(struct rx_ring *);
#endif
@@ -242,7 +243,6 @@ static bool em_tso_setup(struct tx_ring
static void em_set_promisc(struct adapter *);
static void em_disable_promisc(struct adapter *);
static void em_set_multi(struct adapter *);
-static void em_print_hw_stats(struct adapter *);
static void em_update_link_status(struct adapter *);
static void em_refresh_mbufs(struct rx_ring *, int);
static void em_register_vlan(void *, struct ifnet *, u16);
@@ -252,11 +252,9 @@ static int em_xmit(struct tx_ring *, str
static int em_dma_malloc(struct adapter *, bus_size_t,
struct em_dma_alloc *, int);
static void em_dma_free(struct adapter *, struct em_dma_alloc *);
-static void em_print_debug_info(struct adapter *);
+static int em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS);
static void em_print_nvm_info(struct adapter *);
static int em_is_valid_ether_addr(u8 *);
-static int em_sysctl_stats(SYSCTL_HANDLER_ARGS);
-static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
static void em_add_int_delay_sysctl(struct adapter *, const char *,
const char *, struct em_int_delay_info *, int, int);
@@ -347,8 +345,13 @@ static int em_debug_sbp = FALSE;
TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
/* Local controls for MSI/MSIX */
+#ifdef EM_MULTIQUEUE
static int em_enable_msix = TRUE;
static int em_msix_queues = 2; /* for 82574, can be 1 or 2 */
+#else
+static int em_enable_msix = FALSE;
+static int em_msix_queues = 0; /* disable */
+#endif
TUNABLE_INT("hw.em.enable_msix", &em_enable_msix);
TUNABLE_INT("hw.em.msix_queues", &em_msix_queues);
@@ -447,13 +450,8 @@ em_attach(device_t dev)
/* SYSCTL stuff */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
- em_sysctl_debug_info, "I", "Debug Information");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
- em_sysctl_stats, "I", "Statistics");
+ OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
+ em_sysctl_nvm_info, "I", "NVM Information");
callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
@@ -651,6 +649,8 @@ em_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
em_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
+ em_add_hw_stats(adapter);
+
/* Non-AMT based hardware can now take control from firmware */
if (adapter->has_manage && !adapter->has_amt)
em_get_hw_control(adapter);
@@ -1351,12 +1351,13 @@ em_poll(struct ifnet *ifp, enum poll_cmd
struct adapter *adapter = ifp->if_softc;
struct tx_ring *txr = adapter->tx_rings;
struct rx_ring *rxr = adapter->rx_rings;
- u32 reg_icr, rx_done = 0;
+ u32 reg_icr;
+ int rx_done;
EM_CORE_LOCK(adapter);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
EM_CORE_UNLOCK(adapter);
- return (rx_done);
+ return (0);
}
if (cmd == POLL_AND_CHECK_STATUS) {
@@ -1371,9 +1372,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd
}
EM_CORE_UNLOCK(adapter);
- EM_RX_LOCK(rxr);
- rx_done = em_rxeof(rxr, count);
- EM_RX_UNLOCK(rxr);
+ em_rxeof(rxr, count, &rx_done);
EM_TX_LOCK(txr);
em_txeof(txr);
@@ -1445,16 +1444,15 @@ em_handle_que(void *context, int pending
struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
struct rx_ring *rxr = adapter->rx_rings;
- bool more_rx;
+ bool more;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- EM_RX_LOCK(rxr);
- more_rx = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
+ more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
EM_TX_LOCK(txr);
- em_txeof(txr);
+ if (em_txeof(txr))
+ more = TRUE;
#ifdef EM_MULTIQUEUE
if (!drbr_empty(ifp, txr->br))
em_mq_start_locked(ifp, txr, NULL);
@@ -1463,7 +1461,7 @@ em_handle_que(void *context, int pending
em_start_locked(ifp, txr);
#endif
EM_TX_UNLOCK(txr);
- if (more_rx) {
+ if (more) {
taskqueue_enqueue(adapter->tq, &adapter->que_task);
return;
}
@@ -1511,10 +1509,8 @@ em_msix_rx(void *arg)
struct adapter *adapter = rxr->adapter;
bool more;
- EM_RX_LOCK(rxr);
++rxr->rx_irq;
- more = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
+ more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
@@ -1539,7 +1535,7 @@ em_msix_link(void *arg)
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.mac.get_link_status = 1;
- taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
+ em_handle_link(adapter, 0);
} else
E1000_WRITE_REG(&adapter->hw, E1000_IMS,
EM_MSIX_LINK | E1000_IMS_LSC);
@@ -1553,9 +1549,7 @@ em_handle_rx(void *context, int pending)
struct adapter *adapter = rxr->adapter;
bool more;
- EM_RX_LOCK(rxr);
- more = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
+ more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
@@ -2069,9 +2063,6 @@ em_local_timer(void *arg)
if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
- if (em_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING)
- em_print_hw_stats(adapter);
-
/*
** Check for time since any descriptor was cleaned
*/
@@ -2431,11 +2422,6 @@ em_allocate_msix(struct adapter *adapter
adapter->linkvec = vector;
adapter->ivars |= (8 | vector) << 16;
adapter->ivars |= 0x80000000;
- TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter);
- adapter->tq = taskqueue_create_fast("em_link", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
- device_get_nameunit(adapter->dev));
return (0);
}
@@ -4090,8 +4076,8 @@ em_initialize_receive_unit(struct adapte
*
* For polling we also now return the number of cleaned packets
*********************************************************************/
-static int
-em_rxeof(struct rx_ring *rxr, int count)
+static bool
+em_rxeof(struct rx_ring *rxr, int count, int *done)
{
struct adapter *adapter = rxr->adapter;
struct ifnet *ifp = adapter->ifp;
@@ -4102,7 +4088,7 @@ em_rxeof(struct rx_ring *rxr, int count)
bool eop;
struct e1000_rx_desc *cur;
- EM_RX_LOCK_ASSERT(rxr);
+ EM_RX_LOCK(rxr);
for (i = rxr->next_to_check, processed = 0; count != 0;) {
@@ -4196,8 +4182,13 @@ skip:
i = 0;
/* Send to the stack */
- if (sendmp != NULL)
+ if (sendmp != NULL) {
+ rxr->next_to_check = i;
+ EM_RX_UNLOCK(rxr);
(*ifp->if_input)(ifp, sendmp);
+ EM_RX_LOCK(rxr);
+ i = rxr->next_to_check;
+ }
/* Only refresh mbufs every 8 descriptors */
if (processed == 8) {
@@ -4213,12 +4204,11 @@ skip:
}
rxr->next_to_check = i;
+ if (done != NULL)
+ *done = rxdone;
+ EM_RX_UNLOCK(rxr);
-#ifdef DEVICE_POLLING
- return (rxdone);
-#else
return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE);
-#endif
}
#ifndef __NO_STRICT_ALIGNMENT
@@ -4869,114 +4859,285 @@ em_update_stats_counters(struct adapter
}
-/**********************************************************************
- *
- * This routine is called only when em_display_debug_stats is enabled.
- * This routine provides a way to take a look at important statistics
- * maintained by the driver and hardware.
- *
- **********************************************************************/
+/*
+ * Add sysctl variables, one per statistic, to the system.
+ */
static void
-em_print_debug_info(struct adapter *adapter)
+em_add_hw_stats(struct adapter *adapter)
{
+
device_t dev = adapter->dev;
- u8 *hw_addr = adapter->hw.hw_addr;
- struct rx_ring *rxr = adapter->rx_rings;
- struct tx_ring *txr = adapter->tx_rings;
- device_printf(dev, "Adapter hardware address = %p \n", hw_addr);
- device_printf(dev, "CTRL = 0x%x RCTL = 0x%x \n",
- E1000_READ_REG(&adapter->hw, E1000_CTRL),
- E1000_READ_REG(&adapter->hw, E1000_RCTL));
- device_printf(dev, "Packet buffer = Tx=%dk Rx=%dk \n",
- ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff0000) >> 16),\
- (E1000_READ_REG(&adapter->hw, E1000_PBA) & 0xffff) );
- device_printf(dev, "Flow control watermarks high = %d low = %d\n",
- adapter->hw.fc.high_water,
- adapter->hw.fc.low_water);
- device_printf(dev, "tx_int_delay = %d, tx_abs_int_delay = %d\n",
- E1000_READ_REG(&adapter->hw, E1000_TIDV),
- E1000_READ_REG(&adapter->hw, E1000_TADV));
- device_printf(dev, "rx_int_delay = %d, rx_abs_int_delay = %d\n",
- E1000_READ_REG(&adapter->hw, E1000_RDTR),
- E1000_READ_REG(&adapter->hw, E1000_RADV));
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(dev);
+ struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
+ struct e1000_hw_stats *stats = &adapter->stats;
+
+ struct sysctl_oid *stat_node, *int_node, *host_node;
+ struct sysctl_oid_list *stat_list, *int_list, *host_list;
+
+ /* Driver Statistics */
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq, 0,
+ "Link MSIX IRQ Handled");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
+ CTLFLAG_RD, &adapter->mbuf_alloc_failed,
+ "Std mbuf failed");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
+ CTLFLAG_RD, &adapter->mbuf_cluster_failed,
+ "Std mbuf cluster failed");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
+ CTLFLAG_RD, &adapter->dropped_pkts,
+ "Driver dropped packets");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
+ CTLFLAG_RD, &adapter->no_tx_dma_setup,
+ "Driver tx dma failure in xmit");
+
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water",
+ CTLFLAG_RD, &adapter->hw.fc.high_water, 0,
+ "Flow Control High Watermark");
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water",
+ CTLFLAG_RD, &adapter->hw.fc.low_water, 0,
+ "Flow Control Low Watermark");
+
+ /* MAC stats get the own sub node */
+
+ stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
+ CTLFLAG_RD, NULL, "Statistics");
+ stat_list = SYSCTL_CHILDREN(stat_node);
+
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll",
+ CTLFLAG_RD, &stats->ecol,
+ "Excessive collisions");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
+ CTLFLAG_RD, &adapter->stats.symerrs,
+ "Symbol Errors");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
+ CTLFLAG_RD, &adapter->stats.sec,
+ "Sequence Errors");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "defer_count",
+ CTLFLAG_RD, &adapter->stats.dc,
+ "Defer Count");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "missed_packets",
+ CTLFLAG_RD, &adapter->stats.mpc,
+ "Missed Packets");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
+ CTLFLAG_RD, &adapter->stats.rnbc,
+ "Receive No Buffers");
+ /* RLEC is inaccurate on some hardware, calculate our own. */
+/* SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_len_errs", */
+/* CTLFLAG_RD, adapter->stats.roc + adapter->stats.ruc, */
+/* "Receive Length Errors"); */
+
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_errs",
+ CTLFLAG_RD, &adapter->stats.rxerrc,
+ "Receive Errors");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "crc_errs",
+ CTLFLAG_RD, &adapter->stats.crcerrs,
+ "CRC errors");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
+ CTLFLAG_RD, &adapter->stats.algnerrc,
+ "Alignment Errors");
+ /* On 82575 these are collision counts */
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
+ CTLFLAG_RD, &adapter->stats.cexterr,
+ "Collision/Carrier extension errors");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_overruns",
+ CTLFLAG_RD, &adapter->rx_overruns,
+ "RX overruns");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "watchdog_timeouts",
+ CTLFLAG_RD, &adapter->watchdog_events,
+ "Watchdog timeouts");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
+ CTLFLAG_RD, &adapter->stats.xonrxc,
+ "XON Received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_txd",
+ CTLFLAG_RD, &adapter->stats.xontxc,
+ "XON Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
+ CTLFLAG_RD, &adapter->stats.xoffrxc,
+ "XOFF Received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
+ CTLFLAG_RD, &adapter->stats.xofftxc,
+ "XOFF Transmitted");
+
+ /* Packet Reception Stats */
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
+ CTLFLAG_RD, &adapter->stats.tpr,
+ "Total Packets Received ");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
+ CTLFLAG_RD, &adapter->stats.gprc,
+ "Good Packets Received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
+ CTLFLAG_RD, &adapter->stats.bprc,
+ "Broadcast Packets Received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
+ CTLFLAG_RD, &adapter->stats.mprc,
+ "Multicast Packets Received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
+ CTLFLAG_RD, &adapter->stats.prc64,
+ "64 byte frames received ");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
+ CTLFLAG_RD, &adapter->stats.prc127,
+ "65-127 byte frames received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
+ CTLFLAG_RD, &adapter->stats.prc255,
+ "128-255 byte frames received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
+ CTLFLAG_RD, &adapter->stats.prc511,
+ "256-511 byte frames received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
+ CTLFLAG_RD, &adapter->stats.prc1023,
+ "512-1023 byte frames received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
+ CTLFLAG_RD, &adapter->stats.prc1522,
+ "1023-1522 byte frames received");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd",
+ CTLFLAG_RD, &adapter->stats.gorc,
+ "Good Octets Received");
+
+ /* Packet Transmission Stats */
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octest_txd",
+ CTLFLAG_RD, &adapter->stats.gotc,
+ "Good Octest Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
+ CTLFLAG_RD, &adapter->stats.tpt,
+ "Total Packets Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
+ CTLFLAG_RD, &adapter->stats.gptc,
+ "Good Packets Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
+ CTLFLAG_RD, &adapter->stats.bptc,
+ "Broadcast Packets Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
+ CTLFLAG_RD, &adapter->stats.mptc,
+ "Multicast Packets Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
+ CTLFLAG_RD, &adapter->stats.ptc64,
+ "64 byte frames transmitted ");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
+ CTLFLAG_RD, &adapter->stats.ptc127,
+ "65-127 byte frames transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
+ CTLFLAG_RD, &adapter->stats.ptc255,
+ "128-255 byte frames transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
+ CTLFLAG_RD, &adapter->stats.ptc511,
+ "256-511 byte frames transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
+ CTLFLAG_RD, &adapter->stats.ptc1023,
+ "512-1023 byte frames transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
+ CTLFLAG_RD, &adapter->stats.ptc1522,
+ "1024-1522 byte frames transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_txd",
+ CTLFLAG_RD, &adapter->stats.tsctc,
+ "TSO Contexts Transmitted");
+ SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
+ CTLFLAG_RD, &adapter->stats.tsctfc,
+ "TSO Contexts Failed");
+
+
+ /* Interrupt Stats */
+
+ int_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "interrupts",
+ CTLFLAG_RD, NULL, "Interrupt Statistics");
+ int_list = SYSCTL_CHILDREN(int_node);
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "asserts",
+ CTLFLAG_RD, &adapter->stats.iac,
+ "Interrupt Assertion Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_pkt_timer",
+ CTLFLAG_RD, &adapter->stats.icrxptc,
+ "Interrupt Cause Rx Pkt Timer Expire Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_abs_timer",
+ CTLFLAG_RD, &adapter->stats.icrxatc,
+ "Interrupt Cause Rx Abs Timer Expire Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_pkt_timer",
+ CTLFLAG_RD, &adapter->stats.ictxptc,
+ "Interrupt Cause Tx Pkt Timer Expire Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_abs_timer",
+ CTLFLAG_RD, &adapter->stats.ictxatc,
+ "Interrupt Cause Tx Abs Timer Expire Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_empty",
+ CTLFLAG_RD, &adapter->stats.ictxqec,
+ "Interrupt Cause Tx Queue Empty Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_min_thresh",
+ CTLFLAG_RD, &adapter->stats.ictxqmtc,
+ "Interrupt Cause Tx Queue Min Thresh Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh",
+ CTLFLAG_RD, &adapter->stats.icrxdmtc,
+ "Interrupt Cause Rx Desc Min Thresh Count");
+
+ SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_overrun",
+ CTLFLAG_RD, &adapter->stats.icrxoc,
+ "Interrupt Cause Receiver Overrun Count");
+
+ /* Host to Card Stats */
+
+ host_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "host",
+ CTLFLAG_RD, NULL,
+ "Host to Card Statistics");
+
+ host_list = SYSCTL_CHILDREN(host_node);
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_tx_pkt",
+ CTLFLAG_RD, &adapter->stats.cbtmpc,
+ "Circuit Breaker Tx Packet Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "host_tx_pkt_discard",
+ CTLFLAG_RD, &adapter->stats.htdpmc,
+ "Host Transmit Discarded Packets");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "rx_pkt",
+ CTLFLAG_RD, &adapter->stats.rpthc,
+ "Rx Packets To Host");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_rx_pkts",
+ CTLFLAG_RD, &adapter->stats.cbrmpc,
+ "Circuit Breaker Rx Packet Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_rx_pkt_drop",
+ CTLFLAG_RD, &adapter->stats.cbrdpc,
+ "Circuit Breaker Rx Dropped Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "tx_good_pkt",
+ CTLFLAG_RD, &adapter->stats.hgptc,
+ "Host Good Packets Tx Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "breaker_tx_pkt_drop",
+ CTLFLAG_RD, &adapter->stats.htcbdpc,
+ "Host Tx Circuit Breaker Dropped Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "rx_good_bytes",
+ CTLFLAG_RD, &adapter->stats.hgorc,
+ "Host Good Octets Received Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "tx_good_bytes",
+ CTLFLAG_RD, &adapter->stats.hgotc,
+ "Host Good Octets Transmit Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "length_errors",
+ CTLFLAG_RD, &adapter->stats.lenerrs,
+ "Length Errors");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "serdes_violation_pkt",
+ CTLFLAG_RD, &adapter->stats.scvpc,
+ "SerDes/SGMII Code Violation Pkt Count");
+
+ SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "header_redir_missed",
+ CTLFLAG_RD, &adapter->stats.hrmpc,
+ "Header Redirection Missed Packet Count");
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- device_printf(dev, "Queue(%d) tdh = %d, tdt = %d\n", i,
- E1000_READ_REG(&adapter->hw, E1000_TDH(i)),
- E1000_READ_REG(&adapter->hw, E1000_TDT(i)));
- device_printf(dev, "TX(%d) no descriptors avail event = %ld\n",
- txr->me, txr->no_desc_avail);
- device_printf(dev, "TX(%d) MSIX IRQ Handled = %ld\n",
- txr->me, txr->tx_irq);
- device_printf(dev, "Num Tx descriptors avail = %d\n",
- txr->tx_avail);
- device_printf(dev, "Tx Descriptors not avail1 = %ld\n",
- txr->no_desc_avail);
- }
- for (int i = 0; i < adapter->num_queues; i++, rxr++) {
- device_printf(dev, "RX(%d) MSIX IRQ Handled = %ld\n",
- rxr->me, rxr->rx_irq);
- device_printf(dev, "hw rdh = %d, hw rdt = %d\n",
- E1000_READ_REG(&adapter->hw, E1000_RDH(i)),
- E1000_READ_REG(&adapter->hw, E1000_RDT(i)));
- }
- device_printf(dev, "Std mbuf failed = %ld\n",
- adapter->mbuf_alloc_failed);
- device_printf(dev, "Std mbuf cluster failed = %ld\n",
- adapter->mbuf_cluster_failed);
- device_printf(dev, "Driver dropped packets = %ld\n",
- adapter->dropped_pkts);
-}
-static void
-em_print_hw_stats(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- device_printf(dev, "Excessive collisions = %lld\n",
- (long long)adapter->stats.ecol);
-#if (DEBUG_HW > 0) /* Dont output these errors normally */
- device_printf(dev, "Symbol errors = %lld\n",
- (long long)adapter->stats.symerrs);
-#endif
- device_printf(dev, "Sequence errors = %lld\n",
- (long long)adapter->stats.sec);
- device_printf(dev, "Defer count = %lld\n",
- (long long)adapter->stats.dc);
- device_printf(dev, "Missed Packets = %lld\n",
- (long long)adapter->stats.mpc);
- device_printf(dev, "Receive No Buffers = %lld\n",
- (long long)adapter->stats.rnbc);
- /* RLEC is inaccurate on some hardware, calculate our own. */
- device_printf(dev, "Receive Length Errors = %lld\n",
- ((long long)adapter->stats.roc + (long long)adapter->stats.ruc));
- device_printf(dev, "Receive errors = %lld\n",
- (long long)adapter->stats.rxerrc);
- device_printf(dev, "Crc errors = %lld\n",
- (long long)adapter->stats.crcerrs);
- device_printf(dev, "Alignment errors = %lld\n",
- (long long)adapter->stats.algnerrc);
- device_printf(dev, "Collision/Carrier extension errors = %lld\n",
- (long long)adapter->stats.cexterr);
- device_printf(dev, "watchdog timeouts = %ld\n",
- adapter->watchdog_events);
- device_printf(dev, "XON Rcvd = %lld\n",
- (long long)adapter->stats.xonrxc);
- device_printf(dev, "XON Xmtd = %lld\n",
- (long long)adapter->stats.xontxc);
- device_printf(dev, "XOFF Rcvd = %lld\n",
- (long long)adapter->stats.xoffrxc);
- device_printf(dev, "XOFF Xmtd = %lld\n",
- (long long)adapter->stats.xofftxc);
- device_printf(dev, "Good Packets Rcvd = %lld\n",
- (long long)adapter->stats.gprc);
- device_printf(dev, "Good Packets Xmtd = %lld\n",
- (long long)adapter->stats.gptc);
- device_printf(dev, "TSO Contexts Xmtd = %lld\n",
- (long long)adapter->stats.tsctc);
- device_printf(dev, "TSO Contexts Failed = %lld\n",
- (long long)adapter->stats.tsctfc);
}
/**********************************************************************
@@ -4986,28 +5147,9 @@ em_print_hw_stats(struct adapter *adapte
* 32 words, stuff that matters is in that extent.
*
**********************************************************************/
-static void
-em_print_nvm_info(struct adapter *adapter)
-{
- u16 eeprom_data;
- int i, j, row = 0;
-
- /* Its a bit crude, but it gets the job done */
- printf("\nInterface EEPROM Dump:\n");
- printf("Offset\n0x0000 ");
- for (i = 0, j = 0; i < 32; i++, j++) {
- if (j == 8) { /* Make the offset block */
- j = 0; ++row;
- printf("\n0x00%x0 ",row);
- }
- e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data);
- printf("%04x ", eeprom_data);
- }
- printf("\n");
-}
static int
-em_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
+em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS)
{
struct adapter *adapter;
int error;
@@ -5019,16 +5161,12 @@ em_sysctl_debug_info(SYSCTL_HANDLER_ARGS
if (error || !req->newptr)
return (error);
- if (result == 1) {
- adapter = (struct adapter *)arg1;
- em_print_debug_info(adapter);
- }
/*
* This value will cause a hex dump of the
* first 32 16-bit words of the EEPROM to
* the screen.
*/
- if (result == 2) {
+ if (result == 1) {
adapter = (struct adapter *)arg1;
em_print_nvm_info(adapter);
}
@@ -5036,26 +5174,24 @@ em_sysctl_debug_info(SYSCTL_HANDLER_ARGS
return (error);
}
-
-static int
-em_sysctl_stats(SYSCTL_HANDLER_ARGS)
+static void
+em_print_nvm_info(struct adapter *adapter)
{
- struct adapter *adapter;
- int error;
- int result;
-
- result = -1;
- error = sysctl_handle_int(oidp, &result, 0, req);
-
- if (error || !req->newptr)
- return (error);
+ u16 eeprom_data;
+ int i, j, row = 0;
- if (result == 1) {
- adapter = (struct adapter *)arg1;
- em_print_hw_stats(adapter);
+ /* Its a bit crude, but it gets the job done */
+ printf("\nInterface EEPROM Dump:\n");
+ printf("Offset\n0x0000 ");
+ for (i = 0, j = 0; i < 32; i++, j++) {
+ if (j == 8) { /* Make the offset block */
+ j = 0; ++row;
+ printf("\n0x00%x0 ",row);
+ }
+ e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data);
+ printf("%04x ", eeprom_data);
}
-
- return (error);
+ printf("\n");
}
static int
Modified: stable/8/sys/dev/e1000/if_igb.c
==============================================================================
--- stable/8/sys/dev/e1000/if_igb.c Fri Jun 18 16:36:57 2010 (r209308)
+++ stable/8/sys/dev/e1000/if_igb.c Fri Jun 18 17:22:08 2010 (r209309)
@@ -99,7 +99,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 1.9.5";
+char igb_driver_version[] = "version - 1.9.6";
/*********************************************************************
@@ -205,14 +205,13 @@ static __inline void igb_rx_discard(stru
static __inline void igb_rx_input(struct rx_ring *,
struct ifnet *, struct mbuf *, u32);
-static bool igb_rxeof(struct igb_queue *, int);
+static bool igb_rxeof(struct igb_queue *, int, int *);
static void igb_rx_checksum(u32, struct mbuf *, u32);
static int igb_tx_ctx_setup(struct tx_ring *, struct mbuf *);
static bool igb_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static void igb_set_promisc(struct adapter *);
static void igb_disable_promisc(struct adapter *);
static void igb_set_multi(struct adapter *);
-static void igb_print_hw_stats(struct adapter *);
static void igb_update_link_status(struct adapter *);
static void igb_refresh_mbufs(struct rx_ring *, int);
@@ -224,11 +223,10 @@ static int igb_xmit(struct tx_ring *, st
static int igb_dma_malloc(struct adapter *, bus_size_t,
struct igb_dma_alloc *, int);
static void igb_dma_free(struct adapter *, struct igb_dma_alloc *);
-static void igb_print_debug_info(struct adapter *);
+static int igb_sysctl_nvm_info(SYSCTL_HANDLER_ARGS);
static void igb_print_nvm_info(struct adapter *);
static int igb_is_valid_ether_addr(u8 *);
-static int igb_sysctl_stats(SYSCTL_HANDLER_ARGS);
-static int igb_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
+static void igb_add_hw_stats(struct adapter *adapter);
/* Management and WOL Support */
static void igb_init_manageability(struct adapter *);
static void igb_release_manageability(struct adapter *);
@@ -240,7 +238,6 @@ static void igb_led_func(void *, int
static int igb_irq_fast(void *);
static void igb_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
-static void igb_handle_rxtx(void *context, int pending);
static void igb_handle_que(void *context, int pending);
static void igb_handle_link(void *context, int pending);
@@ -412,13 +409,8 @@ igb_attach(device_t dev)
/* SYSCTL stuff */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
- igb_sysctl_debug_info, "I", "Debug Information");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
- igb_sysctl_stats, "I", "Statistics");
+ OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
+ igb_sysctl_nvm_info, "I", "NVM Information");
SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
@@ -584,6 +576,8 @@ igb_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
igb_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
+ igb_add_hw_stats(adapter);
+
/* Tell the stack that the interface is not active */
adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
@@ -818,21 +812,25 @@ igb_start(struct ifnet *ifp)
static int
igb_mq_start(struct ifnet *ifp, struct mbuf *m)
{
- struct adapter *adapter = ifp->if_softc;
- struct tx_ring *txr;
- int i = 0, err = 0;
+ struct adapter *adapter = ifp->if_softc;
+ struct igb_queue *que;
+ struct tx_ring *txr;
+ int i = 0, err = 0;
/* Which queue to use */
if ((m->m_flags & M_FLOWID) != 0)
i = m->m_pkthdr.flowid % adapter->num_queues;
txr = &adapter->tx_rings[i];
+ que = &adapter->queues[i];
if (IGB_TX_TRYLOCK(txr)) {
err = igb_mq_start_locked(ifp, txr, m);
IGB_TX_UNLOCK(txr);
- } else
+ } else {
err = drbr_enqueue(ifp, txr->br, m);
+ taskqueue_enqueue(que->tq, &que->que_task);
+ }
return (err);
}
@@ -1225,50 +1223,24 @@ igb_init(void *arg)
static void
-igb_handle_rxtx(void *context, int pending)
-{
- struct igb_queue *que = context;
- struct adapter *adapter = que->adapter;
- struct tx_ring *txr = adapter->tx_rings;
- struct ifnet *ifp;
-
- ifp = adapter->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (igb_rxeof(que, adapter->rx_process_limit))
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
- IGB_TX_LOCK(txr);
- igb_txeof(txr);
-
-#if __FreeBSD_version >= 800000
- if (!drbr_empty(ifp, txr->br))
- igb_mq_start_locked(ifp, txr, NULL);
-#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- igb_start_locked(txr, ifp);
-#endif
- IGB_TX_UNLOCK(txr);
- }
-
- igb_enable_intr(adapter);
-}
-
-static void
igb_handle_que(void *context, int pending)
{
struct igb_queue *que = context;
struct adapter *adapter = que->adapter;
struct tx_ring *txr = que->txr;
struct ifnet *ifp = adapter->ifp;
- bool more;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- more = igb_rxeof(que, -1);
+ bool more;
+
+ more = igb_rxeof(que, -1, NULL);
IGB_TX_LOCK(txr);
- igb_txeof(txr);
+ if (igb_txeof(txr))
+ more = TRUE;
#if __FreeBSD_version >= 800000
- igb_mq_start_locked(ifp, txr, NULL);
+ if (!drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr, NULL);
#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
igb_start_locked(txr, ifp);
@@ -1280,11 +1252,15 @@ igb_handle_que(void *context, int pendin
}
}
- /* Reenable this interrupt */
#ifdef DEVICE_POLLING
- if (!(ifp->if_capenable & IFCAP_POLLING))
+ if (ifp->if_capenable & IFCAP_POLLING)
+ return;
#endif
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
+ /* Reenable this interrupt */
+ if (que->eims)
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
+ else
+ igb_enable_intr(adapter);
}
/* Deal with link in a sleepable context */
@@ -1306,8 +1282,9 @@ igb_handle_link(void *context, int pendi
static int
igb_irq_fast(void *arg)
{
- struct adapter *adapter = arg;
- uint32_t reg_icr;
+ struct adapter *adapter = arg;
+ struct igb_queue *que = adapter->queues;
+ u32 reg_icr;
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
@@ -1329,11 +1306,11 @@ igb_irq_fast(void *arg)
* MSI message reordering errata on certain systems.
*/
igb_disable_intr(adapter);
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
+ taskqueue_enqueue(que->tq, &que->que_task);
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ taskqueue_enqueue(que->tq, &adapter->link_task);
if (reg_icr & E1000_ICR_RXO)
adapter->rx_overruns++;
@@ -1373,15 +1350,14 @@ igb_poll(struct ifnet *ifp, enum poll_cm
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ igb_handle_link(adapter, 0);
if (reg_icr & E1000_ICR_RXO)
adapter->rx_overruns++;
}
IGB_CORE_UNLOCK(adapter);
- /* TODO: rx_count */
- rx_done = igb_rxeof(que, count) ? 1 : 0;
+ igb_rxeof(que, count, &rx_done);
IGB_TX_LOCK(txr);
do {
@@ -1421,7 +1397,7 @@ igb_msix_que(void *arg)
more_tx = igb_txeof(txr);
IGB_TX_UNLOCK(txr);
- more_rx = igb_rxeof(que, adapter->rx_process_limit);
+ more_rx = igb_rxeof(que, adapter->rx_process_limit, NULL);
if (igb_enable_aim == FALSE)
goto no_calc;
@@ -1501,7 +1477,7 @@ igb_msix_link(void *arg)
icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
if (!(icr & E1000_ICR_LSC))
goto spurious;
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ igb_handle_link(adapter, 0);
spurious:
/* Rearm */
@@ -1900,7 +1876,6 @@ static void
igb_local_timer(void *arg)
{
struct adapter *adapter = arg;
- struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
struct tx_ring *txr = adapter->tx_rings;
@@ -1910,9 +1885,6 @@ igb_local_timer(void *arg)
igb_update_link_status(adapter);
igb_update_stats_counters(adapter);
- if (igb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING)
- igb_print_hw_stats(adapter);
-
/*
** Watchdog: check for time since any descriptor was cleaned
*/
@@ -1923,11 +1895,6 @@ igb_local_timer(void *arg)
goto timeout;
}
- /* Trigger an RX interrupt on all queues */
-#ifdef DEVICE_POLLING
- if (!(ifp->if_capenable & IFCAP_POLLING))
-#endif
- E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->rx_mask);
callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
return;
@@ -2142,20 +2109,20 @@ igb_allocate_legacy(struct adapter *adap
* Try allocating a fast interrupt and the associated deferred
* processing contexts.
*/
- TASK_INIT(&adapter->rxtx_task, 0, igb_handle_rxtx, que);
+ TASK_INIT(&que->que_task, 0, igb_handle_que, que);
/* Make tasklet for deferred link handling */
TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter);
- adapter->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
+ que->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
+ taskqueue_thread_enqueue, &que->tq);
+ taskqueue_start_threads(&que->tq, 1, PI_NET, "%s taskq",
device_get_nameunit(adapter->dev));
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list