Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Oct 2004 05:36:41 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 63621 for review
Message-ID:  <200410240536.i9O5afJs067959@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=63621

Change 63621 by sam@sam_ebb on 2004/10/24 05:36:39

	o put the chip in full sleep only when suspending, detaching, or
	  otherwise bringing the device to a complete stop (e.g. not when
	  changing channels); this fixes a race condition where the chip
	  might be put to sleep then immediately followed by a read of a
	  register in the PCI clock domain--which would lock the bus
	o improve radio revision printing; only display radio rev when
	  the hardware is really there and print an unadorned rev when
	  the radio is multi-band
	o move the WME<->h/w tx queue mapping prints to bootverbose

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#3 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#3 (text+ko) ====

@@ -94,6 +94,7 @@
 	  (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
 
 static void	ath_init(void *);
+static void	ath_stop_locked(struct ifnet *);
 static void	ath_stop(struct ifnet *);
 static void	ath_start(struct ifnet *);
 static int	ath_reset(struct ifnet *);
@@ -778,7 +779,7 @@
 	 * Stop anything previously setup.  This is safe
 	 * whether this is the first time through or not.
 	 */
-	ath_stop(ifp);
+	ath_stop_locked(ifp);
 
 	/*
 	 * The basic interface to setting the hardware in a good
@@ -845,7 +846,7 @@
 }
 
 static void
-ath_stop(struct ifnet *ifp)
+ath_stop_locked(struct ifnet *ifp)
 {
 	struct ath_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -854,7 +855,7 @@
 	DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
 		__func__, sc->sc_invalid, ifp->if_flags);
 
-	ATH_LOCK(sc);
+	ATH_LOCK_ASSERT(sc);
 	if (ifp->if_flags & IFF_RUNNING) {
 		/*
 		 * Shutdown the hardware and driver:
@@ -887,8 +888,27 @@
 			sc->sc_rxlink = NULL;
 		IFQ_DRV_PURGE(&ifp->if_snd);
 		ath_beacon_free(sc);
-		if (!sc->sc_invalid)
-			ath_hal_setpower(ah, HAL_PM_FULL_SLEEP, 0);
+	}
+}
+
+static void
+ath_stop(struct ifnet *ifp)
+{
+	struct ath_softc *sc = ifp->if_softc;
+
+	ATH_LOCK(sc);
+	ath_stop_locked(ifp);
+	if (!sc->sc_invalid) {
+		/*
+		 * Set the chip in full sleep mode.  Note that we are
+		 * careful to do this only when bringing the interface
+		 * completely to a stop.  When the chip is in this state
+		 * it must be carefully woken up or references to
+		 * registers in the PCI clock domain may freeze the bus
+		 * (and system).  This varies by chip and is mostly an
+		 * issue with newer parts that go to sleep more quickly.
+		 */
+		ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP, 0);
 	}
 	ATH_UNLOCK(sc);
 }
@@ -3775,7 +3795,7 @@
 			if (!sc->sc_invalid)
 				ath_init(ifp);	/* XXX lose error */
 		} else
-			ath_stop(ifp);
+			ath_stop_locked(ifp);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
@@ -3988,23 +4008,42 @@
 static void
 ath_announce(struct ath_softc *sc)
 {
+#define	HAL_MODE_DUALBAND	(HAL_MODE_11A|HAL_MODE_11B)
 	struct ifnet *ifp = &sc->sc_if;
 	struct ath_hal *ah = sc->sc_ah;
-	int i;
+	u_int modes, cc;
 
 	if_printf(ifp, "mac %d.%d phy %d.%d",
 		ah->ah_macVersion, ah->ah_macRev,
 		ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
-	if (ah->ah_analog5GhzRev)
-		printf(" 5ghz radio %d.%d",
-			ah->ah_analog5GhzRev >> 4, ah->ah_analog5GhzRev & 0xf);
-	if (ah->ah_analog2GhzRev)
-		printf(" 2ghz radio %d.%d",
-			ah->ah_analog2GhzRev >> 4, ah->ah_analog2GhzRev & 0xf);
+	/*
+	 * Print radio revision(s).  We check the wireless modes
+	 * to avoid falsely printing revs for inoperable parts.
+	 * Dual-band radio revs are returned in the 5Ghz rev number.
+	 */
+	ath_hal_getcountrycode(ah, &cc);
+	modes = ath_hal_getwirelessmodes(ah, cc);
+	if ((modes & HAL_MODE_DUALBAND) == HAL_MODE_DUALBAND) {
+		if (ah->ah_analog5GhzRev && ah->ah_analog2GhzRev)
+			printf(" 5ghz radio %d.%d 2ghz radio %d.%d",
+				ah->ah_analog5GhzRev >> 4,
+				ah->ah_analog5GhzRev & 0xf,
+				ah->ah_analog2GhzRev >> 4,
+				ah->ah_analog2GhzRev & 0xf);
+		else
+			printf(" radio %d.%d", ah->ah_analog5GhzRev >> 4,
+				ah->ah_analog5GhzRev & 0xf);
+	} else
+		printf(" radio %d.%d", ah->ah_analog5GhzRev >> 4,
+			ah->ah_analog5GhzRev & 0xf);
 	printf("\n");
-	for (i = 0; i <= WME_AC_VO; i++) {
-		struct ath_txq *txq = sc->sc_ac2q[i];
-		if_printf(ifp, "Use hw queue %u for %s traffic\n",
-			txq->axq_qnum, acnames[i]);
+	if (bootverbose) {
+		int i;
+		for (i = 0; i <= WME_AC_VO; i++) {
+			struct ath_txq *txq = sc->sc_ac2q[i];
+			if_printf(ifp, "Use hw queue %u for %s traffic\n",
+				txq->axq_qnum, acnames[i]);
+		}
 	}
+#undef HAL_MODE_DUALBAND
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200410240536.i9O5afJs067959>