Patching an in-tree Linux kernel module

I’ve written a patch for an in-tree kernel module (r8169). I got it working by patching the kernel:

boot.kernelPatches = [{
  name = "r8169";
  patch = ./r8169.patch;
}];

But this requires rebuilding the whole kernel. How can I build just the r8169 module with a patched source? I’m hoping I can then include it in boot.extraModulePackages and skip the long kernel build times.

I ended up doing it like this:

realtek.nix:

{ stdenv, lib, kernel }:

let
  modPath = "drivers/net/ethernet/realtek";
  modDestDir = "$out/lib/modules/${kernel.modDirVersion}/kernel/${modPath}";

in stdenv.mkDerivation rec {
  name = "realtek-${kernel.version}";

  inherit (kernel) src version;

  postPatch = ''
    cd ${modPath}
  '';

  nativeBuildInputs = kernel.moduleBuildDependencies;

  makeFlags = kernel.makeFlags ++ [
    "-C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
    "M=$(PWD)"
    "modules"
  ];

  enableParallelBuilding = true;

  installPhase = ''
    runHook preInstall

    mkdir -p ${modDestDir}
    find . -name '*.ko' -exec cp --parents '{}' ${modDestDir} \;
    find ${modDestDir} -name '*.ko' -exec xz -f '{}' \;

    runHook postInstall
  '';

  meta = with lib; {
    description = "Realtek ethernet drivers";
    inherit (kernel.meta) license platforms;
  };
}

default.nix:

{ config, lib, pkgs, ... }:

let
  realtek-kernel-module = pkgs.callPackage ./realtek.nix { inherit (config.boot.kernelPackages) kernel; };
  patched = realtek-kernel-module.overrideAttrs (prev: {
    patches = [ ./r8169.patch ];
  });
in
{
  boot.extraModulePackages = [
    (lib.hiPrio patched)
  ];
}

I was surprised there wasn’t a simple mkLinuxKernelModule or similar. I cobbled together the above from examples in nixpkgs.

2 Likes