From: Tobias Heider Subject: Re: bwfm fixes To: Moritz Buhl Cc: tech@openbsd.org Date: Wed, 6 Aug 2025 23:51:00 +0200 On Mon, Aug 04, 2025 at 08:19:08PM +0200, Moritz Buhl wrote: > Dear tech, > > I currently use a MacBook m2 and I always have trouble with the > bwfm in it. > > Here are three fixes: > 1. receive EAPOL event messages. > After debugging this for a few days, I noticed that EAPOL frames > do not cause an interrupt and with my macbook the messag either > comes with the previous WL_EVENTS that change the link state and > finish the ASSOC state, or the firmware crashes about 100ms later. > > I can imagine this may also help with crashes in AP mode on other > devices. > > 2. do ieee80211 state changes inside of the interrupt handler. > To my understanding this is in line with outher drivers and it is > necessary for the wpa handshake to process it within 100 ms which > we could miss because of the additional queueing. > > 3. process control messages before rx messages. > Otherwise a EAPOL frame could be processed before changing from > ASSOC to RUN. > > I would appreciate additional testing on other devices. > > mbuhl tested by and ok tobhe@ once you fixed stsp@s suggestions. This doesn't fix all of my bwfm problems but I feel it works more reliably and it certainly didn't get worse. I still occasionally see firmware crashes when roaming or turning of my AP while the laptop is connected. Nice work! > > Index: ic/bwfm.c > =================================================================== > RCS file: /cvs/src/sys/dev/ic/bwfm.c,v > diff -u -p -r1.111 bwfm.c > --- ic/bwfm.c 19 Feb 2024 21:23:02 -0000 1.111 > +++ ic/bwfm.c 4 Aug 2025 15:43:12 -0000 > @@ -494,6 +494,7 @@ bwfm_init(struct ifnet *ifp) > BWFM_EVENT(BWFM_E_LINK); > BWFM_EVENT(BWFM_E_AUTH); > BWFM_EVENT(BWFM_E_ASSOC); > + BWFM_EVENT(BWFM_E_EAPOL_MSG); > BWFM_EVENT(BWFM_E_DEAUTH); > BWFM_EVENT(BWFM_E_DISASSOC); > BWFM_EVENT(BWFM_E_ESCAN_RESULT); > @@ -503,6 +504,7 @@ bwfm_init(struct ifnet *ifp) > BWFM_EVENT(BWFM_E_AUTH_IND); > BWFM_EVENT(BWFM_E_ASSOC_IND); > BWFM_EVENT(BWFM_E_REASSOC_IND); > + BWFM_EVENT(BWFM_E_EAPOL_MSG); > BWFM_EVENT(BWFM_E_DEAUTH_IND); > BWFM_EVENT(BWFM_E_DISASSOC_IND); > BWFM_EVENT(BWFM_E_ESCAN_RESULT); > @@ -2551,12 +2551,44 @@ void > bwfm_rx_event(struct bwfm_softc *sc, struct mbuf *m) > { > int s; > + struct ieee80211com *ic = &sc->sc_ic; > + struct bwfm_event *e = mtod(m, void *); > > s = splnet(); > + switch (ntohl(e->msg.event_type)) { > + case BWFM_E_AUTH: > + if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > + ic->ic_state == IEEE80211_S_AUTH) { > + ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1); > + goto done; > + } > + goto enqueue; > + case BWFM_E_ASSOC: > + if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > + ic->ic_state == IEEE80211_S_ASSOC) { > + ieee80211_new_state(ic, IEEE80211_S_RUN, -1); > + } else if (ntohl(e->msg.status) != BWFM_E_STATUS_UNSOLICITED) { > + goto enqueue; > + } > + goto done; > + case BWFM_E_LINK: > + if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > + ntohl(e->msg.reason) == 0) > + goto done; > + goto enqueue; > + default: > + goto enqueue; > + } > +done: > + splx(s); > + m_freem(m); > + return; > +enqueue: > ml_enqueue(&sc->sc_evml, m); > splx(s); > > task_add(sc->sc_taskq, &sc->sc_task); > + return; > } > > void > @@ -2631,18 +2663,10 @@ bwfm_rx_event_cb(struct bwfm_softc *sc, > break; > } > case BWFM_E_AUTH: > - if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > - ic->ic_state == IEEE80211_S_AUTH) > - ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1); > - else > - ieee80211_begin_scan(ifp); > + ieee80211_begin_scan(ifp); > break; > case BWFM_E_ASSOC: > - if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > - ic->ic_state == IEEE80211_S_ASSOC) > - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); > - else if (ntohl(e->msg.status) != BWFM_E_STATUS_UNSOLICITED) > - ieee80211_begin_scan(ifp); > + ieee80211_begin_scan(ifp); > break; > case BWFM_E_DEAUTH: > case BWFM_E_DISASSOC: > @@ -2650,9 +2674,6 @@ bwfm_rx_event_cb(struct bwfm_softc *sc, > ieee80211_begin_scan(ifp); > break; > case BWFM_E_LINK: > - if (ntohl(e->msg.status) == BWFM_E_STATUS_SUCCESS && > - ntohl(e->msg.reason) == 0) > - break; > /* Link status has changed */ > if (ic->ic_state > IEEE80211_S_SCAN) > ieee80211_begin_scan(ifp); > Index: pci/if_bwfm_pci.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_bwfm_pci.c,v > diff -u -p -r1.77 if_bwfm_pci.c > --- pci/if_bwfm_pci.c 12 Jul 2024 08:33:25 -0000 1.77 > +++ pci/if_bwfm_pci.c 4 Aug 2025 15:45:07 -0000 > @@ -2369,9 +2369,9 @@ bwfm_pci_intr(void *v) > mask = BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB; > > if (status & mask) { > + bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete, &ml); > bwfm_pci_ring_rx(sc, &sc->sc_rx_complete, &ml); > bwfm_pci_ring_rx(sc, &sc->sc_tx_complete, &ml); > - bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete, &ml); > > if (ifiq_input(&ifp->if_rcv, &ml)) > if_rxr_livelocked(&sc->sc_rxbuf_ring); >