diff options
Diffstat (limited to 'sys/dev/ae/if_ae.c')
-rw-r--r-- | sys/dev/ae/if_ae.c | 126 |
1 files changed, 61 insertions, 65 deletions
diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c index 1a82516..d315607 100644 --- a/sys/dev/ae/if_ae.c +++ b/sys/dev/ae/if_ae.c @@ -124,10 +124,10 @@ static int ae_resume(device_t dev); static unsigned int ae_tx_avail_size(ae_softc_t *sc); static int ae_encap(ae_softc_t *sc, struct mbuf **m_head); static void ae_start(struct ifnet *ifp); +static void ae_start_locked(struct ifnet *ifp); static void ae_link_task(void *arg, int pending); static void ae_stop_rxmac(ae_softc_t *sc); static void ae_stop_txmac(ae_softc_t *sc); -static void ae_tx_task(void *arg, int pending); static void ae_mac_config(ae_softc_t *sc); static int ae_intr(void *arg); static void ae_int_task(void *arg, int pending); @@ -207,43 +207,6 @@ TUNABLE_INT("hw.ae.msi_disable", &msi_disable); #define AE_TXD_VLAN(vtag) \ (((vtag) << 4) | (((vtag) >> 13) & 0x07) | (((vtag) >> 9) & 0x08)) -/* - * ae statistics. - */ -#define STATS_ENTRY(node, desc, field) \ - { node, desc, offsetof(struct ae_stats, field) } -struct { - const char *node; - const char *desc; - intptr_t offset; -} ae_stats_tx[] = { - STATS_ENTRY("bcast", "broadcast frames", tx_bcast), - STATS_ENTRY("mcast", "multicast frames", tx_mcast), - STATS_ENTRY("pause", "PAUSE frames", tx_pause), - STATS_ENTRY("control", "control frames", tx_ctrl), - STATS_ENTRY("defers", "deferrals occuried", tx_defer), - STATS_ENTRY("exc_defers", "excessive deferrals occuried", tx_excdefer), - STATS_ENTRY("singlecols", "single collisions occuried", tx_singlecol), - STATS_ENTRY("multicols", "multiple collisions occuried", tx_multicol), - STATS_ENTRY("latecols", "late collisions occuried", tx_latecol), - STATS_ENTRY("aborts", "transmit aborts due collisions", tx_abortcol), - STATS_ENTRY("underruns", "Tx FIFO underruns", tx_underrun) -}, ae_stats_rx[] = { - STATS_ENTRY("bcast", "broadcast frames", rx_bcast), - STATS_ENTRY("mcast", "multicast frames", rx_mcast), - STATS_ENTRY("pause", "PAUSE frames", rx_pause), - STATS_ENTRY("control", "control frames", rx_ctrl), - STATS_ENTRY("crc_errors", "frames with CRC errors", rx_crcerr), - STATS_ENTRY("code_errors", "frames with invalid opcode", rx_codeerr), - STATS_ENTRY("runt", "runt frames", rx_runt), - STATS_ENTRY("frag", "fragmented frames", rx_frag), - STATS_ENTRY("align_errors", "frames with alignment errors", rx_align), - STATS_ENTRY("truncated", "frames truncated due to Rx FIFO inderrun", - rx_trunc) -}; -#define AE_STATS_RX_LEN (sizeof(ae_stats_rx) / sizeof(*ae_stats_rx)) -#define AE_STATS_TX_LEN (sizeof(ae_stats_tx) / sizeof(*ae_stats_tx)) - static int ae_probe(device_t dev) { @@ -402,7 +365,6 @@ ae_attach(device_t dev) /* * Create and run all helper tasks. */ - TASK_INIT(&sc->tx_task, 1, ae_tx_task, ifp); sc->tq = taskqueue_create_fast("ae_taskq", M_WAITOK, taskqueue_thread_enqueue, &sc->tq); if (sc->tq == NULL) { @@ -434,13 +396,15 @@ fail: return (error); } +#define AE_SYSCTL(stx, parent, name, desc, ptr) \ + SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, name, CTLFLAG_RD, ptr, 0, desc) + static void ae_init_tunables(ae_softc_t *sc) { struct sysctl_ctx_list *ctx; struct sysctl_oid *root, *stats, *stats_rx, *stats_tx; struct ae_stats *ae_stats; - unsigned int i; KASSERT(sc != NULL, ("[ae, %d]: sc is NULL", __LINE__)); ae_stats = &sc->stats; @@ -455,20 +419,54 @@ ae_init_tunables(ae_softc_t *sc) */ stats_rx = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(stats), OID_AUTO, "rx", CTLFLAG_RD, NULL, "Rx MAC statistics"); - for (i = 0; i < AE_STATS_RX_LEN; i++) - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(stats_rx), OID_AUTO, - ae_stats_rx[i].node, CTLFLAG_RD, (char *)ae_stats + - ae_stats_rx[i].offset, 0, ae_stats_rx[i].desc); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "bcast", + "broadcast frames", &ae_stats->rx_bcast); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "mcast", + "multicast frames", &ae_stats->rx_mcast); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "pause", + "PAUSE frames", &ae_stats->rx_pause); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "control", + "control frames", &ae_stats->rx_ctrl); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "crc_errors", + "frames with CRC errors", &ae_stats->rx_crcerr); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "code_errors", + "frames with invalid opcode", &ae_stats->rx_codeerr); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "runt", + "runt frames", &ae_stats->rx_runt); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "frag", + "fragmented frames", &ae_stats->rx_frag); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "align_errors", + "frames with alignment errors", &ae_stats->rx_align); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_rx), "truncated", + "frames truncated due to Rx FIFO inderrun", &ae_stats->rx_trunc); /* * Receiver statistcics. */ stats_tx = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(stats), OID_AUTO, "tx", CTLFLAG_RD, NULL, "Tx MAC statistics"); - for (i = 0; i < AE_STATS_TX_LEN; i++) - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(stats_tx), OID_AUTO, - ae_stats_tx[i].node, CTLFLAG_RD, (char *)ae_stats + - ae_stats_tx[i].offset, 0, ae_stats_tx[i].desc); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "bcast", + "broadcast frames", &ae_stats->tx_bcast); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "mcast", + "multicast frames", &ae_stats->tx_mcast); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "pause", + "PAUSE frames", &ae_stats->tx_pause); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "control", + "control frames", &ae_stats->tx_ctrl); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "defers", + "deferrals occuried", &ae_stats->tx_defer); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "exc_defers", + "excessive deferrals occuried", &ae_stats->tx_excdefer); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "singlecols", + "single collisions occuried", &ae_stats->tx_singlecol); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "multicols", + "multiple collisions occuried", &ae_stats->tx_multicol); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "latecols", + "late collisions occuried", &ae_stats->tx_latecol); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "aborts", + "transmit aborts due collisions", &ae_stats->tx_abortcol); + AE_SYSCTL(ctx, SYSCTL_CHILDREN(stats_tx), "underruns", + "Tx FIFO underruns", &ae_stats->tx_underrun); } static void @@ -763,7 +761,6 @@ ae_detach(device_t dev) AE_UNLOCK(sc); callout_drain(&sc->tick_ch); taskqueue_drain(sc->tq, &sc->int_task); - taskqueue_drain(sc->tq, &sc->tx_task); taskqueue_drain(taskqueue_swi, &sc->link_task); ether_ifdetach(ifp); } @@ -1518,23 +1515,32 @@ static void ae_start(struct ifnet *ifp) { ae_softc_t *sc; + + sc = ifp->if_softc; + AE_LOCK(sc); + ae_start_locked(ifp); + AE_UNLOCK(sc); +} + +static void +ae_start_locked(struct ifnet *ifp) +{ + ae_softc_t *sc; unsigned int count; struct mbuf *m0; int error; sc = ifp->if_softc; KASSERT(sc != NULL, ("[ae, %d]: sc is NULL", __LINE__)); - AE_LOCK(sc); + AE_LOCK_ASSERT(sc); #ifdef AE_DEBUG if_printf(ifp, "Start called.\n"); #endif if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING || (sc->flags & AE_FLAG_LINK) == 0) { - AE_UNLOCK(sc); + IFF_DRV_RUNNING || (sc->flags & AE_FLAG_LINK) == 0) return; - } count = 0; while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { @@ -1570,7 +1576,6 @@ ae_start(struct ifnet *ifp) if_printf(ifp, "Tx pos now is %d.\n", sc->txd_cur); #endif } - AE_UNLOCK(sc); } static void @@ -1704,15 +1709,6 @@ ae_stop_txmac(ae_softc_t *sc) } static void -ae_tx_task(void *arg, int pending) -{ - struct ifnet *ifp; - - ifp = (struct ifnet *)arg; - ae_start(ifp); -} - -static void ae_mac_config(ae_softc_t *sc) { struct mii_data *mii; @@ -1869,7 +1865,7 @@ ae_tx_intr(ae_softc_t *sc) if ((sc->flags & AE_FLAG_TXAVAIL) != 0) { if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - taskqueue_enqueue(sc->tq, &sc->tx_task); + ae_start_locked(ifp); } /* @@ -1997,7 +1993,7 @@ ae_watchdog(ae_softc_t *sc) ifp->if_drv_flags &= ~IFF_DRV_RUNNING; ae_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - taskqueue_enqueue(sc->tq, &sc->tx_task); + ae_start_locked(ifp); } static void |