PERFORCE change 68118 for review
Sam Leffler
sam at FreeBSD.org
Sun Jan 2 05:26:07 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=68118
Change 68118 by sam at 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 <sys/cdefs.h>
-__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 {
More information about the p4-projects
mailing list