Module Name:    src
Committed By:   christos
Date:           Sun Jan 20 20:21:58 UTC 2013

Modified Files:
        src/sys/dev/usb: if_urtwn.c if_urtwnreg.h if_urtwnvar.h

Log Message:
more (and less) locking fixes


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/usb/if_urtwn.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/usb/if_urtwnreg.h
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/usb/if_urtwnvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/if_urtwn.c
diff -u src/sys/dev/usb/if_urtwn.c:1.11 src/sys/dev/usb/if_urtwn.c:1.12
--- src/sys/dev/usb/if_urtwn.c:1.11	Fri Jan 18 08:45:51 2013
+++ src/sys/dev/usb/if_urtwn.c	Sun Jan 20 15:21:57 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urtwn.c,v 1.11 2013/01/18 13:45:51 jmcneill Exp $	*/
+/*	$NetBSD: if_urtwn.c,v 1.12 2013/01/20 20:21:57 christos Exp $	*/
 /*	$OpenBSD: if_urtwn.c,v 1.20 2011/11/26 06:39:33 ckuethe Exp $	*/
 
 /*-
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.11 2013/01/18 13:45:51 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.12 2013/01/20 20:21:57 christos Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -74,6 +74,12 @@ __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v
 #include <dev/usb/if_urtwnvar.h>
 #include <dev/usb/if_urtwn_data.h>
 
+/*
+ * The sc_write_mtx locking is to prevent sequences of writes from
+ * being intermingled with each other.  I don't know if this is really
+ * needed.  I have added it just to be on the safe side.
+ */
+
 #ifdef URTWN_DEBUG
 #define	DBG_INIT	__BIT(0)
 #define	DBG_FN		__BIT(1)
@@ -168,17 +174,31 @@ static void	urtwn_do_async(struct urtwn_
 static void	urtwn_wait_async(struct urtwn_softc *);
 static int	urtwn_write_region_1(struct urtwn_softc *, uint16_t, uint8_t *,
 		    int);
+static void	urtwn_write_1(struct urtwn_softc *, uint16_t, uint8_t);
+static void	urtwn_write_2(struct urtwn_softc *, uint16_t, uint16_t);
+static void	urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t);
+static int	urtwn_write_region(struct urtwn_softc *, uint16_t, uint8_t *,
+		    int);
 static int	urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *,
 		    int);
+static uint8_t	urtwn_read_1(struct urtwn_softc *, uint16_t);
+static uint16_t	urtwn_read_2(struct urtwn_softc *, uint16_t);
+static uint32_t	urtwn_read_4(struct urtwn_softc *, uint16_t);
 static int	urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int);
+static void	urtwn_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t);
 static uint32_t	urtwn_rf_read(struct urtwn_softc *, int, uint8_t);
 static int	urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t);
 static uint8_t	urtwn_efuse_read_1(struct urtwn_softc *, uint16_t);
 static void	urtwn_efuse_read(struct urtwn_softc *);
 static int	urtwn_read_chipid(struct urtwn_softc *);
+#ifdef URTWN_DEBUG
+static void	urtwn_dump_rom(struct urtwn_softc *, struct r92c_rom *);
+#endif
 static void	urtwn_read_rom(struct urtwn_softc *);
 static int	urtwn_media_change(struct ifnet *);
 static int	urtwn_ra_init(struct urtwn_softc *);
+static int	urtwn_get_nettype(struct urtwn_softc *);
+static void	urtwn_set_nettype0_msr(struct urtwn_softc *, uint8_t);
 static void	urtwn_tsf_sync_enable(struct urtwn_softc *);
 static void	urtwn_set_led(struct urtwn_softc *, int, int);
 static void	urtwn_calib_to(void *);
@@ -195,7 +215,7 @@ static void	urtwn_rx_frame(struct urtwn_
 static void	urtwn_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
 static void	urtwn_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
 static int	urtwn_tx(struct urtwn_softc *, struct mbuf *,
-		    struct ieee80211_node *);
+		    struct ieee80211_node *, struct urtwn_tx_data *);
 static void	urtwn_start(struct ifnet *);
 static void	urtwn_watchdog(struct ifnet *);
 static int	urtwn_ioctl(struct ifnet *, u_long, void *);
