PERFORCE change 46242 for review
Sam Leffler
sam at FreeBSD.org
Fri Jan 30 22:01:53 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=46242
Change 46242 by sam at 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)))
More information about the p4-projects
mailing list