PERFORCE change 66116 for review
Sam Leffler
sam at FreeBSD.org
Tue Nov 30 10:02:07 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=66116
Change 66116 by sam at sam_ebb on 2004/11/30 18:01:27
more beacon cleanups:
o move swba processing above tx+rx processing; it's the
most time-critical so don't delay
o reorg beacon xmit code so we construct the tx descriptor
for each beacon
o periodically switch antenna for beacon xmit
o count beacon xmits and stuck conditions
o rename beacon stuck task for consistency
Affected files ...
.. //depot/projects/wifi/sys/dev/ath/if_ath.c#32 edit
.. //depot/projects/wifi/sys/dev/ath/if_athioctl.h#4 edit
Differences ...
==== //depot/projects/wifi/sys/dev/ath/if_ath.c#32 (text+ko) ====
@@ -114,13 +114,12 @@
static void ath_key_update_begin(struct ieee80211com *);
static void ath_key_update_end(struct ieee80211com *);
static void ath_mode_init(struct ath_softc *);
-static int ath_beacon_setup(struct ath_softc *,
- struct ath_buf *, struct mbuf *);
static void ath_setslottime(struct ath_softc *);
static void ath_updateslot(struct ifnet *);
static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);
+static void ath_beacon_setup(struct ath_softc *, struct ath_buf *);
static void ath_beacon_proc(void *, int);
-static void ath_beacon_stuck_proc(void *, int);
+static void ath_bstuck_proc(void *, int);
static void ath_beacon_free(struct ath_softc *);
static void ath_beacon_config(struct ath_softc *);
static int ath_desc_alloc(struct ath_softc *);
@@ -357,7 +356,7 @@
TASK_INIT(&sc->sc_rxorntask, 0, ath_rxorn_proc, sc);
TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc);
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
- TASK_INIT(&sc->sc_bstucktask, 0, ath_beacon_stuck_proc, sc);
+ TASK_INIT(&sc->sc_bstucktask, 0, ath_bstuck_proc, sc);
/*
* Allocate hardware transmit queues: one queue for
@@ -690,6 +689,15 @@
ath_hal_intrset(ah, 0); /* disable intr's until reset */
taskqueue_enqueue(taskqueue_swi, &sc->sc_rxorntask);
} else {
+ if (status & HAL_INT_SWBA) {
+ /*
+ * Software beacon alert--time to send a beacon.
+ * Handle beacon transmission directly; deferring
+ * this is too slow to meet timing constraints
+ * under load.
+ */
+ ath_beacon_proc(sc, 0);
+ }
if (status & HAL_INT_RXEOL) {
/*
* NB: the hardware should re-read the link when
@@ -708,15 +716,6 @@
taskqueue_enqueue(taskqueue_swi, &sc->sc_rxtask);
if (status & HAL_INT_TX)
taskqueue_enqueue(taskqueue_swi, &sc->sc_txtask);
- if (status & HAL_INT_SWBA) {
- /*
- * Software beacon alert--time to send a beacon.
- * Handle beacon transmission directly; deferring
- * this is too slow to meet timing constraints
- * under load.
- */
- ath_beacon_proc(sc, 0);
- }
if (status & HAL_INT_BMISS) {
sc->sc_stats.ast_bmiss++;
taskqueue_enqueue(taskqueue_swi, &sc->sc_bmisstask);
@@ -1630,79 +1629,6 @@
}
/*
- * Setup the beacon frame. The frame is mapped for DMA
- * and the transmit descriptor is filled in.
- */
-static int
-ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m)
-{
-#define USE_SHPREAMBLE(_ic) \
- (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
- == IEEE80211_F_SHPREAMBLE)
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211_node *ni = bf->bf_node;
- struct ath_hal *ah = sc->sc_ah;
- struct ath_node *an = ATH_NODE(ni);
- struct ath_desc *ds;
- u_int8_t rate;
- int error, flags;
-
- DPRINTF(sc, ATH_DEBUG_BEACON, "%s: m %p len %u\n",
- __func__, m, m->m_len);
-
- error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
- ath_mbuf_load_cb, bf,
- BUS_DMA_NOWAIT);
- if (error != 0) {
- m_freem(m);
- return error;
- }
- KASSERT(bf->bf_nseg == 1,
- ("%s: multi-segment packet; nseg %u", __func__, bf->bf_nseg));
- bf->bf_m = m;
-
- /* setup descriptors */
- ds = bf->bf_desc;
-
- flags = HAL_TXDESC_NOACK;
- if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
- ds->ds_link = bf->bf_daddr; /* self-linked */
- flags |= HAL_TXDESC_VEOL;
- } else
- ds->ds_link = 0;
- ds->ds_data = bf->bf_segs[0].ds_addr;
- /*
- * Calculate rate code.
- * XXX everything at min xmit rate
- */
- if (USE_SHPREAMBLE(ic))
- rate = an->an_tx_mgtratesp;
- else
- rate = an->an_tx_mgtrate;
- ath_hal_setuptxdesc(ah, ds
- , m->m_len + IEEE80211_CRC_LEN /* frame length */
- , sizeof(struct ieee80211_frame)/* header length */
- , HAL_PKT_TYPE_BEACON /* Atheros packet type */
- , ni->ni_txpower /* txpower XXX */
- , rate, 1 /* series 0 rate/tries */
- , HAL_TXKEYIX_INVALID /* no encryption */
- , 0 /* antenna mode */
- , flags /* no ack, veol for beacons */
- , 0 /* rts/cts rate */
- , 0 /* rts/cts duration */
- );
- /* NB: beacon's BufLen must be a multiple of 4 bytes */
- ath_hal_filltxdesc(ah, ds
- , roundup(m->m_len, 4) /* buffer length */
- , AH_TRUE /* first segment */
- , AH_TRUE /* last segment */
- , ds /* first descriptor */
- );
- return 0;
-#undef USE_SHPREAMBLE
-}
-
-/*
* Set the slot time based on the current setting.
*/
static void
@@ -1769,13 +1695,90 @@
sc->sc_stats.ast_be_nombuf++;
return ENOMEM;
}
- bf->bf_node = ni;
- error = ath_beacon_setup(sc, bf, m);
- if (error == 0)
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
+ ath_mbuf_load_cb, bf,
+ BUS_DMA_NOWAIT);
+ if (error == 0) {
bf->bf_m = m;
+ bf->bf_node = ni; /* NB: no held reference */
+ } else {
+ m_freem(m);
+ }
+ return error;
+}
+
+/*
+ * Setup the beacon frame for transmit.
+ */
+static void
+ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
+{
+#define USE_SHPREAMBLE(_ic) \
+ (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
+ == IEEE80211_F_SHPREAMBLE)
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni = bf->bf_node;
+ struct mbuf *m = bf->bf_m;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_desc *ds;
+ int flags, antenna;
+ u_int8_t rate;
+
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: m %p len %u\n",
+ __func__, m, m->m_len);
+
+ /* setup descriptors */
+ ds = bf->bf_desc;
+
+ flags = HAL_TXDESC_NOACK;
+ if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
+ ds->ds_link = bf->bf_daddr; /* self-linked */
+ flags |= HAL_TXDESC_VEOL;
+ /*
+ * Let hardware handle antenna switching.
+ */
+ antenna = 0;
+ } else {
+ ds->ds_link = 0;
+ /*
+ * Switch antenna every 4 beacons.
+ * XXX assumes two antenna
+ */
+ antenna = (sc->sc_stats.ast_be_xmit & 4 ? 2 : 1);
+ }
+
+ KASSERT(bf->bf_nseg == 1,
+ ("multi-segment beacon frame; nseg %u", bf->bf_nseg));
+ ds->ds_data = bf->bf_segs[0].ds_addr;
+ /*
+ * Calculate rate code.
+ * XXX everything at min xmit rate
+ */
+ if (USE_SHPREAMBLE(ic))
+ rate = an->an_tx_mgtratesp;
else
- m_free(m);
- return error;
+ rate = an->an_tx_mgtrate;
+ ath_hal_setuptxdesc(ah, ds
+ , m->m_len + IEEE80211_CRC_LEN /* frame length */
+ , sizeof(struct ieee80211_frame)/* header length */
+ , HAL_PKT_TYPE_BEACON /* Atheros packet type */
+ , ni->ni_txpower /* txpower XXX */
+ , rate, 1 /* series 0 rate/tries */
+ , HAL_TXKEYIX_INVALID /* no encryption */
+ , antenna /* antenna mode */
+ , flags /* no ack, veol for beacons */
+ , 0 /* rts/cts rate */
+ , 0 /* rts/cts duration */
+ );
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ ath_hal_filltxdesc(ah, ds
+ , roundup(m->m_len, 4) /* buffer length */
+ , AH_TRUE /* first segment */
+ , AH_TRUE /* last segment */
+ , ds /* first descriptor */
+ );
+#undef USE_SHPREAMBLE
}
/*
@@ -1791,7 +1794,7 @@
struct ath_buf *bf = sc->sc_bcbuf;
struct ath_hal *ah = sc->sc_ah;
struct mbuf *m;
- int ncabq;
+ int ncabq, error;
DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: pending %u\n",
__func__, pending);
@@ -1803,13 +1806,19 @@
__func__, ic->ic_flags, bf, bf ? bf->bf_m : NULL);
return;
}
+ /*
+ * Check if the previous beacon has gone out. If
+ * not don't don't try to post another, skip this
+ * period and wait for the next. Missed beacons
+ * indicate a problem and should not occur. If we
+ * miss too many consecutive beacons reset the device.
+ */
if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) {
sc->sc_bmisscount++;
DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
"%s: missed %u consecutive beacons\n",
__func__, sc->sc_bmisscount);
- /* XXX reset if too many? */
- if (sc->sc_bmisscount > 3)
+ if (sc->sc_bmisscount > 3) /* NB: 3 is a guess */
taskqueue_enqueue(taskqueue_swi, &sc->sc_bstucktask);
return;
}
@@ -1822,17 +1831,23 @@
/*
* Update dynamic beacon contents. If this returns
- * non-zero then we need to update the descriptor
- * state because the beacon frame changed size
- * (probably because of the TIM bitmap).
+ * non-zero then we need to remap the memory because
+ * the beacon frame changed size (probably because
+ * of the TIM bitmap).
*/
m = bf->bf_m;
ncabq = ath_hal_numtxpending(ah, sc->sc_cabq->axq_qnum);
if (ieee80211_beacon_update(ic, bf->bf_node, &sc->sc_boff, m, ncabq)) {
+ /* XXX too conservative? */
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
- if (ath_beacon_setup(sc, bf, m) != 0) {
- /* XXX statistic */
- return; /* XXX help??? */
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
+ ath_mbuf_load_cb, bf,
+ BUS_DMA_NOWAIT);
+ if (error != 0) {
+ if_printf(ic->ic_ifp,
+ "%s: bus_dmamap_load_mbuf failed, error %u\n",
+ __func__, error);
+ return;
}
}
@@ -1850,13 +1865,19 @@
ath_setslottime(sc); /* commit change to h/w */
/*
+ * Construct tx descriptor.
+ */
+ ath_beacon_setup(sc, bf);
+
+ /*
* Stop any current dma and put the new frame on the queue.
+ * This should never fail since we check above that no frames
+ * are still pending on the queue.
*/
if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) {
DPRINTF(sc, ATH_DEBUG_ANY,
"%s: beacon queue %u did not stop?\n",
__func__, sc->sc_bhalq);
- /* NB: should never happen since we check above? */
}
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
@@ -1871,10 +1892,15 @@
DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
"%s: TXDP[%u] = %p (%p)\n", __func__,
sc->sc_bhalq, (caddr_t)bf->bf_daddr, bf->bf_desc);
+
+ sc->sc_stats.ast_be_xmit++;
}
+/*
+ * Reset the hardware after detecting beacons have stopped.
+ */
static void
-ath_beacon_stuck_proc(void *arg, int pending)
+ath_bstuck_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
struct ifnet *ifp = &sc->sc_if;
==== //depot/projects/wifi/sys/dev/ath/if_athioctl.h#4 (text+ko) ====
@@ -46,6 +46,7 @@
u_int32_t ast_watchdog; /* device reset by watchdog */
u_int32_t ast_hardware; /* fatal hardware error interrupts */
u_int32_t ast_bmiss; /* beacon miss interrupts */
+ u_int32_t ast_bstuck; /* beacon stuck interrupts */
u_int32_t ast_rxorn; /* rx overrun interrupts */
u_int32_t ast_rxeol; /* rx eol interrupts */
u_int32_t ast_txurn; /* tx underrun interrupts */
@@ -90,6 +91,7 @@
u_int32_t ast_rx_ctl; /* rx discarded 'cuz ctl frame */
int8_t ast_tx_rssi; /* tx rssi of last ack */
int8_t ast_rx_rssi; /* rx rssi from histogram */
+ u_int32_t ast_be_xmit; /* beacons transmitted */
u_int32_t ast_be_nombuf; /* beacon setup failed 'cuz no mbuf */
u_int32_t ast_per_cal; /* periodic calibration calls */
u_int32_t ast_per_calfail;/* periodic calibration failed */
More information about the p4-projects
mailing list