I've been told 0x20101A28 has to do with switching channel width
between 20 and 40 MHz. Specifically, it means we are configuring
the PHY to use 20 MHz only, while allowing firmware to send frames
with 40 MHz width via Tx rate selection. This is a contradiction.
Knowing this, it should not be very difficult to prevent this error.
But I will need to find time to write a patch.
Meanwhile, if you force your AP to use 20 MHz channel width only
as a workaround, this problem should stop happening.
Hi Stefan,
thanks again for the diagnosis (ADVANCED_SYSASSERT 0x20101A28, 20 vs
40 MHz channel width mismatch). Based on your explanation AI drafted
a patch for me, and it would be great if you could take a look.
It seems, the mismatch appears when the PHY context is
changed while associated:
- iwx_run() configures the PHY for 40 MHz and then sends the TLC
config with max_ch_width = 40MHZ, matching in_phyctxt->sco.
- Later, net80211 can call iwx_updatechan() while we stay in RUN
(for example on HT 20/40 coexistence updates from the AP's
beacons). iwx_phy_ctxt_task() then recomputes 'sco' and may
reconfigure the PHY context down to 20 MHz -- but the TLC
configuration is never re-sent.
- Firmware Tx rate selection still believes 40 MHz is allowed,
selects 40 MHz rates while the PHY runs at 20 MHz, and asserts.
The draft below re-sends the TLC configuration after a successful
PHY context update in iwx_phy_ctxt_task(), so that Tx rate selection
always matches the current PHY width. Monitor mode is excluded since
there is no rate scaling there.
I have not compiled or tested this yet; please treat it as a sketch.
If you see problems (e.g. calling iwx_rs_init() from this task
context, or other paths that need the same treatment) I am happy to
test whatever you come up with.
--- sys/dev/pci/if_iwx.c.orig
+++ sys/dev/pci/if_iwx.c
@@ -3673,8 +3673,20 @@
err = iwx_phy_ctxt_update(sc, in->in_phyctxt,
in->in_phyctxt->channel, chains, chains, 0, sco,
vht_chan_width);
- if (err)
+ if (err) {
printf("%s: failed to update PHY\n", DEVNAME(sc));
+ } else if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ /*
+ * Tx rate selection must not use a channel width
+ * wider than the PHY context is configured for,
+ * or the firmware will crash. Re-send the TLC
+ * configuration to match the new PHY state.
+ */
+ err = iwx_rs_init(sc, in);
+ if (err)
+ printf("%s: failed to init rate scaling "
+ "(error %d)\n", DEVNAME(sc), err);
+ }
}
refcnt_rele_wake(&sc->task_refs);
Thanks,
Robert