Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Jan 2004 22:01:50 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 46242 for review
Message-ID:  <200401310601.i0V61nSf005054@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=46242

Change 46242 by sam@sam_ebb on 2004/01/30 22:01:27

	o revamp beacon handling to do dynamic updates required for
	  11g and pspoll (dtim)
	o set slot time correctly (for 11g)

Affected files ...

.. //depot/projects/netperf+sockets/sys/dev/ath/if_ath.c#20 edit
.. //depot/projects/netperf+sockets/sys/dev/ath/if_athvar.h#6 edit

Differences ...

==== //depot/projects/netperf+sockets/sys/dev/ath/if_ath.c#20 (text+ko) ====

@@ -1116,48 +1116,31 @@
 	bcopy(seg, bf->bf_segs, nseg * sizeof (seg[0]));
 }
 
+/*
+ * Setup the beacon frame.  The frame is mapped for DMA
+ * and the transmit descriptor is filled in.
+ */
 static int
-ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
+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 ath_hal *ah = sc->sc_ah;
-	struct ath_node *an = ATH_NODE(ni);
-	struct ath_buf *bf;
+	struct ath_node *an = ATH_NODE(bf->bf_node);
 	struct ath_desc *ds;
-	struct mbuf *m;
 	int error;
 	u_int8_t rate;
 
-	bf = sc->sc_bcbuf;
-	if (bf->bf_m != NULL) {
-		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
-		m_freem(bf->bf_m);
-		bf->bf_m = NULL;
-		bf->bf_node = NULL;
-	}
-	/*
-	 * NB: the beacon data buffer must be 32-bit aligned;
-	 * we assume the mbuf routines will return us something
-	 * with this alignment (perhaps should assert).
-	 */
-	m = ieee80211_beacon_alloc(ic, ni);
-	if (m == NULL) {
-		DPRINTF(ATH_DEBUG_BEACON, ("%s: cannot get mbuf/cluster\n",
-			__func__));
-		sc->sc_stats.ast_be_nombuf++;
-		return ENOMEM;
-	}
 	DPRINTF(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);
+	if (error != 0)
 		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;
@@ -1168,7 +1151,7 @@
 	 * Calculate rate code.
 	 * XXX everything at min xmit rate
 	 */
-	if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+	if (USE_SHPREAMBLE(ic))
 		rate = an->an_tx_mgtratesp;
 	else
 		rate = an->an_tx_mgtrate;
@@ -1191,16 +1174,78 @@
 		, AH_TRUE				/* first segment */
 		, AH_TRUE				/* last segment */
 	);
+	return 0;
+#undef USE_SHPREAMBLE
+}
 
-	return 0;
+/*
+ * Set the slot time based on the current setting.
+ */
+static void
+ath_setslottime(struct ath_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ath_hal *ah = sc->sc_ah;
+
+	if (ic->ic_flags & IEEE80211_F_SHSLOT)
+		ath_hal_setslottime(ah, HAL_SLOT_TIME_9);
+	else
+		ath_hal_setslottime(ah, HAL_SLOT_TIME_20);
+	sc->sc_icflags = ic->ic_flags;
+}
+
+/*
+ * Allocate and setup an initial beacon frame.
+ */
+static int
+ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ath_buf *bf;
+	struct mbuf *m;
+	int error;
+
+	bf = sc->sc_bcbuf;
+	if (bf->bf_m != NULL) {
+		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+		m_freem(bf->bf_m);
+		bf->bf_m = NULL;
+		bf->bf_node = NULL;
+	}
+	/*
+	 * NB: the beacon data buffer must be 32-bit aligned;
+	 * we assume the mbuf routines will return us something
+	 * with this alignment (perhaps should assert).
+	 */
+	m = ieee80211_beacon_alloc(ic, ni, &sc->sc_boff);
+	if (m == NULL) {
+		DPRINTF(ATH_DEBUG_BEACON, ("%s: cannot get mbuf/cluster\n",
+			__func__));
+		sc->sc_stats.ast_be_nombuf++;
+		return ENOMEM;
+	}
+	bf->bf_node = ni;
+	error = ath_beacon_setup(sc, bf, m);
+	if (error == 0)
+		bf->bf_m = m;
+	else
+		m_freem(m);
+	ath_setslottime(sc);		/* initialize slot time state */
+	return error;
 }
 
+/*
+ * Transmit a beacon frame at SWBA.  Dynamic updates to the
+ * frame contents are done as needed and the slot time is
+ * also adjusted based on current state.
+ */
 static void
 ath_beacon_proc(struct ath_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ath_buf *bf = sc->sc_bcbuf;
 	struct ath_hal *ah = sc->sc_ah;
+	struct mbuf *m;
 
 	DPRINTF(ATH_DEBUG_BEACON_PROC, ("%s\n", __func__));
 	if (ic->ic_opmode == IEEE80211_M_STA ||
@@ -1209,7 +1254,34 @@
 			__func__, ic->ic_flags, bf, bf ? bf->bf_m : NULL));
 		return;
 	}
