Files
Jungfraujoch/docs/FPGA_PCIE_DRIVER.md
T
leonarski_f 30b6800289
Build Packages / build:windows:nocuda (push) Successful in 17m20s
Build Packages / build:windows:cuda (push) Successful in 19m52s
Build Packages / build:viewer-tgz:cpu (push) Successful in 9m38s
Build Packages / build:viewer-tgz:cuda (push) Successful in 11m18s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 9m34s
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 5m42s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 20m33s
Build Packages / Create release (push) Successful in 33s
Build Packages / build:rugnux:windows (push) Successful in 12m0s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 15m42s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m59s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m8s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m35s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 16m55s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 16m58s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / build:rpm (rocky8) (push) Successful in 15m21s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / build:rpm (rocky9) (push) Successful in 16m23s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m2s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m6s
Build Packages / Unit tests (push) Successful in 1h10m26s
v1.0.0-rc.171 (#81)
* Rugnux: basic support for CCD images (marCCD, SMV) and for gzipped miniCBF.
* `jfjoch_viewer`: opens the CCD formats, and fixes to the dataset plots.
* Documentation updates.

Reviewed-on: #81
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-09-17 14:42:52 +02:00

5.4 KiB

FPGA PCIe driver

Compilation

To compile the kernel module, type:

make

Installation

To install kernel module, you need to have root permissions and run:

sudo make install

Loading driver into kernel

After installing the kernel driver, it should be possible to insert it into the kernel via:

modprobe jfjoch

Ownership of the character devices

By default, character devices /dev/jfjoch<device number> are owned by root (user/group) and are not accessible by others. This means that jfjoch_broker must be running as superuser, which might not be optimal for security reasons in most cases. The behavior can be changed by creating udev rules. Create a file called /etc/udev/rules.d/99-jfjoch.rules with the following content:

KERNEL=="jfjoch*", OWNER="<UNIX username>", GROUP="<UNIX group>"

It is OK to provide only group, for example to make the devices accessible by group jungfrau:

KERNEL=="jfjoch*", GROUP="jungfrau"

DKMS

To avoid problems with updating the kernel, it is possible to use DKMS to autobuild Jungfraujoch kernel module, when new kernel is installed. For RHEL 8 it is well tested to use the RPM module built automatically from Jungfraujoch source. For other systems, it is necessary to follow the procedure below, though it is not well tested.

This first requires installing DKMS - for RHEL it is available via EPEL repository:

sudo dnf install dkms

Then use the script provided in the driver directory to copy driver code to DKMS directory:

./install_dkms.sh

If upgrading the driver, please first remove the current driver from DKMS system:

dkms remove jfjoch -v <version> --all

Driver parameters

Currently, there is one driver parameter nbuffers, that defines count of exchange buffers (see below). This can be adjusted in the modprobe operation, for example:

modprobe jfjoch nbuffers=1024

Exchange buffers

The parameter defines number of buffers used to exchange data between card and host application. Each buffer can hold one detector module (1024x512) in 16-bit or 32-bit mode + associated processing results and metadata. These buffers are used by both card-to-host and host-to-card operations.

Buffers use special allocation, as they are contiguous in physical address space, which helps the FPGA card to transfer all data associated with detector module in two DMA transfers (one data, one metadata). Useful buffer size is a bit more than 2 MiB, but given that kernel allocates physical memory in powers of two, 4 MiB is a safe number for one buffer size. A buffer can be mapped into user space by performing the mmap system call on the /dev/jfjoch<device number> character device.

Buffer count can be adjusted by setting nbuffers parameter. There are two considerations for setting optimal value:

  1. For card-to-host transfers, minimal value is roughly <number of threads in receiver> * <number of modules processed by thread; usually equal to number of modules per card>, this way each thread can have enough data for operation. Default thread count for Jungfraujoch receiver is 64.
  2. For host-to-card transfers, full detector calibration has to fit into memory and one buffer accommodates one calibration set for one module. So minimal count is <number of modules> * (3 + 3 * <number of storage cells>).

Based on both rules, optimal number is 512 buffers (2 GiB), though this can be adjusted for particular system and configuration.

Known problems

To avoid inconsistent behavior, this driver won't load if release number differs between the kernel driver and FPGA card.

CMake file

While CMake file is present in the driver directory, it is only for the purpose of proper detection of the files in CLion IDE. It is not made for actual compilation of the kernel driver and should not be used for that purpose.

Character device access

For each FPGA device a character device is created called /dev/jfjoch<device number>. When the device is opened, two operations are possible:

  • mmap() to map exchange buffers
  • ioctl() to communicate with the card Interfacing should be done through the JungfraujochDevice class in fpga/host_library directory.

Sysfs access

Certain performance counters can be read through sysfs mechanism in the kernel. One needs to cat files in /sys/class/misc/jfjoch<device number>/ directory.

RHEL 9.5+ virtual memory flags

RedHat Enterprise Linux 9.5 backported the vm_flags_set interface from Linux kernel 6.3 while still reporting kernel version 5.14, so a plain kernel-version test picks the wrong branch and the build fails. This is now detected automatically from RHEL_RELEASE_CODE, so the module builds unaided on RHEL 9.5 and later and on the CentOS Stream, Rocky and AlmaLinux equivalents, as well as on distributions that have not backported it. No user action is needed. The HAVE_VM_FLAGS_SET environment variable that earlier releases required is obsolete; it is still honoured if set, but setting it is no longer necessary and the DKMS packaging never passed it anyway.

Which kernel DKMS builds for

The DKMS package builds the module for the kernel it is being installed for, not the one currently running, so a module built while a kernel update is being applied loads correctly after the reboot. Building by hand in fpga/pcie_driver/ still defaults to the running kernel; pass KDIR=/lib/modules/<version>/build (or KVER=<version>) to target another one.