From owner-freebsd-stable@FreeBSD.ORG Tue Jul 27 10:05:27 2010 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9AF9D1065677 for ; Tue, 27 Jul 2010 10:05:27 +0000 (UTC) (envelope-from h.schmalzbauer@omnilan.de) Received: from stith.flb.omnilan.net (s1.omnilan.net [62.245.232.135]) by mx1.freebsd.org (Postfix) with ESMTP id 8CEEA8FC18 for ; Tue, 27 Jul 2010 10:05:24 +0000 (UTC) Received: from titan.flb.omnilan.net (titan.lo4.flb.omnilan.net [172.21.1.150]) (authenticated bits=0) by stith.flb.omnilan.net (8.13.8/8.13.8) with ESMTP id o6RA5ARB090480 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 27 Jul 2010 12:05:10 +0200 (CEST) (envelope-from h.schmalzbauer@omnilan.de) X-Authentication-Warning: smtp.dmz.omnisec.de: Host titan.lo4.flb.omnilan.net [172.21.1.150] claimed to be titan.flb.omnilan.net Message-ID: <4C4EAF55.9070908@omnilan.de> Date: Tue, 27 Jul 2010 12:05:09 +0200 From: Harald Schmalzbauer Organization: OmniLAN User-Agent: Thunderbird 2.0.0.23 (X11/20090906) MIME-Version: 1.0 To: "Brian A. Seklecki" References: <1275419919.30057.50.camel@soundwave.ws.pitbpa0.priv.collaborativefusion.com> <20100601193733.GA44816@icarus.home.lan> <4C3CBC1E.9030106@omnilan.de> <1279212377.31311.144.camel@soundwave> <1279212602.31311.151.camel@soundwave> <84875A93-3851-476E-8F2E-A7008CA6BD5C@FreeBSD.org> <4C3F49E8.9090201@comcast.net> <1279552398.31311.443.camel@soundwave> <4C447684.7010308@omnilan.de> <4C4DB59D.6020204@noc.cfi.pgh.pa.us> <4C4DD917.3050007@omnilan.de> <1280170608.17017.17.camel@soundwave> In-Reply-To: <1280170608.17017.17.camel@soundwave> X-Enigmail-Version: 0.95.6 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig5A94A6482AB6BCA889B3EE66" Cc: FreeBSD Stable Subject: Re: e1000 patchset for 8.1-release [Was: em(4) duplex problems with 82541EI on RELENG_8, -CURRENT on PowerEdge 1850] X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Jul 2010 10:05:27 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig5A94A6482AB6BCA889B3EE66 Content-Type: multipart/mixed; boundary="------------020106010007020907000302" This is a multi-part message in MIME format. --------------020106010007020907000302 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Brian A. Seklecki schrieb am 26.07.2010 20:56 (localtime): =2E.. I made a new convenience patch which brings the comperhensive r209309=20 merge from HEAD to RELENG_8 (not RELENG_8_1, so not included in=20 FreeBSD-8.1-RELEASE) along with the new fix for TX checksum offload=20 panics (r209959, not yet merged) to RELENG_8_1 >> t not 209959, which addresses >>> the TX checksum panic?) >> Looks like I really missed r209259 > > > I fudged it manually --- Attached: > >=20 cf_e1000-releng8_send_out_the_clowns_then_dougBarton_then_Vanila_Ice.patc= h > > It applies cleanly to 8.1, but it doesn't fix my problem. This patch differs in many lines from yours. I haven't checked the diff=20 of the diff, but maybe something went wrong. Perhaps it's worth trying=20 my new patchset. Please find attached. -Harry --------------020106010007020907000302 Content-Type: text/x-patch; name="e1000-r209309+r209959.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="e1000-r209309+r209959.patch" --- src/sys/dev/e1000/if_em.c.orig 2010-06-14 04:09:06.000000000 +0200 +++ src/sys/dev/e1000/if_em.c 2010-07-27 10:06:45.317871239 +0200 @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. =20 ************************************************************************= ******/ -/*$FreeBSD: src/sys/dev/e1000/if_em.c,v 1.21.2.10.2.1 2010/06/14 02:09:0= 6 kensmith Exp $*/ +/*$FreeBSD: src/sys/dev/e1000/if_em.c,v 1.51 2010/07/12 21:47:30 jfv Exp= $*/ =20 #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_device_polling.h" @@ -230,8 +230,9 @@ 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 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_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 @@ TUNABLE_INT("hw.em.sbp", &em_debug_sbp); =20 /* Local controls for MSI/MSIX */ +#ifdef EM_MULTIQUEUE static int em_enable_msix =3D TRUE; static int em_msix_queues =3D 2; /* for 82574, can be 1 or 2 */ +#else +static int em_enable_msix =3D FALSE; +static int em_msix_queues =3D 0; /* disable */ +#endif TUNABLE_INT("hw.em.enable_msix", &em_enable_msix); TUNABLE_INT("hw.em.msix_queues", &em_msix_queues); =20 @@ -447,13 +450,8 @@ /* 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"); =20 callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); =20 @@ -651,6 +649,8 @@ adapter->vlan_detach =3D EVENTHANDLER_REGISTER(vlan_unconfig, em_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);=20 =20 + 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 @@ struct adapter *adapter =3D ifp->if_softc; struct tx_ring *txr =3D adapter->tx_rings; struct rx_ring *rxr =3D adapter->rx_rings; - u32 reg_icr, rx_done =3D 0; + u32 reg_icr; + int rx_done; =20 EM_CORE_LOCK(adapter); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) =3D=3D 0) { EM_CORE_UNLOCK(adapter); - return (rx_done); + return (0); } =20 if (cmd =3D=3D POLL_AND_CHECK_STATUS) { @@ -1371,9 +1372,7 @@ } EM_CORE_UNLOCK(adapter); =20 - EM_RX_LOCK(rxr); - rx_done =3D em_rxeof(rxr, count); - EM_RX_UNLOCK(rxr); + em_rxeof(rxr, count, &rx_done); =20 EM_TX_LOCK(txr); em_txeof(txr); @@ -1445,16 +1444,15 @@ struct ifnet *ifp =3D adapter->ifp; struct tx_ring *txr =3D adapter->tx_rings; struct rx_ring *rxr =3D adapter->rx_rings; - bool more_rx; + bool more; =20 =20 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - EM_RX_LOCK(rxr); - more_rx =3D em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); + more =3D em_rxeof(rxr, adapter->rx_process_limit, NULL); =20 EM_TX_LOCK(txr); - em_txeof(txr); + if (em_txeof(txr)) + more =3D TRUE; #ifdef EM_MULTIQUEUE if (!drbr_empty(ifp, txr->br)) em_mq_start_locked(ifp, txr, NULL); @@ -1463,7 +1461,7 @@ 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 @@ struct adapter *adapter =3D rxr->adapter; bool more; =20 - EM_RX_LOCK(rxr); ++rxr->rx_irq; - more =3D em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); + more =3D em_rxeof(rxr, adapter->rx_process_limit, NULL); if (more) taskqueue_enqueue(rxr->tq, &rxr->rx_task); else @@ -1539,7 +1535,7 @@ =20 if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { adapter->hw.mac.get_link_status =3D 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 @@ struct adapter *adapter =3D rxr->adapter; bool more; =20 - EM_RX_LOCK(rxr); - more =3D em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); + more =3D em_rxeof(rxr, adapter->rx_process_limit, NULL); if (more) taskqueue_enqueue(rxr->tq, &rxr->rx_task); else @@ -1744,6 +1738,19 @@ do_tso =3D ((m_head->m_pkthdr.csum_flags & CSUM_TSO) !=3D 0); =20 /* + ** 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 =3D m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); + *m_headp =3D m_head; + if (m_head =3D=3D NULL) + return (ENOBUFS); + } + + /* * TSO workaround:=20 * If an mbuf is only header we need =20 * to pull 4 bytes of data into it.=20 @@ -2069,9 +2076,6 @@ if (e1000_get_laa_state_82571(&adapter->hw) =3D=3D TRUE) e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); =20 - 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 @@ adapter->linkvec =3D vector; adapter->ivars |=3D (8 | vector) << 16; adapter->ivars |=3D 0x80000000; - TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter); - adapter->tq =3D 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)); =20 return (0); } @@ -3276,6 +3275,7 @@ =20 =20 cmd =3D hdr_len =3D ipproto =3D 0; + *txd_upper =3D *txd_lower =3D 0; cur =3D txr->next_avail_desc; =20 /* @@ -3319,29 +3319,21 @@ *txd_upper |=3D E1000_TXD_POPTS_IXSM << 8; } =20 - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - hdr_len =3D ehdrlen + ip_hlen; ipproto =3D ip->ip_p; - break; + case ETHERTYPE_IPV6: ip6 =3D (struct ip6_hdr *)(mp->m_data + ehdrlen); ip_hlen =3D sizeof(struct ip6_hdr); /* XXX: No header stacking. */ =20 - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - /* IPv6 doesn't have a header checksum. */ =20 hdr_len =3D ehdrlen + ip_hlen; ipproto =3D ip6->ip6_nxt; - break; + default: - *txd_upper =3D 0; - *txd_lower =3D 0; return; } =20 @@ -3395,6 +3387,8 @@ break; } =20 + if (TXD =3D=3D NULL) + return; TXD->tcp_seg_setup.data =3D htole32(0); TXD->cmd_and_length =3D htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); @@ -4090,8 +4084,8 @@ * =20 * 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 =3D rxr->adapter; struct ifnet *ifp =3D adapter->ifp; @@ -4102,7 +4096,7 @@ bool eop; struct e1000_rx_desc *cur; =20 - EM_RX_LOCK_ASSERT(rxr); + EM_RX_LOCK(rxr); =20 for (i =3D rxr->next_to_check, processed =3D 0; count !=3D 0;) { =20 @@ -4196,8 +4190,13 @@ i =3D 0; =20 /* Send to the stack */ - if (sendmp !=3D NULL) + if (sendmp !=3D NULL) { + rxr->next_to_check =3D i; + EM_RX_UNLOCK(rxr); (*ifp->if_input)(ifp, sendmp); + EM_RX_LOCK(rxr); + i =3D rxr->next_to_check; + } =20 /* Only refresh mbufs every 8 descriptors */ if (processed =3D=3D 8) { @@ -4213,12 +4212,11 @@ } =20 rxr->next_to_check =3D i; + if (done !=3D NULL) + *done =3D rxdone; + EM_RX_UNLOCK(rxr); =20 -#ifdef DEVICE_POLLING - return (rxdone); -#else return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); -#endif } =20 #ifndef __NO_STRICT_ALIGNMENT @@ -4869,114 +4867,285 @@ } =20 =20 -/********************************************************************** - * - * 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 =3D adapter->dev; - u8 *hw_addr =3D adapter->hw.hw_addr; - struct rx_ring *rxr =3D adapter->rx_rings; - struct tx_ring *txr =3D adapter->tx_rings; =20 - device_printf(dev, "Adapter hardware address =3D %p \n", hw_addr); - device_printf(dev, "CTRL =3D 0x%x RCTL =3D 0x%x \n", - E1000_READ_REG(&adapter->hw, E1000_CTRL), - E1000_READ_REG(&adapter->hw, E1000_RCTL)); - device_printf(dev, "Packet buffer =3D Tx=3D%dk Rx=3D%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 =3D %d low =3D %d\n", - adapter->hw.fc.high_water, - adapter->hw.fc.low_water); - device_printf(dev, "tx_int_delay =3D %d, tx_abs_int_delay =3D %d\n", - E1000_READ_REG(&adapter->hw, E1000_TIDV), - E1000_READ_REG(&adapter->hw, E1000_TADV)); - device_printf(dev, "rx_int_delay =3D %d, rx_abs_int_delay =3D %d\n", - E1000_READ_REG(&adapter->hw, E1000_RDTR), - E1000_READ_REG(&adapter->hw, E1000_RADV)); + struct sysctl_ctx_list *ctx =3D device_get_sysctl_ctx(dev); + struct sysctl_oid *tree =3D device_get_sysctl_tree(dev); + struct sysctl_oid_list *child =3D SYSCTL_CHILDREN(tree); + struct e1000_hw_stats *stats =3D &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",=20 + CTLFLAG_RD, &adapter->link_irq, 0, + "Link MSIX IRQ Handled"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",=20 + CTLFLAG_RD, &adapter->mbuf_alloc_failed, + "Std mbuf failed"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",=20 + CTLFLAG_RD, &adapter->mbuf_cluster_failed, + "Std mbuf cluster failed"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",=20 + CTLFLAG_RD, &adapter->dropped_pkts, + "Driver dropped packets"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",=20 + 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",=20 + CTLFLAG_RD, &adapter->hw.fc.low_water, 0, + "Flow Control Low Watermark"); + + /* MAC stats get the own sub node */ + + stat_node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",=20 + CTLFLAG_RD, NULL, "Statistics"); + stat_list =3D SYSCTL_CHILDREN(stat_node); + + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll",=20 + 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",=20 + CTLFLAG_RD, &adapter->stats.gorc,=20 + "Good Octets Received");=20 + + /* Packet Transmission Stats */ + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octest_txd",=20 + CTLFLAG_RD, &adapter->stats.gotc,=20 + "Good Octest Transmitted");=20 + 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 =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "interrupts",=20 + CTLFLAG_RD, NULL, "Interrupt Statistics"); + int_list =3D 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 =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "host",=20 + CTLFLAG_RD, NULL,=20 + "Host to Card Statistics"); + + host_list =3D 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"); =20 - for (int i =3D 0; i < adapter->num_queues; i++, txr++) { - device_printf(dev, "Queue(%d) tdh =3D %d, tdt =3D %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 =3D %ld\n", - txr->me, txr->no_desc_avail); - device_printf(dev, "TX(%d) MSIX IRQ Handled =3D %ld\n", - txr->me, txr->tx_irq); - device_printf(dev, "Num Tx descriptors avail =3D %d\n", - txr->tx_avail); - device_printf(dev, "Tx Descriptors not avail1 =3D %ld\n", - txr->no_desc_avail); - } - for (int i =3D 0; i < adapter->num_queues; i++, rxr++) { - device_printf(dev, "RX(%d) MSIX IRQ Handled =3D %ld\n", - rxr->me, rxr->rx_irq); - device_printf(dev, "hw rdh =3D %d, hw rdt =3D %d\n", - E1000_READ_REG(&adapter->hw, E1000_RDH(i)), - E1000_READ_REG(&adapter->hw, E1000_RDT(i))); - } - device_printf(dev, "Std mbuf failed =3D %ld\n", - adapter->mbuf_alloc_failed); - device_printf(dev, "Std mbuf cluster failed =3D %ld\n", - adapter->mbuf_cluster_failed); - device_printf(dev, "Driver dropped packets =3D %ld\n", - adapter->dropped_pkts); -} =20 -static void -em_print_hw_stats(struct adapter *adapter) -{ - device_t dev =3D adapter->dev; =20 - device_printf(dev, "Excessive collisions =3D %lld\n", - (long long)adapter->stats.ecol); -#if (DEBUG_HW > 0) /* Dont output these errors normally */ - device_printf(dev, "Symbol errors =3D %lld\n", - (long long)adapter->stats.symerrs); -#endif - device_printf(dev, "Sequence errors =3D %lld\n", - (long long)adapter->stats.sec); - device_printf(dev, "Defer count =3D %lld\n", - (long long)adapter->stats.dc); - device_printf(dev, "Missed Packets =3D %lld\n", - (long long)adapter->stats.mpc); - device_printf(dev, "Receive No Buffers =3D %lld\n", - (long long)adapter->stats.rnbc); - /* RLEC is inaccurate on some hardware, calculate our own. */ - device_printf(dev, "Receive Length Errors =3D %lld\n", - ((long long)adapter->stats.roc + (long long)adapter->stats.ruc)); - device_printf(dev, "Receive errors =3D %lld\n", - (long long)adapter->stats.rxerrc); - device_printf(dev, "Crc errors =3D %lld\n", - (long long)adapter->stats.crcerrs); - device_printf(dev, "Alignment errors =3D %lld\n", - (long long)adapter->stats.algnerrc); - device_printf(dev, "Collision/Carrier extension errors =3D %lld\n", - (long long)adapter->stats.cexterr); - device_printf(dev, "watchdog timeouts =3D %ld\n", - adapter->watchdog_events); - device_printf(dev, "XON Rcvd =3D %lld\n", - (long long)adapter->stats.xonrxc); - device_printf(dev, "XON Xmtd =3D %lld\n", - (long long)adapter->stats.xontxc); - device_printf(dev, "XOFF Rcvd =3D %lld\n", - (long long)adapter->stats.xoffrxc); - device_printf(dev, "XOFF Xmtd =3D %lld\n", - (long long)adapter->stats.xofftxc); - device_printf(dev, "Good Packets Rcvd =3D %lld\n", - (long long)adapter->stats.gprc); - device_printf(dev, "Good Packets Xmtd =3D %lld\n", - (long long)adapter->stats.gptc); - device_printf(dev, "TSO Contexts Xmtd =3D %lld\n", - (long long)adapter->stats.tsctc); - device_printf(dev, "TSO Contexts Failed =3D %lld\n", - (long long)adapter->stats.tsctfc); } =20 /********************************************************************** @@ -4986,28 +5155,9 @@ * 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 =3D 0; - - /* Its a bit crude, but it gets the job done */ - printf("\nInterface EEPROM Dump:\n"); - printf("Offset\n0x0000 "); - for (i =3D 0, j =3D 0; i < 32; i++, j++) { - if (j =3D=3D 8) { /* Make the offset block */ - j =3D 0; ++row; - printf("\n0x00%x0 ",row); - } - e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); - printf("%04x ", eeprom_data); - } - printf("\n"); -} =20 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 @@ if (error || !req->newptr) return (error); =20 - if (result =3D=3D 1) { - adapter =3D (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 =3D=3D 2) { + if (result =3D=3D 1) { adapter =3D (struct adapter *)arg1; em_print_nvm_info(adapter); } @@ -5036,26 +5182,24 @@ return (error); } =20 - -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 =3D -1; - error =3D sysctl_handle_int(oidp, &result, 0, req); - - if (error || !req->newptr) - return (error); + u16 eeprom_data; + int i, j, row =3D 0; =20 - if (result =3D=3D 1) { - adapter =3D (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 =3D 0, j =3D 0; i < 32; i++, j++) { + if (j =3D=3D 8) { /* Make the offset block */ + j =3D 0; ++row; + printf("\n0x00%x0 ",row); + } + e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); + printf("%04x ", eeprom_data); } - - return (error); + printf("\n"); } =20 static int --- src/sys/dev/e1000/if_igb.c.orig 2010-06-14 04:09:06.000000000 +0200 +++ src/sys/dev/e1000/if_igb.c 2010-07-27 10:06:53.833945364 +0200 @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. =20 ************************************************************************= ******/ -/*$FreeBSD: src/sys/dev/e1000/if_igb.c,v 1.21.2.8.2.1 2010/06/14 02:09:0= 6 kensmith Exp $*/ +/*$FreeBSD: src/sys/dev/e1000/if_igb.c,v 1.21.2.9 2010/06/18 17:22:08 jf= v Exp $*/ =20 =20 #ifdef HAVE_KERNEL_OPTION_HEADERS @@ -99,7 +99,7 @@ /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] =3D "version - 1.9.5"; +char igb_driver_version[] =3D "version - 1.9.6"; =20 =20 /********************************************************************* @@ -205,14 +205,13 @@ static __inline void igb_rx_input(struct rx_ring *, struct ifnet *, struct mbuf *, u32); =20 -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); =20 @@ -224,11 +223,10 @@ 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 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); =20 @@ -412,13 +409,8 @@ /* 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"); =20 SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), @@ -584,6 +576,8 @@ adapter->vlan_detach =3D EVENTHANDLER_REGISTER(vlan_unconfig, igb_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); =20 + igb_add_hw_stats(adapter); + /* Tell the stack that the interface is not active */ adapter->ifp->if_drv_flags &=3D ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); =20 @@ -818,21 +812,25 @@ static int igb_mq_start(struct ifnet *ifp, struct mbuf *m) { - struct adapter *adapter =3D ifp->if_softc; - struct tx_ring *txr; - int i =3D 0, err =3D 0; + struct adapter *adapter =3D ifp->if_softc; + struct igb_queue *que; + struct tx_ring *txr; + int i =3D 0, err =3D 0; =20 /* Which queue to use */ if ((m->m_flags & M_FLOWID) !=3D 0) i =3D m->m_pkthdr.flowid % adapter->num_queues; =20 txr =3D &adapter->tx_rings[i]; + que =3D &adapter->queues[i]; =20 if (IGB_TX_TRYLOCK(txr)) { err =3D igb_mq_start_locked(ifp, txr, m); IGB_TX_UNLOCK(txr); - } else + } else { err =3D drbr_enqueue(ifp, txr->br, m); + taskqueue_enqueue(que->tq, &que->que_task); + } =20 return (err); } @@ -1225,50 +1223,24 @@ =20 =20 static void -igb_handle_rxtx(void *context, int pending) -{ - struct igb_queue *que =3D context; - struct adapter *adapter =3D que->adapter; - struct tx_ring *txr =3D adapter->tx_rings; - struct ifnet *ifp; - - ifp =3D 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 >=3D 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 =3D context; struct adapter *adapter =3D que->adapter; struct tx_ring *txr =3D que->txr; struct ifnet *ifp =3D adapter->ifp; - bool more; =20 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - more =3D igb_rxeof(que, -1); + bool more; + + more =3D igb_rxeof(que, -1, NULL); =20 IGB_TX_LOCK(txr); - igb_txeof(txr); + if (igb_txeof(txr)) + more =3D TRUE; #if __FreeBSD_version >=3D 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 @@ } } =20 - /* 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); } =20 /* Deal with link in a sleepable context */ @@ -1306,8 +1282,9 @@ static int igb_irq_fast(void *arg) { - struct adapter *adapter =3D arg; - uint32_t reg_icr; + struct adapter *adapter =3D arg; + struct igb_queue *que =3D adapter->queues; + u32 reg_icr; =20 =20 reg_icr =3D E1000_READ_REG(&adapter->hw, E1000_ICR); @@ -1329,11 +1306,11 @@ * 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); =20 /* 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); =20 if (reg_icr & E1000_ICR_RXO) adapter->rx_overruns++; @@ -1373,15 +1350,14 @@ reg_icr =3D 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); =20 if (reg_icr & E1000_ICR_RXO) adapter->rx_overruns++; } IGB_CORE_UNLOCK(adapter); =20 - /* TODO: rx_count */ - rx_done =3D igb_rxeof(que, count) ? 1 : 0; + igb_rxeof(que, count, &rx_done); =20 IGB_TX_LOCK(txr); do { @@ -1421,7 +1397,7 @@ more_tx =3D igb_txeof(txr); IGB_TX_UNLOCK(txr); =20 - more_rx =3D igb_rxeof(que, adapter->rx_process_limit); + more_rx =3D igb_rxeof(que, adapter->rx_process_limit, NULL); =20 if (igb_enable_aim =3D=3D FALSE) goto no_calc; @@ -1501,7 +1477,7 @@ icr =3D 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); =20 spurious: /* Rearm */ @@ -1900,7 +1876,6 @@ igb_local_timer(void *arg) { struct adapter *adapter =3D arg; - struct ifnet *ifp =3D adapter->ifp; device_t dev =3D adapter->dev; struct tx_ring *txr =3D adapter->tx_rings; =20 @@ -1910,9 +1885,6 @@ igb_update_link_status(adapter); igb_update_stats_counters(adapter); =20 - 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 @@ goto timeout; } =20 - /* 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; =20 @@ -2142,20 +2109,20 @@ * 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 =3D taskqueue_create_fast("igb_taskq", M_NOWAIT, - taskqueue_thread_enqueue, &adapter->tq); - taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", + que->tq =3D 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)); if ((error =3D bus_setup_intr(dev, adapter->res, INTR_TYPE_NET | INTR_MPSAFE, igb_irq_fast, NULL, adapter, &adapter->tag)) !=3D 0) { device_printf(dev, "Failed to register fast interrupt " "handler: %d\n", error); - taskqueue_free(adapter->tq); - adapter->tq =3D NULL; + taskqueue_free(que->tq); + que->tq =3D NULL; return (error); } =20 @@ -2194,6 +2161,9 @@ device_printf(dev, "Failed to register Queue handler"); return (error); } +#if __FreeBSD_version >=3D 800504 + bus_describe_intr(dev, que->res, que->tag, "que %d", i); +#endif que->msix =3D vector; if (adapter->hw.mac.type =3D=3D e1000_82575) que->eims =3D E1000_EICR_TX_QUEUE0 << i; @@ -2229,15 +2199,11 @@ device_printf(dev, "Failed to register Link handler"); return (error); } +#if __FreeBSD_version >=3D 800504 + bus_describe_intr(dev, adapter->res, adapter->tag, "link"); +#endif adapter->linkvec =3D vector; =20 - /* Make tasklet for deferred handling */ - TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter); - adapter->tq =3D taskqueue_create_fast("igb_link", M_NOWAIT, - taskqueue_thread_enqueue, &adapter->tq); - taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s link", - device_get_nameunit(adapter->dev)); - return (0); } =20 @@ -3570,7 +3536,7 @@ cleaned =3D -1; /* Signify no completions */ while (i !=3D limit) { rxbuf =3D &rxr->rx_buffers[i]; - if (rxbuf->m_head =3D=3D NULL) { + if ((rxbuf->m_head =3D=3D NULL) && (rxr->hdr_split)) { mh =3D m_gethdr(M_DONTWAIT, MT_DATA); if (mh =3D=3D NULL) goto update; @@ -3776,16 +3742,24 @@ */ igb_free_receive_ring(rxr); =20 + /* Configure for header split? */ + if (igb_header_split) + rxr->hdr_split =3D TRUE; + /* Now replenish the ring mbufs */ for (int j =3D 0; j !=3D adapter->num_rx_desc; ++j) { struct mbuf *mh, *mp; =20 rxbuf =3D &rxr->rx_buffers[j]; + if (rxr->hdr_split =3D=3D FALSE) + goto skip_head; =20 /* First the header */ rxbuf->m_head =3D m_gethdr(M_DONTWAIT, MT_DATA); - if (rxbuf->m_head =3D=3D NULL) + if (rxbuf->m_head =3D=3D NULL) { + error =3D ENOBUFS; goto fail; + } m_adj(rxbuf->m_head, ETHER_ALIGN); mh =3D rxbuf->m_head; mh->m_len =3D mh->m_pkthdr.len =3D MHLEN; @@ -3801,11 +3775,14 @@ /* Update descriptor */ rxr->rx_base[j].read.hdr_addr =3D htole64(hseg[0].ds_addr); =20 +skip_head: /* Now the payload cluster */ rxbuf->m_pack =3D m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); - if (rxbuf->m_pack =3D=3D NULL) + if (rxbuf->m_pack =3D=3D NULL) { + error =3D ENOBUFS; goto fail; + } mp =3D rxbuf->m_pack; mp->m_pkthdr.len =3D mp->m_len =3D adapter->rx_mbuf_sz; /* Get the memory mapping */ @@ -3824,11 +3801,8 @@ rxr->next_to_check =3D 0; rxr->next_to_refresh =3D 0; rxr->lro_enabled =3D FALSE; - - if (igb_header_split) - rxr->hdr_split =3D TRUE; - else - ifp->if_capabilities &=3D ~IFCAP_LRO; + rxr->rx_split_packets =3D 0; + rxr->rx_bytes =3D 0; =20 rxr->fmp =3D NULL; rxr->lmp =3D NULL; @@ -3872,7 +3846,7 @@ igb_setup_receive_structures(struct adapter *adapter) { struct rx_ring *rxr =3D adapter->rx_rings; - int i, j; + int i; =20 for (i =3D 0; i < adapter->num_queues; i++, rxr++) if (igb_setup_receive_ring(rxr)) @@ -3883,13 +3857,11 @@ /* * Free RX buffers allocated so far, we will only handle * the rings that completed, the failing case will have - * cleaned up for itself. The value of 'i' will be the - * failed ring so we must pre-decrement it. + * cleaned up for itself. 'i' is the endpoint. */ - rxr =3D adapter->rx_rings; - for (--i; i > 0; i--, rxr++) { - for (j =3D 0; j < adapter->num_rx_desc; j++) - igb_free_receive_ring(rxr); + for (int j =3D 0; j > i; ++j) { + rxr =3D &adapter->rx_rings[i]; + igb_free_receive_ring(rxr); } =20 return (ENOBUFS); @@ -4195,7 +4167,9 @@ if (tcp_lro_rx(&rxr->lro, m, 0) =3D=3D 0) return; } + IGB_RX_UNLOCK(rxr); (*ifp->if_input)(ifp, m); + IGB_RX_LOCK(rxr); } =20 /********************************************************************* @@ -4210,14 +4184,14 @@ * Return TRUE if more to clean, FALSE otherwise *********************************************************************/ static bool -igb_rxeof(struct igb_queue *que, int count) +igb_rxeof(struct igb_queue *que, int count, int *done) { struct adapter *adapter =3D que->adapter; struct rx_ring *rxr =3D que->rxr; struct ifnet *ifp =3D adapter->ifp; struct lro_ctrl *lro =3D &rxr->lro; struct lro_entry *queued; - int i, processed =3D 0; + int i, processed =3D 0, rxdone =3D 0; u32 ptype, staterr =3D 0; union e1000_adv_rx_desc *cur; =20 @@ -4366,8 +4340,12 @@ /* ** Send to the stack or LRO */ - if (sendmp !=3D NULL) + if (sendmp !=3D NULL) { + rxr->next_to_check =3D i; igb_rx_input(rxr, ifp, sendmp, ptype); + i =3D rxr->next_to_check; + rxdone++; + } =20 /* Every 8 descriptors we go to refresh mbufs */ if (processed =3D=3D 8) { @@ -4394,6 +4372,9 @@ =20 IGB_RX_UNLOCK(rxr); =20 + if (done !=3D NULL) + *done =3D rxdone; + /* ** We still have cleaning to do? ** Schedule another interrupt if so. @@ -4751,8 +4732,10 @@ /* For the 64-bit byte counters the low dword must be read first. */ /* Both registers clear on the read of the high dword */ =20 - adapter->stats.gorc +=3D E1000_READ_REG(&adapter->hw, E1000_GORCH); - adapter->stats.gotc +=3D E1000_READ_REG(&adapter->hw, E1000_GOTCH); + adapter->stats.gorc +=3D E1000_READ_REG(&adapter->hw, E1000_GORCL) + + ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); + adapter->stats.gotc +=3D E1000_READ_REG(&adapter->hw, E1000_GOTCL) + + ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32) ; =20 adapter->stats.rnbc +=3D E1000_READ_REG(&adapter->hw, E1000_RNBC); adapter->stats.ruc +=3D E1000_READ_REG(&adapter->hw, E1000_RUC); @@ -4774,6 +4757,38 @@ adapter->stats.mptc +=3D E1000_READ_REG(&adapter->hw, E1000_MPTC); adapter->stats.bptc +=3D E1000_READ_REG(&adapter->hw, E1000_BPTC); =20 + /* Interrupt Counts */ + + adapter->stats.iac +=3D E1000_READ_REG(&adapter->hw, E1000_IAC); + adapter->stats.icrxptc +=3D E1000_READ_REG(&adapter->hw, E1000_ICRXPTC)= ; + adapter->stats.icrxatc +=3D E1000_READ_REG(&adapter->hw, E1000_ICRXATC)= ; + adapter->stats.ictxptc +=3D E1000_READ_REG(&adapter->hw, E1000_ICTXPTC)= ; + adapter->stats.ictxatc +=3D E1000_READ_REG(&adapter->hw, E1000_ICTXATC)= ; + adapter->stats.ictxqec +=3D E1000_READ_REG(&adapter->hw, E1000_ICTXQEC)= ; + adapter->stats.ictxqmtc +=3D E1000_READ_REG(&adapter->hw, E1000_ICTXQMT= C); + adapter->stats.icrxdmtc +=3D E1000_READ_REG(&adapter->hw, E1000_ICRXDMT= C); + adapter->stats.icrxoc +=3D E1000_READ_REG(&adapter->hw, E1000_ICRXOC); + + /* Host to Card Statistics */ + + adapter->stats.cbtmpc +=3D E1000_READ_REG(&adapter->hw, E1000_CBTMPC); + adapter->stats.htdpmc +=3D E1000_READ_REG(&adapter->hw, E1000_HTDPMC); + adapter->stats.cbrdpc +=3D E1000_READ_REG(&adapter->hw, E1000_CBRDPC); + adapter->stats.cbrmpc +=3D E1000_READ_REG(&adapter->hw, E1000_CBRMPC); + adapter->stats.rpthc +=3D E1000_READ_REG(&adapter->hw, E1000_RPTHC); + adapter->stats.hgptc +=3D E1000_READ_REG(&adapter->hw, E1000_HGPTC); + adapter->stats.htcbdpc +=3D E1000_READ_REG(&adapter->hw, E1000_HTCBDPC)= ; + adapter->stats.hgorc +=3D (E1000_READ_REG(&adapter->hw, E1000_HGORCL) += + ((u64)E1000_READ_REG(&adapter->hw,=20 + E1000_HGORCH) << 32)); + + adapter->stats.hgotc +=3D (E1000_READ_REG(&adapter->hw, E1000_HGOTCL) += + ((u64)E1000_READ_REG(&adapter->hw,=20 + E1000_HGOTCH) << 32)); + adapter->stats.lenerrs +=3D E1000_READ_REG(&adapter->hw, E1000_LENERRS)= ; + adapter->stats.scvpc +=3D E1000_READ_REG(&adapter->hw, E1000_SCVPC); + adapter->stats.hrmpc +=3D E1000_READ_REG(&adapter->hw, E1000_HRMPC); + adapter->stats.algnerrc +=3D=20 E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); adapter->stats.rxerrc +=3D=20 @@ -4802,140 +4817,375 @@ } =20 =20 -/********************************************************************** - * - * This routine is called only when igb_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 -igb_print_debug_info(struct adapter *adapter) +igb_add_hw_stats(struct adapter *adapter) { + device_t dev =3D adapter->dev; - struct igb_queue *que =3D adapter->queues; - struct rx_ring *rxr =3D adapter->rx_rings; + struct tx_ring *txr =3D adapter->tx_rings; - uint8_t *hw_addr =3D adapter->hw.hw_addr; + struct rx_ring *rxr =3D adapter->rx_rings; =20 - device_printf(dev, "Adapter hardware address =3D %p \n", hw_addr); - device_printf(dev, "CTRL =3D 0x%x RCTL =3D 0x%x \n", - E1000_READ_REG(&adapter->hw, E1000_CTRL), - E1000_READ_REG(&adapter->hw, E1000_RCTL)); - -#if (DEBUG_HW > 0) /* Dont output these errors normally */ - device_printf(dev, "IMS =3D 0x%x EIMS =3D 0x%x \n", - E1000_READ_REG(&adapter->hw, E1000_IMS), - E1000_READ_REG(&adapter->hw, E1000_EIMS)); -#endif + struct sysctl_ctx_list *ctx =3D device_get_sysctl_ctx(dev); + struct sysctl_oid *tree =3D device_get_sysctl_tree(dev); + struct sysctl_oid_list *child =3D SYSCTL_CHILDREN(tree); + struct e1000_hw_stats *stats =3D &adapter->stats; + + struct sysctl_oid *stat_node, *queue_node, *int_node, *host_node; + struct sysctl_oid_list *stat_list, *queue_list, *int_list, *host_list; + +#define QUEUE_NAME_LEN 32 + char namebuf[QUEUE_NAME_LEN]; + + /* Driver Statistics */ + SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "link_irq",=20 + CTLFLAG_RD, &adapter->link_irq, 0, + "Link MSIX IRQ Handled"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",=20 + CTLFLAG_RD, &adapter->dropped_pkts, + "Driver dropped packets"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",=20 + CTLFLAG_RD, &adapter->no_tx_dma_setup, + "Driver tx dma failure in xmit"); + + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "device_control",=20 + CTLFLAG_RD, &adapter->device_control, + "Device Control Register"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_control",=20 + CTLFLAG_RD, &adapter->rx_control, + "Receiver Control Register"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "interrupt_mask",=20 + CTLFLAG_RD, &adapter->int_mask, + "Interrupt Mask"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "extended_int_mask",=20 + CTLFLAG_RD, &adapter->eint_mask, + "Extended Interrupt Mask"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_buf_alloc",=20 + CTLFLAG_RD, &adapter->packet_buf_alloc_tx, + "Transmit Buffer Packet Allocation"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_buf_alloc",=20 + CTLFLAG_RD, &adapter->packet_buf_alloc_rx, + "Receive Buffer Packet Allocation"); + 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",=20 + CTLFLAG_RD, &adapter->hw.fc.low_water, 0, + "Flow Control Low Watermark"); =20 - device_printf(dev, "Packet buffer =3D Tx=3D%dk Rx=3D%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 =3D %d low =3D %d\n", - adapter->hw.fc.high_water, - adapter->hw.fc.low_water); - - for (int i =3D 0; i < adapter->num_queues; i++, rxr++, txr++) { - device_printf(dev, "Queue(%d) tdh =3D %d, tdt =3D %d ", i, - E1000_READ_REG(&adapter->hw, E1000_TDH(i)), - E1000_READ_REG(&adapter->hw, E1000_TDT(i))); - device_printf(dev, "rdh =3D %d, rdt =3D %d\n", - E1000_READ_REG(&adapter->hw, E1000_RDH(i)), - E1000_READ_REG(&adapter->hw, E1000_RDT(i))); - device_printf(dev, "TX(%d) no descriptors avail event =3D %lld\n", - txr->me, (long long)txr->no_desc_avail); - device_printf(dev, "TX(%d) Packets sent =3D %lld\n", - txr->me, (long long)txr->tx_packets); - device_printf(dev, "RX(%d) Packets received =3D %lld ", - rxr->me, (long long)rxr->rx_packets); + for (int i =3D 0; i < adapter->num_queues; i++, txr++) { + snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); + queue_node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, + CTLFLAG_RD, NULL, "Queue Name"); + queue_list =3D SYSCTL_CHILDREN(queue_node); + + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "txd_head", + CTLFLAG_RD, &txr->tdh, 0, + "Transmit Descriptor Head"); + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "txd_tail", + CTLFLAG_RD, &txr->tdt, 0, + "Transmit Descriptor Tail"); + SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",=20 + CTLFLAG_RD, &txr->no_desc_avail, + "Queue No Descriptor Available"); + SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_packets", + CTLFLAG_RD, &txr->tx_packets, + "Queue Packets Transmitted"); } =20 for (int i =3D 0; i < adapter->num_queues; i++, rxr++) { struct lro_ctrl *lro =3D &rxr->lro; - device_printf(dev, "Queue(%d) rdh =3D %d, rdt =3D %d\n", i, - E1000_READ_REG(&adapter->hw, E1000_RDH(i)), - E1000_READ_REG(&adapter->hw, E1000_RDT(i))); - device_printf(dev, "RX(%d) Packets received =3D %lld\n", rxr->me, - (long long)rxr->rx_packets); - device_printf(dev, " Split Packets =3D %lld ", - (long long)rxr->rx_split_packets); - device_printf(dev, " Byte count =3D %lld\n", - (long long)rxr->rx_bytes); - device_printf(dev,"RX(%d) LRO Queued=3D %d ", - i, lro->lro_queued); - device_printf(dev,"LRO Flushed=3D %d\n",lro->lro_flushed); - } - - for (int i =3D 0; i < adapter->num_queues; i++, que++) - device_printf(dev,"QUE(%d) IRQs =3D %llx\n", - i, (long long)que->irqs); - - device_printf(dev, "LINK MSIX IRQ Handled =3D %u\n", adapter->link_irq)= ; - device_printf(dev, "Mbuf defrag failed =3D %ld\n", - adapter->mbuf_defrag_failed); - device_printf(dev, "Std mbuf header failed =3D %ld\n", - adapter->mbuf_header_failed); - device_printf(dev, "Std mbuf packet failed =3D %ld\n", - adapter->mbuf_packet_failed); - device_printf(dev, "Driver dropped packets =3D %ld\n", - adapter->dropped_pkts); - device_printf(dev, "Driver tx dma failure in xmit =3D %ld\n", - adapter->no_tx_dma_setup); -} =20 -static void -igb_print_hw_stats(struct adapter *adapter) -{ - device_t dev =3D adapter->dev; + snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); + queue_node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,=20 + CTLFLAG_RD, NULL, "Queue Name"); + queue_list =3D SYSCTL_CHILDREN(queue_node); + + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "rxd_head", + CTLFLAG_RD, &rxr->rdh, 0, + "Receive Descriptor Head"); + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "rxd_tail", + CTLFLAG_RD, &rxr->rdt, 0, + "Receive Descriptor Tail"); + SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_packets", + CTLFLAG_RD, &rxr->rx_packets, + "Queue Packets Received"); + SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_bytes", + CTLFLAG_RD, &rxr->rx_bytes, + "Queue Bytes Received"); + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "lro_queued", + CTLFLAG_RD, &lro->lro_queued, 0, + "LRO Queued"); + SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "lro_flushed", + CTLFLAG_RD, &lro->lro_flushed, 0, + "LRO Flushed"); + } + + /* MAC stats get the own sub node */ + + stat_node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",=20 + CTLFLAG_RD, NULL, "MAC Statistics"); + stat_list =3D SYSCTL_CHILDREN(stat_node); + + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll",=20 + CTLFLAG_RD, &stats->ecol, + "Excessive collisions"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "single_coll",=20 + CTLFLAG_RD, &stats->scc, + "Single collisions"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "multiple_coll",=20 + CTLFLAG_RD, &stats->mcc, + "Multiple collisions"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "late_coll",=20 + CTLFLAG_RD, &stats->latecol, + "Late collisions"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "collision_count",=20 + CTLFLAG_RD, &stats->colc, + "Collision Count"); + 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"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_undersize", + CTLFLAG_RD, &adapter->stats.ruc, + "Receive Undersize"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", + CTLFLAG_RD, &adapter->stats.rfc, + "Fragmented Packets Received "); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_oversize", + CTLFLAG_RD, &adapter->stats.roc, + "Oversized Packets Received"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_jabber", + CTLFLAG_RD, &adapter->stats.rjc, + "Recevied Jabber"); =20 - device_printf(dev, "Excessive collisions =3D %lld\n", - (long long)adapter->stats.ecol); -#if (DEBUG_HW > 0) /* Dont output these errors normally */ - device_printf(dev, "Symbol errors =3D %lld\n", - (long long)adapter->stats.symerrs); -#endif - device_printf(dev, "Sequence errors =3D %lld\n", - (long long)adapter->stats.sec); - device_printf(dev, "Defer count =3D %lld\n", - (long long)adapter->stats.dc); - device_printf(dev, "Missed Packets =3D %lld\n", - (long long)adapter->stats.mpc); - device_printf(dev, "Receive No Buffers =3D %lld\n", - (long long)adapter->stats.rnbc); /* RLEC is inaccurate on some hardware, calculate our own. */ - device_printf(dev, "Receive Length Errors =3D %lld\n", - ((long long)adapter->stats.roc + (long long)adapter->stats.ruc)); - device_printf(dev, "Receive errors =3D %lld\n", - (long long)adapter->stats.rxerrc); - device_printf(dev, "Crc errors =3D %lld\n", - (long long)adapter->stats.crcerrs); - device_printf(dev, "Alignment errors =3D %lld\n", - (long long)adapter->stats.algnerrc); +/* 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 */ - device_printf(dev, "Collision/Carrier extension errors =3D %lld\n", - (long long)adapter->stats.cexterr); - device_printf(dev, "RX overruns =3D %ld\n", adapter->rx_overruns); - device_printf(dev, "watchdog timeouts =3D %ld\n", - adapter->watchdog_events); - device_printf(dev, "XON Rcvd =3D %lld\n", - (long long)adapter->stats.xonrxc); - device_printf(dev, "XON Xmtd =3D %lld\n", - (long long)adapter->stats.xontxc); - device_printf(dev, "XOFF Rcvd =3D %lld\n", - (long long)adapter->stats.xoffrxc); - device_printf(dev, "XOFF Xmtd =3D %lld\n", - (long long)adapter->stats.xofftxc); - device_printf(dev, "Good Packets Rcvd =3D %lld\n", - (long long)adapter->stats.gprc); - device_printf(dev, "Good Packets Xmtd =3D %lld\n", - (long long)adapter->stats.gptc); - device_printf(dev, "TSO Contexts Xmtd =3D %lld\n", - (long long)adapter->stats.tsctc); - device_printf(dev, "TSO Contexts Failed =3D %lld\n", - (long long)adapter->stats.tsctfc); -} + 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",=20 + CTLFLAG_RD, &adapter->stats.gorc,=20 + "Good Octets Received");=20 + + /* Packet Transmission Stats */ + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octest_txd",=20 + CTLFLAG_RD, &adapter->stats.gotc,=20 + "Good Octest Transmitted");=20 + 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 =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "interrupts",=20 + CTLFLAG_RD, NULL, "Interrupt Statistics"); + int_list =3D 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 =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "host",=20 + CTLFLAG_RD, NULL,=20 + "Host to Card Statistics"); + + host_list =3D 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"); =20 + +} /********************************************************************** * * This routine provides a way to dump out the adapter eeprom, @@ -4943,28 +5193,8 @@ * 32 words, stuff that matters is in that extent. * **********************************************************************/= -static void -igb_print_nvm_info(struct adapter *adapter) -{ - u16 eeprom_data; - int i, j, row =3D 0; - - /* Its a bit crude, but it gets the job done */ - printf("\nInterface EEPROM Dump:\n"); - printf("Offset\n0x0000 "); - for (i =3D 0, j =3D 0; i < 32; i++, j++) { - if (j =3D=3D 8) { /* Make the offset block */ - j =3D 0; ++row; - printf("\n0x00%x0 ",row); - } - e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); - printf("%04x ", eeprom_data); - } - printf("\n"); -} - static int -igb_sysctl_debug_info(SYSCTL_HANDLER_ARGS) +igb_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) { struct adapter *adapter; int error; @@ -4976,16 +5206,12 @@ if (error || !req->newptr) return (error); =20 - if (result =3D=3D 1) { - adapter =3D (struct adapter *)arg1; - igb_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 =3D=3D 2) { + if (result =3D=3D 1) { adapter =3D (struct adapter *)arg1; igb_print_nvm_info(adapter); } @@ -4993,26 +5219,24 @@ return (error); } =20 - -static int -igb_sysctl_stats(SYSCTL_HANDLER_ARGS) +static void +igb_print_nvm_info(struct adapter *adapter) { - struct adapter *adapter; - int error; - int result; - - result =3D -1; - error =3D sysctl_handle_int(oidp, &result, 0, req); - - if (error || !req->newptr) - return (error); + u16 eeprom_data; + int i, j, row =3D 0; =20 - if (result =3D=3D 1) { - adapter =3D (struct adapter *)arg1; - igb_print_hw_stats(adapter); + /* Its a bit crude, but it gets the job done */ + printf("\nInterface EEPROM Dump:\n"); + printf("Offset\n0x0000 "); + for (i =3D 0, j =3D 0; i < 32; i++, j++) { + if (j =3D=3D 8) { /* Make the offset block */ + j =3D 0; ++row; + printf("\n0x00%x0 ",row); + } + e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); + printf("%04x ", eeprom_data); } - - return (error); + printf("\n"); } =20 static void --- src/sys/dev/e1000/if_igb.h.orig 2010-06-14 04:09:06.000000000 +0200 +++ src/sys/dev/e1000/if_igb.h 2010-07-27 10:07:14.477145093 +0200 @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. =20 ************************************************************************= ******/ -/*$FreeBSD: src/sys/dev/e1000/if_igb.h,v 1.4.2.2.2.1 2010/06/14 02:09:06= kensmith Exp $*/ +/*$FreeBSD: src/sys/dev/e1000/if_igb.h,v 1.4.2.3 2010/06/18 17:22:08 jfv= Exp $*/ =20 #ifndef _IGB_H_DEFINED_ #define _IGB_H_DEFINED_ @@ -317,6 +317,9 @@ int watchdog_time; u64 no_desc_avail; u64 tx_packets; + /* Statistics for reporting, ONLY. */ + u32 tdh; /* Transmit Descriptor Head */ + u32 tdt; /* Transmit Descriptor Tail */ }; =20 /* @@ -353,6 +356,9 @@ u64 rx_discarded; u64 rx_packets; u64 rx_bytes; + /* Statistics for reporting, ONLY. */ + u32 rdh; /* Transmit Descriptor Head */ + u32 rdt; /* Transmit Descriptor Tail */ }; =20 struct adapter { @@ -382,8 +388,6 @@ int min_frame_size; struct mtx core_mtx; int igb_insert_vlan_header; - struct task rxtx_task; - struct taskqueue *tq; /* adapter task queue */ u16 num_queues; =20 eventhandler_tag vlan_attach; @@ -428,6 +432,12 @@ unsigned long no_tx_dma_setup; unsigned long watchdog_events; unsigned long rx_overruns; + unsigned long device_control; + unsigned long rx_control; + unsigned long int_mask; + unsigned long eint_mask; + unsigned long packet_buf_alloc_rx; + unsigned long packet_buf_alloc_tx; =20 boolean_t in_detach; =20 --- src/sys/dev/e1000/if_lem.c.orig 2010-06-14 04:09:06.000000000 +0200 +++ src/sys/dev/e1000/if_lem.c 2010-07-27 10:07:12.343126580 +0200 @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. =20 ************************************************************************= ******/ -/*$FreeBSD: src/sys/dev/e1000/if_lem.c,v 1.3.2.4.2.1 2010/06/14 02:09:06= kensmith Exp $*/ +/*$FreeBSD: src/sys/dev/e1000/if_lem.c,v 1.7 2010/07/12 21:47:30 jfv Exp= $*/ =20 #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_device_polling.h" @@ -200,7 +200,7 @@ static void lem_tx_purge(struct adapter *); static int lem_allocate_receive_structures(struct adapter *); static int lem_allocate_transmit_structures(struct adapter *); -static int lem_rxeof(struct adapter *, int); +static bool lem_rxeof(struct adapter *, int, int *); #ifndef __NO_STRICT_ALIGNMENT static int lem_fixup_rx(struct adapter *); #endif @@ -1255,7 +1255,7 @@ } EM_CORE_UNLOCK(adapter); =20 - rx_done =3D lem_rxeof(adapter, count); + lem_rxeof(adapter, count, &rx_done); =20 EM_TX_LOCK(adapter); lem_txeof(adapter); @@ -1308,7 +1308,7 @@ =20 EM_TX_LOCK(adapter); lem_txeof(adapter); - lem_rxeof(adapter, -1); + lem_rxeof(adapter, -1, NULL); lem_txeof(adapter); if (ifp->if_drv_flags & IFF_DRV_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) @@ -1350,7 +1350,7 @@ =20 =20 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if (lem_rxeof(adapter, adapter->rx_process_limit) !=3D 0) + if (lem_rxeof(adapter, adapter->rx_process_limit, NULL) !=3D 0) taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); EM_TX_LOCK(adapter); lem_txeof(adapter); @@ -1566,6 +1566,19 @@ } =20 /* + ** 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 =3D m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); + *m_headp =3D m_head; + if (m_head =3D=3D NULL) + return (ENOBUFS); + } + + /* * Map the packet for DMA * * Capture the first descriptor index, @@ -2851,6 +2864,7 @@ =20 =20 cmd =3D hdr_len =3D ipproto =3D 0; + *txd_upper =3D *txd_lower =3D 0; curr_txd =3D adapter->next_avail_tx_desc; =20 /* @@ -2894,9 +2908,6 @@ *txd_upper |=3D E1000_TXD_POPTS_IXSM << 8; } =20 - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - hdr_len =3D ehdrlen + ip_hlen; ipproto =3D ip->ip_p; =20 @@ -2905,18 +2916,13 @@ ip6 =3D (struct ip6_hdr *)(mp->m_data + ehdrlen); ip_hlen =3D sizeof(struct ip6_hdr); /* XXX: No header stacking. */ =20 - if (mp->m_len < ehdrlen + ip_hlen) - return; /* failure */ - /* IPv6 doesn't have a header checksum. */ =20 hdr_len =3D ehdrlen + ip_hlen; ipproto =3D ip6->ip6_nxt; - break; + default: - *txd_upper =3D 0; - *txd_lower =3D 0; return; } =20 @@ -2970,6 +2976,8 @@ break; } =20 + if (TXD =3D=3D NULL) + return; TXD->tcp_seg_setup.data =3D htole32(0); TXD->cmd_and_length =3D htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); @@ -3449,8 +3457,8 @@ * =20 * For polling we also now return the number of cleaned packets *********************************************************************/ -static int -lem_rxeof(struct adapter *adapter, int count) +static bool +lem_rxeof(struct adapter *adapter, int count, int *done) { struct ifnet *ifp =3D adapter->ifp;; struct mbuf *mp; @@ -3466,8 +3474,10 @@ BUS_DMASYNC_POSTREAD); =20 if (!((current_desc->status) & E1000_RXD_STAT_DD)) { + if (done !=3D NULL) + *done =3D rx_sent; EM_RX_UNLOCK(adapter); - return (rx_sent); + return (FALSE); } =20 while ((current_desc->status & E1000_RXD_STAT_DD) && @@ -3626,8 +3636,10 @@ if (--i < 0) i =3D adapter->num_rx_desc - 1; E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); + if (done !=3D NULL) + *done =3D rx_sent; EM_RX_UNLOCK(adapter); - return (rx_sent); + return (current_desc->status & E1000_RXD_STAT_DD); } =20 #ifndef __NO_STRICT_ALIGNMENT --------------020106010007020907000302-- --------------enig5A94A6482AB6BCA889B3EE66 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.13 (FreeBSD) iEYEARECAAYFAkxOr1YACgkQLDqVQ9VXb8hc6QCgzg9dPQ8LBpzOkORDbNpIog2J MlUAoMsu87CgvUgcClm9Ud5kUGqPyeTk =al3B -----END PGP SIGNATURE----- --------------enig5A94A6482AB6BCA889B3EE66--