I run Ubuntu 24.04 on an older HP Envy 17, and for months I’ve tiptoed around a maddening bug: every time the laptop went to sleep, it would wake up straight into airplane mode. The Wi-Fi hardware light glowed orange, NetworkManager insisted the radio was off, and the only way out was a full reboot. I finally set aside an evening to attack the problem, notebook in hand, determined to turn it into a postmortem instead of another rage-reboot.
First order of business was to prove the failure. I built a little diagnostic script that scooped up rfkill, nmcli, dmesg, and journal entries right after waking from suspend. The very first log told the story: the Intel 7260 Wi-Fi adapter came back “hard blocked.” In other words, the embedded controller itself was asserting the hardware kill switch. That meant user-space toggles were doomed from the start.
Since systemd loves to restore previous radio states, I masked systemd-rfkill.service and its socket. A reboot, suspend, and another diagnostic run later, the hard block was still there. So much for an easy win. The logs did, however, show the HP WMI hotkey driver participating in the resume sequence, so I tried blacklisting it next. No dice; the EC simply reasserted the kill line on its own.
With the firmware still in charge, I tried to wrestle control back in software. I dropped a systemd sleep hook that unbound and rebound the iwlwifi driver after every resume, sprinkled in rfkill unblock all, and told NetworkManager to wake up. The hook dutifully ran—my logs suddenly showed the device jumping from phy0 to phy1—but the EC flipped the RF_KILL bit again the instant the driver came back. Close, but not enough.
I even crawled through the InsydeH2O BIOS setup, hoping for a hidden “Wireless Button State” toggle. Nothing. That sent me back to the kernel docs, where I found a clue: this HP implements classic S3 suspend (deep), which hands control fully over to the embedded controller. If the EC is buggy, switching to the lighter-weight s2idle state can keep it from meddling with the radio.
I manually nudged /sys/power/mem_sleep to s2idle, closed the lid, and held my breath. When the machine woke up, Wi-Fi stayed alive. No hard block, no orange LED, no angry logs. That was the breakthrough. All that was left was to make it permanent by adding mem_sleep_default=s2idle to /etc/default/grub and regenerating GRUB.
Looking back, the path was messy but methodical: gather evidence, eliminate the usual suspects (systemd-rfkill, HP WMI), experiment with manual driver resets, and finally change the suspend strategy. For anyone else fighting resume-induced airplane mode on HP hardware, switching to s2idle might be the cleanest fix. At the very least, you’ll have a script full of juicy logs to show for the effort.
The diagnostic script:
#!/bin/bash
# Collect diagnostic data when Wi-Fi stays disabled after resume.
set -o pipefail
set -o nounset
if [[ "$EUID" -ne 0 ]]; then
echo "Please run this script with sudo." >&2
exit 1
fi
out_path="${1:-/home/dfish/suspend_airplane_diag_$(date +%Y%m%d_%H%M%S).log}"
mkdir -p "$(dirname "$out_path")"
{
echo "==== Suspend/Radio Diagnostic Report ===="
echo "Timestamp: $(date --iso-8601=seconds)"
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -r)"
echo "---- rfkill ----"
rfkill list || echo "rfkill list failed"
echo "---- nmcli radio ----"
if command -v nmcli >/dev/null 2>&1; then
nmcli radio all || echo "nmcli radio all failed"
nmcli device status || echo "nmcli device status failed"
else
echo "nmcli not installed"
fi
echo "---- Network Interfaces ----"
ip link show
echo
ip addr show
echo "---- Wireless Tools ----"
if command -v iwconfig >/dev/null 2>&1; then
iwconfig 2>/dev/null || true
else
echo "iwconfig not installed"
fi
if command -v iw >/dev/null 2>&1; then
iw dev || true
else
echo "iw not installed"
fi
echo "---- systemd rfkill ----"
systemctl status systemd-rfkill.service --no-pager || true
systemctl status systemd-rfkill.socket --no-pager || true
echo "---- Recent journal (last 5 minutes) ----"
journalctl -b --since "5 minutes ago" --no-pager || true
echo "---- Recent rfkill/hp_wmi logs (current boot) ----"
journalctl -b --no-pager | grep -Ei 'rfkill|hp_wmi|wlan|iwl|ath|suspend|resume' || true
echo "---- Recent dmesg (last 200 lines) ----"
dmesg | tail -n 200 || true
echo "---- Loaded wireless modules ----"
lsmod | grep -E 'iwl|ath|rtl|brcm|hp_wmi' || true
echo "---- PCI wireless devices ----"
lspci -nn | grep -Ei 'network|wireless' || true
echo "---- USB wireless devices ----"
lsusb | grep -Ei 'network|wireless' || true
echo "==== End of Report ===="
} > "$out_path"
echo "Diagnostic data saved to $out_path"
Leave a Reply