Skip site navigation (1)Skip section navigation (2)
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>