From owner-p4-projects@FreeBSD.ORG Fri Jan 30 22:01:53 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 578D516A4D0; Fri, 30 Jan 2004 22:01:53 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2B8BC16A4CE for ; Fri, 30 Jan 2004 22:01:53 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7ACD443D1F for ; Fri, 30 Jan 2004 22:01:50 -0800 (PST) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i0V61o0B005063 for ; Fri, 30 Jan 2004 22:01:50 -0800 (PST) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i0V61nSf005054 for perforce@freebsd.org; Fri, 30 Jan 2004 22:01:50 -0800 (PST) (envelope-from sam@freebsd.org) Date: Fri, 30 Jan 2004 22:01:50 -0800 (PST) Message-Id: <200401310601.i0V61nSf005054@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 46242 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Jan 2004 06:01:53 -0000 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)))