From: Peter Hessler Subject: Re: fix fatal firmware error when forcing iwx to 11a/b/g mode To: tech@openbsd.org Date: Tue, 10 Mar 2026 01:50:28 +0100 On 2026 Mar 09 (Mon) at 13:49:59 +0100 (+0100), Stefan Sperling wrote: :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? : makes sense, and it follow what I understand of 802.11. Minor nit, can we get defines for htole16(3895) and htole16(3839) ? Not a blocker, but magic numbers gives me hives. OK Tested on ax211 that is switching between 11n/11ac/11g whie traveling. :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 << : -- To a Real Woman, every ejaculation is premature.