Fixing DisplayLink on Parrot OS 7
Most of my work happens on a Mac. Some of it doesn’t, so I keep a separate box running Parrot OS for when that comes up. The kind of setup where everything should just be there when you need it. When I sat down to use it and the DisplayLink USB dock wasn’t being recognised, that assumption immediately became a problem worth solving properly.
The words bad exit status: 2 are never the beginning of a short afternoon.
The First Wall
DisplayLink is the technology inside most USB docks and USB to HDMI adapters. It lets you run three monitors off a machine with a single video output. On Linux, it relies on a kernel module called evdi (Extended Virtual Display Interface), which is maintained outside the main kernel source tree by Synaptics. That matters, because it means every kernel update can potentially break it: the kernel’s internal APIs change, and evdi has to chase those changes on its own release schedule.
A fresh sudo apt install displaylink-driver produced this:
Building module(s)...(bad exit status: 2)
Error! Bad return status for module build on kernel: 6.17.13+2-amd64 (x86_64)
Consult /var/lib/dkms/evdi/1.14.8+dfsg/build/make.log for more information.
dpkg: error processing package evdi-dkms (--configure):
installed evdi-dkms package post-installation script subprocess returned error exit status 10The story, once you’ve seen it a few times, is straightforward. DKMS (the system that recompiles out of tree modules automatically when kernels change) tried to build evdi 1.14.8 against kernel 6.17.13, failed, and because displaylink-driver depends on evdi-dkms, the entire install collapsed. Both packages ended up in an unconfigured state, poisoning every subsequent apt command.
The Obvious Fix That Wasn’t Quite Enough
The repo version of evdi was clearly too old. The sensible move was to grab the latest source from GitHub and build it manually:
bash
sudo apt install git build-essential dkms libdrm-dev -y
git clone https://github.com/DisplayLink/evdi.git
cd evdi
sudo makeThe build started and immediately produced hundreds of compiler errors, all variations of:
error: comparison of integer expressions of different signedness:
'long unsigned int' and 'int' [-Werror=sign-compare]This wasn’t a bug in evdi’s code. Kernel 6.19 had introduced new header files containing comparisons between signed and unsigned integers, a pattern the C compiler flags as potentially dangerous. The evdi Makefile was using -Werror=sign-compare, which promotes that warning to a fatal error. The kernel headers themselves were triggering the stop.
The fix was a single line. Tell the compiler to warn but not die:
bash
sed -i 's/-Werror=sign-compare/-Wno-error=sign-compare/' Makefile
sudo make clean
sudo makeThis time the build completed cleanly. Module compiled, library built. So far, so good.
The Packaging Trap
bash
sudo make install -C module
sudo make install -C library
sudo apt install displaylink-driverThe module and library installed without complaint. Then apt install displaylink-driver ran, pulled in evdi-dkms as a dependency, and DKMS kicked off a fresh build of the old evdi 1.14.8 from the repo. Which failed. Again.
The question was no longer how to compile evdi. It was how to get the packaging system to accept a working installation when the package it depends on insists on compiling something broken.
The Treadmill
The natural instinct was to patch the DKMS package source at /usr/src/evdi-1.14.8+dfsg/ and retry. I did. And every single time, the patch was gone before the build ran.
Understanding why required reading what the evdi-dkms post install script actually does. Each time dpkg tries to configure the package, the script runs a full DKMS remove and readd cycle: it deletes the existing DKMS tree entry, copies the source in fresh from /usr/src/, and then attempts a build. My patch was landing on the source directory; the copy being used for the actual build was recreated after my patch, every time.
So I patched both locations and drove DKMS manually:
bash
sudo sed -i 's/-Werror=sign-compare/-Wno-error=sign-compare/' /usr/src/evdi-1.14.8+dfsg/Makefile
sudo dkms remove evdi/1.14.8+dfsg --all
sudo dkms add /usr/src/evdi-1.14.8+dfsg
sudo sed -i 's/-Werror=sign-compare/-Wno-error=sign-compare/' /var/lib/dkms/evdi/1.14.8+dfsg/source/Makefile
sudo dkms build evdi/1.14.8+dfsg -k $(uname -r)This also failed. But the error was completely different, and reading the make.log finally made the real problem visible.
The Actual Problem
evdi_drm_drv.c:150:10: error: 'struct drm_driver' has no member named 'date'
evdi_modeset.c:346:39: error: 'struct drm_device' has no member named 'struct_mutex'
evdi_fb.c:459:10: error: 'struct drm_fb_helper_funcs' has no member named 'fb_probe'These aren’t compiler configuration issues. These are genuine source code incompatibilities. The Linux DRM subsystem went through significant API changes between the kernel that evdi 1.14.8 was written for and kernel 6.19:
- The
datefield was removed fromstruct drm_driver, completing a long deprecation. struct_mutexwas removed fromstruct drm_device, finishing a multiyear effort to replace a single global lock with more granular locking.- Several function signatures changed across the framebuffer and connector subsystems.
The packaged evdi was written before any of these changes. No amount of compiler flag tweaking would fix structural incompatibility with the kernel’s internal interfaces. Every approach built on the DKMS package was doomed from the start.
The sign compare errors had looked like the problem. They were a problem, but fixing them only uncovered the real one underneath. If I’d read the make.log from the very first DKMS failure instead of assuming it was a packaging issue, I’d have seen the API errors immediately and saved myself an hour on the treadmill.
The Fix
The GitHub source at version 1.14.15 had already been updated for the kernel 6.19 API changes. The manual build from earlier, the one that compiled cleanly after the sign compare fix, was the working module all along. The remaining task was just to make the packaging system accept it.
bash
# Remove everything broken
sudo apt remove evdi-dkms displaylink-driver --purge
# Install the known-good module from the GitHub build
cd ~/Downloads/evdi
sudo make install -C module
sudo make install -C library
# Rebuild the module dependency database
# (The install had warned about a missing System.map and skipped depmod)
sudo depmod -a
# Verify the module loads
sudo modprobe evdi
lsmod | grep evdi
# Install displaylink-driver, bypassing the broken dependency
sudo apt download displaylink-driver
sudo dpkg --force-depends -i displaylink-driver*.debA note on --force-depends, because it has a bad reputation. In most situations, forcing past a declared dependency means you genuinely have a missing runtime component and things will break in obscure ways later. This isn’t that situation. The declared dependency is evdi-dkms, a packaging construct whose job is to compile and install evdi.ko. The actual runtime requirement is evdi.ko being present and loadable in the running kernel, which the manual install already satisfies. The packaging metadata doesn’t reflect reality, and --force-depends is the correct tool for telling dpkg to trust your judgement over the metadata.
The depmod -a step caught out an earlier attempt. The module install had warned about a missing System.map and skipped its own depmod run, so the module was in the right directory but the kernel’s module dependency database didn’t know about it. Running depmod -a explicitly registers newly installed modules. Without it, modprobe evdi returns “module not found” even though the file is right there.
Living With It
This fix won’t survive a kernel update automatically. The whole purpose of DKMS is to rebuild out of tree modules when new kernels arrive, and we’ve bypassed it entirely. When Parrot ships the next kernel, evdi will stop loading until you rebuild from the GitHub source again.
Three ways to handle that. First, watch the distro repos. Once the Parrot packagers ship a compatible evdi-dkms, you can reinstall the standard way and let DKMS take over. The gap is typically weeks, not months. Second, write a hook that triggers after kernel installation and runs the manual build automatically. More setup work, but fully autonomous after that. Third, pin the kernel version until the packages catch up, if you can’t accept DisplayLink breaking after an update.
For most people, option one is practical enough.
What I’d Tell Someone Starting Where I Started
Read the make.log first, not last. The dpkg output says “bad exit status: 2” and nothing else useful. The make.log tells you what the compiler actually complained about. Every minute spent troubleshooting the packaging layer without reading the build errors is wasted.
Separate compiler strictness failures from real incompatibilities. The sign compare errors looked fixable, and they were, but fixing them only revealed the structural API mismatches underneath. If you see DKMS failures on a recent kernel, check the make.log for missing struct members or changed function signatures before spending time on compiler flags. If the source is genuinely incompatible with the kernel, no flag will save it.
Understand the DKMS lifecycle when it breaks. The post install script runs a full remove and readd cycle, which recreates the build tree from scratch. Patching the source directory isn’t enough if the build tree is being rebuilt after your patch. Either patch both locations or drive DKMS manually.
Force options exist for a reason. --force-depends is a sharp tool and shouldn’t be the first thing you reach for. But when the declared dependency is a packaging construct and the actual runtime requirement is demonstrably satisfied by other means, it’s the right call.
Bleeding edge distros require engineers who can work below the packaging layer. If you run Parrot OS or any distro that prioritises recent kernels, you will occasionally hit situations where the kernel is ahead of driver support. This isn’t a distro bug. It’s an expected consequence of the design priorities. Knowing how to bridge that gap manually is part of running the system.
Quick Reference
bash
# Prerequisites
sudo apt install git build-essential dkms libdrm-dev -y
# Get the latest evdi source
git clone https://github.com/DisplayLink/evdi.git
cd evdi
# Fix the compiler strictness flag for kernel 6.19 headers
sed -i 's/-Werror=sign-compare/-Wno-error=sign-compare/' Makefile
# Build
sudo make
# Install the module and library
sudo make install -C module
sudo make install -C library
# Update module database
sudo depmod -a
# Load and verify
sudo modprobe evdi
lsmod | grep evdi
# Clean up broken packages
sudo apt remove evdi-dkms --purge
# Install displaylink-driver bypassing the broken dependency
sudo apt download displaylink-driver
sudo dpkg --force-depends -i displaylink-driver*.deb
# Check the service
systemctl status displaylink-driverTested on Parrot OS 7, kernel 6.19.6+parrot7-amd64, evdi 1.14.8 (repo) vs 1.14.15 (GitHub), March 2026. If you’re reading this after a subsequent kernel release, check the evdi GitHub issues page for current compatibility before assuming these steps apply unchanged.