@@ -254,13 +274,16 @@ urtwn_attach(device_t parent, device_t s
 	aprint_naive("\n");
 	aprint_normal("\n");
 
+	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
+
 	devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
 	aprint_normal_dev(self, "%s\n", devinfop);
 	usbd_devinfo_free(devinfop);
 
 	mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
-	mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NET);
+	mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
 	mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
 
 	usb_init_task(&sc->sc_task, urtwn_task, sc);
 
@@ -412,10 +435,6 @@ urtwn_detach(device_t self, int flags)
 		ieee80211_ifdetach(&sc->sc_ic);
 		if_detach(ifp);
 
-		/* Free Tx/Rx buffers. */
-		urtwn_free_tx_list(sc);
-		urtwn_free_rx_list(sc);
-	
 		/* Abort and close Tx/Rx pipes. */
 		urtwn_close_pipes(sc);
 	}
@@ -426,6 +445,8 @@ urtwn_detach(device_t self, int flags)
 
 	callout_destroy(&sc->sc_scan_to);
 	callout_destroy(&sc->sc_calib_to);
+
+	mutex_destroy(&sc->sc_write_mtx);
 	mutex_destroy(&sc->sc_fwcmd_mtx);
 	mutex_destroy(&sc->sc_tx_mtx);
 	mutex_destroy(&sc->sc_task_mtx);
@@ -483,7 +504,8 @@ urtwn_open_pipes(struct urtwn_softc *sc)
 	error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE,
 	    &sc->rx_pipe);
 	if (error != 0) {
-		aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
+		aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe"
+		    ": %d\n", error);
 		goto fail;
 	}
 
@@ -493,7 +515,8 @@ urtwn_open_pipes(struct urtwn_softc *sc)
 		    USBD_EXCLUSIVE_USE, &sc->tx_pipe[i]);
 		if (error != 0) {
 			aprint_error_dev(sc->sc_dev,
-			    "could not open Tx bulk pipe 0x%02x\n", epaddr[i]);
+			    "could not open Tx bulk pipe 0x%02x: %d\n",
+			    epaddr[i], error);
 			goto fail;
 		}
 	}
