Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 May 2014 08:12:21 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r265350 - head/sys/dev/ath
Message-ID:  <201405050812.s458CLXZ054608@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Mon May  5 08:12:21 2014
New Revision: 265350
URL: http://svnweb.freebsd.org/changeset/base/265350

Log:
  Break out the multicast programming into its own hardware specific
  call, which assumes the hardware is awake.
  
  Turn ath_update_mcast() into a routine that's only called from the
  net80211 layer - and it forces the hardware awake first.
  
  This fixes a LOR from the EDMA RX path which calls ath_mode_init()
  with the RX lock held - the driver lock can't also be grabbed.
  This path assumes that the ath_mode_init() callers all wake up
  the NIC first.
  
  Tested:
  
  * AR9485, STA mode, powersave

Modified:
  head/sys/dev/ath/if_ath.c

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Mon May  5 08:00:50 2014	(r265349)
+++ head/sys/dev/ath/if_ath.c	Mon May  5 08:12:21 2014	(r265350)
@@ -165,6 +165,7 @@ static void	ath_bmiss_vap(struct ieee802
 static void	ath_bmiss_proc(void *, int);
 static void	ath_key_update_begin(struct ieee80211vap *);
 static void	ath_key_update_end(struct ieee80211vap *);
+static void	ath_update_mcast_hw(struct ath_softc *);
 static void	ath_update_mcast(struct ifnet *);
 static void	ath_update_promisc(struct ifnet *);
 static void	ath_updateslot(struct ifnet *);
@@ -3379,10 +3380,15 @@ ath_update_promisc(struct ifnet *ifp)
 	DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt);
 }
 
+/*
+ * Driver-internal mcast update call.
+ *
+ * Assumes the hardware is already awake.
+ */
 static void
-ath_update_mcast(struct ifnet *ifp)
+ath_update_mcast_hw(struct ath_softc *sc)
 {
-	struct ath_softc *sc = ifp->if_softc;
+	struct ifnet *ifp = sc->sc_ifp;
 	u_int32_t mfilt[2];
 
 	/* calculate and install multicast filter */
@@ -3410,13 +3416,31 @@ ath_update_mcast(struct ifnet *ifp)
 		if_maddr_runlock(ifp);
 	} else
 		mfilt[0] = mfilt[1] = ~0;
+
+	ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
+
+	DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n",
+		__func__, mfilt[0], mfilt[1]);
+}
+
+/*
+ * Called from the net80211 layer - force the hardware
+ * awake before operating.
+ */
+static void
+ath_update_mcast(struct ifnet *ifp)
+{
+	struct ath_softc *sc = ifp->if_softc;
+
 	ATH_LOCK(sc);
 	ath_power_set_power_state(sc, HAL_PM_AWAKE);
-	ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
+	ATH_UNLOCK(sc);
+
+	ath_update_mcast_hw(sc);
+
+	ATH_LOCK(sc);
 	ath_power_restore_power_state(sc);
 	ATH_UNLOCK(sc);
-	DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n",
-		__func__, mfilt[0], mfilt[1]);
 }
 
 void
@@ -3444,7 +3468,7 @@ ath_mode_init(struct ath_softc *sc)
 	ath_hal_setmac(ah, IF_LLADDR(ifp));
 
 	/* calculate and install multicast filter */
-	ath_update_mcast(ifp);
+	ath_update_mcast_hw(sc);
 }
 
 /*



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