Wifi card vanishing from the PCIe bus? Stop rebooting, make it self-heal
On a Toshiba CB35-3340 (Bay Trail Chromebook running MX Linux / Debian 13 on MrChromebox
firmware), the internal Intel Wireless 7260 disappears every few hours. The SSID list goes
empty, every scan fails with -EIO, and toggling wifi does nothing. Only a reboot brought
it back.
The giveaway is in the kernel log:
iwlwifi 0000:01:00.0: iwlwifi device memory mapped registers:
iwlwifi 0000:01:00.0: 00000000: ffffffff ffffffff ffffffff ffffffff
WARNING: ... __iwl_trans_pcie_grab_nic_access+0x14c/0x150 [iwlwifi]
iwlwifi 0000:01:00.0: Error sending STATISTICS_CMD: enqueue_hcmd failed: -5
MMIO reads returning all-ones means the device is off the bus, not merely confused.
That is why modprobe -r iwlwifi && modprobe iwlwifi fails with
Could not load the [0] uCode section — there is nothing there to load firmware into.
Two things fix the recovery path. First, let the driver admit the device is gone:
# /etc/modprobe.d/iwlwifi-stability.conf
options iwlwifi remove_when_gone=1
Then a bare bus rescan re-enumerates it completely — firmware reloads, iwlwifi rebinds, the netdev comes back:
echo 1 | sudo tee /sys/bus/pci/rescan
No module reload, no reboot. Put it in a watchdog and the outage becomes invisible; mine recovered a real failure in 8 seconds:
#!/bin/bash
DEV=0000:01:00.0
while :; do
if [ ! -e "/sys/bus/pci/devices/$DEV" ]; then
echo 1 > /sys/bus/pci/rescan
sleep 8
fi
sleep 20
done
Two traps will make that rescan backfire. If broadcom-sta is installed, its wl module
has a wildcarded PCI match and can win the probe race after a rescan, binding itself to
your Intel card — and unbinding it then wedges uninterruptibly in the kernel, so only a
reboot clears it. If the machine has no Broadcom wireless, blacklist wl and move on.
The other trap is NetworkManager. A profile carrying connection.interface-name=wlan0
silently refuses to activate when the card returns as wlan1, which is exactly what
happens if anything else claimed wlan0 in the meantime. You get a working card with no
network. Bind profiles to the card instead of the name:
sudo nmcli con mod <uuid> connection.interface-name "" \
802-11-wireless.mac-address a4:c4:94:a3:1a:5b
Finally, the thing not to bother with: disabling ASPM. It is the obvious suspect, and on
this box it is worse than the disease. pcie_aspm.policy=performance on the kernel command
line was completely inert — coreboot's _OSC never grants the OS ASPM control, so the
kernel ignores the policy and lspci -vv still shows LnkCtl: ASPM L1 Enabled. Disabling
it per-device does work:
echo 0 | sudo tee /sys/bus/pci/devices/0000:01:00.0/link/l1_aspm
...and the card then died at 2h12m instead of 5h, with correctable PCIe errors jumping from
0.6/min to 60/min. Note you can disable ASPM at runtime but not re-enable it, for the same
_OSC reason — reverting needs a reboot.
One debugging aside that cost me an hour: if the RTC backup battery is dead, journalctl
wall-clock timestamps lie. The clock comes up wrong and chrony steps it seconds into boot
(System clock was stepped by 22559603.802825 seconds), so a single 5.8-day boot appeared
to span nine months and journalctl -b -1 returned different counts for the same boot.
Use journalctl -o short-monotonic and trust uptime, not dates.