Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
Re: fix fatal firmware error when forcing iwx to 11a/b/g mode
To:
Stefan Sperling <stsp@stsp.name>
Cc:
tech@openbsd.org
Date:
Mon, 09 Mar 2026 22:31:41 +0100

Download raw body.

Thread
> Date: Mon, 9 Mar 2026 13:49:59 +0100
> From: Stefan Sperling <stsp@stsp.name>
> 
> Forcing iwx(4) into 11a/b/g mode produces a fatal firmware error with
> BZ firmware, and possibly other firmware, too. This also happens when
> I try to disable mimo with "ifconfig iwx0 nwflag nomimo".
> 
> The driver does not take limitations of 11a/b/g modes into account while
> initializing Tx rate selection, which triggers some sanity checks in the
> firmware. The patch below fixes this.
> 
> ok?

Lightly tested on MA.  Seems forcing it into 11a without the diff
doesn't produce a fatal firmware error.  With or without your diff.

Diff doesn't look unreasonable to me, but I fear it goes beyond my
understanding of ieee802.11.


> M  sys/dev/pci/if_iwx.c  |  24+  10-
> 
> 1 file changed, 24 insertions(+), 10 deletions(-)
> 
> path + /usr/src
> commit - bf3713f7dfbf19ede85da952a0d01b849aa8a252
> blob - e731cf032ef66ed7a7eab46a3669fc5d80d9e8d3
> file + sys/dev/pci/if_iwx.c
> --- sys/dev/pci/if_iwx.c
> +++ sys/dev/pci/if_iwx.c
> @@ -8483,18 +8483,25 @@ iwx_rs_init_v3(struct iwx_softc *sc, struct iwx_node *
>  		cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT;
>  
>  	cfg_cmd.sta_id = IWX_STATION_ID;
> -	if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
> +	if ((ni->ni_flags & IEEE80211_NODE_VHT) &&
> +	    in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ;
> -	else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
> -	    in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB)
> +	else if ((ni->ni_flags & IEEE80211_NODE_HT) &&
> +	    (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
> +	    in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB))
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ;
>  	else
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ;
> -	cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
> +	if ((ni->ni_flags & IEEE80211_NODE_HT) && iwx_mimo_enabled(sc))
> +		cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
> +	else
> +		cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK;
>  	if (ni->ni_flags & IEEE80211_NODE_VHT)
>  		cfg_cmd.max_mpdu_len = htole16(3895);
> -	else
> +	else if (ni->ni_flags & IEEE80211_NODE_HT)
>  		cfg_cmd.max_mpdu_len = htole16(3839);
> +	else
> +		cfg_cmd.max_mpdu_len = IEEE80211_MAX_LEN;
>  	if (ni->ni_flags & IEEE80211_NODE_HT) {
>  		if (ieee80211_node_supports_ht_sgi20(ni)) {
>  			cfg_cmd.sgi_ch_width_supp |= (1 <<
> @@ -8551,18 +8558,25 @@ iwx_rs_init_v4(struct iwx_softc *sc, struct iwx_node *
>  		cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT;
>  
>  	cfg_cmd.sta_id = IWX_STATION_ID;
> -	if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
> +	if ((ni->ni_flags & IEEE80211_NODE_VHT) &&
> +	    in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80)
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ;
> -	else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
> -	    in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB)
> +	else if ((ni->ni_flags & IEEE80211_NODE_HT) &&
> +	    (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA ||
> +	    in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB))
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ;
>  	else
>  		cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ;
> -	cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
> +	if ((ni->ni_flags & IEEE80211_NODE_HT) && iwx_mimo_enabled(sc))
> +		cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK;
> +	else
> +		cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK;
>  	if (ni->ni_flags & IEEE80211_NODE_VHT)
>  		cfg_cmd.max_mpdu_len = htole16(3895);
> -	else
> +	else if (ni->ni_flags & IEEE80211_NODE_HT)
>  		cfg_cmd.max_mpdu_len = htole16(3839);
> +	else
> +		cfg_cmd.max_mpdu_len = IEEE80211_MAX_LEN;
>  	if (ni->ni_flags & IEEE80211_NODE_HT) {
>  		if (ieee80211_node_supports_ht_sgi20(ni)) {
>  			cfg_cmd.sgi_ch_width_supp |= (1 <<
> 
>