From: Stefan Sperling Subject: fix fatal firmware error when forcing iwx to 11a/b/g mode To: tech@openbsd.org Date: Mon, 9 Mar 2026 13:49:59 +0100 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? 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 <<