Date: Tue, 30 Nov 2004 18:02:05 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 66116 for review Message-ID: <200411301802.iAUI25Ur010661@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=66116 Change 66116 by sam@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411301802.iAUI25Ur010661>