Files
Alexander Heldt 64640e98aa pinwheel: Fix intermittent webcam failure from IPU6 isys oops
On 7.3 the in-tree IPU6 isys driver can be runtime-suspended while
isys_probe() is still running, before it has set drvdata. The suspend
callback then dereferences a NULL isys, oopses, and psys never probes,
so /dev/ipu-psys0 is missing and the camera HAL fails with "Failed to
open PSYS".

Patch the isys runtime PM callbacks to return early when drvdata is
not set yet. The patched module is built on its own from the kernel
source and installed under updates/, so it overrides the in-tree one
without having to rebuild the whole kernel.
2026-11-03 13:46:56 +01:00

105 lines
2.9 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
inherit (config.boot.kernelPackages) kernel kernelModuleMakeFlags;
ipu6-isys = pkgs.stdenv.mkDerivation {
pname = "ipu6-isys";
inherit (kernel) version;
__structuredAttrs = true;
patches = [ ./ipu6-isys-runtime-pm-null-check.patch ];
nativeBuildInputs = kernel.moduleBuildDependencies;
unpackPhase = ''
tar -xf ${kernel.src} --strip-components=1 --wildcards '*/drivers/media/pci/intel/ipu6/*'
'';
postPatch = ''
sed -i '/+= intel-ipu6\.o/d' drivers/media/pci/intel/ipu6/Makefile
'';
makeFlags = kernelModuleMakeFlags ++ [
"KERNELRELEASE=${kernel.modDirVersion}"
];
installFlags = [
"DEPMOD=true"
"INSTALL_MOD_PATH=${placeholder "out"}"
];
buildPhase = ''
runHook preBuild
make -C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build \
M=$(pwd)/drivers/media/pci/intel/ipu6 "''${makeFlags[@]}"
runHook postBuild
'';
installPhase = ''
runHook preInstall
make -C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build \
M=$(pwd)/drivers/media/pci/intel/ipu6 modules_install \
"''${makeFlags[@]}" "''${installFlags[@]}"
runHook postInstall
'';
};
in
{
nixpkgs.overlays = [
(final: prev: {
ipu6epmtl-camera-hal = prev.ipu6epmtl-camera-hal.overrideAttrs (old: {
postPatch = (old.postPatch or "") + ''
substituteInPlace src/v4l2/MediaControl.cpp \
--replace-fail 'static const string ivscName = "Intel IVSC CSI";' \
'static const string ivscName = "Intel CVS";'
'';
});
gst_all_1 = prev.gst_all_1 // {
icamerasrc-ipu6epmtl =
(prev.gst_all_1.icamerasrc-ipu6epmtl.override {
ipu6-camera-hal = final.ipu6epmtl-camera-hal;
}).overrideAttrs
(old: {
version = "20250923_ov02e";
src = final.fetchFromGitHub {
owner = "intel";
repo = "icamerasrc";
tag = "20250923_ov02e";
hash = "sha256-mKRK0Z3dnyvzvoL6BotpVFRtkb53GQw9wUOrHIUoEsA=";
};
});
};
})
];
boot.extraModulePackages = [ ipu6-isys ];
hardware.ipu6 = {
enable = true;
platform = "ipu6epmtl";
};
services.v4l2-relayd.instances.ipu6.input = {
pipeline = lib.mkForce "icamerasrc buffer-count=10";
width = 1920;
height = 1080;
};
systemd.services.v4l2-relayd-ipu6 = {
preStart = lib.mkOverride 40 ''
mkdir -p "$(dirname "$V4L2_DEVICE_FILE")"
${config.boot.kernelPackages.v4l2loopback.bin}/bin/v4l2loopback-ctl \
add --name "Intel MIPI Camera" --exclusive-caps=1 --buffers 8 \
${toString config.hardware.ipu6.videoDeviceNumber} || [ $? -eq 17 ]
echo /dev/video${toString config.hardware.ipu6.videoDeviceNumber} > "$V4L2_DEVICE_FILE"
'';
};
}