From owner-svn-src-all@FreeBSD.ORG Mon May 17 16:57:55 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B99D81065675; Mon, 17 May 2010 16:57:55 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (unknown [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A6EC68FC13; Mon, 17 May 2010 16:57:55 +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 o4HGvtBW082753; Mon, 17 May 2010 16:57:55 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o4HGvtxS082749; Mon, 17 May 2010 16:57:55 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201005171657.o4HGvtxS082749@svn.freebsd.org> From: Pyun YongHyeon Date: Mon, 17 May 2010 16:57:55 +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: r208199 - stable/8/sys/dev/fxp X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 May 2010 16:57:55 -0000 Author: yongari Date: Mon May 17 16:57:55 2010 New Revision: 208199 URL: http://svn.freebsd.org/changeset/base/208199 Log: MFC r207832: Export hardware MAC statistics through sysctl node. Previously fxp(4) already used to extract most hardware MAC statistics but it didn't show them. With this change, all MAC statistics counters are exported. Because there are a couple of new counters for 82558 and 82559, enable extended MAC statistics functionality to get these counters. Accoring to public data sheet, 82559 MAC statistics return 24 DWORD counters(3 counters are unknown at this moment) so increase MAC counter structure to meet the MAC statistics block size. The completion of MAC counter dump is now checked against FXP_STATS_DR_COMPLETE status code which is appended at the end of status block. Previously fxp(4) ignored the status of the FXP_SCB_COMMAND_CU_DUMPRESET command. fxp(4) does not wait for the completion of pending command before issuing FXP_SCB_COMMAND_CU_DUMPRESET. Instead it skips the command and try it next time. This scheme may show better performance but there is chance to loose updated counters after stopping controller. So make sure to update MAC statistics in fxp_stop(). While I'm here move sysctl node creation to fxp_sysctl_node(). Tested by: Larry Baird < lab <> gta dot com > Modified: stable/8/sys/dev/fxp/if_fxp.c stable/8/sys/dev/fxp/if_fxpreg.h stable/8/sys/dev/fxp/if_fxpvar.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) stable/8/sys/geom/sched/ (props changed) Modified: stable/8/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/8/sys/dev/fxp/if_fxp.c Mon May 17 16:55:26 2010 (r208198) +++ stable/8/sys/dev/fxp/if_fxp.c Mon May 17 16:57:55 2010 (r208199) @@ -262,6 +262,8 @@ static int fxp_miibus_readreg(device_t static int fxp_miibus_writereg(device_t dev, int phy, int reg, int value); static void fxp_load_ucode(struct fxp_softc *sc); +static void fxp_update_stats(struct fxp_softc *sc); +static void fxp_sysctl_node(struct fxp_softc *sc); static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high); static int sysctl_hw_fxp_bundle_max(SYSCTL_HANDLER_ARGS); @@ -537,39 +539,7 @@ fxp_attach(device_t dev) && (data & FXP_PHY_SERIAL_ONLY)) sc->flags |= FXP_FLAG_SERIAL_MEDIA; - SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "int_delay", CTLTYPE_INT | CTLFLAG_RW, - &sc->tunable_int_delay, 0, sysctl_hw_fxp_int_delay, "I", - "FXP driver receive interrupt microcode bundling delay"); - SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "bundle_max", CTLTYPE_INT | CTLFLAG_RW, - &sc->tunable_bundle_max, 0, sysctl_hw_fxp_bundle_max, "I", - "FXP driver receive interrupt microcode bundle size limit"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "rnr", CTLFLAG_RD, &sc->rnr, 0, - "FXP RNR events"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "noflow", CTLFLAG_RW, &sc->tunable_noflow, 0, - "FXP flow control disabled"); - - /* - * Pull in device tunables. - */ - sc->tunable_int_delay = TUNABLE_INT_DELAY; - sc->tunable_bundle_max = TUNABLE_BUNDLE_MAX; - sc->tunable_noflow = 1; - (void) resource_int_value(device_get_name(dev), device_get_unit(dev), - "int_delay", &sc->tunable_int_delay); - (void) resource_int_value(device_get_name(dev), device_get_unit(dev), - "bundle_max", &sc->tunable_bundle_max); - (void) resource_int_value(device_get_name(dev), device_get_unit(dev), - "noflow", &sc->tunable_noflow); - sc->rnr = 0; - + fxp_sysctl_node(sc); /* * Enable workarounds for certain chip revision deficiencies. * @@ -2020,6 +1990,81 @@ fxp_intr_body(struct fxp_softc *sc, stru return (rx_npkts); } +static void +fxp_update_stats(struct fxp_softc *sc) +{ + struct ifnet *ifp = sc->ifp; + struct fxp_stats *sp = sc->fxp_stats; + struct fxp_hwstats *hsp; + uint32_t *status; + + FXP_LOCK_ASSERT(sc, MA_OWNED); + + bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + /* Update statistical counters. */ + if (sc->revision >= FXP_REV_82559_A0) + status = &sp->completion_status; + else if (sc->revision >= FXP_REV_82558_A4) + status = (uint32_t *)&sp->tx_tco; + else + status = &sp->tx_pause; + if (*status == htole32(FXP_STATS_DR_COMPLETE)) { + hsp = &sc->fxp_hwstats; + hsp->tx_good += le32toh(sp->tx_good); + hsp->tx_maxcols += le32toh(sp->tx_maxcols); + hsp->tx_latecols += le32toh(sp->tx_latecols); + hsp->tx_underruns += le32toh(sp->tx_underruns); + hsp->tx_lostcrs += le32toh(sp->tx_lostcrs); + hsp->tx_deffered += le32toh(sp->tx_deffered); + hsp->tx_single_collisions += le32toh(sp->tx_single_collisions); + hsp->tx_multiple_collisions += + le32toh(sp->tx_multiple_collisions); + hsp->tx_total_collisions += le32toh(sp->tx_total_collisions); + hsp->rx_good += le32toh(sp->rx_good); + hsp->rx_crc_errors += le32toh(sp->rx_crc_errors); + hsp->rx_alignment_errors += le32toh(sp->rx_alignment_errors); + hsp->rx_rnr_errors += le32toh(sp->rx_rnr_errors); + hsp->rx_overrun_errors += le32toh(sp->rx_overrun_errors); + hsp->rx_cdt_errors += le32toh(sp->rx_cdt_errors); + hsp->rx_shortframes += le32toh(sp->rx_shortframes); + hsp->tx_pause += le32toh(sp->tx_pause); + hsp->rx_pause += le32toh(sp->rx_pause); + hsp->rx_controls += le32toh(sp->rx_controls); + hsp->tx_tco += le16toh(sp->tx_tco); + hsp->rx_tco += le16toh(sp->rx_tco); + + ifp->if_opackets += le32toh(sp->tx_good); + ifp->if_collisions += le32toh(sp->tx_total_collisions); + if (sp->rx_good) { + ifp->if_ipackets += le32toh(sp->rx_good); + sc->rx_idle_secs = 0; + } else if (sc->flags & FXP_FLAG_RXBUG) { + /* + * Receiver's been idle for another second. + */ + sc->rx_idle_secs++; + } + ifp->if_ierrors += + le32toh(sp->rx_crc_errors) + + le32toh(sp->rx_alignment_errors) + + le32toh(sp->rx_rnr_errors) + + le32toh(sp->rx_overrun_errors); + /* + * If any transmit underruns occured, bump up the transmit + * threshold by another 512 bytes (64 * 8). + */ + if (sp->tx_underruns) { + ifp->if_oerrors += le32toh(sp->tx_underruns); + if (tx_threshold < 192) + tx_threshold += 64; + } + *status = 0; + bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + } +} + /* * Update packet in/out/collision statistics. The i82557 doesn't * allow you to access these counters without doing a fairly @@ -2036,35 +2081,11 @@ fxp_tick(void *xsc) { struct fxp_softc *sc = xsc; struct ifnet *ifp = sc->ifp; - struct fxp_stats *sp = sc->fxp_stats; FXP_LOCK_ASSERT(sc, MA_OWNED); - bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, BUS_DMASYNC_POSTREAD); - ifp->if_opackets += le32toh(sp->tx_good); - ifp->if_collisions += le32toh(sp->tx_total_collisions); - if (sp->rx_good) { - ifp->if_ipackets += le32toh(sp->rx_good); - sc->rx_idle_secs = 0; - } else if (sc->flags & FXP_FLAG_RXBUG) { - /* - * Receiver's been idle for another second. - */ - sc->rx_idle_secs++; - } - ifp->if_ierrors += - le32toh(sp->rx_crc_errors) + - le32toh(sp->rx_alignment_errors) + - le32toh(sp->rx_rnr_errors) + - le32toh(sp->rx_overrun_errors); - /* - * If any transmit underruns occured, bump up the transmit - * threshold by another 512 bytes (64 * 8). - */ - if (sp->tx_underruns) { - ifp->if_oerrors += le32toh(sp->tx_underruns); - if (tx_threshold < 192) - tx_threshold += 64; - } + + /* Update statistical counters. */ + fxp_update_stats(sc); /* * Release any xmit buffers that have completed DMA. This isn't @@ -2099,24 +2120,7 @@ fxp_tick(void *xsc) /* * Start another stats dump. */ - bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, - BUS_DMASYNC_PREREAD); fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMPRESET); - } else { - /* - * A previous command is still waiting to be accepted. - * Just zero our copy of the stats and wait for the - * next timer event to update them. - */ - sp->tx_good = 0; - sp->tx_underruns = 0; - sp->tx_total_collisions = 0; - - sp->rx_good = 0; - sp->rx_crc_errors = 0; - sp->rx_alignment_errors = 0; - sp->rx_rnr_errors = 0; - sp->rx_overrun_errors = 0; } if (sc->miibus != NULL) mii_tick(device_get_softc(sc->miibus)); @@ -2160,6 +2164,8 @@ fxp_stop(struct fxp_softc *sc) /* Disable interrupts. */ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); + fxp_update_stats(sc); + /* * Release any xmit buffers. */ @@ -2262,7 +2268,9 @@ fxp_init_body(struct fxp_softc *sc) * Initialize base of dump-stats buffer. */ fxp_scb_wait(sc); - bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, BUS_DMASYNC_PREREAD); + bzero(sc->fxp_stats, sizeof(struct fxp_stats)); + bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->stats_addr); fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMP_ADR); @@ -2383,6 +2391,22 @@ fxp_init_body(struct fxp_softc *sc) cbp->pri_fc_loc = 1; /* FC pri location (byte31) */ } + /* Enable 82558 and 82559 extended statistics functionality. */ + if (sc->revision >= FXP_REV_82558_A4) { + if (sc->revision >= FXP_REV_82559_A0) { + /* + * Extend configuration table size to 32 + * to include TCO configuration. + */ + cbp->byte_count = 32; + cbp->ext_stats_dis = 1; + /* Enable TCO stats. */ + cbp->tno_int_or_tco_en = 1; + cbp->gamla_rx = 1; + } else + cbp->ext_stats_dis = 0; + } + /* * Start the config command/DMA. */ @@ -3004,6 +3028,113 @@ fxp_load_ucode(struct fxp_softc *sc) sc->flags |= FXP_FLAG_UCODE; } +#define FXP_SYSCTL_STAT_ADD(c, h, n, p, d) \ + SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) + +static void +fxp_sysctl_node(struct fxp_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *child, *parent; + struct sysctl_oid *tree; + struct fxp_hwstats *hsp; + + ctx = device_get_sysctl_ctx(sc->dev); + child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); + + SYSCTL_ADD_PROC(ctx, child, + OID_AUTO, "int_delay", CTLTYPE_INT | CTLFLAG_RW, + &sc->tunable_int_delay, 0, sysctl_hw_fxp_int_delay, "I", + "FXP driver receive interrupt microcode bundling delay"); + SYSCTL_ADD_PROC(ctx, child, + OID_AUTO, "bundle_max", CTLTYPE_INT | CTLFLAG_RW, + &sc->tunable_bundle_max, 0, sysctl_hw_fxp_bundle_max, "I", + "FXP driver receive interrupt microcode bundle size limit"); + SYSCTL_ADD_INT(ctx, child,OID_AUTO, "rnr", CTLFLAG_RD, &sc->rnr, 0, + "FXP RNR events"); + SYSCTL_ADD_INT(ctx, child, + OID_AUTO, "noflow", CTLFLAG_RW, &sc->tunable_noflow, 0, + "FXP flow control disabled"); + + /* + * Pull in device tunables. + */ + sc->tunable_int_delay = TUNABLE_INT_DELAY; + sc->tunable_bundle_max = TUNABLE_BUNDLE_MAX; + sc->tunable_noflow = 1; + (void) resource_int_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "int_delay", &sc->tunable_int_delay); + (void) resource_int_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "bundle_max", &sc->tunable_bundle_max); + (void) resource_int_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "noflow", &sc->tunable_noflow); + sc->rnr = 0; + + hsp = &sc->fxp_hwstats; + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, + NULL, "FXP statistics"); + parent = SYSCTL_CHILDREN(tree); + + /* Rx MAC statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD, + NULL, "Rx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + FXP_SYSCTL_STAT_ADD(ctx, child, "good_frames", + &hsp->rx_good, "Good frames"); + FXP_SYSCTL_STAT_ADD(ctx, child, "crc_errors", + &hsp->rx_crc_errors, "CRC errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "alignment_errors", + &hsp->rx_alignment_errors, "Alignment errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "rnr_errors", + &hsp->rx_rnr_errors, "RNR errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "overrun_errors", + &hsp->rx_overrun_errors, "Overrun errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "cdt_errors", + &hsp->rx_cdt_errors, "Collision detect errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "shortframes", + &hsp->rx_shortframes, "Short frame errors"); + if (sc->revision >= FXP_REV_82558_A4) { + FXP_SYSCTL_STAT_ADD(ctx, child, "pause", + &hsp->rx_pause, "Pause frames"); + FXP_SYSCTL_STAT_ADD(ctx, child, "controls", + &hsp->rx_controls, "Unsupported control frames"); + } + if (sc->revision >= FXP_REV_82559_A0) + FXP_SYSCTL_STAT_ADD(ctx, child, "tco", + &hsp->rx_tco, "TCO frames"); + + /* Tx MAC statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, + NULL, "Tx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + FXP_SYSCTL_STAT_ADD(ctx, child, "good_frames", + &hsp->tx_good, "Good frames"); + FXP_SYSCTL_STAT_ADD(ctx, child, "maxcols", + &hsp->tx_maxcols, "Maximum collisions errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "latecols", + &hsp->tx_latecols, "Late collisions errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "underruns", + &hsp->tx_underruns, "Underrun errors"); + FXP_SYSCTL_STAT_ADD(ctx, child, "lostcrs", + &hsp->tx_lostcrs, "Lost carrier sense"); + FXP_SYSCTL_STAT_ADD(ctx, child, "deffered", + &hsp->tx_deffered, "Deferred"); + FXP_SYSCTL_STAT_ADD(ctx, child, "single_collisions", + &hsp->tx_single_collisions, "Single collisions"); + FXP_SYSCTL_STAT_ADD(ctx, child, "multiple_collisions", + &hsp->tx_multiple_collisions, "Multiple collisions"); + FXP_SYSCTL_STAT_ADD(ctx, child, "total_collisions", + &hsp->tx_total_collisions, "Total collisions"); + if (sc->revision >= FXP_REV_82558_A4) + FXP_SYSCTL_STAT_ADD(ctx, child, "pause", + &hsp->tx_pause, "Pause frames"); + if (sc->revision >= FXP_REV_82559_A0) + FXP_SYSCTL_STAT_ADD(ctx, child, "tco", + &hsp->tx_tco, "TCO frames"); +} + +#undef FXP_SYSCTL_STAT_ADD + static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high) { Modified: stable/8/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/8/sys/dev/fxp/if_fxpreg.h Mon May 17 16:55:26 2010 (r208198) +++ stable/8/sys/dev/fxp/if_fxpreg.h Mon May 17 16:57:55 2010 (r208199) @@ -418,7 +418,15 @@ struct fxp_stats { uint32_t rx_overrun_errors; uint32_t rx_cdt_errors; uint32_t rx_shortframes; + uint32_t tx_pause; + uint32_t rx_pause; + uint32_t rx_controls; + uint16_t tx_tco; + uint16_t rx_tco; uint32_t completion_status; + uint32_t reserved0; + uint32_t reserved1; + uint32_t reserved2; }; #define FXP_STATS_DUMP_COMPLETE 0xa005 #define FXP_STATS_DR_COMPLETE 0xa007 Modified: stable/8/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/8/sys/dev/fxp/if_fxpvar.h Mon May 17 16:55:26 2010 (r208198) +++ stable/8/sys/dev/fxp/if_fxpvar.h Mon May 17 16:57:55 2010 (r208199) @@ -149,6 +149,30 @@ struct fxp_ident { char *name; }; +struct fxp_hwstats { + uint32_t tx_good; + uint32_t tx_maxcols; + uint32_t tx_latecols; + uint32_t tx_underruns; + uint32_t tx_lostcrs; + uint32_t tx_deffered; + uint32_t tx_single_collisions; + uint32_t tx_multiple_collisions; + uint32_t tx_total_collisions; + uint32_t tx_pause; + uint32_t tx_tco; + uint32_t rx_good; + uint32_t rx_crc_errors; + uint32_t rx_alignment_errors; + uint32_t rx_rnr_errors; + uint32_t rx_overrun_errors; + uint32_t rx_cdt_errors; + uint32_t rx_shortframes; + uint32_t rx_pause; + uint32_t rx_controls; + uint32_t rx_tco; +}; + /* * NOTE: Elements are ordered for optimal cacheline behavior, and NOT * for functional grouping. @@ -175,6 +199,7 @@ struct fxp_softc { int tx_queued; /* # of active TxCB's */ struct fxp_stats *fxp_stats; /* Pointer to interface stats */ uint32_t stats_addr; /* DMA address of the stats structure */ + struct fxp_hwstats fxp_hwstats; int rx_idle_secs; /* # of seconds RX has been idle */ struct callout stat_ch; /* stat callout */ int watchdog_timer; /* seconds until chip reset */