Madalin
Development enhanced by AI

It's Not Linux. It's the Firmware.

Three symptoms on a Dell XPS 13 9310 that look like Linux bugs — a battery setting that won't save, a heat warning in a cold room, and Wi-Fi that crashes itself. All three are the firmware, with real logs and fixes.

A moody close-up product shot of a laptop chassis edge in near-darkness, focused on a small illuminated amber warning indicator that glows confidently — even though everything around it is cool and calm. Cold slate-blue ambient light vs. the lone warm amber dot. Shallow depth of field, cinematic, minimal, editorial tech aesthetic. No text, no logos, no readable screens. 16:9.

Field notes from a Dell XPS 13 9310 · Arch Linux · kernel 7.0.14-zen1 · BIOS 3.34.0

Still a keeper in 2026

I still reach for my Dell XPS 13 9310 every day, and I don’t feel like I’m compromising. The 11th-gen Tiger Lake chip is plenty for real work, the 16:10 display has aged gracefully, the build is solid, and it runs cool and quiet with all-day battery. Five years on, it’s the rare laptop that never made me want to replace it.

Part of why I bought it was deliberate: it’s an Intel Evo machine, and I picked it with the idea of keeping the internals pure Intel — CPU and wireless both. On Linux, third-party Wi-Fi (Broadcom, Realtek, some Qualcomm) has historically been where the pain lives, so an all-Intel radio was a feature, not a detail. Hold that thought — it pays off in Case 03.

Because here’s the catch: run current Linux on the 9310 and you’ll hit a small cluster of behaviours that read as broken software. A setting that won’t save. A warning that fires in a cold room. Wi-Fi that periodically falls over. I spent an evening chasing each one to ground — and every single time, the OS was innocent. The firmware was the culprit, and in two of the three cases there was nothing to “fix” at all, only something to understand.

What follows is three case files. Each has the symptom you’d see, the evidence that convicts the firmware, and the actual resolution.


Case 01 — The battery setting that refuses to save

In GNOME Settings I pick “Preserve Battery Health.” I watch the window. Within a couple of seconds it flips itself back to “Maximize Charge.” Every time.

The obvious read is that GNOME is dropping the setting. It isn’t. The kernel exposes the charge limit as a plain sysfs file, so I went underneath GNOME entirely and wrote to it by hand — every value, not just the one GNOME wanted:

Exhibit A — writing the threshold directly

$ for v in 85 80 100 90; do echo $v | sudo tee \
    /sys/class/power_supply/BAT0/charge_control_end_threshold; done
tee: …/charge_control_end_threshold: Input/output error   # 85
tee: …/charge_control_end_threshold: Input/output error   # 80
tee: …/charge_control_end_threshold: Input/output error   # 100
tee: …/charge_control_end_threshold: Input/output error   # 90
$ cat …/charge_control_end_threshold
90   # unmoved. every write refused.

There it is. Every write returns EIO and the value stays pinned at 90. This isn’t GNOME losing your choice — it’s the Dell EC refusing it. On this platform the charge threshold lives in firmware NVRAM; the dell_laptop driver is just a thin window onto a value the embedded controller owns and persists across reboots. The OS can look, but it can’t touch.

So the “reset” is really: GNOME writes 80 → firmware rejects it → GNOME re-reads the file, sees 90, and honestly redraws the toggle to match. The UI is telling the truth about a value it was never allowed to change.

🟠 NOT AN OS BUG — Firmware NVRAM lock. Set it in BIOS (F2 → Power → Battery Charge Configuration), and treat GNOME’s toggle as read-only.


Case 02 — “Performance disabled due to high temperature” — at 49 °C

Cold boot. Cool room. I haven’t done anything yet. GNOME still warns that performance mode is throttled because the laptop is running hot.

My gut said this was nonsense, so I asked the daemon and the thermal zones the same question at the same moment:

Exhibit B — the claim vs. the sensors

$ powerprofilesctl
  performance:
    Degraded: yes (high-operating-temperature)
$ # what the sensors actually report, same second:
  TCPU 49°C   x86_pkg 49°C   TVR 59°C   TSKN 48°C
$ fwupdmgr get-updates
  System Firmware … up to date (3.34.0)

Forty-nine degrees is idle-cool. Nothing is throttling. The “high-operating-temperature” string isn’t a live temperature reading at all — it’s a degraded flag the firmware asserts through the ACPI platform-profile interface, and on the 9310 it can get stuck on and stay on. power-profiles-daemon is simply relaying, faithfully, a bit the firmware set and forgot to clear.

