From owner-svn-src-stable-7@FreeBSD.ORG Tue Aug 31 19:26:29 2010 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9544D10656A8; Tue, 31 Aug 2010 19:26:29 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 82E5C8FC16; Tue, 31 Aug 2010 19:26:29 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o7VJQT4J039596; Tue, 31 Aug 2010 19:26:29 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o7VJQTF3039592; Tue, 31 Aug 2010 19:26:29 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201008311926.o7VJQTF3039592@svn.freebsd.org> From: John Baldwin Date: Tue, 31 Aug 2010 19:26:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212068 - stable/7/sys/dev/e1000 X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Aug 2010 19:26:29 -0000 Author: jhb Date: Tue Aug 31 19:26:29 2010 New Revision: 212068 URL: http://svn.freebsd.org/changeset/base/212068 Log: MFC 206429: Sync em(4) and igb(4) drivers with 8 except for VF support: - Remove unneeded rxtx handler, make que handler generic in igb. - Do not allocate header mbufs in rx ring if not doing hdr split in igb. - Release the lock in rxeof call to stack. - Change rxeof api for poll friendliness, and eliminate unnecessary link tasklet use. - Move statistics for em into sysctl tree. - Reenable hardware checksum offload for VLAN frames in igb. - Fix for a panic when TX checksum offload is done and a packet has only a header in the first mbuf in em. Approved by: jfv Modified: stable/7/sys/dev/e1000/if_em.c stable/7/sys/dev/e1000/if_igb.c stable/7/sys/dev/e1000/if_igb.h stable/7/sys/dev/e1000/if_lem.c Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/dev/e1000/if_em.c ============================================================================== --- stable/7/sys/dev/e1000/if_em.c Tue Aug 31 19:01:46 2010 (r212067) +++ stable/7/sys/dev/e1000/if_em.c Tue Aug 31 19:26:29 2010 (r212068) @@ -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); @@ -1345,18 +1345,19 @@ em_init(void *arg) * Legacy polling routine: note this only works with single queue * *********************************************************************/ -static void +static int em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) { 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; + 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); @@ -1386,7 +1385,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd #endif EM_TX_UNLOCK(txr); - return; + return (rx_done); } #endif /* DEVICE_POLLING */ @@ -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 @@ -1744,6 +1738,19 @@ em_xmit(struct tx_ring *txr, struct mbuf do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0); /* + ** When doing checksum offload, it is critical to + ** make sure the first mbuf has more than header, + ** because that routine expects data to be present. + */ + if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) && + (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) { + m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); + *m_headp = m_head; + if (m_head == NULL) + return (ENOBUFS); + } + + /* * TSO workaround: * If an mbuf is only header we need * to pull 4 bytes of data into it. @@ -2069,9 +2076,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 +2435,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); } @@ -3276,6 +3275,7 @@ em_transmit_checksum_setup(struct tx_rin cmd = hdr_len = ipproto = 0; + *txd_upper = *txd_lower = 0; cur = txr->next_avail_desc; /* @@ -3319,29 +3319,21 @@ em_transmit_checksum_setup(struct tx_rin *txd_upper |= E1000_TXD_POPTS_IXSM << 8; } - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - hdr_len = ehdrlen + ip_hlen; ipproto = ip->ip_p; - break; + case ETHERTYPE_IPV6: ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */ - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - /* IPv6 doesn't have a header checksum. */ hdr_len = ehdrlen + ip_hlen; ipproto = ip6->ip6_nxt; - break; + default: - *txd_upper = 0; - *txd_lower = 0; return; } @@ -3395,6 +3387,8 @@ em_transmit_checksum_setup(struct tx_rin break; } + if (TXD == NULL) + return; TXD->tcp_seg_setup.data = htole32(0); TXD->cmd_and_length = htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); @@ -4090,8 +4084,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 +4096,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 +4190,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 +4212,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 +4867,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 +5155,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 +5169,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 +5182,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/7/sys/dev/e1000/if_igb.c ============================================================================== --- stable/7/sys/dev/e1000/if_igb.c Tue Aug 31 19:01:46 2010 (r212067) +++ stable/7/sys/dev/e1000/if_igb.c Tue Aug 31 19:26:29 2010 (r212068) @@ -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,7 +205,7 @@ 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 *); @@ -238,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); @@ -813,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); } @@ -1220,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); @@ -1275,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 */ @@ -1301,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); @@ -1324,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++; @@ -1368,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 { @@ -1416,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; @@ -1496,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 */ @@ -1914,11 +1895,6 @@ igb_local_timer(void *arg) goto timeout; } - /* Trigger an RX interrupt on all queues */ -#ifdef DEVICE_POLLING *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***