ThinkPad T450s ethernet and suspend
There seems to be a problem in Linux with the Intel E1000 ethernet device on a ThinkPad T450s, and possibly
other machines that use the e1000e device driver.
The symptom is that Network Manager (NM) hangs
trying to initialize the ethernet link after a suspend/resume cycle.
After a resume, NM shows a spinning icon for about 10 seconds trying to get an IP address, and it
eventually gives up. Telling NM to try again results in the same failure, forcing
you to unplug and replug the network cable.
I observed this problem with every Linux Mint version from 19.1 up, and on Fedora 42.
It seems that the e1000e network device driver fails to establish a link after
a suspend / resume cycle.
The solution is to do the following before a suspend:
- Disable NetworkManager
- Bring down the ethernet link.
- Unload the
e1000ekernel module.
It’s very important to unload the e1000e module after all the other steps;
otherwise it will have a non-zero reference count and the kernel will refuse
to unload it.
On resume, undo those steps in reverse order:
- Load the
e1000ekernel module. - Bring up the ethernet link.
- Enable NetworkManager.
After some searching, I came across a fix (link is broken now 1) that uses systemd to disable the ethernet device before suspend, and enable it after resume. Unfortunately, there are some typos in the proposed systemd scripts: a superfluous ‘[’ character, and missing spaces surrounding semicolons in the command lines.
Below is the modified fix for the problem. Log in as root to perform all
of these steps, or prefix each command with sudo.
Create the file /etc/systemd/system/network-suspend.service with the following
contents:
#/etc/systemd/system/network-suspend.service
#sudo systemctl enable network-suspend.service
[Unit]
Description=Stop network components prior to suspending
Before=sleep.target
[Service]
Type=oneshot
ExecStart=/bin/systemctl stop NetworkManager.service ; /bin/ip link set enp0s25 down ; /sbin/modprobe -r e1000e
[Install]
WantedBy=sleep.targetIf you are using a different ethernet device, use the ifconfig command to determine
the device name for ip link, and the lspci -v command to determine the driver name for modprobe.
Similarly, create the file /etc/systemd/system/network-resume.service with the following contents:
#/etc/systemd/system/network-resume.service
#sudo systemctl enable network-resume.service
[Unit]
Description=Start network components after resuming
After=suspend.target
[Service]
Type=oneshot
ExecStartPre=/bin/sleep 1s
ExecStart=/sbin/modprobe e1000e ; /bin/sleep 1s ; /bin/ip link set enp0s25 up ; /bin/systemctl start NetworkManager.service
[Install]
WantedBy=suspend.targetTell systemd to enable and then load the new service files using:
systemctl enable network-suspend.service
systemctl enable network-resume.service
systemctl daemon-reloadBefore seeing if these new services work in a suspend/resume cycle, you can test them manually. First, try the suspend service:
systemctl start network-suspend.service
systemctl status network-suspend.serviceThe second command should show any errors that might have occurred.
Similarly, test the resume service using:
systemctl start network-resume.service
systemctl status network-resume.serviceNow you can test a suspend/resume cycle. Note that after the resume, there is a two second delay
before Network Manager reports that the ethernet device is connected.
This is due to the two sleep commands in /etc/systemd/system/network-resume.service.
It’s possible that these delays could be reduced further, but two seconds seems
innocuous.
-
This is why I always try to copy solutions into my own posts, as a hedge against Internet Rot. ↩︎