@@ -591,6 +614,7 @@ urtwn_alloc_tx_list(struct urtwn_softc *
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	mutex_enter(&sc->sc_tx_mtx);
 	TAILQ_INIT(&sc->tx_free_list);
 	for (i = 0; i < URTWN_TX_LIST_COUNT; i++) {
 		data = &sc->tx_data[i];
@@ -616,10 +640,12 @@ urtwn_alloc_tx_list(struct urtwn_softc *
 		/* Append this Tx buffer to our free list. */
 		TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
 	}
+	mutex_exit(&sc->sc_tx_mtx);
 	return (0);
 
  fail:
 	urtwn_free_tx_list(sc);
+	mutex_exit(&sc->sc_tx_mtx);
 	return (error);
 }
 
@@ -717,6 +743,8 @@ urtwn_write_region_1(struct urtwn_softc 
 	usb_device_request_t req;
 	usbd_status error;
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = R92C_REQ_REGS;
 	USETW(req.wValue, addr);
@@ -852,6 +880,8 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uin
 	DPRINTFN(DBG_REG, ("%s: %s: id=%d, buf=%p, len=%d\n",
 	    device_xname(sc->sc_dev), __func__, id, buf, len));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	mutex_enter(&sc->sc_fwcmd_mtx);
 	fwcur = sc->fwcur;
 	sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
@@ -932,6 +962,8 @@ urtwn_llt_write(struct urtwn_softc *sc, 
 {
 	int ntries;
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	urtwn_write_4(sc, R92C_LLT_INIT,
 	    SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) |
 	    SM(R92C_LLT_INIT_ADDR, addr) |
@@ -954,6 +986,8 @@ urtwn_efuse_read_1(struct urtwn_softc *s
 	uint32_t reg;
 	int ntries;
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
 	reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
 	reg &= ~R92C_EFUSE_CTRL_VALID;
@@ -984,6 +1018,8 @@ urtwn_efuse_read(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL);
 	if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) {
 		urtwn_write_2(sc, R92C_SYS_ISO_CTRL,
@@ -1152,6 +1188,8 @@ urtwn_read_rom(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	mutex_enter(&sc->sc_write_mtx);
+
 	/* Read full ROM image. */
 	urtwn_efuse_read(sc);
 #ifdef URTWN_DEBUG
@@ -1170,6 +1208,8 @@ urtwn_read_rom(struct urtwn_softc *sc)
 	    sc->board_type, sc->regulatory));
 
 	IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
+
+	mutex_exit(&sc->sc_write_mtx);
 }
 
 static int
@@ -1212,6 +1252,8 @@ urtwn_ra_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Get normal and basic rates mask. */
 	rates = basicrates = 0;
 	maxrate = maxbasicrate = 0;
@@ -1326,6 +1368,8 @@ urtwn_set_nettype0_msr(struct urtwn_soft
 	DPRINTFN(DBG_FN, ("%s: %s: type=%d\n", device_xname(sc->sc_dev),
 	    __func__, type));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	reg = urtwn_read_1(sc, R92C_CR + 2) & 0x0c;
 	urtwn_write_1(sc, R92C_CR + 2, reg | type);
 }
@@ -1338,6 +1382,8 @@ urtwn_tsf_sync_enable(struct urtwn_softc
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Enable TSF synchronization. */
 	urtwn_write_1(sc, R92C_BCN_CTRL,
 	    urtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0);
@@ -1366,6 +1412,8 @@ urtwn_set_led(struct urtwn_softc *sc, in
 	DPRINTFN(DBG_FN, ("%s: %s: led=%d, on=%d\n", device_xname(sc->sc_dev),
 	    __func__, led, on));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	if (led == URTWN_LED_LINK) {
 		reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70;
 		if (!on) {
@@ -1401,6 +1449,7 @@ urtwn_calib_to_cb(struct urtwn_softc *sc
 	if (sc->sc_ic.ic_state != IEEE80211_S_RUN)
 		goto restart_timer;
 
+	mutex_enter(&sc->sc_write_mtx);
 	if (sc->avg_pwdb != -1) {
 		/* Indicate Rx signal strength to FW for rate adaptation. */
 		memset(&cmd, 0, sizeof(cmd));
@@ -1413,6 +1462,7 @@ urtwn_calib_to_cb(struct urtwn_softc *sc
 
 	/* Do temperature compensation. */
 	urtwn_temp_calib(sc);
+	mutex_exit(&sc->sc_write_mtx);
 
  restart_timer:
 	if (!sc->sc_dying) {
@@ -1473,6 +1523,10 @@ urtwn_newstate_cb(struct urtwn_softc *sc
 	    ieee80211_state_name[nstate], nstate));
 
 	s = splnet();
+	mutex_enter(&sc->sc_write_mtx);
+
+	callout_stop(&sc->sc_scan_to);
+	callout_stop(&sc->sc_calib_to);
 
 	switch (ostate) {
 	case IEEE80211_S_INIT:
@@ -1594,11 +1648,19 @@ urtwn_newstate_cb(struct urtwn_softc *sc
 	case IEEE80211_S_AUTH:
 		/* Set initial gain under link. */
 		reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
+#ifdef doaslinux
 		reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
+#else
+		reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
+#endif
 		urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
 
 		reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
+#ifdef doaslinux
 		reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
+#else
+		reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
+#endif
 		urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
 
 		/* Set media status to 'No Link'. */
@@ -1695,6 +1757,7 @@ urtwn_newstate_cb(struct urtwn_softc *sc
 
 	(*sc->sc_newstate)(ic, nstate, cmd->arg);
 
+	mutex_exit(&sc->sc_write_mtx);
 	splx(s);
 }
 
@@ -1732,6 +1795,7 @@ urtwn_wme_update_cb(struct urtwn_softc *
 	    __func__));
 
 	s = splnet();
+	mutex_enter(&sc->sc_write_mtx);
 	slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
 	for (ac = 0; ac < WME_NUM_AC; ac++) {
 		wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
@@ -1743,6 +1807,7 @@ urtwn_wme_update_cb(struct urtwn_softc *
 		    SM(R92C_EDCA_PARAM_ECWMAX, wmep->wmep_logcwmax) |
 		    SM(R92C_EDCA_PARAM_AIFS, aifs));
 	}
+	mutex_exit(&sc->sc_write_mtx);
 	splx(s);
 }
 
@@ -1782,8 +1847,9 @@ urtwn_update_avgrssi(struct urtwn_softc 
 	else
 		sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20);
 
-	DPRINTFN(DBG_RF, ("%s: %s: PWDB=%d EMA=%d\n", device_xname(sc->sc_dev),
-	    __func__, pwdb, sc->avg_pwdb));
+	DPRINTFN(DBG_RF, ("%s: %s: rate=%d rssi=%d PWDB=%d EMA=%d\n",
+		     device_xname(sc->sc_dev), __func__,
+		     rate, rssi, pwdb, sc->avg_pwdb));
 }
 
 static int8_t
@@ -1992,7 +2058,6 @@ urtwn_rxeof(usbd_xfer_handle xfer, usbd_
 		if (__predict_false(pktlen == 0)) {
 			DPRINTFN(DBG_RX, ("%s: %s: pktlen is 0 byte\n",
 			    device_xname(sc->sc_dev), __func__));
-			break;
 		}
 
 		infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
@@ -2058,12 +2123,12 @@ urtwn_txeof(usbd_xfer_handle xfer, usbd_
 }
 
 static int
-urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
+urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
+    struct urtwn_tx_data *data)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_frame *wh;
 	struct ieee80211_key *k = NULL;
-	struct urtwn_tx_data *data;
 	struct r92c_tx_desc *txd;
 	usbd_pipe_handle pipe;
 	uint16_t seq, sum;
@@ -2077,10 +2142,9 @@ urtwn_tx(struct urtwn_softc *sc, struct 
 
 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 		k = ieee80211_crypto_encap(ic, ni, m);
-		if (k == NULL) {
-			m_freem(m);
-			return (ENOBUFS);
-		}
+		if (k == NULL)
+			return ENOBUFS;
+
 		/* packet header may have moved, reset our local pointer */
 		wh = mtod(m, struct ieee80211_frame *);
 	}
@@ -2115,12 +2179,6 @@ urtwn_tx(struct urtwn_softc *sc, struct 
 	/* Get the USB pipe to use for this AC. */
 	pipe = sc->tx_pipe[sc->ac2idx[qid]];
 
-	/* Grab a Tx buffer from our free list. */
-	mutex_enter(&sc->sc_tx_mtx);
-	data = TAILQ_FIRST(&sc->tx_free_list);
-	TAILQ_REMOVE(&sc->tx_free_list, data, next);
-	mutex_exit(&sc->sc_tx_mtx);
-
 	if (((sizeof(*txd) + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */
 		padsize = 8;
 	else
@@ -2224,7 +2282,6 @@ urtwn_tx(struct urtwn_softc *sc, struct 
 
 	xferlen = sizeof(*txd) + m->m_pkthdr.len + padsize;
 	m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[1] + padsize);
-	m_freem(m);
 
 	s = splnet();
 	data->pipe = pipe;
@@ -2237,15 +2294,10 @@ urtwn_tx(struct urtwn_softc *sc, struct 
 		splx(s);
 		DPRINTFN(DBG_TX, ("%s: %s: transfer failed %d\n",
 		    device_xname(sc->sc_dev), __func__, error));
-		mutex_enter(&sc->sc_tx_mtx);
-		/* Put this Tx buffer back to our free list. */
-		TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
-		mutex_exit(&sc->sc_tx_mtx);
-		return (error);
+		return error;
 	}
 	splx(s);
-	ieee80211_free_node(ni);
-	return (0);
+	return 0;
 }
 
 static void
@@ -2253,6 +2305,7 @@ urtwn_start(struct ifnet *ifp)
 {
 	struct urtwn_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = &sc->sc_ic;
+	struct urtwn_tx_data *data;
 	struct ether_header *eh;
 	struct ieee80211_node *ni;
 	struct mbuf *m;
@@ -2262,18 +2315,25 @@ urtwn_start(struct ifnet *ifp)
 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
 		return;
 
+	data = NULL;
 	for (;;) {
 		mutex_enter(&sc->sc_tx_mtx);
-		if (TAILQ_EMPTY(&sc->tx_free_list)) {
-			mutex_exit(&sc->sc_tx_mtx);
-			ifp->if_flags |= IFF_OACTIVE;
-			break;
+		if (data == NULL) {
+			data = TAILQ_FIRST(&sc->tx_free_list);
+			if (data == NULL) {
+				mutex_exit(&sc->sc_tx_mtx);
+				ifp->if_flags |= IFF_OACTIVE;
+				DPRINTFN(DBG_TX, ("%s: empty tx_free_list\n",
+					     device_xname(sc->sc_dev)));
+				return;
+			}
+			TAILQ_REMOVE(&sc->tx_free_list, data, next);
 		}
-		mutex_exit(&sc->sc_tx_mtx);
 
 		/* Send pending management frames first. */
 		IF_DEQUEUE(&ic->ic_mgtq, m);
 		if (m != NULL) {
+			mutex_exit(&sc->sc_tx_mtx);
 			ni = (void *)m->m_pkthdr.rcvif;
 			m->m_pkthdr.rcvif = NULL;
 			goto sendit;
@@ -2285,6 +2345,9 @@ urtwn_start(struct ifnet *ifp)
 		IFQ_DEQUEUE(&ifp->if_snd, m);
 		if (m == NULL)
 			break;
+
+		mutex_exit(&sc->sc_tx_mtx);
+
 		if (m->m_len < (int)sizeof(*eh) &&
 		    (m = m_pullup(m, sizeof(*eh))) == NULL) {
 			ifp->if_oerrors++;
@@ -2308,15 +2371,22 @@ urtwn_start(struct ifnet *ifp)
  sendit:
 		bpf_mtap3(ic->ic_rawbpf, m);
 
-		if (urtwn_tx(sc, m, ni) != 0) {
+		if (urtwn_tx(sc, m, ni, data) != 0) {
+			m_freem(m);
 			ieee80211_free_node(ni);
 			ifp->if_oerrors++;
 			continue;
 		}
-
+		data = NULL;
+		m_freem(m);
+		ieee80211_free_node(ni);
 		sc->tx_timer = 5;
 		ifp->if_timer = 1;
 	}
+
+	/* Return the Tx buffer to the free list */
+	TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
+	mutex_exit(&sc->sc_tx_mtx);
 }
 
 static void
@@ -2365,8 +2435,8 @@ urtwn_ioctl(struct ifnet *ifp, u_long cm
 	case SIOCSIFFLAGS:
 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
 			break;
-		switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
-		case IFF_UP|IFF_RUNNING:
+		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+		case IFF_UP | IFF_RUNNING:
 			break;
 		case IFF_UP:
 			urtwn_init(ifp);
@@ -2393,8 +2463,10 @@ urtwn_ioctl(struct ifnet *ifp, u_long cm
 		    ic->ic_opmode == IEEE80211_M_MONITOR) {
 			if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
 			    (IFF_UP | IFF_RUNNING)) {
+				mutex_enter(&sc->sc_write_mtx);
 				urtwn_set_chan(sc, ic->ic_ibss_chan,
 				    IEEE80211_HTINFO_2NDCHAN_NONE);
+				mutex_exit(&sc->sc_write_mtx);
 			}
 			error = 0;
 		}
@@ -2425,6 +2497,8 @@ urtwn_power_on(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Wait for autoload done bit. */
 	for (ntries = 0; ntries < 1000; ntries++) {
 		if (urtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN)
@@ -2514,6 +2588,8 @@ urtwn_llt_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Reserve pages [0; R92C_TX_PAGE_COUNT]. */
 	for (i = 0; i < R92C_TX_PAGE_COUNT; i++) {
 		if ((error = urtwn_llt_write(sc, i, i + 1)) != 0)
@@ -2543,6 +2619,8 @@ urtwn_fw_reset(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Tell 8051 to reset itself. */
 	urtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
 
@@ -2601,6 +2679,8 @@ urtwn_load_firmware(struct urtwn_softc *
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Read firmware image from the filesystem. */
 	if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) ==
 	    URTWN_CHIP_UMC_A_CUT)
@@ -2716,6 +2796,8 @@ urtwn_dma_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Initialize LLT table. */
 	error = urtwn_llt_init(sc);
 	if (error != 0)
@@ -2800,6 +2882,8 @@ urtwn_mac_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Write MAC initialization values. */
 	for (i = 0; i < (int)__arraycount(rtl8192cu_mac); i++)
 		urtwn_write_1(sc, rtl8192cu_mac[i].reg, rtl8192cu_mac[i].val);
@@ -2814,6 +2898,8 @@ urtwn_bb_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Enable BB and RF. */
 	urtwn_write_2(sc, R92C_SYS_FUNC_EN,
 	    urtwn_read_2(sc, R92C_SYS_FUNC_EN) |
@@ -3018,6 +3104,8 @@ urtwn_cam_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) {
 		content = (idx & 3)
 		    | (R92C_CAM_ALGO_AES << R92C_CAM_ALGO_S)
@@ -3063,6 +3151,8 @@ urtwn_pa_bias_init(struct urtwn_softc *s
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	for (i = 0; i < sc->nrxchains; i++) {
 		if (sc->pa_setting & (1U << i))
 			continue;
@@ -3085,6 +3175,8 @@ urtwn_rxfilter_init(struct urtwn_softc *
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* Initialize Rx filter. */
 	/* TODO: use better filter for monitor mode. */
 	urtwn_write_4(sc, R92C_RCR,
@@ -3108,6 +3200,8 @@ urtwn_edca_init(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	/* set spec SIFS (used in NAV) */
 	urtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
 	urtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
@@ -3330,6 +3424,8 @@ urtwn_set_chan(struct urtwn_softc *sc, s
 	DPRINTFN(DBG_FN, ("%s: %s: chan=%d\n", device_xname(sc->sc_dev),
 	    __func__, chan));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	if (ht40m == IEEE80211_HTINFO_2NDCHAN_ABOVE) {
 		chan += 2;
 	} else if (ht40m == IEEE80211_HTINFO_2NDCHAN_BELOW){
@@ -3419,6 +3515,8 @@ urtwn_lc_calib(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	txmode = urtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
 	if ((txmode & 0x70) != 0) {
 		/* Disable all continuous Tx. */
@@ -3463,6 +3561,8 @@ urtwn_temp_calib(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	KASSERT(mutex_owned(&sc->sc_write_mtx));
+
 	if (sc->thcal_state == 0) {
 		/* Start measuring temperature. */
 		DPRINTFN(DBG_RF, ("%s: %s: start measuring temperature\n",
@@ -3511,6 +3611,8 @@ urtwn_init(struct ifnet *ifp)
 
 	urtwn_stop(ifp, 0);
 
+	mutex_enter(&sc->sc_write_mtx);
+
 	mutex_enter(&sc->sc_task_mtx);
 	/* Init host async commands ring. */
 	sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
@@ -3521,21 +3623,18 @@ urtwn_init(struct ifnet *ifp)
 	sc->fwcur = 0;
 	mutex_exit(&sc->sc_fwcmd_mtx);
 
-	if (!(sc->sc_flags & URTWN_FLAG_INIT_ONCE)) {
-		/* Allocate Tx/Rx buffers. */
-		error = urtwn_alloc_rx_list(sc);
-		if (error != 0) {
-			aprint_error_dev(sc->sc_dev,
-			    "could not allocate Rx buffers\n");
-			goto fail;
-		}
-		error = urtwn_alloc_tx_list(sc);
-		if (error != 0) {
-			aprint_error_dev(sc->sc_dev,
-			    "could not allocate Tx buffers\n");
-			goto fail;
-		}
-		sc->sc_flags |= URTWN_FLAG_INIT_ONCE;
+	/* Allocate Tx/Rx buffers. */
+	error = urtwn_alloc_rx_list(sc);
+	if (error != 0) {
+		aprint_error_dev(sc->sc_dev,
+		    "could not allocate Rx buffers\n");
+		goto fail;
+	}
+	error = urtwn_alloc_tx_list(sc);
+	if (error != 0) {
+		aprint_error_dev(sc->sc_dev,
+		    "could not allocate Tx buffers\n");
+		goto fail;
 	}
 
 	/* Power on adapter. */
@@ -3711,9 +3810,13 @@ urtwn_init(struct ifnet *ifp)
 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 	else
 		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+
+	mutex_exit(&sc->sc_write_mtx);
 	return (0);
 
  fail:
+	mutex_exit(&sc->sc_write_mtx);
+
 	urtwn_stop(ifp, 1);
 	return (error);
 }
@@ -3748,6 +3851,10 @@ urtwn_stop(struct ifnet *ifp, int disabl
 	/* Stop Rx pipe. */
 	usbd_abort_pipe(sc->rx_pipe);
 
+	/* Free Tx/Rx buffers. */
+	urtwn_free_tx_list(sc);
+	urtwn_free_rx_list(sc);
+
 	if (disable)
 		urtwn_chip_stop(sc);
 }
@@ -3760,6 +3867,8 @@ urtwn_chip_stop(struct urtwn_softc *sc)
 
 	DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
+	mutex_enter(&sc->sc_write_mtx);
+
 	/*
 	 * RF Off Sequence
 	 */
@@ -3861,6 +3970,8 @@ urtwn_chip_stop(struct urtwn_softc *sc)
 	    R92C_APS_FSMCO_PFM_ALDN);
 
 	urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
+
+	mutex_exit(&sc->sc_write_mtx);
 }
 
 MODULE(MODULE_CLASS_DRIVER, if_urtwn, "bpf");
@@ -3891,3 +4002,4 @@ if_urtwn_modcmd(modcmd_t cmd, void *aux)
 		return (ENOTTY);
 	}
 }
+

Index: src/sys/dev/usb/if_urtwnreg.h
diff -u src/sys/dev/usb/if_urtwnreg.h:1.1 src/sys/dev/usb/if_urtwnreg.h:1.2
--- src/sys/dev/usb/if_urtwnreg.h:1.1	Sat Mar 24 20:11:16 2012
+++ src/sys/dev/usb/if_urtwnreg.h	Sun Jan 20 15:21:57 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urtwnreg.h,v 1.1 2012/03/25 00:11:16 nonaka Exp $	*/
+/*	$NetBSD: if_urtwnreg.h,v 1.2 2013/01/20 20:21:57 christos Exp $	*/
 /*	$OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $	*/
 
 /*-
@@ -1011,3 +1011,4 @@ struct r92c_tx_desc {
 	uint16_t	txdsum;
 	uint16_t	pad;
 } __packed __aligned(4);
+

Index: src/sys/dev/usb/if_urtwnvar.h
diff -u src/sys/dev/usb/if_urtwnvar.h:1.3 src/sys/dev/usb/if_urtwnvar.h:1.4
--- src/sys/dev/usb/if_urtwnvar.h:1.3	Thu Jan 17 20:41:07 2013
+++ src/sys/dev/usb/if_urtwnvar.h	Sun Jan 20 15:21:57 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urtwnvar.h,v 1.3 2013/01/18 01:41:07 jmcneill Exp $	*/
+/*	$NetBSD: if_urtwnvar.h,v 1.4 2013/01/20 20:21:57 christos Exp $	*/
 /*	$OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $	*/
 
 /*-
@@ -16,6 +16,8 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifndef _IF_URTWNVAR_H_
+#define _IF_URTWNVAR_H_
 
 /*
  * Driver definitions.
@@ -117,7 +119,6 @@ struct urtwn_softc {
 #define URTWN_FLAG_CCK_HIPWR	__BIT(0)
 #define	URTWN_FLAG_ATTACHED	__BIT(1)
 #define	URTWN_FLAG_FWREADY	__BIT(2)
-#define URTWN_FLAG_INIT_ONCE	__BIT(3)
 	int				sc_dying;
 
 	struct usb_task			sc_task;
@@ -127,6 +128,7 @@ struct urtwn_softc {
 	kmutex_t			sc_task_mtx;
 	kmutex_t			sc_fwcmd_mtx;
 	kmutex_t			sc_tx_mtx;
+	kmutex_t			sc_write_mtx;
 
 	usbd_pipe_handle		rx_pipe;
 	int				rx_npipe;
@@ -177,3 +179,6 @@ struct urtwn_softc {
 #define sc_txtap	sc_txtapu.th
 	int				sc_txtap_len;
 };
+
+#endif /* _IF_URTWNVAR_H_ */
+

Reply via email to