PERFORCE change 127059 for review
Andrew Thompson
thompsa at FreeBSD.org
Mon Oct 1 03:04:10 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127059
Change 127059 by thompsa at thompsa_heff on 2007/10/01 10:03:57
- drop default debug level back to 0
- use macro names for locking
- add _locked versions of some functions
- only do partial config in monitor mode
- set the channel passed from net80211
Obtained from: sam (mostly)
Affected files ...
.. //depot/projects/wifi/sys/dev/ipw/if_ipw.c#28 edit
.. //depot/projects/wifi/sys/dev/ipw/if_ipwreg.h#8 edit
.. //depot/projects/wifi/sys/dev/ipw/if_ipwvar.h#10 edit
Differences ...
==== //depot/projects/wifi/sys/dev/ipw/if_ipw.c#28 (text+ko) ====
@@ -4,6 +4,7 @@
* Copyright (c) 2004-2006
* Damien Bergamini <damien.bergamini at free.fr>. All rights reserved.
* Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Andrew Thompson <thompsa at FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -83,7 +84,7 @@
#ifdef IPW_DEBUG
#define DPRINTF(x) do { if (ipw_debug > 0) printf x; } while (0)
#define DPRINTFN(n, x) do { if (ipw_debug >= (n)) printf x; } while (0)
-int ipw_debug = 3;
+int ipw_debug = 0;
SYSCTL_INT(_debug, OID_AUTO, ipw, CTLFLAG_RW, &ipw_debug, 0, "ipw debug level");
#else
#define DPRINTF(x)
@@ -112,9 +113,9 @@
static void ipw_media_status(struct ifnet *, struct ifmediareq *);
static int ipw_newstate(struct ieee80211com *, enum ieee80211_state, int);
static uint16_t ipw_read_prom_word(struct ipw_softc *, uint8_t);
-static void ipw_command_intr(struct ipw_softc *, struct ipw_soft_buf *);
-static void ipw_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
-static void ipw_data_intr(struct ipw_softc *, struct ipw_status *,
+static void ipw_rx_cmd_intr(struct ipw_softc *, struct ipw_soft_buf *);
+static void ipw_rx_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
+static void ipw_rx_data_intr(struct ipw_softc *, struct ipw_status *,
struct ipw_soft_bd *, struct ipw_soft_buf *);
static void ipw_rx_intr(struct ipw_softc *);
static void ipw_release_sbd(struct ipw_softc *, struct ipw_soft_bd *);
@@ -126,6 +127,7 @@
static int ipw_tx_start(struct ifnet *, struct mbuf *,
struct ieee80211_node *);
static void ipw_start(struct ifnet *);
+static void ipw_start_locked(struct ifnet *);
static void ipw_watchdog(void *);
static int ipw_ioctl(struct ifnet *, u_long, caddr_t);
static void ipw_stop_master(struct ipw_softc *);
@@ -139,7 +141,9 @@
static int ipw_config(struct ipw_softc *);
static void ipw_init_task(void *, int);
static void ipw_init(void *);
+static void ipw_init_locked(struct ipw_softc *, int);
static void ipw_stop(void *);
+static void ipw_stop_locked(struct ipw_softc *);
static int ipw_sysctl_stats(SYSCTL_HANDLER_ARGS);
static int ipw_sysctl_radio(SYSCTL_HANDLER_ARGS);
static uint32_t ipw_read_table1(struct ipw_softc *, uint32_t);
@@ -738,18 +742,19 @@
{
struct ipw_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ic.ic_ifp;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
pci_write_config(dev, 0x41, 0, 1);
if (ifp->if_flags & IFF_UP) {
- ifp->if_init(ifp->if_softc);
+ ipw_init_locked(sc, 0);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ifp->if_start(ifp);
+ ipw_start_locked(ifp);
}
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
return 0;
}
@@ -759,21 +764,19 @@
{
struct ipw_softc *sc = ifp->if_softc;
int error;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
-
+ IPW_LOCK(sc);
error = ieee80211_media_change(ifp);
- if (error != ENETRESET) {
- mtx_unlock(&sc->sc_mtx);
- return error;
+ if (error == ENETRESET) {
+ if ((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING))
+ ipw_init_locked(sc, 0);
+ error = 0;
}
+ IPW_UNLOCK(sc);
- if ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- ipw_init(sc);
-
- mtx_unlock(&sc->sc_mtx);
-
- return 0;
+ return (error);
}
/*
@@ -960,7 +963,7 @@
}
static void
-ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
+ipw_rx_cmd_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
struct ipw_cmd *cmd;
@@ -978,7 +981,7 @@
}
static void
-ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
+ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
#define IEEESTATE(ic) ieee80211_state_name[ic->ic_state]
struct ieee80211com *ic = &sc->sc_ic;
@@ -1002,7 +1005,7 @@
case IPW_STATE_SCANNING:
DPRINTFN(3, ("Scanning (%s flags 0x%x)\n",
- IEEESTATE(ic), sc->flags));
+ IEEESTATE(ic), sc->flags));
/*
* NB: Check driver state for association on assoc
* loss as the firmware will immediately start to
@@ -1051,7 +1054,7 @@
DPRINTFN(2, ("Radio off (%s flags 0x%x)\n",
IEEESTATE(ic), sc->flags));
ic->ic_ifp->if_flags &= ~IFF_UP;
- ipw_stop(sc);
+ ipw_stop_locked(sc);
break;
default:
@@ -1125,7 +1128,7 @@
}
static void
-ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status,
+ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -1135,6 +1138,7 @@
struct ieee80211_node *ni;
bus_addr_t physaddr;
int error;
+ IPW_LOCK_DECL;
DPRINTFN(5, ("received frame len=%u, rssi=%u\n", le32toh(status->len),
status->rssi));
@@ -1192,7 +1196,7 @@
struct ipw_rx_radiotap_header *tap = &sc->sc_rxtap;
tap->wr_flags = 0;
- tap->wr_antsignal = status->rssi;
+ tap->wr_antsignal = status->rssi + IPW_RSSI_TO_DBM;
tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
@@ -1203,7 +1207,7 @@
ipw_fix_channel(sc, m);
wh = mtod(m, struct ieee80211_frame *);
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
/* send the frame to the 802.11 layer */
@@ -1211,7 +1215,7 @@
/* node is no longer needed */
ieee80211_free_node(ni);
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
bus_dmamap_sync(sc->rbd_dmat, sc->rbd_map, BUS_DMASYNC_PREWRITE);
}
@@ -1239,16 +1243,16 @@
switch (le16toh(status->code) & 0xf) {
case IPW_STATUS_CODE_COMMAND:
- ipw_command_intr(sc, sbuf);
+ ipw_rx_cmd_intr(sc, sbuf);
break;
case IPW_STATUS_CODE_NEWSTATE:
- ipw_newstate_intr(sc, sbuf);
+ ipw_rx_newstate_intr(sc, sbuf);
break;
case IPW_STATUS_CODE_DATA_802_3:
case IPW_STATUS_CODE_DATA_802_11:
- ipw_data_intr(sc, status, sbd, sbuf);
+ ipw_rx_data_intr(sc, status, sbd, sbuf);
break;
case IPW_STATUS_CODE_NOTIFICATION:
@@ -1345,7 +1349,7 @@
sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ipw_start(ifp);
+ ipw_start_locked(ifp);
}
static void
@@ -1353,11 +1357,12 @@
{
struct ipw_softc *sc = arg;
uint32_t r;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
if ((r = CSR_READ_4(sc, IPW_CSR_INTR)) == 0 || r == 0xffffffff) {
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
return;
}
@@ -1385,7 +1390,7 @@
/* re-enable interrupts */
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK);
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
}
static void
@@ -1457,9 +1462,6 @@
bus_addr_t physaddr;
int error;
- if (mtx_recursed(&sc->sc_mtx))
- device_printf(sc->sc_dev, "OMG, msleeping on a recursed mtx\n");
-
if (sc->flags & IPW_FLAG_BUSY) {
device_printf(sc->sc_dev, "%s: %s not sent, busy\n",
__func__, ipw_cmdname(type));
@@ -1677,17 +1679,26 @@
ipw_start(struct ifnet *ifp)
{
struct ipw_softc *sc = ifp->if_softc;
+ IPW_LOCK_DECL;
+
+ IPW_LOCK(sc);
+ ipw_start_locked(ifp);
+ IPW_UNLOCK(sc);
+}
+
+static void
+ipw_start_locked(struct ifnet *ifp)
+{
+ struct ipw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m0;
struct ether_header *eh;
struct ieee80211_node *ni;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK_ASSERT(sc);
- if (ic->ic_state != IEEE80211_S_RUN) {
- mtx_unlock(&sc->sc_mtx);
+ if (ic->ic_state != IEEE80211_S_RUN)
return;
- }
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
@@ -1730,8 +1741,6 @@
/* start watchdog timer */
sc->sc_tx_timer = 5;
}
-
- mtx_unlock(&sc->sc_mtx);
}
static void
@@ -1741,7 +1750,7 @@
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = sc->sc_ifp;
- mtx_assert(&sc->sc_mtx, MA_OWNED);
+ IPW_LOCK_ASSERT(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
@@ -1771,17 +1780,18 @@
struct ipw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
int error = 0;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ipw_init(sc);
+ ipw_init_locked(sc, 0);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ipw_stop(sc);
+ ipw_stop_locked(sc);
}
break;
@@ -1791,12 +1801,13 @@
if (error == ENETRESET) {
if ((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING))
- ipw_init(sc);
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+ (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
+ ipw_init_locked(sc, 0);
error = 0;
}
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
return error;
}
@@ -2049,7 +2060,7 @@
wpaie.len = htole32(ielen);
/* XXX verify length */
memcpy(&wpaie.ie, ie, ielen);
- DPRINTF(("Setting wpa ie\n"));
+ DPRINTF(("Setting WPA IE\n"));
return ipw_cmd(sc, IPW_CMD_SET_WPA_IE, &wpaie, sizeof(wpaie));
}
@@ -2114,10 +2125,11 @@
ipw_scan_task(void *context, int pending)
{
struct ipw_softc *sc = context;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
ipw_scan(sc);
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
}
static int
@@ -2222,7 +2234,7 @@
}
if (ic->ic_opmode == IEEE80211_M_MONITOR)
- ipw_enable(sc);
+ return ipw_enable(sc);
IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
DPRINTF(("Setting MAC address to %6D\n", ic->ic_myaddr, ":"));
@@ -2367,10 +2379,11 @@
ipw_assoc_task(void *context, int pending)
{
struct ipw_softc *sc = context;
+ IPW_LOCK_DECL;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
ipw_auth_and_assoc(sc);
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
}
static int
@@ -2475,35 +2488,38 @@
ipw_init(void *priv)
{
struct ipw_softc *sc = priv;
+ IPW_LOCK_DECL;
+
+ IPW_LOCK(sc);
+ ipw_init_locked(sc, 0);
+ IPW_UNLOCK(sc);
+}
+
+static void
+ipw_init_locked(struct ipw_softc *sc, int force)
+{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
const struct firmware *fp;
const struct ipw_firmware_hdr *hdr;
const char *imagename, *fw;
- int owned;
+ IPW_LOCK_DECL;
+
+ IPW_LOCK_ASSERT(sc);
- /*
- * ipw_init() is exposed through ifp->if_init so it might be called
- * without the driver's lock held. Since msleep() doesn't like being
- * called on a recursed mutex, we acquire the driver's lock only if
- * we're not already holding it.
- */
- if (!(owned = mtx_owned(&sc->sc_mtx)))
- mtx_lock(&sc->sc_mtx);
+ DPRINTF(("%s: state %s flags 0x%x\n", __func__,
+ ieee80211_state_name[ic->ic_state], sc->flags));
/*
* Avoid re-entrant calls. We need to release the mutex in ipw_init()
* when loading the firmware and we don't want to be called during this
* operation.
*/
- if (sc->flags & IPW_FLAG_INIT_LOCKED) {
- if (!owned)
- mtx_unlock(&sc->sc_mtx);
+ if (sc->flags & IPW_FLAG_INIT_LOCKED)
return;
- }
sc->flags |= IPW_FLAG_INIT_LOCKED;
- ipw_stop(sc);
+ ipw_stop_locked(sc);
if (ipw_reset(sc) != 0) {
device_printf(sc->sc_dev, "could not reset adapter\n");
@@ -2530,11 +2546,11 @@
*/
if (sc->sc_firmware == NULL || strcmp(sc->sc_firmware->name,
imagename) != 0) {
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
if (sc->sc_firmware != NULL)
firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
sc->sc_firmware = firmware_get(imagename);
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
}
if (sc->sc_firmware == NULL) {
@@ -2559,6 +2575,7 @@
goto fail2;
}
+ DPRINTF(("Loading firmware image '%s'\n", imagename));
fw = (const char *)fp->data + sizeof *hdr + le32toh(hdr->mainsz);
if (ipw_load_ucode(sc, fw, le32toh(hdr->ucodesz)) != 0) {
device_printf(sc->sc_dev, "could not load microcode\n");
@@ -2613,7 +2630,7 @@
* we need to notify user apps so they can manually
* get us going again.
*/
- if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
+ if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL || force)
ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
} else
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
@@ -2623,30 +2640,34 @@
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
-
- if (!owned)
- mtx_unlock(&sc->sc_mtx);
-
return;
fail2: firmware_put(fp, FIRMWARE_UNLOAD);
sc->sc_firmware = NULL;
fail1: ifp->if_flags &= ~IFF_UP;
- ipw_stop(sc);
+ ipw_stop_locked(sc);
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
- if (!owned)
- mtx_unlock(&sc->sc_mtx);
}
static void
ipw_stop(void *priv)
{
struct ipw_softc *sc = priv;
+ IPW_LOCK_DECL;
+
+ IPW_LOCK(sc);
+ ipw_stop_locked(sc);
+ IPW_UNLOCK(sc);
+}
+
+static void
+ipw_stop_locked(struct ipw_softc *sc)
+{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
int i;
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK_ASSERT(sc);
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
@@ -2663,8 +2684,6 @@
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- mtx_unlock(&sc->sc_mtx);
}
static int
@@ -2764,12 +2783,12 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
+ IPW_LOCK_DECL;
- device_printf(sc->sc_dev, "%s\n", __func__);
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
if (!(sc->flags & IPW_FLAG_SCANNING))
taskqueue_enqueue_fast(taskqueue_fast, &sc->sc_scan_task);
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
}
static void
@@ -2777,17 +2796,20 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
+ IPW_LOCK_DECL;
- device_printf(sc->sc_dev, "%s\n", __func__);
+ IPW_LOCK(sc);
+ if (ic->ic_opmode == IEEE80211_M_IBSS ||
+ ic->ic_opmode == IEEE80211_M_MONITOR) {
+ ipw_setchannel(sc, ic->ic_curchan);
+ }
+ IPW_UNLOCK(sc);
}
static void
ipw_scan_curchan(struct ieee80211com *ic, unsigned long maxdwell)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
-
- device_printf(sc->sc_dev, "%s\n", __func__);
+ /* NB: all channels are scanned at once */
}
static void
@@ -2801,9 +2823,9 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
+ IPW_LOCK_DECL;
- device_printf(sc->sc_dev, "%s\n", __func__);
- mtx_lock(&sc->sc_mtx);
+ IPW_LOCK(sc);
sc->flags &= ~IPW_FLAG_SCANNING;
- mtx_unlock(&sc->sc_mtx);
+ IPW_UNLOCK(sc);
}
==== //depot/projects/wifi/sys/dev/ipw/if_ipwreg.h#8 (text+ko) ====
==== //depot/projects/wifi/sys/dev/ipw/if_ipwvar.h#10 (text+ko) ====
@@ -168,3 +168,18 @@
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
};
+
+/*
+ * NB.: This models the only instance of async locking in ipw_init_locked
+ * and must be kept in sync.
+ */
+#define IPW_LOCK_DECL int __waslocked = 0
+#define IPW_LOCK(sc) do { \
+ if (!(__waslocked = mtx_owned(&(sc)->sc_mtx))) \
+ mtx_lock(&sc->sc_mtx); \
+} while (0)
+#define IPW_UNLOCK(sc) do { \
+ if (!__waslocked) \
+ mtx_unlock(&sc->sc_mtx); \
+} while (0)
+#define IPW_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
More information about the p4-projects
mailing list