From owner-p4-projects@FreeBSD.ORG Sun Jan 2 05:26:07 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E11C116A4D0; Sun, 2 Jan 2005 05:26:06 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9E73716A4CE for ; Sun, 2 Jan 2005 05:26:06 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5D6E943D2D for ; Sun, 2 Jan 2005 05:26:06 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j025Q63P085562 for ; Sun, 2 Jan 2005 05:26:06 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j025Q55D085559 for perforce@freebsd.org; Sun, 2 Jan 2005 05:26:05 GMT (envelope-from sam@freebsd.org) Date: Sun, 2 Jan 2005 05:26:05 GMT Message-Id: <200501020526.j025Q55D085559@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 68118 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Jan 2005 05:26:07 -0000 http://perforce.freebsd.org/chv.cgi?CH=68118 Change 68118 by sam@sam_ebb on 2005/01/02 05:25:04 make softled support flash the led based on tx/rx traffic Affected files ... .. //depot/projects/wifi/sys/dev/ath/if_ath.c#53 edit .. //depot/projects/wifi/sys/dev/ath/if_athvar.h#21 edit Differences ... ==== //depot/projects/wifi/sys/dev/ath/if_ath.c#53 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,7 +35,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.65 2004/12/31 20:35:05 sam Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.66 2004/12/31 22:41:45 sam Exp $"); /* * Driver for the Atheros Wireless LAN controller. @@ -93,6 +93,11 @@ ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) +enum { + ATH_LED_TX, + ATH_LED_RX, +}; + static void ath_init(void *); static void ath_stop_locked(struct ifnet *); static void ath_stop(struct ifnet *); @@ -157,7 +162,7 @@ struct ieee80211_node *, int); static int ath_getchannels(struct ath_softc *, u_int cc, HAL_BOOL outdoor, HAL_BOOL xchanmode); -static void ath_update_led(struct ath_softc *); +static void ath_led_event(struct ath_softc *, int); static void ath_update_txpow(struct ath_softc *); static int ath_rate_setup(struct ath_softc *, u_int mode); @@ -215,6 +220,7 @@ ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */ ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */ ATH_DEBUG_NODE = 0x00080000, /* node management */ + ATH_DEBUG_LED = 0x00100000, /* led management */ ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */ ATH_DEBUG_ANY = 0xffffffff }; @@ -441,6 +447,7 @@ } sc->sc_ledstate = 1; + callout_init(&sc->sc_ledtimer, CALLOUT_MPSAFE); /* * Auto-enable soft led processing for IBM cards and for * 5211 minipci cards. Users can also manually enable/disable @@ -448,8 +455,9 @@ */ sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID); if (sc->sc_softled) { + sc->sc_ledon = 0; /* low true */ ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); - ath_hal_gpioset(ah, sc->sc_ledpin, 0); + ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } ifp->if_softc = sc; @@ -933,8 +941,11 @@ ifp->if_flags &= ~IFF_RUNNING; ifp->if_timer = 0; if (!sc->sc_invalid) { - if (sc->sc_softled) - ath_hal_gpioset(ah, sc->sc_ledpin, 1); + if (sc->sc_softled) { + callout_stop(&sc->sc_ledtimer); + ath_hal_gpioset(ah, sc->sc_ledpin, + !sc->sc_ledon); + } ath_hal_intrset(ah, 0); } ath_draintxq(sc); @@ -2606,8 +2617,6 @@ len = ds->ds_rxstat.rs_datalen; m->m_pkthdr.len = m->m_len = len; - if (sc->sc_softled) - ath_update_led(sc); sc->sc_stats.ast_ant_rx[ds->ds_rxstat.rs_antenna]++; if (sc->sc_drvbpf) { @@ -2690,9 +2699,6 @@ ni = ieee80211_find_rxnode(ic, mtod(m, const struct ieee80211_frame_min *)); - /* - * Track rx rssi and do any rx antenna management. - */ an = ATH_NODE(ni); ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi); if (sc->sc_diversity) { @@ -2715,6 +2721,20 @@ ieee80211_input(ic, m, ni, ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp); + if (sc->sc_softled) { + /* + * Blink for any non-beacon frames. We decide if + * this was a beacon frame by monitoring the stats + * which means we'll blink for things like ACK frames + * when in monitor mode--probably not what we want. + */ + if (sc->sc_beacon == ic->ic_stats.is_rx_beacon) { + sc->sc_rxrate = ds->ds_rxstat.rs_rate; + ath_led_event(sc, ATH_LED_RX); + } else + sc->sc_beacon = ic->ic_stats.is_rx_beacon; + } + /* * Reclaim node reference. */ @@ -3094,6 +3114,7 @@ */ ath_rate_findrate(sc, an, shortPreamble, pktlen, &rix, &try0, &txrate); + sc->sc_txrate = txrate; /* for LED blinking */ /* * Default all non-QoS traffic to the background queue. */ @@ -3339,9 +3360,6 @@ txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; ATH_TXQ_UNLOCK(txq); - if (sc->sc_softled) - ath_update_led(sc); - /* * The CAB queue is started from the SWBA handler since * frames only go out on DTIM and to avoid possible races. @@ -3469,6 +3487,9 @@ ifp->if_flags &= ~IFF_OACTIVE; sc->sc_tx_timer = 0; + if (sc->sc_softled) + ath_led_event(sc, ATH_LED_TX); + ath_start(ifp); } @@ -3494,6 +3515,9 @@ ifp->if_flags &= ~IFF_OACTIVE; sc->sc_tx_timer = 0; + if (sc->sc_softled) + ath_led_event(sc, ATH_LED_TX); + ath_start(ifp); } @@ -3518,6 +3542,9 @@ ifp->if_flags &= ~IFF_OACTIVE; sc->sc_tx_timer = 0; + if (sc->sc_softled) + ath_led_event(sc, ATH_LED_TX); + ath_start(ifp); } @@ -4001,26 +4028,55 @@ } static void -ath_update_led(struct ath_softc *sc) +ath_led_done(void *arg) +{ + struct ath_softc *sc = arg; + + sc->sc_blinking = 0; +} + +/* + * Turn the LED off: flip the pin and then set a timer so no + * update will happen for the specified duration. + */ +static void +ath_led_off(void *arg) +{ + struct ath_softc *sc = arg; + + ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon); + callout_reset(&sc->sc_ledtimer, sc->sc_ledoff, ath_led_done, sc); +} + +/* + * Blink the LED according to the specified on/off times. + */ +static void +ath_led_blink(struct ath_softc *sc, int on, int off) +{ + DPRINTF(sc, ATH_DEBUG_LED, "%s: on %u off %u\n", __func__, on, off); + ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, sc->sc_ledon); + sc->sc_blinking = 1; + sc->sc_ledoff = off; + callout_reset(&sc->sc_ledtimer, on, ath_led_off, sc); +} + +static void +ath_led_event(struct ath_softc *sc, int event) { struct ieee80211com *ic = &sc->sc_ic; - struct ath_hal *ah = sc->sc_ah; - u_int32_t threshold; - /* - * When not associated, flash LED on for 5s, off for 200ms. - * XXX this assumes 100ms beacon interval. - */ - if (ic->ic_state != IEEE80211_S_RUN) { - threshold = 2 + sc->sc_ledstate * 48; - } else { - threshold = 2 + sc->sc_ledstate * 18; - } - if (ic->ic_stats.is_rx_beacon - sc->sc_beacons >= threshold) { - ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); - ath_hal_gpioset(ah, sc->sc_ledpin, sc->sc_ledstate); - sc->sc_ledstate ^= 1; - sc->sc_beacons = ic->ic_stats.is_rx_beacon; + if (sc->sc_blinking) /* don't interrupt active blink */ + return; + switch (event) { + case ATH_LED_TX: + ath_led_blink(sc, sc->sc_hwledon[sc->sc_txrate], + sc->sc_hwledoff[sc->sc_txrate]); + break; + case ATH_LED_RX: + ath_led_blink(sc, sc->sc_hwledon[sc->sc_rxrate], + sc->sc_hwledoff[sc->sc_rxrate]); + break; } } @@ -4094,8 +4150,30 @@ static void ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode) { +#define N(a) (sizeof(a)/sizeof(a[0])) + /* NB: on/off times from the Atheros NDIS driver, w/ permission */ + static const struct { + u_int rate; /* tx/rx 802.11 rate */ + u_int16_t timeOn; /* LED on time (ms) */ + u_int16_t timeOff; /* LED off time (ms) */ + } blinkrates[] = { + { 108, 40, 10 }, + { 96, 44, 11 }, + { 72, 50, 13 }, + { 48, 57, 14 }, + { 36, 67, 16 }, + { 24, 80, 20 }, + { 22, 100, 25 }, + { 18, 133, 34 }, + { 12, 160, 40 }, + { 10, 200, 50 }, + { 6, 240, 58 }, + { 4, 267, 66 }, + { 2, 400, 100 }, + { 0, 500, 130 }, + }; const HAL_RATE_TABLE *rt; - int i; + int i, j; memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap)); rt = sc->sc_rates[mode]; @@ -4106,12 +4184,23 @@ memset(sc->sc_hwflags, 0, sizeof(sc->sc_hwflags)); for (i = 0; i < 32; i++) { u_int8_t ix = rt->rateCodeToIndex[i]; - if (ix == 0xff) + if (ix == 0xff) { + sc->sc_hwledon[i] = (500 * hz) / 1000; + sc->sc_hwledoff[i] = (130 * hz) / 1000; continue; + } sc->sc_hwmap[i] = rt->info[ix].dot11Rate & IEEE80211_RATE_VAL; if (rt->info[ix].shortPreamble || rt->info[ix].phy == IEEE80211_T_OFDM) sc->sc_hwflags[i] |= IEEE80211_RADIOTAP_F_SHORTPRE; + /* setup blink rate table to avoid per-packet lookup */ + for (j = 0; j < N(blinkrates)-1; j++) + if (blinkrates[j].rate == sc->sc_hwmap[i]) + break; + /* NB: this uses the last entry if the rate isn't found */ + /* XXX beware of overlow */ + sc->sc_hwledon[i] = (blinkrates[j].timeOn * hz) / 1000; + sc->sc_hwledoff[i] = (blinkrates[j].timeOff * hz) / 1000; } sc->sc_currates = rt; sc->sc_curmode = mode; @@ -4122,6 +4211,7 @@ */ sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0); /* NB: caller is responsible for reseting rate control state */ +#undef N } #ifdef AR_DEBUG @@ -4368,12 +4458,11 @@ error = sysctl_handle_int(oidp, &softled, 0, req); if (error || !req->newptr) return error; - if (softled > 1) - softled = 1; + softled = (softled != 0); if (softled != sc->sc_softled) { if (softled) ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin); - ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !softled); + ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon); sc->sc_softled = softled; } return 0; @@ -4484,6 +4573,9 @@ "ledpin", CTLFLAG_RW, &sc->sc_ledpin, 0, "GPIO pin connected to LED"); SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ledon", CTLFLAG_RW, &sc->sc_ledon, 0, + "setting to turn LED on"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "txantenna", CTLFLAG_RW, &sc->sc_txantenna, 0, "tx antenna (0=auto)"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, ==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#21 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,7 +33,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * - * $FreeBSD: src/sys/dev/ath/if_athvar.h,v 1.16 2004/12/31 20:32:40 sam Exp $ + * $FreeBSD: src/sys/dev/ath/if_athvar.h,v 1.17 2004/12/31 22:41:45 sam Exp $ */ /* @@ -173,7 +173,9 @@ sc_hasdiversity : 1,/* rx diversity available */ sc_diversity : 1,/* enable rx diversity */ sc_hasveol : 1, /* tx VEOL support */ - sc_hastpc : 1; /* per-packet TPC support */ + sc_hastpc : 1, /* per-packet TPC support */ + sc_ledstate: 1, /* LED on/off state */ + sc_blinking: 1; /* LED blink operation active */ /* rate tables */ const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX]; const HAL_RATE_TABLE *sc_currates; /* current rate table */ @@ -189,9 +191,15 @@ u_int sc_keymax; /* size of key cache */ u_int8_t sc_keymap[16]; /* bit map of key cache use */ - u_int32_t sc_beacons; /* beacon count for LED mgmt */ - u_int16_t sc_ledstate; /* LED on/off state */ - u_int16_t sc_ledpin; /* GPIO pin for driving LED */ + u_int sc_ledpin; /* GPIO pin for driving LED */ + u_int sc_ledon; /* pin setting for LED on */ + u_int32_t sc_beacon; /* last beacon count */ + u_int8_t sc_rxrate; /* current rx rate for LED */ + u_int8_t sc_txrate; /* current tx rate for LED */ + u_int16_t sc_ledoff; /* off time for current blink */ + u_int16_t sc_hwledon[32]; /* h/w rate ix to LED on time */ + u_int16_t sc_hwledoff[32];/* " " " to LED off time */ + struct callout sc_ledtimer; /* led off timer */ struct bpf_if *sc_drvbpf; union {