module for recovering shitty realtek controller when it gets stuck in bugged power state

This commit is contained in:
2026-10-15 10:48:08 +02:00
parent 74d3d6870d
commit ac7a47c26a
3 changed files with 148 additions and 0 deletions
@@ -0,0 +1,58 @@
{ config, lib, pkgs, namespace, ... }:
let
cfg = config.${namespace}.rtl8125-recovery;
recovery = pkgs.writeShellApplication {
name = "rtl8125-recover";
runtimeInputs = with pkgs; [ coreutils gnugrep pciutils ethtool systemd ];
text = builtins.readFile ./recover.sh;
};
in {
options.${namespace}.rtl8125-recovery = {
enable = lib.mkEnableOption "RTL8125 PCI recovery after boot and resume";
pciAddress = lib.mkOption {
type = lib.types.str;
default = "0000:0a:00.0";
description = "PCI address of the onboard RTL8125 controller.";
};
bridgeAddress = lib.mkOption {
type = lib.types.str;
default = "0000:06:03.0";
description = "Immediate parent PCI bridge of the controller.";
};
};
config = lib.mkIf cfg.enable {
systemd.services.rtl8125-recovery = {
description = "Recover RTL8125 from failed PCI power restoration";
wantedBy = [ "multi-user.target" ];
after = [ "NetworkManager.service" ];
environment = {
NIC_PCI = cfg.pciAddress;
NIC_BRIDGE = cfg.bridgeAddress;
};
serviceConfig = {
Type = "oneshot";
ExecStart = lib.getExe recovery;
TimeoutStartSec = "90s";
StateDirectory = "rtl8125-recovery";
StateDirectoryMode = "0700";
UMask = "0077";
};
};
# sleep.target is stopped after resume. Queue recovery separately so its
# grace period does not hold up the sleep transaction or user sessions.
systemd.services.rtl8125-resume = {
description = "Queue RTL8125 recovery after waking";
wantedBy = [ "sleep.target" ];
before = [ "sleep.target" ];
unitConfig.StopWhenUnneeded = true;
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.coreutils}/bin/true";
ExecStop = "${pkgs.systemd}/bin/systemctl --no-block start rtl8125-recovery.service";
};
};
};
}