From: Kevin Lo Subject: Re: fix fatal firmware error when forcing iwx to 11a/b/g mode To: tech@openbsd.org Date: Tue, 10 Mar 2026 10:31:24 +0800 On Mon, Mar 09, 2026 at 10:31:41PM +0100, Mark Kettenis wrote: > > > Date: Mon, 9 Mar 2026 13:49:59 +0100 > > From: Stefan Sperling > > > > 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. Tested on MA and got the same result. iwx0 at pci1 dev 0 function 0 "Intel Wi-Fi 6 AX210" rev 0x1a, msix iwx0: hw rev 0x420, fw 77.f92b5fed.0, pnvm 285b3568, address ac:82:47:xx:xx:xx > 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 << > > > > >