BIOS is already the latest, with no update pending, so there’s no patch to chase. This one has no fix because it has no real problem — the correct action is to recognise it as cosmetic and ignore it.

🟠 NOT AN OS BUG — Stale ACPI degraded flag. Cosmetic; verify your sensors are cool once, then let it be.


Case 03 — The “Killer” Wi-Fi that keeps killing itself

Every so often the connection stutters, throughput collapses to dial-up speeds, and the kernel log fills with the same red lines over and over.

This is the one that was a real bug — and the logs name the offender precisely.

Exhibit C — the firmware assert

iwlwifi 0000:00:14.3: Microcode SW error detected. Restarting 0x0.
iwlwifi 0000:00:14.3: 0x000022CE | ADVANCED_SYSASSERT
iwlwifi 0000:00:14.3: 0x20000070 | NMI_INTERRUPT_LMAC_FATAL
iwlwifi 0000:00:14.3: Device error - SW reset
iwlwifi 0000:00:14.3: missed_beacons:35, missed_beacons_since_rx:3
                      … ×128 this boot

But first, a confession-and-relief. Remember the pure-Intel bet? The card shows up as a “Killer AX1650s” — a Rivet Networks brand — and for a second I thought I’d been sold a third-party radio in an Evo machine. I hadn’t. Rivet Networks has been owned by Intel since 2020, and the AX1650s is a genuine Intel AX201 under the marketing skin. The all-Intel bet held; “Killer” is just a sticker on Intel silicon.

Which is also why the fix is the classic Intel-Wi-Fi one. The AX201’s firmware asserts under load, and it’s badly aggravated by Wi-Fi power-saving: the radio naps between the access point’s beacons, misses a run of them, and the recovery path can tip the firmware over. The textbook mitigation is to stop the radio from ever power-napping — force continuous active mode at the driver level:

# /etc/modprobe.d/iwlwifi.conf
# Force CAM — the radio never sleeps, so it never misses beacons
options iwlmvm power_scheme=1
options iwlwifi power_save=0

The twist: the “obvious” fix — disabling Wi-Fi power save in NetworkManager — does nothing here. My NetworkManager drives the iwd backend (a leftover from a more minimalist past life of this install), and NM’s wifi.powersave is only implemented for the other backend, wpa_supplicant. It’s silently ignored. That’s why the driver-level power_scheme=1 matters: it’s blind to which backend you run and just keeps the radio awake. (If you’re on iwd and want the userspace flag off too, add a NetworkManager dispatcher that runs iw dev wlan0 set power_save off on connect.)

Reboot to load it fresh, and the difference is not subtle:

Metric Before After
Link rate 65 Mbit/s 1441 Mbit/s
Missed-beacon events / boot 128 0
Firmware asserts recurring 0

🟢 FIXED — Driver-level CAM. Full Wi-Fi 6 restored, zero crashes.


If you just want the answers

# Symptom The real fix
01 Battery cap won’t save Set it in BIOS, not the OS — the kernel gets EIO on every write. Treat GNOME’s toggle as read-only.
02 “High temperature” at idle A stuck firmware flag, not a reading. No config, no patch — ignore it.
03 AX201 Wi-Fi crashes options iwlmvm power_scheme=1 in /etc/modprobe.d/iwlwifi.conf. On the iwd backend, add a dispatcher running iw dev wlan0 set power_save off.

Verify the Wi-Fi fix after a reboot:

$ iw dev wlan0 get power_save
Power save: off
$ sudo dmesg | grep -iE "missed_beacons|SYSASSERT|SW reset"
   (silence)

Moral of the story — when a Linux laptop “misbehaves,” check who actually owns the value before you blame the OS. Half the time the kernel is just the messenger for a firmware that decided, years ago, how things were going to be. And sometimes the scary-branded part is exactly what you hoped it was underneath.

Madalin

Madalin

AI integrator

🚀 Senior Architect | SRE & Database Expert | AI Orchestrator 👋 Building the future at the speed of thought. ⚡️ I don't just write code; I architect high-performance, bulletproof ecosystems. With a foundation in Systems Engineering and a mastery of Go and TypeScript, I bridge the gap between heavy-duty backend reliability and seamless, high-conversion frontends.

Continue the conversation

If this article reflects the challenges your organisation is navigating, explore more practical guidance across Madalin.