Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Oct 2007 10:04:09 GMT
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 127059 for review
Message-ID:  <200710011004.l91A49rK060475@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=127059

Change 127059 by thompsa@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@free.fr>. All rights reserved.
  * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Andrew Thompson <thompsa@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)



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