Hit a witness panic during boot yesterday. Can't repro, have never
seen it before. The photo is a mess (ask if you want it) but the
backtrace is:
panic
witness_checkorder
rw_enter_write
solock
route input
ieee80211_set_link_state
ieee80211_recv_4way_msg3
ieee80211_eapol_key_input
ieee80211_decap
ieee80211_input_ba_flush
ieee80211_input_ba_gap_timeout
timeout_run
softclock_process_tick_timeout
sotclock
We're not allowed to take sleeping locks during the execution of a
timeout, hence the witness panic.
The backtrace omits that ieee80211_set_link_state() calls
rtm_80211info(), which calls route_input().
The guilty call is in ieee80211_proto.c, line 1327:
1295 void
1296 ieee80211_set_link_state(struct ieee80211com *ic, int nstate)
1297 {
1298 struct ifnet *ifp = &ic->ic_if;
1299
1300 switch (ic->ic_opmode) {
/* ... */
1312 }
1313 if (nstate != ifp->if_link_state) {
1314 ifp->if_link_state = nstate;
1315 if (LINK_STATE_IS_UP(nstate)) {
1316 struct if_ieee80211_data ifie;
1317 memset(&ifie, 0, sizeof(ifie));
1318 ifie.ifie_nwid_len = ic->ic_bss->ni_esslen;
1319 memcpy(ifie.ifie_nwid, ic->ic_bss->ni_essid,
1320 sizeof(ifie.ifie_nwid));
1321 memcpy(ifie.ifie_addr, ic->ic_bss->ni_bssid,
1322 sizeof(ifie.ifie_addr));
1323 ifie.ifie_channel = ieee80211_chan2ieee(ic,
1324 ic->ic_bss->ni_chan);
1325 ifie.ifie_flags = ic->ic_flags;
1326 ifie.ifie_xflags = ic->ic_xflags;
1327 rtm_80211info(&ic->ic_if, &ifie);
1328 }
1329 if_link_state_change(ifp);
1330 }
1331 }
So if the link state is changing from not-up to up we send a routing
info message to userspace.
Typical solution would be to postpone the rtm_80211info() call to a
task, but I'm not familiar with this stack so maybe we can't do that?