-	/* TODO: update beacon to reflect PS poll state */
+
+	/*
+	 * Update dynamic beacon contents.  If this returns non-zero
+	 * then we need to update the descriptor state because the
+	 * beacon frame changed size and/or was re-allocated.
+	 */
+	m = bf->bf_m;
+	if (ieee80211_beacon_update(ic, bf->bf_node, &sc->sc_boff, &m)) {
+		/* NB: the old mbuf is free'd */
+		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+		bf->bf_m = NULL;
+		if (ath_beacon_setup(sc, bf, m) != 0) {
+			m_freem(m);
+			/* XXX statistic */
+			return;		/* XXX??? */
+		}
+		bf->bf_m = m;
+	}
+
+	/*
+	 * Check for slot time change.
+	 */
+	if ((ic->ic_flags ^ sc->sc_icflags) & IEEE80211_F_SHSLOT)
+		ath_setslottime(sc);
+
+	/*
+	 * Stop any current dma and put the new frame on the queue.
+	 */
 	if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) {
 		DPRINTF(ATH_DEBUG_ANY, ("%s: beacon queue %u did not stop?\n",
 			__func__, sc->sc_bhalq));
@@ -1224,6 +1296,9 @@
 		sc->sc_bhalq, (caddr_t)bf->bf_daddr, bf->bf_desc));
 }
 
+/*
+ * Reclaim beacon resources.
+ */
 static void
 ath_beacon_free(struct ath_softc *sc)
 {
@@ -1839,7 +1914,8 @@
 	struct ifnet *ifp = &sc->sc_if;
 	struct ath_hal *ah = sc->sc_ah;
 	int i, error, iswep, hdrlen, pktlen, try0;
-	u_int8_t rix, cix, txrate, ctsrate;
+	u_int8_t rix, txrate, ctsrate;
+	u_int8_t cix = 0xff;		/* NB: silence compiler */
 	struct ath_desc *ds;
 	struct mbuf *m;
 	struct ieee80211_frame *wh;
@@ -2037,10 +2113,26 @@
 		sc->sc_stats.ast_tx_noack++;
 	} else if (pktlen > ic->ic_rtsthreshold) {
 		flags |= HAL_TXDESC_RTSENA;	/* RTS based on frame length */
+		cix = rt->info[rix].controlRate;
 		sc->sc_stats.ast_tx_rts++;
 	}
 
 	/*
+	 * Determine whether to use RTS/CTS or just CTS for
+	 * 802.11g protection.
+	 * XXX use only before transmitting OFDM, not CCK.
+	 */
+	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+	    (ni->ni_flags & IEEE80211_NODE_ERP)) {
+		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+			flags |= HAL_TXDESC_RTSENA;
+		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+			flags |= HAL_TXDESC_CTSENA;
+		cix = rt->info[sc->sc_protrix].controlRate;
+		/* XXX statistics */
+	}
+
+	/*
 	 * Calculate duration.  This logically belongs in the 802.11
 	 * layer but it lacks sufficient information to calculate it.
 	 */
@@ -2060,12 +2152,14 @@
 	 */
 	ctsduration = 0;
 	if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
+		/* XXX optimize a la data transmit rate */
 		/*
 		 * CTS transmit rate is derived from the transmit rate
 		 * by looking in the h/w rate table.  We must also factor
 		 * in whether or not a short preamble is to be used.
 		 */
-		cix = rt->info[rix].controlRate;
+		/* NB: cix is set above where RTS/CTS is enabled */
+		KASSERT(cix != 0xff, ("cix not setup"));
 		ctsrate = rt->info[cix].rateCode;
 		if (shortPreamble)
 			ctsrate |= rt->info[cix].shortPreamble;
@@ -2796,6 +2890,12 @@
 	}
 	sc->sc_currates = rt;
 	sc->sc_curmode = mode;
+	/*
+	 * All protection frames are transmited at 2Mb/s for
+	 * 11g, otherwise at 1Mb/s.
+	 * XXX select protection rate index from rate table.
+	 */
+	sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0);
 	/* NB: caller is responsible for reseting rate control state */
 }
 

==== //depot/projects/netperf+sockets/sys/dev/ath/if_athvar.h#6 (text+ko) ====

@@ -121,7 +121,9 @@
 	enum ieee80211_phymode	sc_curmode;	/* current phy mode */
 	u_int8_t		sc_rixmap[256];	/* IEEE to h/w rate table ix */
 	u_int8_t		sc_hwmap[32];	/* h/w rate ix to IEEE table */
+	u_int8_t		sc_protrix;	/* protection rate index */
 	HAL_INT			sc_imask;	/* interrupt mask copy */
+	u_int32_t		sc_icflags;	/* shadow of ic_flags */
 
 	struct bpf_if		*sc_drvbpf;
 	union {
@@ -158,6 +160,7 @@
 	u_int			sc_bhalq;	/* HAL q for outgoing beacons */
 	struct ath_buf		*sc_bcbuf;	/* beacon buffer */
 	struct ath_buf		*sc_bufptr;	/* allocated buffer ptr */
+	struct ieee80211_beacon_offsets sc_boff;/* dynamic update state */
 	struct task		sc_bmisstask;	/* bmiss int processing */
 
 	struct callout		sc_cal_ch;	/* callout handle for cals */
@@ -303,6 +306,8 @@
 	((*(_ah)->ah_getRfGain)((_ah)))
 #define	ath_hal_rxmonitor(_ah) \
 	((*(_ah)->ah_rxMonitor)((_ah)))
+#define	ath_hal_setslottime(_ah, _us) \
+	((*(_ah)->ah_setSlotTime)((_ah), (_us)))
 
 #define	ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
 	((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401310601.i0V61nSf005054>