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