PERFORCE change 135771 for review

Sam Leffler sam at FreeBSD.org
Wed Feb 20 04:12:11 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=135771

Change 135771 by sam at sam_ebb on 2008/02/20 04:11:48

	Make a lame attempt at locking vap create/delete; we can't
	do this properly because there are lots of calls deep below
	us that do malloc(M_WAITOK).

Affected files ...

.. //depot/projects/vap/sys/dev/ath/if_ath.c#30 edit

Differences ...

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

@@ -741,15 +741,17 @@
 	uint8_t mac[IEEE80211_ADDR_LEN];
 	int ic_opmode, needbeacon;
 
+	avp = (struct ath_vap *) malloc(sizeof(struct ath_vap),
+	    M_80211_VAP, M_WAITOK | M_ZERO);
 	needbeacon = 0;
 	IEEE80211_ADDR_COPY(mac, mac0);
 
-	/* XXX ic unlocked and race against add? */
+	ATH_LOCK(sc);
 	switch (opmode) {
 	case IEEE80211_M_STA:
 		if (sc->sc_nstavaps != 0) {	/* XXX only 1 sta for now */
 			device_printf(sc->sc_dev, "only 1 sta vap supported\n");
-			return NULL;
+			goto bad;
 		}
 		if (sc->sc_nvaps) {
 			/*
@@ -768,7 +770,7 @@
 		if (sc->sc_nvaps != 0) {	/* XXX only 1 for now */
 			device_printf(sc->sc_dev,
 			    "only 1 ibss vap supported\n");
-			return NULL;
+			goto bad;
 		}
 		ic_opmode = opmode;
 		needbeacon = 1;
@@ -789,7 +791,7 @@
 		if (sc->sc_nvaps && ic->ic_opmode == IEEE80211_M_STA) {
 			device_printf(sc->sc_dev,
 			    "wds not supported in sta mode\n");
-			return NULL;
+			goto bad;
 		}
 		if (opmode == IEEE80211_M_WDS) {
 			/*
@@ -803,29 +805,26 @@
 		break;
 	default:
 		device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
-		return NULL;
+		goto bad;
 	}
 	/*
 	 * Check that a beacon buffer is available; the code below assumes it.
 	 */
 	if (needbeacon & STAILQ_EMPTY(&sc->sc_bbuf)) {
 		device_printf(sc->sc_dev, "no beacon buffer available\n");
-		return NULL;
+		goto bad;
 	}
 
-	avp = (struct ath_vap *) malloc(sizeof(struct ath_vap),
-	    M_80211_VAP, M_NOWAIT | M_ZERO);
-	if (avp == NULL) {
-		device_printf(sc->sc_dev, "unable to allocate memory\n");
-		return NULL;
-	}
-
 	/* STA, AHDEMO? */
 	if (opmode == IEEE80211_M_HOSTAP)
 		assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
 
 	vap = &avp->av_vap;
+	/* XXX can't hold mutex across if_alloc */
+	ATH_UNLOCK(sc);
+	/* XXX check return */
 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+	ATH_LOCK(sc);
 
 	/* h/w crypto support */
 	vap->iv_key_alloc = ath_key_alloc;
@@ -875,8 +874,6 @@
 		STAILQ_INIT(&avp->av_mcastq.axq_q);
 		ATH_TXQ_LOCK_INIT(sc, &avp->av_mcastq);
 	}
-	/* complete setup */
-	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
 
 	ic->ic_opmode = ic_opmode;
 	if (opmode != IEEE80211_M_WDS)
@@ -899,14 +896,22 @@
 		/* XXX should not happen */
 		break;
 	}
-
 	if (sc->sc_hastsfadd) {
 		/*
 		 * Configure whether or not TSF adjust should be done.
 		 */
 		ath_hal_settsfadjust(sc->sc_ah, sc->sc_stagbeacons);
 	}
+	ATH_UNLOCK(sc);
+
+	/* complete setup */
+	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
 	return vap;
+bad:
+	/* XXX can leak ic->ic_ifp */
+	free(avp, M_80211_VAP);
+	ATH_UNLOCK(sc);
+	return NULL;
 }
 
 static void
@@ -930,6 +935,7 @@
 	}
 
 	ieee80211_vap_detach(vap);
+	ATH_LOCK(sc);
 	/*
 	 * Reclaim beacon state.  Note this must be done before
 	 * the vap instance is reclaimed as we may have a reference
@@ -965,6 +971,7 @@
 	}
 	if (vap->iv_opmode != IEEE80211_M_WDS)
 		sc->sc_nvaps--;
+	ATH_UNLOCK(sc);
 	free(avp, M_80211_VAP);
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {


More information about the p4-projects mailing list