Index | Thread | Search

From:
Tobias Heider <tobias.heider@stusta.de>
Subject:
Re: bwfm fixes
To:
Moritz Buhl <mbuhl@openbsd.org>
Cc:
tech@openbsd.org
Date:
Wed, 6 Aug 2025 23:51:00 +0200

Download raw body.

Thread
  • Tobias Heider:

    bwfm fixes

  • Jan Stary:

    bwfm fixes

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);
>