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_ */
+