Linux Error Guide: 'firmware: failed to load rtl_nic/rtl8168g-2.fw (-2)' — Fix Missing Firmware
Fix Linux device init failures from missing firmware blobs, bad kernel modules, or IOMMU conflicts. Use dmesg and lspci to diagnose driver probe errors.
- #linux
- #troubleshooting
- #errors
- #kernel
Stuck on this Linux Admins error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
When Linux loads a kernel driver during boot or module insertion, the driver often needs to fetch a firmware blob — a binary file containing microcode or configuration data — from the filesystem before it can bring the hardware online. If that firmware is absent, or if the driver encounters a resource conflict during its probe sequence, the kernel logs one or more failure messages and the device never becomes usable.
The two most common forms appear in dmesg and journalctl -k like this:
[ 3.412198] firmware: failed to load rtl_nic/rtl8168g-2.fw (-2)
[ 3.412241] r8169 0000:03:00.0: Direct firmware load for rtl_nic/rtl8168g-2.fw failed with error -2
[ 3.413005] r8169: probe of 0000:03:00.0 failed with error -12
Error -2 is the kernel’s ENOENT — the firmware file was not found anywhere under /lib/firmware. Error -12 is ENOMEM — the driver could not complete memory allocation during probe, usually because an earlier initialization step (such as the firmware load) already failed and left it in an inconsistent state. Different drivers and hardware combinations produce similar patterns: the device is visible on the bus (lspci shows it), the correct kernel module is loaded, but the driver cannot finish initialization, so the interface never appears in userspace.
Symptoms
- A network interface, GPU, Wi-Fi adapter, sound card, or storage controller is physically installed but does not appear as a usable device. For example,
ip linkshows onlylo, oraplay -lreports no sound cards found. dmesg | grep -i failreports firmware load failures, probe errors, or resource conflicts immediately after boot or aftermodprobe.lspci -kshows the hardware but theKernel driver in use:line is absent, or it lists the wrong driver.- Attempting to
modprobethe driver manually returns immediately without error but the device still does not appear, anddmesgshows the failure. - On systems that upgraded the kernel without refreshing the
linux-firmwarepackage, a device that worked previously now fails after the reboot into the new kernel. journalctl -k --boot=0showsprobe of <PCI address> failed with error <negative number>for one or more devices in the first few seconds of boot.
Common Root Causes
Missing firmware package. The kernel driver exists but the matching binary firmware blobs — typically installed by linux-firmware on Debian/Ubuntu/Arch or linux-firmware on Fedora/RHEL — are absent. This is the most common cause after a minimal OS installation, a container-to-VM migration, or upgrading the kernel without pulling in the updated firmware package.
Firmware version mismatch. The installed firmware package is too old for the driver version shipped with the new kernel. The driver requests a file by a specific name and version that the older package does not contain.
Blacklisted or missing kernel module. A blacklist entry in /etc/modprobe.d/ prevents the correct driver from loading at all. Alternatively, the module is not present in the installed kernel’s module tree — common on custom or embedded builds where non-essential drivers are omitted.
IOMMU or PCI resource conflict. With IOMMU enabled and misconfigured, the driver may fail to map DMA regions because the BIOS has not reserved a valid aperture for the device. This surfaces as -ENOMEM or -ENODEV during probe rather than a firmware error.
Secure Boot with unsigned firmware. On systems enforcing UEFI Secure Boot with a strict key database, unsigned or third-party firmware blobs may be rejected by the kernel’s firmware loader before the driver ever receives them.
Hardware fault or PCIe slot issue. The device is visible on the bus but not responding correctly. The driver times out or receives bad data during firmware upload, logging a probe failure even though the firmware file is present.
Diagnostic Workflow
Start by reading the kernel ring buffer from the most recent boot and filtering broadly for device and firmware keywords:
dmesg | grep -iE 'firmware|probe|failed|error' | head -50
journalctl -k --boot=0 | grep -iE 'firmware|probe|fail' | head -50
Note the PCI address from the error message — it looks like 0000:03:00.0 — and look up the device:
lspci -k -s 0000:03:00.0
The output shows the device name, the Kernel driver in use: line (absent if no driver claimed it), and the Kernel modules: line listing every module capable of driving the device. If the driver is listed under Kernel modules but not Kernel driver in use, the module loaded but its probe failed.
Check whether the firmware file the driver requested actually exists on disk:
find /lib/firmware -name 'rtl8168g-2.fw'
find /lib/firmware -name '*.fw' | grep -i rtl
If the file is absent, the linux-firmware package either was not installed or needs to be updated:
# Debian / Ubuntu
apt-get install --reinstall linux-firmware
apt-get install firmware-realtek # additional non-free Realtek firmware on Debian
# RHEL / Fedora / CentOS Stream
dnf install linux-firmware
# Arch Linux
pacman -S linux-firmware
After installing firmware, reload the module without rebooting:
modprobe -r r8169 && modprobe r8169
dmesg | tail -20
Use modinfo to see exactly which firmware filenames a driver requests:
modinfo r8169 | grep -E 'firmware|depends|vermagic'
If lspci -k shows no module is available for the device at all, check whether the driver is compiled into this kernel build:
find /lib/modules/$(uname -r) -name '*.ko*' | grep r8169
cat /boot/config-$(uname -r) | grep -i CONFIG_R8169
A result of CONFIG_R8169=m means the module exists; CONFIG_R8169=y means it is built directly into the kernel image; absence means the driver was not compiled and you may need a different kernel or a DKMS module.
For IOMMU-related probe failures (commonly error -12, -19, or -22), inspect IOMMU state and the kernel command line:
dmesg | grep -i iommu
cat /proc/cmdline
To test whether IOMMU is the cause, add intel_iommu=off (Intel) or amd_iommu=off (AMD) to the kernel command line in GRUB temporarily and reboot.
Check for conflicting blacklist entries that prevent the correct module from loading:
grep -r 'blacklist' /etc/modprobe.d/
Example Root Cause Analysis
Scenario: After upgrading from Ubuntu 22.04 to 24.04 on a bare-metal server, the onboard Realtek NIC no longer comes up. lspci shows 03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller. ip link shows only lo.
Step 1 — read dmesg for the driver:
$ dmesg | grep -i 'r8169\|firmware\|probe'
[ 3.412198] firmware: failed to load rtl_nic/rtl8168g-2.fw (-2)
[ 3.412241] r8169 0000:03:00.0: Direct firmware load for rtl_nic/rtl8168g-2.fw failed with error -2
[ 3.413005] r8169: probe of 0000:03:00.0 failed with error -12
Step 2 — confirm the firmware file is missing:
$ find /lib/firmware -name 'rtl8168g-2.fw'
(no output)
Step 3 — check installed firmware packages:
$ dpkg -l | grep linux-firmware
(no matching packages)
The linux-firmware package was not carried over during the upgrade because a custom /etc/apt/sources.list was missing the main component.
Step 4 — install and confirm the file lands:
$ apt-get install linux-firmware
$ find /lib/firmware -name 'rtl8168g-2.fw'
/lib/firmware/rtl_nic/rtl8168g-2.fw
Step 5 — reload the driver and verify:
$ modprobe -r r8169 && modprobe r8169
$ dmesg | tail -6
[ 142.331] r8169 0000:03:00.0: firmware: direct-loading firmware rtl_nic/rtl8168g-2.fw
[ 142.411] r8169 0000:03:00.0 eth0: Link is Up - 1Gbps/Full - flow control rx/tx
$ ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
The NIC is fully operational without a reboot.
Prevention Best Practices
- Always install
linux-firmware(or the distribution equivalent) alongside the kernel, even on minimal or cloud images. Skipping it causes silent failures for a wide range of hardware including NICs, Wi-Fi cards, GPUs, and storage controllers. - After upgrading the kernel, verify that the firmware package version is at least as recent as the kernel: compare
apt-cache policy linux-firmwareagainstuname -rand update if the firmware package lags. - In Ansible playbooks or cloud-init scripts that update the kernel, add a task to also update
linux-firmwarein the same play so they never diverge. - On Debian-based systems with non-free hardware (Realtek, Broadcom, Intel Wi-Fi adapters), add the
non-freeandnon-free-firmwarecomponents to/etc/apt/sources.listand install the device-specificfirmware-*package (e.g.,firmware-realtek,firmware-iwlwifi). - After provisioning a new server, run
dmesg | grep -iE 'failed|error|firmware'as part of the post-provisioning validation checklist to catch probe failures before the machine is handed off. - Document the firmware package versions required for each hardware model in your infrastructure runbook so future OS rebuilds include all necessary packages from the start.
Quick Command Reference
# Read kernel messages for firmware and probe failures
dmesg | grep -iE 'firmware|probe|failed|error'
journalctl -k --boot=0 | grep -iE 'firmware|probe|fail'
# Identify device and in-use driver by PCI address
lspci -k -s 0000:03:00.0
lspci -k # all devices
# Check whether a firmware file exists
find /lib/firmware -name '*.fw' | grep -i <name>
# Install / reinstall firmware package
apt-get install --reinstall linux-firmware # Debian/Ubuntu
dnf install linux-firmware # RHEL/Fedora
pacman -S linux-firmware # Arch
# Unload and reload a driver module
modprobe -r <module> && modprobe <module>
# Show firmware filenames a module requests
modinfo <module> | grep firmware
# Check whether module is compiled in this kernel
find /lib/modules/$(uname -r) -name '*.ko*' | grep <module>
cat /boot/config-$(uname -r) | grep -i <CONFIG_NAME>
# Check for blacklisted modules
grep -r blacklist /etc/modprobe.d/
# Check IOMMU status
dmesg | grep -i iommu
cat /proc/cmdline
Conclusion
Device initialization failures in Linux follow a predictable pattern: dmesg records the PCI address, the driver name, and an error code that tells you exactly what went wrong. Error -2 (ENOENT) almost always means a missing firmware blob, solved immediately by installing or reinstalling linux-firmware. Error -12 (ENOMEM) or -19 (ENODEV) during probe suggests a resource conflict — often IOMMU mapping — that requires a kernel parameter change or BIOS configuration adjustment. By reading dmesg | grep -iE 'firmware|probe|failed' immediately after boot and cross-referencing with lspci -k, you can pinpoint any driver initialization failure in minutes and restore hardware functionality without a full reinstall or hardware replacement.
Fixed it? Get 500 Linux Admins & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.