From owner-svn-src-stable-8@FreeBSD.ORG Thu Jan 14 22:15:51 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 98D521065670; Thu, 14 Jan 2010 22:15:51 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 86A918FC13; Thu, 14 Jan 2010 22:15:51 +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 o0EMFpIT062164; Thu, 14 Jan 2010 22:15:51 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0EMFpAl062161; Thu, 14 Jan 2010 22:15:51 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201001142215.o0EMFpAl062161@svn.freebsd.org> From: Pyun YongHyeon Date: Thu, 14 Jan 2010 22:15:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202314 - stable/8/sys/dev/ste X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Jan 2010 22:15:51 -0000 Author: yongari Date: Thu Jan 14 22:15:51 2010 New Revision: 202314 URL: http://svn.freebsd.org/changeset/base/202314 Log: MFC r200904-200908,200910-200913 r200904: Don't reinitialize controller if driver is already running. This reduces number of link state UP/DOWN changes. r200905: Reimplement controller reset. Datasheet says full reset takes about 1ms. Since we switched to memory register mapping make sure to flush PCI posted write by reading the register again. While I'm here add additional delays in loop while driver waits the completion of the reset. r200906: Overhaul RX filter programming. o Let RX filter handler program promiscuous/multicast filter as well as broadcasting. o Remove unnecessary register access. o Simplify ioctl handler and have set_rxfilter to handle IFF_PROMISC and IFF_ALLMULTI change instead of directly programming the controller. o Removed unnecessary error variable reinitialization in ioctl handler. o Add IFF_DRV_RUNNING check before programming multicast filter. o Configure maximum allowed frame length before enabling MAC. Datasheet didn't say the exact ordering of programming sequence but it looks more natural to set maximum allowed frame length first prior to enabling controller. r200907: Don't report link status if driver is not running. r200908: Report the correct result of mii_mediachg(). Previously it always used to return success without respect to the result. While I'm here use mii_mediachg() in ste_init_locked which allows driver to use currently configured media. ste_ifmedia_upd() is supposed to be called whenever user changes current media settings. r200910: Implement hardware MAC statistics counter support. The counters could be accessed with dev.ste.0.stats sysctl node. r200911: Remove unused duplicated register definition. It seems the definition was made to access STE_ASICCTL register as 16bits but ste(4) always access the register as 32bits so it was never used before. r200912: Correct STE_COUNTDOWN register offset. The datasheet was wrong. r200913: We don't need to generate DMA complete interrupt for every transmitted frames. So request interrupt for every 16th frames. Due to the limitation of hardware we can't suppress the interrupt as driver should have to check TX status register. The TX status register can store up to 31 TX status so driver can't send more than 31 frames without reading TX status register. With this change controller would not generate TX completion interrupt for every frame, so reclaim transmitted frames in ste_tick(). Modified: stable/8/sys/dev/ste/if_ste.c stable/8/sys/dev/ste/if_stereg.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/dev/ste/if_ste.c ============================================================================== --- stable/8/sys/dev/ste/if_ste.c Thu Jan 14 22:04:32 2010 (r202313) +++ stable/8/sys/dev/ste/if_ste.c Thu Jan 14 22:15:51 2010 (r202314) @@ -103,7 +103,6 @@ static int ste_eeprom_wait(struct ste_s static int ste_encap(struct ste_softc *, struct mbuf **, struct ste_chain *); static int ste_ifmedia_upd(struct ifnet *); -static void ste_ifmedia_upd_locked(struct ifnet *); static void ste_ifmedia_sts(struct ifnet *, struct ifmediareq *); static void ste_init(void *); static void ste_init_locked(struct ste_softc *); @@ -123,11 +122,13 @@ static int ste_read_eeprom(struct ste_so static void ste_reset(struct ste_softc *); static void ste_restart_tx(struct ste_softc *); static int ste_rxeof(struct ste_softc *, int); -static void ste_setmulti(struct ste_softc *); +static void ste_rxfilter(struct ste_softc *); static void ste_start(struct ifnet *); static void ste_start_locked(struct ifnet *); +static void ste_stats_clear(struct ste_softc *); static void ste_stats_update(struct ste_softc *); static void ste_stop(struct ste_softc *); +static void ste_sysctl_node(struct ste_softc *); static void ste_tick(void *); static void ste_txeoc(struct ste_softc *); static void ste_txeof(struct ste_softc *); @@ -449,31 +450,21 @@ static int ste_ifmedia_upd(struct ifnet *ifp) { struct ste_softc *sc; + struct mii_data *mii; + struct mii_softc *miisc; + int error; sc = ifp->if_softc; STE_LOCK(sc); - ste_ifmedia_upd_locked(ifp); - STE_UNLOCK(sc); - - return (0); -} - -static void -ste_ifmedia_upd_locked(struct ifnet *ifp) -{ - struct ste_softc *sc; - struct mii_data *mii; - - sc = ifp->if_softc; - STE_LOCK_ASSERT(sc); mii = device_get_softc(sc->ste_miibus); - sc->ste_flags &= ~STE_FLAG_LINK; if (mii->mii_instance) { - struct mii_softc *miisc; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) mii_phy_reset(miisc); } - mii_mediachg(mii); + error = mii_mediachg(mii); + STE_UNLOCK(sc); + + return (error); } static void @@ -486,6 +477,10 @@ ste_ifmedia_sts(struct ifnet *ifp, struc mii = device_get_softc(sc->ste_miibus); STE_LOCK(sc); + if ((ifp->if_flags & IFF_UP) == 0) { + STE_UNLOCK(sc); + return; + } mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; @@ -563,27 +558,33 @@ ste_read_eeprom(struct ste_softc *sc, ca } static void -ste_setmulti(struct ste_softc *sc) +ste_rxfilter(struct ste_softc *sc) { struct ifnet *ifp; struct ifmultiaddr *ifma; uint32_t hashes[2] = { 0, 0 }; + uint8_t rxcfg; int h; + STE_LOCK_ASSERT(sc); + ifp = sc->ste_ifp; - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); - STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); - return; + rxcfg = CSR_READ_1(sc, STE_RX_MODE); + rxcfg |= STE_RXMODE_UNICAST; + rxcfg &= ~(STE_RXMODE_ALLMULTI | STE_RXMODE_MULTIHASH | + STE_RXMODE_BROADCAST | STE_RXMODE_PROMISC); + if (ifp->if_flags & IFF_BROADCAST) + rxcfg |= STE_RXMODE_BROADCAST; + if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { + if ((ifp->if_flags & IFF_ALLMULTI) != 0) + rxcfg |= STE_RXMODE_ALLMULTI; + if ((ifp->if_flags & IFF_PROMISC) != 0) + rxcfg |= STE_RXMODE_PROMISC; + goto chipit; } - /* first, zot all the existing hash bits */ - CSR_WRITE_2(sc, STE_MAR0, 0); - CSR_WRITE_2(sc, STE_MAR1, 0); - CSR_WRITE_2(sc, STE_MAR2, 0); - CSR_WRITE_2(sc, STE_MAR3, 0); - - /* now program new ones */ + rxcfg |= STE_RXMODE_MULTIHASH; + /* Now program new ones. */ if_maddr_rlock(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) @@ -597,12 +598,13 @@ ste_setmulti(struct ste_softc *sc) } if_maddr_runlock(ifp); +chipit: CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF); CSR_WRITE_2(sc, STE_MAR2, hashes[1] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR3, (hashes[1] >> 16) & 0xFFFF); - STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); - STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); + CSR_WRITE_1(sc, STE_RX_MODE, rxcfg); + CSR_READ_1(sc, STE_RX_MODE); } #ifdef DEVICE_POLLING @@ -643,8 +645,10 @@ ste_poll_locked(struct ifnet *ifp, enum if (status & STE_ISR_STATS_OFLOW) ste_stats_update(sc); - if (status & STE_ISR_HOSTERR) + if (status & STE_ISR_HOSTERR) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; ste_init_locked(sc); + } } return (rx_npkts); } @@ -692,8 +696,10 @@ ste_intr(void *xsc) if (status & STE_ISR_STATS_OFLOW) ste_stats_update(sc); - if (status & STE_ISR_HOSTERR) + if (status & STE_ISR_HOSTERR) { ste_init_locked(sc); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + } } /* Re-enable interrupts */ @@ -832,6 +838,7 @@ ste_txeoc(struct ste_softc *sc) STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL); ste_wait(sc); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; ste_init_locked(sc); break; } @@ -870,6 +877,13 @@ ste_tick(void *arg) */ if ((sc->ste_flags & STE_FLAG_LINK) == 0) ste_miibus_statchg(sc->ste_dev); + /* + * Because we are not generating Tx completion + * interrupt for every frame, reclaim transmitted + * buffers here. + */ + ste_txeof(sc); + ste_txeoc(sc); ste_stats_update(sc); ste_watchdog(sc); callout_reset(&sc->ste_callout, hz, ste_tick, sc); @@ -918,16 +932,74 @@ ste_txeof(struct ste_softc *sc) } static void +ste_stats_clear(struct ste_softc *sc) +{ + + STE_LOCK_ASSERT(sc); + + /* Rx stats. */ + CSR_READ_2(sc, STE_STAT_RX_OCTETS_LO); + CSR_READ_2(sc, STE_STAT_RX_OCTETS_HI); + CSR_READ_2(sc, STE_STAT_RX_FRAMES); + CSR_READ_1(sc, STE_STAT_RX_BCAST); + CSR_READ_1(sc, STE_STAT_RX_MCAST); + CSR_READ_1(sc, STE_STAT_RX_LOST); + /* Tx stats. */ + CSR_READ_2(sc, STE_STAT_TX_OCTETS_LO); + CSR_READ_2(sc, STE_STAT_TX_OCTETS_HI); + CSR_READ_2(sc, STE_STAT_TX_FRAMES); + CSR_READ_1(sc, STE_STAT_TX_BCAST); + CSR_READ_1(sc, STE_STAT_TX_MCAST); + CSR_READ_1(sc, STE_STAT_CARRIER_ERR); + CSR_READ_1(sc, STE_STAT_SINGLE_COLLS); + CSR_READ_1(sc, STE_STAT_MULTI_COLLS); + CSR_READ_1(sc, STE_STAT_LATE_COLLS); + CSR_READ_1(sc, STE_STAT_TX_DEFER); + CSR_READ_1(sc, STE_STAT_TX_EXDEFER); + CSR_READ_1(sc, STE_STAT_TX_ABORT); +} + +static void ste_stats_update(struct ste_softc *sc) { struct ifnet *ifp; + struct ste_hw_stats *stats; + uint32_t val; STE_LOCK_ASSERT(sc); ifp = sc->ste_ifp; - ifp->if_collisions += CSR_READ_1(sc, STE_LATE_COLLS) - + CSR_READ_1(sc, STE_MULTI_COLLS) - + CSR_READ_1(sc, STE_SINGLE_COLLS); + stats = &sc->ste_stats; + /* Rx stats. */ + val = (uint32_t)CSR_READ_2(sc, STE_STAT_RX_OCTETS_LO) | + ((uint32_t)CSR_READ_2(sc, STE_STAT_RX_OCTETS_HI)) << 16; + val &= 0x000FFFFF; + stats->rx_bytes += val; + stats->rx_frames += CSR_READ_2(sc, STE_STAT_RX_FRAMES); + stats->rx_bcast_frames += CSR_READ_1(sc, STE_STAT_RX_BCAST); + stats->rx_mcast_frames += CSR_READ_1(sc, STE_STAT_RX_MCAST); + stats->rx_lost_frames += CSR_READ_1(sc, STE_STAT_RX_LOST); + /* Tx stats. */ + val = (uint32_t)CSR_READ_2(sc, STE_STAT_TX_OCTETS_LO) | + ((uint32_t)CSR_READ_2(sc, STE_STAT_TX_OCTETS_HI)) << 16; + val &= 0x000FFFFF; + stats->tx_bytes += val; + stats->tx_frames += CSR_READ_2(sc, STE_STAT_TX_FRAMES); + stats->tx_bcast_frames += CSR_READ_1(sc, STE_STAT_TX_BCAST); + stats->tx_mcast_frames += CSR_READ_1(sc, STE_STAT_TX_MCAST); + stats->tx_carrsense_errs += CSR_READ_1(sc, STE_STAT_CARRIER_ERR); + val = CSR_READ_1(sc, STE_STAT_SINGLE_COLLS); + stats->tx_single_colls += val; + ifp->if_collisions += val; + val = CSR_READ_1(sc, STE_STAT_MULTI_COLLS); + stats->tx_multi_colls += val; + ifp->if_collisions += val; + val += CSR_READ_1(sc, STE_STAT_LATE_COLLS); + stats->tx_late_colls += val; + ifp->if_collisions += val; + stats->tx_frames_defered += CSR_READ_1(sc, STE_STAT_TX_DEFER); + stats->tx_excess_defers += CSR_READ_1(sc, STE_STAT_TX_EXDEFER); + stats->tx_abort += CSR_READ_1(sc, STE_STAT_TX_ABORT); } /* @@ -1027,6 +1099,7 @@ ste_attach(device_t dev) error = ENXIO;; goto fail; } + ste_sysctl_node(sc); if ((error = ste_dma_alloc(sc)) != 0) goto fail; @@ -1543,10 +1616,15 @@ static void ste_init_locked(struct ste_softc *sc) { struct ifnet *ifp; + struct mii_data *mii; int i; STE_LOCK_ASSERT(sc); ifp = sc->ste_ifp; + mii = device_get_softc(sc->ste_miibus); + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + return; ste_stop(sc); /* Reset the chip to a known state. */ @@ -1582,24 +1660,11 @@ ste_init_locked(struct ste_softc *sc) /* Set the TX reclaim threshold. */ CSR_WRITE_1(sc, STE_TX_RECLAIM_THRESH, (STE_PACKET_SIZE >> 4)); - /* Set up the RX filter. */ - CSR_WRITE_1(sc, STE_RX_MODE, STE_RXMODE_UNICAST); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) { - STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC); - } else { - STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC); - } - - /* Set capture broadcast bit to accept broadcast frames. */ - if (ifp->if_flags & IFF_BROADCAST) { - STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST); - } else { - STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST); - } + /* Accept VLAN length packets */ + CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); - ste_setmulti(sc); + /* Set up the RX filter. */ + ste_rxfilter(sc); /* Load the address of the RX list. */ STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); @@ -1628,6 +1693,8 @@ ste_init_locked(struct ste_softc *sc) /* Enable stats counters. */ STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_STATS_ENABLE); + /* Clear stats counters. */ + ste_stats_clear(sc); CSR_WRITE_2(sc, STE_ISR, 0xFFFF); #ifdef DEVICE_POLLING @@ -1639,10 +1706,9 @@ ste_init_locked(struct ste_softc *sc) /* Enable interrupts. */ CSR_WRITE_2(sc, STE_IMR, STE_INTRS); - /* Accept VLAN length packets */ - CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); - - ste_ifmedia_upd_locked(ifp); + sc->ste_flags &= ~STE_FLAG_LINK; + /* Switch to the current media. */ + mii_mediachg(mii); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; @@ -1723,20 +1789,27 @@ ste_stop(struct ste_softc *sc) static void ste_reset(struct ste_softc *sc) { + uint32_t ctl; int i; - STE_SETBIT4(sc, STE_ASICCTL, - STE_ASICCTL_GLOBAL_RESET|STE_ASICCTL_RX_RESET| - STE_ASICCTL_TX_RESET|STE_ASICCTL_DMA_RESET| - STE_ASICCTL_FIFO_RESET|STE_ASICCTL_NETWORK_RESET| - STE_ASICCTL_AUTOINIT_RESET|STE_ASICCTL_HOST_RESET| - STE_ASICCTL_EXTRESET_RESET); - - DELAY(100000); + ctl = CSR_READ_4(sc, STE_ASICCTL); + ctl |= STE_ASICCTL_GLOBAL_RESET | STE_ASICCTL_RX_RESET | + STE_ASICCTL_TX_RESET | STE_ASICCTL_DMA_RESET | + STE_ASICCTL_FIFO_RESET | STE_ASICCTL_NETWORK_RESET | + STE_ASICCTL_AUTOINIT_RESET |STE_ASICCTL_HOST_RESET | + STE_ASICCTL_EXTRESET_RESET; + CSR_WRITE_4(sc, STE_ASICCTL, ctl); + CSR_READ_4(sc, STE_ASICCTL); + /* + * Due to the need of accessing EEPROM controller can take + * up to 1ms to complete the global reset. + */ + DELAY(1000); for (i = 0; i < STE_TIMEOUT; i++) { if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RESET_BUSY)) break; + DELAY(10); } if (i == STE_TIMEOUT) @@ -1777,39 +1850,24 @@ ste_ioctl(struct ifnet *ifp, u_long comm switch (command) { case SIOCSIFFLAGS: STE_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->ste_if_flags & IFF_PROMISC)) { - STE_SETBIT1(sc, STE_RX_MODE, - STE_RXMODE_PROMISC); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->ste_if_flags & IFF_PROMISC) { - STE_CLRBIT1(sc, STE_RX_MODE, - STE_RXMODE_PROMISC); - } - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - (ifp->if_flags ^ sc->ste_if_flags) & IFF_ALLMULTI) - ste_setmulti(sc); - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - sc->ste_tx_thresh = STE_TXSTART_THRESH; + if ((ifp->if_flags & IFF_UP) != 0) { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && + ((ifp->if_flags ^ sc->ste_if_flags) & + (IFF_PROMISC | IFF_ALLMULTI)) != 0) + ste_rxfilter(sc); + else ste_init_locked(sc); - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ste_stop(sc); - } + } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + ste_stop(sc); sc->ste_if_flags = ifp->if_flags; STE_UNLOCK(sc); - error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: STE_LOCK(sc); - ste_setmulti(sc); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + ste_rxfilter(sc); STE_UNLOCK(sc); - error = 0; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -1902,7 +1960,11 @@ ste_encap(struct ste_softc *sc, struct m * Tx descriptors here. Otherwise we race with controller. */ desc->ste_next = 0; - desc->ste_ctl = htole32(STE_TXCTL_ALIGN_DIS | STE_TXCTL_DMAINTR); + if ((sc->ste_cdata.ste_tx_prod % STE_TX_INTR_FRAMES) == 0) + desc->ste_ctl = htole32(STE_TXCTL_ALIGN_DIS | + STE_TXCTL_DMAINTR); + else + desc->ste_ctl = htole32(STE_TXCTL_ALIGN_DIS); txc->ste_mbuf = *m_head; STE_INC(sc->ste_cdata.ste_tx_prod, STE_TX_LIST_CNT); sc->ste_cdata.ste_tx_cnt++; @@ -2005,6 +2067,7 @@ ste_watchdog(struct ste_softc *sc) ste_txeof(sc); ste_txeoc(sc); ste_rxeof(sc, -1); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; ste_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) @@ -2024,3 +2087,70 @@ ste_shutdown(device_t dev) return (0); } + +#define STE_SYSCTL_STAT_ADD32(c, h, n, p, d) \ + SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) +#define STE_SYSCTL_STAT_ADD64(c, h, n, p, d) \ + SYSCTL_ADD_QUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d) + +static void +ste_sysctl_node(struct ste_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *child, *parent; + struct sysctl_oid *tree; + struct ste_hw_stats *stats; + + stats = &sc->ste_stats; + ctx = device_get_sysctl_ctx(sc->ste_dev); + child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ste_dev)); + + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, + NULL, "STE statistics"); + parent = SYSCTL_CHILDREN(tree); + + /* Rx statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD, + NULL, "Rx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + STE_SYSCTL_STAT_ADD64(ctx, child, "good_octets", + &stats->rx_bytes, "Good octets"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_frames", + &stats->rx_frames, "Good frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_bcast_frames", + &stats->rx_bcast_frames, "Good broadcast frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_mcast_frames", + &stats->rx_mcast_frames, "Good multicast frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "lost_frames", + &stats->rx_lost_frames, "Lost frames"); + + /* Tx statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, + NULL, "Tx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + STE_SYSCTL_STAT_ADD64(ctx, child, "good_octets", + &stats->tx_bytes, "Good octets"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_frames", + &stats->tx_frames, "Good frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_bcast_frames", + &stats->tx_bcast_frames, "Good broadcast frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "good_mcast_frames", + &stats->tx_mcast_frames, "Good multicast frames"); + STE_SYSCTL_STAT_ADD32(ctx, child, "carrier_errs", + &stats->tx_carrsense_errs, "Carrier sense errors"); + STE_SYSCTL_STAT_ADD32(ctx, child, "single_colls", + &stats->tx_single_colls, "Single collisions"); + STE_SYSCTL_STAT_ADD32(ctx, child, "multi_colls", + &stats->tx_multi_colls, "Multiple collisions"); + STE_SYSCTL_STAT_ADD32(ctx, child, "late_colls", + &stats->tx_late_colls, "Late collisions"); + STE_SYSCTL_STAT_ADD32(ctx, child, "defers", + &stats->tx_frames_defered, "Frames with deferrals"); + STE_SYSCTL_STAT_ADD32(ctx, child, "excess_defers", + &stats->tx_excess_defers, "Frames with excessive derferrals"); + STE_SYSCTL_STAT_ADD32(ctx, child, "abort", + &stats->tx_abort, "Aborted frames due to Excessive collisions"); +} + +#undef STE_SYSCTL_STAT_ADD32 +#undef STE_SYSCTL_STAT_ADD64 Modified: stable/8/sys/dev/ste/if_stereg.h ============================================================================== --- stable/8/sys/dev/ste/if_stereg.h Thu Jan 14 22:04:32 2010 (r202313) +++ stable/8/sys/dev/ste/if_stereg.h Thu Jan 14 22:15:51 2010 (r202314) @@ -63,6 +63,7 @@ #define STE_RX_DMABURST_THRESH 0x14 #define STE_RX_DMAURG_THRESH 0x15 #define STE_RX_DMAPOLL_PERIOD 0x16 +#define STE_COUNTDOWN 0x18 #define STE_DEBUGCTL 0x1A #define STE_ASICCTL 0x30 #define STE_EEPROM_DATA 0x34 @@ -75,7 +76,6 @@ #define STE_WAKE_EVENT 0x45 #define STE_TX_STATUS 0x46 #define STE_TX_FRAMEID 0x47 -#define STE_COUNTDOWN 0x48 #define STE_ISR_ACK 0x4A #define STE_IMR 0x4C #define STE_ISR 0x4E @@ -92,11 +92,25 @@ #define STE_MAR1 0x62 #define STE_MAR2 0x64 #define STE_MAR3 0x66 -#define STE_STATS 0x68 -#define STE_LATE_COLLS 0x75 -#define STE_MULTI_COLLS 0x76 -#define STE_SINGLE_COLLS 0x77 +#define STE_STAT_RX_OCTETS_LO 0x68 +#define STE_STAT_RX_OCTETS_HI 0x6A +#define STE_STAT_TX_OCTETS_LO 0x6C +#define STE_STAT_TX_OCTETS_HI 0x6E +#define STE_STAT_TX_FRAMES 0x70 +#define STE_STAT_RX_FRAMES 0x72 +#define STE_STAT_CARRIER_ERR 0x74 +#define STE_STAT_LATE_COLLS 0x75 +#define STE_STAT_MULTI_COLLS 0x76 +#define STE_STAT_SINGLE_COLLS 0x77 +#define STE_STAT_TX_DEFER 0x78 +#define STE_STAT_RX_LOST 0x79 +#define STE_STAT_TX_EXDEFER 0x7A +#define STE_STAT_TX_ABORT 0x7B +#define STE_STAT_TX_BCAST 0x7C +#define STE_STAT_RX_BCAST 0x7D +#define STE_STAT_TX_MCAST 0x7E +#define STE_STAT_RX_MCAST 0x7F #define STE_DMACTL_RXDMA_STOPPED 0x00000001 #define STE_DMACTL_TXDMA_CMPREQ 0x00000002 @@ -199,18 +213,6 @@ #define STE_ASICCTL_SOFTINTR 0x02000000 #define STE_ASICCTL_RESET_BUSY 0x04000000 -#define STE_ASICCTL1_GLOBAL_RESET 0x0001 -#define STE_ASICCTL1_RX_RESET 0x0002 -#define STE_ASICCTL1_TX_RESET 0x0004 -#define STE_ASICCTL1_DMA_RESET 0x0008 -#define STE_ASICCTL1_FIFO_RESET 0x0010 -#define STE_ASICCTL1_NETWORK_RESET 0x0020 -#define STE_ASICCTL1_HOST_RESET 0x0040 -#define STE_ASICCTL1_AUTOINIT_RESET 0x0080 -#define STE_ASICCTL1_EXTRESET_RESET 0x0100 -#define STE_ASICCTL1_SOFTINTR 0x0200 -#define STE_ASICCTL1_RESET_BUSY 0x0400 - #define STE_EECTL_ADDR 0x00FF #define STE_EECTL_OPCODE 0x0300 #define STE_EECTL_BUSY 0x1000 @@ -388,24 +390,23 @@ #define STE_PME_EN 0x0010 #define STE_PME_STATUS 0x8000 - -struct ste_stats { - uint32_t ste_rx_bytes; - uint32_t ste_tx_bytes; - uint16_t ste_tx_frames; - uint16_t ste_rx_frames; - uint8_t ste_carrsense_errs; - uint8_t ste_late_colls; - uint8_t ste_multi_colls; - uint8_t ste_single_colls; - uint8_t ste_tx_frames_defered; - uint8_t ste_rx_lost_frames; - uint8_t ste_tx_excess_defers; - uint8_t ste_tx_abort_excess_colls; - uint8_t ste_tx_bcast_frames; - uint8_t ste_rx_bcast_frames; - uint8_t ste_tx_mcast_frames; - uint8_t ste_rx_mcast_frames; +struct ste_hw_stats { + uint64_t rx_bytes; + uint32_t rx_frames; + uint32_t rx_bcast_frames; + uint32_t rx_mcast_frames; + uint32_t rx_lost_frames; + uint64_t tx_bytes; + uint32_t tx_frames; + uint32_t tx_bcast_frames; + uint32_t tx_mcast_frames; + uint32_t tx_carrsense_errs; + uint32_t tx_single_colls; + uint32_t tx_multi_colls; + uint32_t tx_late_colls; + uint32_t tx_frames_defered; + uint32_t tx_excess_defers; + uint32_t tx_abort; }; struct ste_frag { @@ -493,6 +494,12 @@ struct ste_desc_onefrag { #define STE_ADDR_LO(x) ((uint64_t)(x) & 0xFFFFFFFF) #define STE_ADDR_HI(x) ((uint64_t)(x) >> 32) +/* + * Since Tx status can hold up to 31 status bytes we should + * check Tx status before controller fills it up. Otherwise + * Tx MAC stalls. + */ +#define STE_TX_INTR_FRAMES 16 #define STE_TX_TIMEOUT 5 #define STE_TIMEOUT 1000 #define STE_MIN_FRAMELEN 60 @@ -566,6 +573,7 @@ struct ste_softc { struct ste_list_data ste_ldata; struct ste_chain_data ste_cdata; struct callout ste_callout; + struct ste_hw_stats ste_stats; struct mtx ste_mtx; };