Repository navigation
Minor Release 7.2.0
Pull Requests Since 7.1.0
Unlabeled
- #265 - feat(ci): FPGA-less CI — emulator + GPU stub + regression suite + DKMS across 5 distros
- #264 - Add GpuAsync user-space lifecycle API and refactor rdmaTest
- #244 - Avoid allocations during runtime
- #267 - Fix bring-up / teardown bugs in data_dev, aximemorymap, axistreamdma
- #266 - include/GpuAsyncUser.h: Add offset methods for latency registers
Pull Request Details
Avoid allocations during runtime
| Author: | Jeremy L. lorelli@slac.stanford.edu |
| Date: | Wed Apr 29 12:29:43 2026 -0700 |
| Pull: | #244 (206 additions, 111 deletions, 3 files changed) |
| Branch: | slaclab/pr-no-allocs |
Notes:
Description
Pre-allocates scratch buffers so we don't have to keep calling
kmallocduringdmaReadIndexand such.Introduces the following limitations:
- Max number of indices that can be returned at once is cfgRxCount + cfgTxCount
- Max number of buffers that can be read or written at once is cfgRxCount + cfgTxCount
If those conditions are violated, the ioctl returns with error.
I am not sure if the DAQ is trying to read/write/return more than its allotted amount.
Add GpuAsync user-space lifecycle API and refactor rdmaTest
| Author: | Larry Ruckman ruckman@slac.stanford.edu |
| Date: | Wed Apr 29 15:59:53 2026 -0700 |
| Pull: | #264 (996 additions, 317 deletions, 12 files changed) |
| Branch: | slaclab/gpu-api-dev |
Notes:
Summary
- Add
GpuAsyncContext+gpuAsyncInit()/gpuAsyncCleanup()toGpuAsyncUser.h, encapsulating the full GPU/FPGA bring-up and strict reverse-order tear-down for GPUDirect RDMA applications- Refactor
rdmaTest.cuto use the new API (replaces ~185 lines of inline boilerplate inmain()and threadsGpuAsyncContext*throughrunSimpleLoop)- Harden ioctl wrappers in
GpuAsync.h:gpuGetGpuAsyncVersionandgpuGetMaxBuffersnow returnssize_tso-1/errnofailures are representable;gpuIsGpuAsyncSupportedcorrectly maps ioctl failure to false; doc comments reflect-1/errno (not-ENOTSUPP)- CUDA 13.2 compatibility via
#if CUDA_VERSION >= 13000guard for thecuCtxCreate3->4 arg change; makeGpuAsyncUser.hself-contained- Add Doxygen comments across the public API and a Sphinx reference page (
docs/reference/gpu-async-api.rst) covering bothGpuAsync.handGpuAsyncUser.h, rendered via BreatheLifecycle correctness
gpuAsyncInit: goto-based unwind where each label unwinds exactly the steps that succeeded; seedsctx->fd = -1before any early-return path; disables FPGA DMA engines early; flushes the GPU stream before enabling engines; checkscuStreamWriteValue32return; logserrno/ CUDA error names on syscall and CUDA failures; cachesgpuGetMaxBuffers/gpuGetGpuAsyncVersion; validatesbufCnt > 0andbufSize > 0before alignment/bound checks; NULL-guards everycudaFreein unwind loops and unwinds partial NVIDIA memory registration on rx failuregpuAsyncCleanup: strict reverse-init order; NULL-guard every handle;fd = -1after teardown to preventclose(stdin)on double cleanup; clearsctx->devRegsand stale handles- Init-failure exit code normalized to
1rdmaTest fixes
- Validate
hdr.sizebefore loopback rx->tx copy and against allocated buffer on file dump- Enqueue loopback device-to-device copy on
ctx->cuStream(not the default stream)- Bound
tmpbuf/-xfile-dump allocation to actual payload size usingsize_tto match the-xpath; clamp dump copy to per-buffercudaMallocsize; guard negatives_dumpBytesbefore vector sizing- Use cached
ctx->dmaHeaderSizein the loopback hot loop copy- Cast
bufSizeto unsigned for%x; dedupe/reorder includesTest plan
make -C data_dev/app cudacompiles cleanly under CUDA 13.2 (NVCC) and CUDA 12.x./rdmaTest -d /dev/datadev_0 -b 16 -s 0x100000 -c 100-- receives events, exits cleanly- Loopback
./rdmaTest ... -l-- round-trip with no data corruption./rdmaTest ... -x <file>-- file dump bounded correctly
feat(ci): FPGA-less CI — emulator + GPU stub + regression suite + DKMS across 5 distros
| Author: | Larry Ruckman ruckman@slac.stanford.edu |
| Date: | Wed Apr 29 13:30:45 2026 -0700 |
| Pull: | #265 (18648 additions, 334 deletions, 112 files changed) |
| Branch: | slaclab/emu-fpga-ci-testing |
Notes:
Summary
End-to-end FPGA-less CI for
aes-stream-drivers. A virtual PCI device emulates the AXIS Gen2 DMA engine in 128-bit descriptor mode, annvidia_p2p_*stub services the GPU Async V4 stack, and a regression suite drives the realdatadevdriver through DMA / GPU / ioctl / mmap / interrupt paths across a five-distro build+load+test matrix on every push — no FPGA hardware or GPUs required. A KVM-based local CI harness reproduces the cloud matrix bit-for-bit.What's in the branch
Emulator kernel module —
emulator/driver/
- Virtual PCI host bridge (
pci_alloc_host_bridge) with full BAR0 register emulation:enableVer,addrWidth,channelCount,maxSize,online,DmaDataBytes.enableVerR/O field enforcement (emu_enforce_enablever_ro()) reassertsversion,Desc128En, andenableCnton every poll cycle so the driver'sAxisG2_Clearfull-word zero on rmmod cannot silently drop the next load into 64-bit mode.online1→0 edge fully resets DMA-engine state (ring base regs, WriteFree shadows) — moved out of the production driver and into the emulator where the reset belongs.- 128-bit descriptor DMA loopback engine preserves AXIS sideband (fuser/luser/cont/dest); seed-phase buffer discovery; IRQ coalescing (one IRQ per poll cycle) prevents WriteFree shadow drain.
irq_work-driven virtual IRQ exercises the real ISR → workqueue →AxisG2_Processpath.iomem_resourceclaim so the driver'srequest_mem_regionsucceeds against alloc_pages-backed BAR0.- In-kernel PRBS LFSR + verifier;
gpu_engineRX/TX FSMs and poll kthread.emu_gpu_pollkthread promoted toSCHED_FIFO(1)viasched_set_fifo_low();emu_gpu_poll_interval_usdefaults to 1000 µs (dev) and is overridden to 100 µs in CI so userspace doorbell spinners on a 2-vCPU runner cannot starve the wakeup.- Lazy
symbol_get+KBUILD_EXTRA_SYMBOLSfor clean gpu_stub drain at unload; stray-DMA guard + RX-warn rate limit on rmmod.build_versionsysfs attr +.build_versionsideband file frozen at Makefile build time.GPU stub module —
emulator/gpu_stub/
nvidia_p2p_stub.koexportsnvidia_p2p_*symbols (V4 only — V1/V2/V3 intentionally skipped).emu_gpu_addr_table.{c,h}— hashtable + miscdevice fops +EXPORT_SYMBOL_GPL; refcount-safefind_by_idx; lock-disciplinedstub_try_drain(hash_empty underaddr_ht_lock,synchronize_rcuoutside lock).- VMA-reuse branch in
nvidia_p2p_get_pages(emu_gpu_addr_is_stub_vma).- Same
build_versionsysfs surface as the emulator driver.- Kernel shims for pre-6.8 (
MAX_PAGE_ORDER) and pre-6.3 (vm_flags_set); RHEL 9.4+ exempt.User-space test programs —
data_dev/app/src/
dmaIoctlTest— exercises 28 ioctls in 27 numbered checks (24 DMA + 2 AXIS + 1 AxiVersion + 1 GPU readiness; check 5 coversGet_Index+Ret_Indexround-trip).dmaFileOpsTest— open / close / select / mmap / read.dmaErrorTest— buffer exhaustion, oversized write, invalid index.dmaGpuIoctlTest— all 6 GPU async ioctls.dmaGpuToggleTest— disable/enable pairs with countReset quiesce + per-frame PRBS preamble + maxBuffers + toggle_resume verification, retried on transient flakes.rdmaTestEmu— GPUDirect-style loopback with--sweep {64, 4096, 65536, 1M}, VA alignment, PRBS check, atexit cleanup, signed-int CLI validation, retry.dmaSmallFrameTest— 1-4 byte payload loopback withselect()drain (closes the count==0 vacuous-PASS hazard).Test harness —
tests/,scripts/ci/
- Phase-1 load + basic DMA:
test_proc,test_params,test_data_integrity,test_dma_rate,test_multichannel,test_reload_segfault.- Phase-3 gap coverage:
test_idx_loopback,test_frame_sizes,test_backpressure,test_irq_modes,test_tuser_sweep,test_concurrent_open,test_small_frames.- Test-5 reload cycle gates
cfgMode=2,cfgBgThold, and rmmod-under-load.- GPU phase runs only the GPU-unique tests (
test_gpu_ioctls,test_gpu_proc,test_gpu_dma_loopback) plus thenvidia_p2p_stubdrain_cb load/unload-order check; CPU coverage is provided once bytest-cpu.shand not re-run.- Modular CI scripts (
scripts/ci/build-{cpu,gpu}.sh,load-modules-{cpu,gpu}.sh,test-{cpu,gpu}.sh,test-dkms-{cpu,gpu}{,-smoke}.sh,unload-modules-{cpu,gpu}.sh,check-dmesg.sh,install-deps.sh).check-dmesg.shmatches canonical kernel tokens, scopes to the subtest window, verifies the kmsg baseline marker landed, and rejects vacuous PASS underdmesg_restrict=1.timeout-wrapped insmod acrosstest-gpu,reload_segfault, and the deterministic test binaries to prevent CI hang on rmmod-under-load oops.- Hardened against
set -epitfalls (((FAILED++)),grep -q && echo || true, pre-increment), retry around known-flaky cells (dmaLoopTest, irq_modes subtests, sweep/soak),printf '%s\n'instead ofechofor arbitrary content (DELTA / DMESG_DELTA / STATUS_RESP / KVER).CI pipeline —
.github/workflows/ci_pipeline.yml
- Single workflow replacing
aes_ci.yml. Five distros run the full build + load + test + DKMS sequence in both CPU and GPU phases:ubuntu:22.04,ubuntu:24.04,rockylinux:9,debian:experimental,fedora:rawhide.- Host kernel headers bind-mounted into containers; load/test gated at runtime on
CI_HOST_MATCH=1, otherwise falls back todkms ldtarball --no-prepare-kernelsmoke.- Kbuild compatibility layer: when host
scripts/binaries (modpost,gendwarfksyms,objtool) are glibc-incompatible, recompile from source withldd/find -Ldetection and selective stubbing;scripts/includeon the recompile path for older distros.ensure_kernel_gccGCC-toolset fallback with flag validation, awk-based version extraction (no PCRE), andgcc-Nsymlink whengcc-toolsetis unavailable; rejectsgcc-Nbinaries whose reported major doesn't match.- Phase-1 doc-build smoke test (Sphinx + Doxygen + HTML validation).
gpu_async.cmerge-base zero-diff gate — production driver source must not drift under the emulator.- Step summaries, error annotations, diagnostic-artifact upload on failure.
Local CI —
scripts/ci-local/,run_local_ci.sh,scripts/run_ci_parity.sh
- KVM runner with virtiofs shared FS, cloud-init VMs matching the cloud kernel.
- Per-cell runner + multi-distro orchestrator with parallel KVM mode (5+5 concurrent cells), diagnostic capture, hang repro.
run_matrix.shparallel-dispatch fix: explicitVM_SLOT=$((VM_SLOT + 1))(the((VM_SLOT++))post-increment returned 0 on the first iteration and trippedset -e, silently dropping all remaining load-test cells).- QEMU/TCG fallback for environments without KVM; QEMU/TCG path loads
nvidia_p2p_stubbeforedatadev_emulatorto match the cloud sequence.AI_LOCAL_CI_TESTING.mdandLOCAL_CI_TESTING.mdrunbooks.Documentation
docs/explanation/ci-pipeline.rst— pipeline architecture, distro matrix, emulator GPU poll thread (SCHED_FIFO + tick cadence), andenableVerR/O field enforcement.docs/reference/test-applications.rst— user-space test program reference with 28-ioctl breakdown.docs/how-to/dkms-install.rst— expanded multi-distro install (Ubuntu/Debian, Rocky/RHEL 9, CentOS 7, RHEL with subscription).include/AxiVersion.handinclude/GpuAsync.hkernel-doc converted to Doxygen@param/ inline/**<;gpuIsGpuAsyncSupportedreturnsboolcorrectly via> 0(signed-bool false-positive on-1fixed).- README adds host/guest kernel-match note.
Key design decisions
- 128-bit descriptor mode only — 64-bit mode is deprecated; the driver only creates a workqueue and processes completions when
Desc128En=1.- GPU Async V4 only — V1/V2/V3 register layouts skipped.
addrWidth=1(2 ring entries) — serializes TX descriptors to prevent shadow-register overwrite race.- One IRQ per poll cycle — coalesces forceInt and TX completion to keep WriteFree shadows from draining the free pool between polls.
- Seed phase for buffer discovery — zero-size RX completions probe valid buffer indices when init-time WriteFree capture is lossy.
BUFF_STREAM(cfgMode=2) in CI — avoids CMA allocation failures on runners.enableVerR/O fields enforced every poll cycle — mirrors the VHDL soAxisG2_Clearrmmod-time zero cannot silently land the next load in 64-bit mode.SCHED_FIFO(1)foremu_gpu_poll— RT priority keepsusleep_rangewakeups punctual under CFS contention from userspace doorbell spinners; CI tightens cadence to 100 µs.- GPU phase runs only GPU-unique tests — CPU coverage runs once.
- Kbuild recompile-from-source — keeps older-glibc distros in the matrix without host-kernel lock-in.
Test plan
- Phase 2 (CPU) green on all five distros: ubuntu:22.04, ubuntu:24.04, rockylinux:9, debian:experimental, fedora:rawhide.
- Phase 3 (GPU) green on all five distros.
- DMA loopback PRBS integrity holds across the 30s-per-cell sustained run.
- All Phase-1 + Phase-3 tests pass (proc, params, data_integrity, dma_rate, multichannel, reload_segfault, idx_loopback, frame_sizes, backpressure, irq_modes, tuser_sweep, concurrent_open, small_frames).
- GPU-unique tests pass:
test_gpu_ioctls,test_gpu_proc,test_gpu_dma_loopback.dmaGpuToggleTestpasses across state transitions with frame-level PRBS verification.rdmaTestEmu --sweeppasses across{64, 4096, 65536, 1M}.- Test-5 reload cycles (
cfgMode=2,cfgBgThold, rmmod-under-load) complete without timeout.- Driver reload after rmmod keeps
Desc128En=1(no silent 64-bit fallback).gpu_async.cmerge-base zero-diff gate stays green.- DKMS smoke passes on non-
CI_HOST_MATCHcells; full DKMS install/remove passes on matching cells (CPU + GPU).- Phase-1 doc build smoke passes.
aes_ci.ymlremoved;ci_pipeline.ymlpreserves required-check job keys.
include/GpuAsyncUser.h: Add offset methods for latency registers
| Author: | Jeremy L. lorelli@slac.stanford.edu |
| Date: | Mon Apr 27 21:18:22 2026 -0700 |
| Pull: | #266 (43 additions, 3 deletions, 1 files changed) |
| Branch: | slaclab/pr-gpu-async-user-update |
Notes:
Description
Adds a version override parameter to the constructor for cases where you want to override the GpuAsyncCore version
Adds methods for getting the offsets for the latency registers, for use with CUDA kernels.
Fix bring-up / teardown bugs in data_dev, aximemorymap, axistreamdma
| Author: | Larry Ruckman ruckman@slac.stanford.edu |
| Date: | Wed Apr 29 13:57:50 2026 -0700 |
| Pull: | #267 (77 additions, 26 deletions, 6 files changed) |
| Branch: | slaclab/datadev-init-cleanup |
Notes:
Summary
Reviewed and fixed bring-up (probe /
_Init) and teardown (remove /_Exit) sequences for three kernel drivers and the shareddma_commonhelpers they call:
data_dev/driver/src/data_dev_top.c(PCIedatadevdriver — symlink tocommon/driver/data_dev_top.c)Yocto/recipes-kernel/aximemorymap/files/aximemorymap.cYocto/recipes-kernel/axistreamdma/files/axistreamdma.cWhile in there, also fixed a pre-existing version-guard bug that was preventing builds against kernel 6.2 / 6.3.
Bugs fixed
Resource leaks on probe failure paths
data_dev_top.c:DataDev_Probefailures afterDma_MapRegsucceeded (IRQ-missing check,dma_set_mask/dma_set_coherent_maskfailures) only calledpci_disable_deviceand leaked theiomap+mem_regionclaim. Addederr_unmaplabel that callsDma_UnmapRegbefore disabling the PCI device.axistreamdma.c:Rce_Probefailures afterirq_of_parse_and_mapandDma_MapRegused barereturn -1and leaked the virtual IRQ mapping plus the ioremap + mem_region claim. Addederr_post_irq_map/err_post_mapreg/err_dma_initlabels that unwind in reverse order, includingirq_dispose_mappingand amemsetto clear thegDmaDevicesslot.Teardown bugs
aximemorymap.c:Map_Exitwas missingcdev_del(&dev.charDev), leaving the character device live across module unload. Teardown order also did not match the reverse ofMap_Init(class_destroyran afterunregister_chrdev_region). Reordered to:cdev_del->device_destroy->class_destroy->unregister_chrdev_region-> free maps.axistreamdma.c:Rce_Removenever calledirq_dispose_mappingon the virtual IRQ created byirq_of_parse_and_map— every probe -> remove cycle leaked an IRQ mapping. (Dma_Cleanis intentionally untouched so the PCI path throughdata_dev_top, which usespdev->irqdirectly, is unaffected.)API-correctness bugs in helper code
dma_common.c/aximemorymap.c:class_create()anddevice_create()returnERR_PTRon failure, notNULL. The existing== NULLchecks let real failures through to a kernel oops ongCl->devnode = .... Switched toIS_ERR_OR_NULL(). Onclass_createfailure, also resetgCl = NULLso the shared(gDmaDevCount == 0 && gCl != NULL)cleanup logic stays safe.dma_common.c/aximemorymap.c:cdev_add()returns-errnoon failure (-EBUSY,-ENOMEM, …), but the checks were== -1and only caught-EPERM. Switched to< 0.dma_common.c:Dma_UnmapRegwas non-idempotent (no NULL check, no clear ofdev->base) andDma_MapRegleftdev->basepointing at unmapped memory after arequest_mem_regionfailure. MadeDma_UnmapRegidempotent andDma_MapRegcleardev->baseon error so multi-path cleanup is safe.Kernel version guards
axistreamdma.c/axistreamdma.h: the platform-driver.removecallback returnsintprior to kernel 6.11 andvoidfrom 6.11 onward. The currentvoid Rce_Remove(...)only matched 6.11+, so the driver did not compile on the supported kernel range (3.10 - 6.10). Version-guarded both the prototype and the definition.dma_common.c/dma_common.h/aximemorymap.c: theclass.devnode()callback becameconst struct device *in upstream commitff62b8e6588f("driver core: make struct class.devnode() take a const *") in v6.2-rc1, not v6.4. The version guard forDma_DevNode/Map_DevNodewas conflated with the separateclass_create()THIS_MODULE-removal change in v6.4 (commit1aaba11da9aa), causing a function-pointer type mismatch when building against kernels 6.2 and 6.3. Lowered only the devnode guard toKERNEL_VERSION(6, 2, 0)(theclass_create()guard at 6.4 stays — that change really is in 6.4). Kept theRHEL_RELEASE_VERSION(9, 4)fallback for both, matching how RHEL 9.4 backported the upstream changes.Commits
Five atomic commits, smallest blast radius first:
dma_common: harden init/cleanup error paths and helper APIsdata_dev_top: unmap registers on probe failures after Dma_MapRegaximemorymap: fix Map_Exit teardown order and init error checksaxistreamdma: clean up probe/remove resource paths and guard remove signaturedma_common, aximemorymap: lower class.devnode const guard from 6.4 to 6.2Test plan
cpplint(matching CI invocation) clean on all modified files- CI whitespace / tab checks clean
- Local
make driveragainst all installed kernels: 5.15.0-91, 5.15.0-139, 5.19.0-50, 6.2.0-39, 6.5.0-45, 6.8.0-59, 6.8.0-107, 6.8.0-110 — all build clean. (Previously 6.2.0-39 failed with-Werror=incompatible-pointer-types.)- Live smoke test on a real
/dev/datadev_0: twormmod datadev+insmod datadev.kocycles on running 6.8.0-110 kernel — module reloaded cleanly each time,/dev/datadev_0re-created, IRQ 162 reacquired, no warnings / oops / leak messages in dmesg,/proc/iomemshows a singlef3000000-f3ffffff : datadev_0claim with no duplication.- CI build matrix (Ubuntu 22.04 / 24.04 / Rocky 9 / Debian experimental / CentOS 7) — to verify on PR
- Yocto / platform-driver path — needs target hardware to validate
axistreamdmarmmod/insmod cycle and confirm IRQ-mapping leak fixNotes for review
- All fixes preserve existing behavior on the success path; only error / teardown paths change.
- No public API change. The only internal-helper signature change is
Dma_UnmapRegbecoming idempotent (no callers needed updating).Dma_Cleanis left unchanged — the PCI path throughdata_dev_topusespdev->irqdirectly and never callsirq_of_parse_and_map, so disposing the mapping there would be wrong. Onlyaxistreamdma'sRce_Removedoes it explicitly.- Sister drivers
rce_stream/driver/src/rce_top.candrce_hp_buffers/driver/src/rce_top.clikely share the same IRQ-mapping leak and inverse.removesignature problem (int-> breaks on 6.11+). Out of scope for this PR.