Date: Wed, 14 Sep 2011 03:18:00 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r225545 - user/adrian/if_ath_tx/sys/dev/ath Message-ID: <201109140318.p8E3I1XH008448@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Wed Sep 14 03:18:00 2011 New Revision: 225545 URL: http://svn.freebsd.org/changeset/base/225545 Log: Back out the interrupt handling changes for now. There are issues with this in hostap mode leading to lost TX completion events. I'll likely look at merging in a fixed version of this patch at a later stage. Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c Wed Sep 14 01:46:58 2011 (r225544) +++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c Wed Sep 14 03:18:00 2011 (r225545) @@ -132,7 +132,6 @@ static int ath_media_change(struct ifnet static void ath_watchdog(void *); static int ath_ioctl(struct ifnet *, u_long, caddr_t); static void ath_fatal_proc(void *, int); -static void ath_handle_intr(void *, int); static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); static void ath_key_update_begin(struct ieee80211vap *); @@ -174,10 +173,8 @@ static int ath_tx_setup(struct ath_softc static int ath_wme_update(struct ieee80211com *); static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *); static void ath_tx_cleanup(struct ath_softc *); -#if 0 static void ath_tx_proc_q0(void *, int); static void ath_tx_proc_q0123(void *, int); -#endif static void ath_tx_proc(void *, int); static int ath_chan_set(struct ath_softc *, struct ieee80211_channel *); static void ath_draintxq(struct ath_softc *); @@ -393,15 +390,14 @@ ath_attach(u_int16_t devid, struct ath_s ATH_TXBUF_LOCK_INIT(sc); - sc->sc_tq = taskqueue_create_fast("ath_taskq", M_NOWAIT, + sc->sc_tq = taskqueue_create("ath_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->sc_tq); taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", ifp->if_xname); + TASK_INIT(&sc->sc_rxtask, 0, ath_rx_proc, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc); - TASK_INIT(&sc->sc_intrtask, 0, ath_handle_intr, sc); - TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc); /* * Allocate hardware transmit queues: one queue for @@ -450,6 +446,23 @@ ath_attach(u_int16_t devid, struct ath_s } /* + * Special case certain configurations. Note the + * CAB queue is handled by these specially so don't + * include them when checking the txq setup mask. + */ + switch (sc->sc_txqsetup &~ (1<<sc->sc_cabq->axq_qnum)) { + case 0x01: + TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0, sc); + break; + case 0x0f: + TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0123, sc); + break; + default: + TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc, sc); + break; + } + + /* * Setup rate control. Some rate control modules * call back to change the anntena state so expose * the necessary entry points. @@ -1332,65 +1345,6 @@ ath_shutdown(struct ath_softc *sc) } /* - * Do deferred interrupt processing; then re-enable interrupts - * if required. - */ -static void -ath_handle_intr(void *arg, int npending) -{ - struct ath_softc *sc = (struct ath_softc *) arg; - HAL_INT status; - struct ath_hal *ah = sc->sc_ah; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_invalid) { - /* - * The hardware is not ready/present, don't touch anything. - * Note this can happen early on if the IRQ is shared. - */ - DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid; ignored\n", __func__); - return; - } - - /* - * Fetch the current interrupt status from the interrupt - * handler. It's assumed that any interrupt which would lead - * us here won't happen until the interrupt is cleared. - * - * XXX Thus I'm not using a lock just yet. - */ - status = sc->sc_intrstatus; - - if (status & HAL_INT_FATAL) { - ath_hal_intrset(ah, 0); /* disable intr's until reset */ - ath_fatal_proc(sc, 0); - return; - } - - if (status & (HAL_INT_RXEOL | HAL_INT_RX)) { - ath_rx_proc(sc, 1); - /* XXX this may reset the hardware? Should handle that! */ - } - if (status & HAL_INT_TXURN) { - /* bump tx trigger level */ - ath_hal_updatetxtriglevel(ah, AH_TRUE); - } - if (status & HAL_INT_TX) { - ath_tx_proc(sc, 1); - } - - /* - * If TX or RX occured, call ath_start() if the interface - * can grab some packets. - */ - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - ath_start(ifp); - - /* re-enable interrupts */ - ath_hal_intrset(sc->sc_ah, sc->sc_imask); -} - -/* * Interrupt handler. Most of the actual processing is deferred. */ void @@ -1400,7 +1354,6 @@ ath_intr(void *arg) struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; HAL_INT status = 0; - int sched = 0; if (sc->sc_invalid) { /* @@ -1436,12 +1389,10 @@ ath_intr(void *arg) if (status == 0x0) return; - /* XXX locking? */ - sc->sc_intrstatus = status; - if (status & HAL_INT_FATAL) { sc->sc_stats.ast_hardware++; - sched = 1; + ath_hal_intrset(ah, 0); /* disable intr's until reset */ + ath_fatal_proc(sc, 0); } else { if (status & HAL_INT_SWBA) { /* @@ -1471,12 +1422,12 @@ ath_intr(void *arg) * traffic so any frames held on the staging * queue are aged and potentially flushed. */ - /* XXX there's no longer an rxtask? How to force? */ - taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_rxtask); + taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); #endif } } if (status & HAL_INT_RXEOL) { + int imask = sc->sc_imask; /* * NB: the hardware should re-read the link when * RXE bit is written, but it doesn't work at @@ -1492,27 +1443,33 @@ ath_intr(void *arg) * by a call to ath_reset() somehow, the * interrupt mask will be correctly reprogrammed. */ - /* XXX this is already reset in the sched call below */ + imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); + ath_hal_intrset(ah, imask); + /* + * Enqueue an RX proc, to handled whatever + * is in the RX queue. + * This will then kick the PCU. + */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); sc->sc_rxlink = NULL; sc->sc_kickpcu = 1; - sched = 1; } if (status & HAL_INT_TXURN) { sc->sc_stats.ast_txurn++; /* bump tx trigger level */ - sched = 1; + ath_hal_updatetxtriglevel(ah, AH_TRUE); } if (status & HAL_INT_RX) { sc->sc_stats.ast_rx_intr++; - sched = 1; + taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); } if (status & HAL_INT_TX) { sc->sc_stats.ast_tx_intr++; - sched = 1; + taskqueue_enqueue(sc->sc_tq, &sc->sc_txtask); } if (status & HAL_INT_BMISS) { sc->sc_stats.ast_bmiss++; - taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_bmisstask); + taskqueue_enqueue(sc->sc_tq, &sc->sc_bmisstask); } if (status & HAL_INT_GTT) sc->sc_stats.ast_tx_timeout++; @@ -1537,19 +1494,6 @@ ath_intr(void *arg) sc->sc_stats.ast_rxorn++; } } - - /* - * If any of the above checks require an ISR schedule, - * enqueue the task and disable interrupts. - * - * Since beacon handling is done in interrupt context at the - * moment, always leave that enabled. - */ - if (sched == 1) { - ath_hal_intrset(ah, - (sc->sc_imask & (HAL_INT_SWBA | HAL_INT_GLOBAL))); - taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_intrtask); - } } static void @@ -1882,9 +1826,6 @@ ath_reset(struct ifnet *ifp) } ath_hal_intrset(ah, sc->sc_imask); - /* - * XXX should this be done in-line? - */ ath_start(ifp); /* restart xmit */ return 0; } @@ -4009,20 +3950,23 @@ rx_next: * XXX kick the PCU again to continue RXing? */ ath_stoprecv(sc); + sc->sc_imask |= (HAL_INT_RXEOL | HAL_INT_RXORN); if (ath_startrecv(sc) != 0) { if_printf(ifp, "%s: couldn't restart RX after RXEOL; resetting\n", __func__); - /* XXX this must be scheduled! */ ath_reset(ifp); return; } + ath_hal_intrset(ah, sc->sc_imask); } if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_ff_age_all(ic, 100); #endif + if (!IFQ_IS_EMPTY(&ifp->if_snd)) + ath_start(ifp); } #undef PA2DESC } @@ -4497,7 +4441,6 @@ ath_tx_processq(struct ath_softc *sc, st return nacked; } -#if 0 static __inline int txqactive(struct ath_hal *ah, int qnum) { @@ -4566,7 +4509,6 @@ ath_tx_proc_q0123(void *arg, int npendin ath_start(ifp); } -#endif /* * Deferred processing of transmit interrupt. @@ -4577,19 +4519,13 @@ ath_tx_proc(void *arg, int npending) struct ath_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; int i, nacked; - u_int32_t txqs = (1 << HAL_NUM_TX_QUEUES) - 1; - - /* - * Just grab the status of all TX queues. - */ - ath_hal_gettxintrtxqs(sc->sc_ah, &txqs); /* * Process each active queue. */ nacked = 0; for (i = 0; i < HAL_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i) && (txqs & (1 << i))) + if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i)) nacked += ath_tx_processq(sc, &sc->sc_txq[i]); if (nacked) sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah); Modified: user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Wed Sep 14 01:46:58 2011 (r225544) +++ user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Wed Sep 14 03:18:00 2011 (r225545) @@ -411,7 +411,6 @@ struct ath_softc { u_int sc_fftxqmax; /* max frames before drop */ u_int sc_txantenna; /* tx antenna (fixed or auto) */ HAL_INT sc_imask; /* interrupt mask copy */ - HAL_INT sc_intrstatus; /* current interrupt status */ u_int sc_keymax; /* size of key cache */ u_int8_t sc_keymap[ATH_KEYBYTES];/* key use bit map */ @@ -430,6 +429,7 @@ struct ath_softc { ath_bufhead sc_rxbuf; /* receive buffer */ struct mbuf *sc_rxpending; /* pending receive data */ u_int32_t *sc_rxlink; /* link ptr in last RX desc */ + struct task sc_rxtask; /* rx int processing */ u_int8_t sc_defant; /* current default antenna */ u_int8_t sc_rxotherant; /* rx's on non-default antenna*/ u_int64_t sc_lastrx; /* tsf at last rx'd frame */ @@ -446,6 +446,7 @@ struct ath_softc { u_int sc_txintrperiod;/* tx interrupt batching */ struct ath_txq sc_txq[HAL_NUM_TX_QUEUES]; struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ + struct task sc_txtask; /* tx int processing */ int sc_wd_timer; /* count down for wd timer */ struct callout sc_wd_ch; /* tx watchdog timer */ struct ath_tx_radiotap_header sc_tx_th; @@ -459,8 +460,6 @@ struct ath_softc { struct ath_txq *sc_cabq; /* tx q for cab frames */ struct task sc_bmisstask; /* bmiss int processing */ struct task sc_bstucktask; /* stuck beacon processing */ - struct task sc_intrtask; /* deferred interrupt processing */ - struct task sc_fataltask; /* deferred reset processing */ enum { OK, /* no change needed */ UPDATE, /* update pending */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201109140318.p8E3I1XH008448>