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.
This commit is contained in:
Xin LI 2008-05-26 07:40:14 +00:00
parent ed5a2ac45c
commit 9f2c7365ab

View File

@ -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
@ -2090,6 +2091,16 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
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;
@ -2097,6 +2108,8 @@ iwn_start(struct ifnet *ifp)
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);
}
}