svn commit: r225545 - user/adrian/if_ath_tx/sys/dev/ath
Adrian Chadd
adrian at FreeBSD.org
Wed Sep 14 03:18:01 UTC 2011
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 */
More information about the svn-src-user
mailing list