summaryrefslogtreecommitdiffstats
path: root/sys/dev/iwn
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2008-05-26 07:40:14 +0000
committerdelphij <delphij@FreeBSD.org>2008-05-26 07:40:14 +0000
commit642c6dfdab53b79ea3b3e494e6a93a4d7bb5b216 (patch)
treead38dee03daf1fb0babf363cd7be955d615b0452 /sys/dev/iwn
parentd546148e70c16bd8528c88bc8ac0e806668f7ab4 (diff)
downloadFreeBSD-src-642c6dfdab53b79ea3b3e494e6a93a4d7bb5b216.zip
FreeBSD-src-642c6dfdab53b79ea3b3e494e6a93a4d7bb5b216.tar.gz
We can not call iwn_start directly in the interrupt
context, where the iwn mutex is being held, and iwn_start assumes that we do not have that mutex held. Resolve this issue with what we do for other NICs by splitting the iwn_start procedure into two parts, iwn_start() do the locking, and iwn_start_locked() assumes that the mutex is being held. This resolves panic when WITNESS is enabled.
Diffstat (limited to 'sys/dev/iwn')
-rw-r--r--sys/dev/iwn/if_iwn.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 8a1ed68..ee7bda5 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -138,6 +138,7 @@ uint8_t iwn_plcp_signal(int);
int iwn_tx_data(struct iwn_softc *, struct mbuf *,
struct ieee80211_node *, struct iwn_tx_ring *);
void iwn_start(struct ifnet *);
+void iwn_start_locked(struct ifnet *);
static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void iwn_watchdog(struct iwn_softc *);
@@ -1627,7 +1628,7 @@ iwn_tx_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc)
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- iwn_start(ifp);
+ iwn_start_locked(ifp);
}
void
@@ -2092,11 +2093,23 @@ void
iwn_start(struct ifnet *ifp)
{
struct iwn_softc *sc = ifp->if_softc;
+
+ IWN_LOCK(sc);
+ iwn_start_locked(ifp);
+ IWN_UNLOCK(sc);
+}
+
+void
+iwn_start_locked(struct ifnet *ifp)
+{
+ struct iwn_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct iwn_tx_ring *txq;
struct mbuf *m;
int pri;
+ IWN_LOCK_ASSERT(sc);
+
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
@@ -2110,7 +2123,6 @@ iwn_start(struct ifnet *ifp)
ieee80211_free_node(ni);
continue;
}
- IWN_LOCK(sc);
if (txq->queued >= IWN_TX_RING_COUNT - 8) {
/* XXX not right */
/* ring is nearly full, stop flow */
@@ -2122,7 +2134,6 @@ iwn_start(struct ifnet *ifp)
IWN_UNLOCK(sc);
break;
}
- IWN_UNLOCK(sc);
}
}
OpenPOWER on IntegriCloud