4.4 KiB
Development log
legolas: NVMe (Corsair MP600 ELITE / Phison E21) suspend/resume crashes
The drive hung on resume from S3 (deep) suspend — boot logs ended at PM: suspend entry (deep) with no resume, followed by a hard reboot. The Phison E21 can't recover from the D3 transition that S3 forces.
Investigation also found two existing workarounds were doing nothing:
- The udev rule
ATTR{d3cold_allowed}="0"was a no-op — that sysfs attribute doesn't exist on this Phison endpoint or its parent root port (0000:00:1d.0). - The
nvme-resume-fixservice was broken:ExecStartused>redirection without a shell, soechojust printed the string and never wrote to therescansysfs file. It never actually rescanned.
Changes (hosts/legolas/hardware-configuration.nix):
- Switched
mem_sleep_defaultfromdeep(S3) tos2idle(modern standby). s2idle avoids the deep D3 path that hangs the drive. - Removed the no-op
d3cold_allowedrule and the broken rescan service. - Added a correct runtime-PM-off udev rule on both the NVMe endpoint (
0000:6e:00.0) and its parent root port (0000:00:1d.0), keeping the PCIe wakeup disable.
Note: runtime PM was already off on the endpoint (power/control=on); that alone never fixed the crash because system suspend uses a separate code path. Verify after rebuild that the cmdline has mem_sleep_default=s2idle (the running generation showed a stale duplicate deep).
Headless home-manager configs (galadriel, elros, elrond)
Added minimal home-manager configs for gunalx and root on headless hosts. These skip all GUI/desktop modules (niri, stylix, foot, noctalia, etc.) and keep only CLI tools: bash (with sops AI keys), git, nixvim (full config reused), opencode, atuin, sshconfig, sops.
Files:
home/gunalx-headless.nix— gunalx's minimal config, same module set asgunalx.nixminus all GUI imports.home/root.nix— identical CLI stack, explicitly setshome.username/home.homeDirectoryto root.home/sops.nix— parameterized age key paths to useconfig.home.homeDirectoryso both users work without duplication.home/sshconfig.nix— removedssh-askpass-fullscreen(unwired GUI dependency, was dead weight).flake.nix— addedheadlessHmModuleslet binding (shared by all three hosts) wiringhome-manager.users.gunalx+home-manager.users.root.
Manual step: root needs the sops age key at /root/.config/sops/age/key.txt (or SSH key at /root/.ssh/nixos) to decrypt AI API secrets. age.generateKey = true will create a new key, but it won't match the encrypted secrets — copy gunalx's age key to root's path, or re-encrypt the secrets with root's age public key.
galadriel: kernel 7.0 EOL
Linux 7.0 was removed from nixpkgs (EOL). pkgs.zfs (stable) is now 2.4.2, same version previously pulled from unstable. Switched boot.kernelPackages to the default (6.18) and boot.zfs.package to pkgs.zfs. No pool compatibility concern since ZFS version is unchanged.
legolas: lid-close still killing the NVMe — stale deep + logind suspend
Root cause of the recurring "SSD dies when lid closed": the booted generation carried a duplicate mem_sleep_default=deep after mem_sleep_default=s2idle (last wins), so /sys/power/mem_sleep was s2idle [deep] — every suspend went to S3. The source config only had s2idle; the stale param lived in the old generation. ACPI advertises S3 (supports S0 S3 S4 S5) but S3 is broken for the Phison E21 on this Skylake-era Intel platform, so only s0/s2idle is reliable. Separately, HandleLidSwitch was unset → defaulted to suspend, which was the actual lid-close trigger.
Changes (hosts/legolas/hardware-configuration.nix):
services.logind.lidSwitch/lidSwitchExternalPower/lidSwitchDocked=ignore. Lid close no longer suspends; niri'sswitch-eventsstill locks via noctalia, so the laptop stays on (RAM powered) but can't enter the S3 path.systemd.services.force-s2idlewritess2idleto/sys/power/mem_sleepat boot — guarantees the active mode is s2idle even if a future cmdline carries a straydeep.- Suspend (s2idle) remains available via
systemctl suspend; hibernation stays disabled.
Also fixed home/niri.nix lid-close command from the undocumented lockScreen lock to the v5-canonical session lock (matching the Mod+M binding).
Verify after rebuild+reboot: /proc/cmdline has no deep, and /sys/power/mem_sleep shows [s2idle] deep.